Skip to content

Instantly share code, notes, and snippets.

@milesrout
Forked from ddevault/gist:61ad82038843aa0d8767
Last active May 29, 2016 05:18
Show Gist options
  • Save milesrout/e0b40f7050414611ec87 to your computer and use it in GitHub Desktop.
Save milesrout/e0b40f7050414611ec87 to your computer and use it in GitHub Desktop.

DCPU-16 Firmware Proposal

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.

Modified by Miles Rout ([email protected]) to use a more modern dialect of DCPU-16 asm, along with a slight code change to make it a little more sensible.

Specification

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.

Rationale

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.

Future Extensibility

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.

Default Firmware

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
    ; 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
    IFN I, 0
        SET PC, device_loop

    ; 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:

This document is hereby released into the public domain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment