VOGONS


Introducing DOSContainer

Topic actions

First post, by bvdw78

User metadata
Rank Newbie
Rank
Newbie

Hello all,
Inspired by running the MiSTer AO486 and PCXT cores, I started working on a toolbox for collection-building. Creating disk images from scratch all the time was getting old really quickly. The problem: the DOS ecosystem comes with a bazillion permutations for running any half-decent game or application. Hence the idea of DOSContainer was born: I stole the idea from Docker in that I'm building up disk images in layers. Start with an inception layer that contains just the sacred trinity of system files, then layer the game/app itself and its requirements on top of there as needed in the form of any number of layers. I'm writing the toolbox in Rust because that's a language I wanted to learn anyway and it lends itself to systems programming.

Current state: I have a very preliminary CLI working with an even more preliminary YAML format that specifies an application's "manifest". The plan is to work up from IBM PC-DOS 1.00 all the way to MS-DOS 6.22. Currently I have PC-DOS 1.00 and 1.10 working and I'm currently implementing PC-DOS 2.00.

DOSContainer is now spitting out floppy images in 160/320 and 180/360 formats. Once I'm done implementing subdirectory support, volume labels and all of the supported directory entry attributes I'll start work on partitioned media (hard drives). The 'golden path' for this will be IBM versions until the point in time where MS started releasing their OS to the general public. When I get to 6.22, I'll look into whether finishing the PC-DOS pedigree makes sense or things like DR-DOS would be more valuable.. but I'm getting way ahead of myself.

The main challenge I'm setting myself is to be as close to the original as I can get. I'm calling this "museum quality". You should be able to write "my" disk images to a physical floppy and not be able to tell it apart from a contemporary original. This is so that collection builders can use my tool to build high quality disk images with the strictest guarantees when it comes to compatibility. This is especially important for the FAT implementation and surrounding structures, so I'm actually rewriting all of that code entirely from scratch based on what IBM/MS documented and by reverse-engineering what these OS'es actually do on hardware.

The state of affairs currently is a very early pre-alpha stage, so why announce it? Simply put: I could use some help. While I was technically alive when these ancient DOS versions were current, I was born in 1978 so I missed most of the first decade of DOS. Anyone who can give me some deeper insights into the what/how/why of ancient DOS beyond the official IBM/MS manuals, please reach out. Also, if you're a Rust developer I'd very much appreciate a code review or two. I'm not a professional developer and I only have ChatGPT as a "mentor" to guide my coding style.

The code for my project lives here: https://code.area536.com/DOSContainer

My CI server drops builds here: ftp://ftp.area536.com/doscontainer/builds/ but beware, my CI dumps *every* build in there so it's a bit of a mess.

Reply 1 of 3, by Snover

User metadata
Rank l33t++
Rank
l33t++

Also, if you're a Rust developer I'd very much appreciate a code review or two. I'm not a professional developer and I only have ChatGPT as a "mentor" to guide my coding style.

Hey, you nerd sniped me. Congratulations! I am not familiar enough with the problem area to give any feedback on the overall design, but as far as general Rust advice goes, looking briefly:

  1. Leverage some more of the existing Rust ecosystem instead of rolling your own; for example, use thiserror for custom errors instead of manually implementing Display, From, etc. Consider something like binrw* for serialising binary formats you do not control. (serde is always a better choice for serialising data where you control the format.)
  2. Notwithstanding the previous, avoid clap. It is incredibly slow to compile and creates giant binaries. There are more sensible argument parsers like pico-args. There are a few Rust crates that are popular but awful in this way; lib.rs can be more useful than crates.io for this problem, because it has better discovery for similar crates in a given category, and makes it much easier to see when a crate has an insane binary size or dependency tree.
  3. Use a single repository and a cargo workspace instead of nine different repositories. Definitely don’t create your own registry; Cargo supports fully qualified URLs (including Git repositories) for your dependencies if you don’t want to use a workspace for some reason. (But, really, use a workspace.)
  4. Allocations: don’t! (Unless you have to.) Don’t return a String when you can return a &str. Don’t use PathBuf when you can use Path. Don’t call collect when you can keep using an iterator (either by using it directly or by returning impl Iterator). Similarly, when borrowing, use the most generic type you can. So, don’t return &Vec<T> when you can use &[T]. cargo clippy should warn about most of these anti-patterns, so use it. (Enable pedantic lints, too.)
  5. from_str is not a bare method, it is part of the FromStr trait.
  6. You can use std::include_bytes! macro instead of inlining boot sector data to the source code.
  7. Follow Rust conventions, e.g. do not put get_ on your methods. See Naming.
  8. The main function can be specified to return a Result which is probably better than using expect or unwrap.
  9. If you aren’t already—though it looks like you probably are—run cargo fmt so you don’t have to think about formatting.

Good luck, have fun!

* I am a co-maintainer of this library so am biased. However, I am also co-maintainer of this library because I tried all the other ones first. 😀 The Rust ntfs crate has been using binrw for a long time so others seem to find it to be a good choice for filesystems.

Yes, it’s my fault.

Reply 2 of 3, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

i dont really get the point of this project. so your basically going around a games installer to pre-install it? and your super worried about disk layouts and versions of dos for some strange reason?

since the spectrum of pc hardware is so vast and wide, its mostly irrelevant. i dont know anyone who actually ran a non-microsoft dos back in the day. compatibility was not there and no games i know of required pc-dos or dr-dos instead that would not work on ms-dos.

how is your pre-build image supposed to handle hardware selection when it installs drivers as it goes? going to have multiple hd images, one per sound card?

why would I write your prebuild image to disk? did you use LBA or CHS? thats the deal breaker, unless you provide the same build for two different geometry formats...
does my bios geometry list support your disk size? pc hardware being so varied... i'd rather run a games installer or unzip that worry about some fixed hd image.

maybe I dont understand what your doing or trying to accomplish.

--/\-[ Stu : Bloody Cactus :: [ https://bloodycactus.com :: http://kråketær.com ]-/\--

Reply 3 of 3, by bvdw78

User metadata
Rank Newbie
Rank
Newbie

Thanks Snover, very useful feedback!! Will look into these points.

What I'm trying to accomplish is to have a tool primarily for collection builders. You write a compact configuration file (not sure yet if it's to be YAML, I want something to be hierarchical), and it spits out a disk image to spec. This config file determines the version of the OS, the exact mouse driver, memory managers, middleware and any other dependency. It also determines the disk type, either a specific floppy or a hard drive with either a specific geometry that you can specify or a sensible default calculated based on size if you don't care.

The purpose, in the end, is for the collection builder to be able to spit out any number of disk images in any configuration that'll be bootable for the end user. You want Monkey Island 1 specifically with EGA and MT32 sounds on a 10MB hard drive? You can specify that *once* in a config manifest and commit to your repo. Not happy and want a 15MB hard drive? Change a single number, run, done. Want CuteMouse instead of MS Mouse? A single line edit. Clean, repeatable, fast.

This is squarely aimed at collection builders, not end users directly and its purpose is to provide an answer to the fact that you can never do it right for everyone. I want my own collection to be:

1. Authentic above all else, as far as I can take this. Personal goal, hence the painstaking focus on versions and accuracy. I like solid foundations.
2. Maintainable. I don't want to have to change a bazillion disk images by hand when a new version of CuteMouse or whatever comes out. I'm also aiming for the option that you can set "I want my games to run in EGA mode if they have it" for a collection of hundreds or even thousands of games in only one place, then spit out a new instance of the collection from a CI/CD environment and be done with it.
3. Easy to use. The disk images should be bootable with zero end-user knowledge required. Configuring the collection itself should also be simple.
4. Configurable. The result should fit your hardware. You want CGA with AdLib? You got it. Want VGA with SBPro? A GUS? A specific mouse driver? You got it. Specific disk geometry? OS version? Set it, done.

It's absolutely legitimate for anyone to not care about any of these factors. I do, and I haven't been able to find anything out there to scratch my itch. That's why I'm writing this now. I like open source, and that's why I'm sharing.