Hacker News new | past | comments | ask | show | jobs | submit login
Bootable minesweeper game in a 512-byte boot sector (github.com/io12)
94 points by illuminated 10 months ago | hide | past | favorite | 17 comments



The final code takes 399 bytes, so there is still free space for the disk label (bytes 440-443), read-only flag (bytes 444-445) and partition table (446-509).

  truncate -s 100M disk.img
  dd if=bootmine.img of=disk.img bs=512 count=1 conv=notrunc
  fdisk disk.img
  # n -> enter -> enter -> enter (new primary partition, use all space)
  # t -> c (set type to FAT32)
  # w (save)
  sudo losetup -f disk.img --show -P
  # it will print the device path, e.g. /dev/loop21
  # -P is to auto-detect partitions
  sudo mkfs.vfat /dev/loop21p1
  # Now you can use e.g. GNOME Disks to see that
  # the partition is "normal" (you can mount it,
  # put files there, etc).
  # Does it boot?
  sudo qemu-system-x86_64 -drive file=/dev/loop21
  # Looks good to me, though I don't have time to play rn.


Pretty cool.

nanochess has some interesting boot sector games like https://github.com/nanochess/cubicDoom


Sneaky Lenovo uses/used more than 512 bytes for booting, hiding the extra code in a 1MB gap before the first partition. I got caught out when copying partition images and the boot sector over to a bigger drive (I think I was resizing both partitions or something, so didn't just dd the whole drive).


Sneaky Lenovo does more more sneaky stuff like insisting on installing their software on your machine even if you elect to install fresh Windows from other media than the one provided by Lenovo.

https://www.windowscentral.com/some-lenovo-pcs-reload-softwa...


Yeah. That kind of nastiness came in a few years after my last Lenovo device (which was also a "business" model, so came with little crapware).


Well I guess I am never buying a Lenovo product then.


This is a pretty common setup for BIOS boot loaders. grub2 typically embeds itself in this space[1] for BIOS based booting.

[1] https://www.gnu.org/software/grub/manual/grub/grub.html#BIOS...


Ah, the "GRUB gap"


That's cool. How can I learn how to do this? What's the background material?


This is a very good series if you want to build it in rust. https://os.phil-opp.com/

That minesweeper game seems to only use the vga buffer and that blog series explains that tech very well.


I doubt you'd be able to fit compiled Rust into 512 bytes, though.


True, fitting a game and a boot loader into 512 bytes is very impressive. You can build pretty tiny rust binaries if you don’t link the std library though. Check this out for some tricks: https://github.com/johnthagen/min-sized-rust

That blog post explains the vga buffer quite nicely so you should also be able to use the same information when writing assembler.


The smallest Rust binary that does something that I've ever seen is 145 bytes https://github.com/tormol/tiny-rust-executable

(I saw a wasm one get a bit lower but that isn't really apples to apples)


The OSDev Wiki has a lot of information:

https://wiki.osdev.org/Expanded_Main_Page

https://wiki.osdev.org/Introduction

It's about Operating System development, but these bootable games are really simple, limited OSes: They don't have much functionality, but they do have to access hardware in all the same ways, so a lot of the same rules apply.


nanochess guy has some ebooks: https://nanochess.org/store.html


This reminds me of working on my C64. When I was young, I thought this was how all programming would be done.


You can easily add a DOS/Windows/Linux bootsector as an optional bootmenu entry in Windows, but usually you will need to enable the CSM/Legacy BIOS feature of the mainboard if all you have is a UEFI system.

Although UEFI actually requires booting to MBR-partitioned USB drives even without CSM enabled, often this does not work due to simple engineering failure.

Also the Windows NTLDR and/or BOOTMGR, will need to be present on an Actively Bootable Marked primary FAT or NTFS volume of non-GPT partitioned drive hardware, such as floppy, HDD, CDROM, SSD, USB stick or SD card. Proper MBR and Windows VBR would be expected to be in place according to whether you were using NT5 (ntldr) or NT6 (bootmgr) at the time. Plus the target bootsector(s) (each in the form of a file) will need to be available and accesible by the WindowsNT boot process. Desired NT5 or NT6 bootsectors can be properly placed using BOOTSECT.EXE. The resulting bootsector can then be copied to a 512-byte binary file using a disk editor or the dd command in Linux.

With NTLDR you will also need NTDETECT.COM, and a BOOT.INI file which contains the bootmenu. BOOT.INI is a plain text file which can be edited using NOTEPAD.

With BOOTMGR you will also need a \BOOT\BCD folder/file which contains the bootmenu. BCD is a binary file which can be edited using BCDEDIT.

Either of these Windows bootmenus is always present, but bypassed on bootup if there is only one bootentry (such as the usual single Windows default entry), or if the TIMEOUT is set for zero or too few seconds. Adding a second entry to your already-present Windows bootmenu is what makes the menu visible upon bootup.

.

Therefore adding a bare-metal bootmine option to Windows NT5 PC's (while simultaneously enabling the NT5 multiboot menu) is quite easy and straightforward:

On a regular Wxp system, copy BOOTMINE.IMG to the root of your C: volume.

Edit your BOOT.INI something like this:

[Boot Loader]

timeout=10

Default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS

[Operating Systems]

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP" /noexecute=optin /fastdetect

C:\bootmine.img="Bootmine bootsector gaming"

Note: for DOS reference, a C:\bootsect.dos="DOS on FAT32 volume" entry in BOOT.INI can be _conveniently_ abbreviated as simply C:\="DOS on FAT32 volume". IOW (on the C: volume) if the bootsector file you wish to load is named anything other than BOOTSECT.DOS, you must specifiy the filename explicitly. C:\BOOTSECT.DOS is the filename given by Windows to the automatically saved DOS bootsector when an NT system is installed over a DOS/W9x system, before the DOS bootsector is overwritten with an NT bootsector.

.

The equivalent bare-metal bootmine option on an NT6 system is quite easy and straightforward also, provided (using CSM if necessary) you have installed W10 on a traditional MBR-partitioned (not GPT) drive:

On a MBR W10 system, copy BOOTMINE.IMG to the root of your C: volume.

Using an administrative command prompt, BCDEDIT to add a bootmine entry:

bcdedit /create /d "Bootmine bootsector gaming" /application bootsector

_Windows will reply with the GUID it automatically assigned to your new bootentry:

The entry {your-new-bootmine-guid-here} has been successfully created.

_use that guid to complete your new bootentry, add it to the items displayed upon bootup, and adjust the timeout with the following commands:

bcdedit /set {your-new-bootmine-guid-here} device partition=c:

bcdedit /set {your-new-bootmine-guid-here} path \bootmine.img

bcdedit /displayorder {your-new-bootmine-guid-here} /addlast

bcdedit /timeout 10

You may also need to disable Windows SecureBoot if present for a UEFI system to work, sometimes even with CSM enabled.

To later remove the new BCD bootentry use the following command in an administrative command prompt:

bcdedit /delete {your-new-bootmine-guid-here}




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: