For wider pixels, the hardware just drew each pixel for longer, and for taller pixels each pixel spanned more lines.
Pixels weren’t real in the CRT days :)
396 karma · joined December 25, 2019
For wider pixels, the hardware just drew each pixel for longer, and for taller pixels each pixel spanned more lines.
Pixels weren’t real in the CRT days :)
At this stage in a project like this, I’d expect the people who were getting boards fabbed to also have the skills to sanity check the schematics and layout before they sent the gerbers off to China.
Even if we assume this _could_ be one-shotted, projects like this from respected members of the retro hardware community would be what made that one-shot even possible.
Perhaps in the fullness of time essential software can be rewritten to Anos’ “native API”, or perhaps that’s a pipe dream and not worth the work, but the option will be there.
I’m glad you found some inspiration and really appreciate your kind comment :)
You can get surprisingly far in this area with a decent libc implementation - once you have that porting a lot of things becomes possible. There will always be harder problems (e.g. anything that hard-depends on fork) but with enough work pretty much anything in user-space should be possible to port eventually.
I’m using newlib for libc, with a custom Anos-specific libgloss that mostly talks to SYSTEM via IPC to get stuff done, and uses syscalls where needed (and a process has the appropriate capabilities). I’m filling out that low-level interface as I go, and will be using porting of exiting BSD or Linux software to drive that implementation :)
Haha yes, that's a very fair comment!
SYSTEM has a tiny arch-specific assembly trampoline which just sets up the initial stack pointer for new processes that it creates and makes the jump, but other than that it's source-compatible across architectures.
The platform detail extraction isn't yet complete, such that devices management on non-ACPI platforms isn't finished, but the idea is the abstraction will be enough that drivers for (at least) MMIO devices will be trivially portable.
It's certainly useful _to me_ and has helped me really nail down concepts I thought I already understood, but it turns out I didn't.
I just hope that, in an age where it feels like code, and maybe even deep technical knowledge have diminishing value, projects like this don't become completely anachronistic.
Finding people with the knowledge, time and willingness to proof-read is also hard - but surely not insurmountable if we collectively decide it’s an endeavour we want to pursue.
That said, I’m once again reminded that we sorely need some updated resources for aspiring OS developers in 2025. Targeting 32-bit x86 and legacy devices that haven’t been “the norm” for decades suggests to me a heavy influence from resources like the osdev wiki which, while occasionally useful, are increasingly outdated in the modern world and lead to many questionable choices early on.
I have come to believe (through multiple iterations of my own OS projects) that there’s more value in largely ignoring resources such as osdev and focusing instead on first-principles design, correct layering, and building based on modern platforms (be that x86_64 or something else) and ignoring legacy devices like the PIT and PS2 etc.
I just wish we had good introductory documentation resources to reflect that, and that outdated resources weren’t overwhelmingly surfaced by search engines and now AI “summaries”.
None of the above is intended to take away from OPs achievement, which is fantastic, or from the work done over the years by the osdev community, who I’m sure largely do the best they can with what they have.
The primary issue with most tutorials that I’ve seen is they don’t, when completed, leave one in a position of understanding “what’s next” in developing a usable system. Sticking with x86_64, those following will of course have set up a basic GDT, and even a bare-bones TSS, but won’t have much understanding of why they’ve done this or what they’ll need to do to next to support syscall, say, or properly layout interrupt stacks for long mode.
By focusing mainly on the minutiae of legacy initialisation (which nobody needs) and racing toward “bang for my buck” interactive features, the tutorials tend to leave those completing it with a patchy, outdated understanding of the basics and a simple baremetal program that is in no way architected as a good base upon which to continue toward building a usable OS kernel.
For all the reasons stated in the link from the README [1] and agreed by the author, this project should not be followed if one wants to gain an understanding of the design and implementation of operating systems for modern systems. Following it will likely lead only to another abandoned “hello world plus shell” that runs only in emulation of decades old hardware.
My advice is get the datasheets and programmers’ manuals (which are largely free) and use those to find ways to implement your own ideas.
What you mention about VGA being common on x86 was what got me curious, since it’s not a thing on riscv. In my own OS project I’m using a framebuffer to show a graphical terminal on both x86 and riscv64 so I wondered if OP was doing similar or was really using SBI output.
I did see the putchar stub in the user.zig but, lacking understanding of zig, wasn’t sure how that could work given common.zig is looking for putChar in kernel.zig as far as I could tell.
I just jumped through a couple of hoops to get zig 0.13 installed and see an error about “root struct of file ‘kernel’ had no member named ‘putchar’” so I guess maybe it’s not implemented here at all.
I was just looking around for your input/output code, I don’t know zig but I expected to find putChar in kernel.zig based on the import in common.zig, but I don’t see it, should I be looking somewhere else? I didn’t see any simple command line processing either as mentioned in the README?
Mostly just looking around since your README mentioned VGA (and you seem to have a BIOS boot) which struck me as interesting on a RISC-V project, I was curious if you were actually using the SBI routines or had actually mapped in a VGA text mode buffer?
At this early stage, the filesystem exists only to prove the disk drivers and the IPC interfaces connecting them. I chose FAT32 for this since there has to be a FAT partition anyway for UEFI.
The concept of the VFS may stick around as a useful thing, but it’s strictly for storage, there is no “everything is a file” ethos. It’s entirely a user space concept - the kernel knows nothing of virtual filesystems, files, or the underlying hardware like disks.
Well, not quite _every_ time. For example, I’m deliberately not doing POSIX with my latest one[0], so I can be a bit more experimental.
For a while I was running both cursor and RubyMine in tandem and switching between as needed, but lately I’ve been using Claude code for most stuff, in a RubyMine terminal and I hardly miss cursor at all.
One minor nit, for the “odd corner case that likely never exists in real code” of taken branches to the next instruction, I can think of at least one example where this is often used: far jumps to the next instruction with a different segment on x86[_64] that are used to reload CS (e.g. on a mode switch).
Aware that’s a very specific case, but it’s one that very much does exist in real code.
I’m still working on a good way to integrate more feedback for this kind of workflow, e.g. for the attempt it made at AP bootstrap - debugging that is just hard, and giving an agent enough control over the running code and the ability to extract the information it would need to debug the resulting triple fault is an interesting challenge (even if probably not all that generally useful).
I have a bunch of pretty ad-hoc test harnesses and the like that I use for general hosted testing, but that can only get you so far in this kind of low-level code.