Skip to content

Instantly share code, notes, and snippets.

@ddevault
Last active October 11, 2015 12:48
Show Gist options
  • Save ddevault/61ad82038843aa0d8767 to your computer and use it in GitHub Desktop.
Save ddevault/61ad82038843aa0d8767 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.

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

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