A revised proposal based on this document.
The following are unofficial modifications to the specification that describe how the firmware should work.
The provided code assumes that the eventual disk drive specifications match the M35FD disk drive specifications from a technical standpoint.
The DCPU-16 comes paired with 512 words of ROM that are only used while booting up the device. This ROM contains the user-flashable firmware, which is loaded with a default firmware as described below.
Additionally, this ROM acts as a device that connected at device index 0. When interrupted, this device could copy its contents to memory, starting at B. Upon booting, the first thing the CPU does is trigger an interrupt on the ROM (HWI 0). The ROM then copies its contents to DCPU memory, starting at 0x0000 (the value of B when the device boots). When the CPU boots, it will then execute this code. For more details on this idea, see this thread.
The rationale for this proposal is to provide a means for users to easily work with the DCPU-16. It would enable users to easily load programs, distribute programs, and reliably use their devices, while staying in canon. Programs, kernels, operating systems, and the like, could all be distributed via disks instead of manually reflashing the device each time.
A potential direction to take this idea is to establish different kinds of hardware that are all compatible with each other. For instance, this one boot loader could potentially load an OS from a disk, from a hard drive, from a network connection - so long as they all have the same hardware ID and compatible interrupts. Additionally, the ROM device could have various functions, such as firmware provided by the network, or booting to a hard drive of some sort.
The following code would work well for the default firmware. Its goal is very simple - to copy the boot sector of the installed disk to memory and execute it. If a disk is present, it will simply boot with no error. If a disk is not present and an LEM-1802 is not present, it will fail to boot and hang. If a disk is not present and an LEM-1802 is present, it will fail to boot and display a message to the user.
The default behavior when several disk drives or several LEM-1802s are installed is to use the first one of each.
The following firmware has been assembled with Organic, but has been designed with respect to current community standards, and should work properly on most currently available assemblers. It has also been tested on Tomato, an emulator that is thought to have perfect emulation accuracy and has no known bugs. A pre-assembled binary is available for download here, in big-endian format.
; Move the firmware to 0x200 to free up space for the boot sector
:init
SET I, firmware
SET J, 0x200
:move
IFE I, 0x200
SET PC, load
STI [J], [I]
SET PC, move
:firmware
.org 0x200
:load
; Enumerate devices
HWN I
:device_loop
SUB I, 1
IFE I, 0xFFFF
SET PC, device_loop_complete
; Query selected device and see if it's a hard disk or LEM-1802
HWQ I
IFE A, 0x24c5
IFE B, 0x4fd5
SET [io_m35fd], I
IFE A, 0xF615
IFE B, 0x7349
SET [io_lem1802], I
SET PC, device_loop
:device_loop_complete
; Check for error conditions
IFE [io_m35fd], 0xFFFF
SET PC, error_nodrive
; Check for disk
SET A, 0 ; Poll device
HWI [io_m35fd]
IFE B, 0 ; STATE_NO_MEDIA
SET PC, error_nodisk
:copy_boot
; Copy the boot sector from the disk to memory
SET A, 2 ; Read sector
SET X, 0
SET Y, 0
HWI [io_m35fd]
IFN B, 1
SET PC, error_readerror
:wait_for_completion
SET A, 0
HWI [io_m35fd]
IFE B, 1 ; Device ready
SET PC, boot ; Launch boot sector (DONE)
SET PC, wait_for_completion
:error_nodrive
IFE [io_lem1802], 0xFFFF
SET PC, end ; Hang forever if there is no screen
JSR map_screen
SET I, msg_nodrive
SET PC, print_err
:error_nodisk
IFE [io_lem1802], 0xFFFF
SET PC, end ; Hang forever if there is no screen
JSR map_screen
SET I, msg_nodisk
SET PC, print_err
:error_readerror
IFE [io_lem1802], 0xFFFF
SUB PC, 1 ; Hang forever if there is no screen
JSR map_screen
SET I, msg_readerror
SET PC, print_err
:map_screen
SET A, 0
SET B, 0x8000
HWI [io_lem1802]
SET PC, POP
:print_err
SET J, 0x8000
:print_loop
IFE [I], 0
SET PC, end ; Hang
SET C, [I]
BOR C, 0xF000
STI [J], C
SET PC, print_loop
:end
SET PC, end
:boot
; Zero registers
SET A, 0
SET B, 0
SET C, 0
SET X, 0
SET Y, 0
SET I, 0
SET J, 0
SET SP, 0
SET PC, 0
:msg_nodrive
dat "ATTACH M35FD AND REBOOT", 0
:msg_nodisk
dat "INSERT DISK AND REBOOT", 0
:msg_readerror
dat "DRIVE READ ERROR", 0
:io_m35fd
dat 0xFFFF
:io_lem1802
dat 0xFFFF
You may contact me for further information:
- [email protected]
- SirCmpwn on irc.freenode.net
This document is hereby released into the public domain.