Skip to content

Commit

Permalink
video: add support for the Zeal 8-bit Video Card
Browse files Browse the repository at this point in the history
It is now possible to use the bootloader with the Zeal 8-bit video card and the PS/2 keyboard.
The standard output can now be chosen in a configuration file.
Note that the UART is still enabled even if it not the standard output because
it is required to receive files.
  • Loading branch information
Zeal8bit committed Apr 17, 2024
1 parent 679ff91 commit cd82532
Show file tree
Hide file tree
Showing 22 changed files with 1,248 additions and 337 deletions.
45 changes: 25 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
CC=$(shell which z88dk-z80asm z88dk.z88dk-z80asm | head -1)
BIN=bootloader.bin
DUMP=bootloader.dump
ENABLE_TESTER = 1
ASMFLAGS=
FILES=rst_vectors.asm boot.asm uart.asm systems.asm video.asm menu.asm format.asm
MAP=bootloader.map
CONFIG_FILE := include/config.asm

# Process the config file to include only lines of the form 'CONFIG_... = ..' and save them to
# a file named 'bootloader.conf'
$(shell grep -o 'CONFIG_.*=.*' $(CONFIG_FILE) > bootloader.config)
-include bootloader.config

# When ACK_CONTINUE is set, a message will always be displayed before redrawing the main menu
ASMFLAGS=-Iinclude/
FILES=rst_vectors.asm boot.asm uart.asm systems.asm pio.asm menu.asm format.asm i2c.asm

# SRCS must be lazily evaluated since it depends FILES, which may be altered below
SRCS=$(addprefix src/,$(FILES))
DISASSEMBLER=$(shell which z88dk-dis z88dk.z88dk-dis | head -1)
BUILDIR=build

ifeq ($(ENABLE_TESTER),1)
ASMFLAGS += -DENABLE_TESTER
FILES += tester.asm i2c.asm
ifeq ($(CONFIG_ENABLE_TESTER),1)
FILES += tester.asm
endif

ifneq ($(CONFIG_UART_AS_STDOUT),1)
FILES += video.asm keyboard.asm
endif

define FIND_ADDRESS =
Expand All @@ -20,21 +31,15 @@ endef

phony: all clean

# First, we need to build all the source files
# Then move and rename the main binary code to $(BUILDIR)/$(BIN)
# Finally, merge the system/os table to it, its address needs to be retrieved dynamically
# We need to build all the source files and then merge the resulting bootloader binary with the system/os table,
# which address needs to be retrieved dynamically
all: clean version.txt
$(CC) -O$(BUILDIR) $(ASMFLAGS) -Iinclude/ -m -b $(SRCS)
cp $(BUILDIR)/src/rst_vectors_RST_VECTORS.bin $(BUILDIR)/$(BIN)
$(CC) -O$(BUILDIR) $(ASMFLAGS) -m -b $(SRCS)
@# Retrieve the address for the SYS_TABLE. Here is becomes... weird, $(call FIND_ADDRESS) will be replace
@# by the macro itself, we need to interpret it at runtime, so we surround it with $$(...)
@# This gives us a hex value, truncate only accepts decimal values so we surround it with $$((...)) to let
@# bash interpret it to a decimal value
@truncate -s $$((0x$$($(call FIND_ADDRESS)))) $(BUILDIR)/$(BIN)
@# Concatenate the SYS_TABLE
cat $(BUILDIR)/src/*SYS_TABLE.bin >> $(BUILDIR)/$(BIN)
@# Generate the disassembly dump for debugging
$(DISASSEMBLER) -o 0x0000 -x $(BUILDIR)/src/*.map $(BUILDIR)/$(BIN) > $(BUILDIR)/$(DUMP)
@# by the macro itself, we need to interpret it at runtime, so we surround it with $$(...).
./concat.sh $(BUILDIR)/$(BIN) 0 $(BUILDIR)/src/rst_vectors_RST_VECTORS.bin 0x$$($(call FIND_ADDRESS)) $(BUILDIR)/src/*SYS_TABLE.bin
@# Copy the map file to the `build/` directory
cp $(BUILDIR)/src/*.map $(BUILDIR)/$(MAP)

version.txt:
@echo `git describe --always --tags` > version.txt
Expand Down
41 changes: 28 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,39 @@
<a href="https://opensource.org/licenses/Apache-2.0">
<img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="Licence" />
</a>
<p align="center">A simple bootloader entirely written in Z80 assembly, for Zeal 8-bit Computer, a homebrew 8-bit computer based on a Z80 CPU.</p>
<p align="center">A bootloader entirely written in Z80 assembly, for Zeal 8-bit Computer, a homebrew 8-bit computer based on a real Z80 CPU</p>
</p>

## About this project

The goal of this project is to provide a small bootloader for Zeal 8-bit Computer that lets us perform several operations directly from the computer itself, such as booting different operating systems, flashing the ROM, testing the hardware, without the need of any external devices.
The goal of this project is to provide a compact bootloader for Zeal 8-bit Computer that lets us perform several operations directly from the computer itself, such as booting different operating systems, flashing the ROM, testing the hardware, etc..., without the need of any external devices.

## Features
## Screenshots

<p align="center">
<img src="img/menu.png" alt="Zeal Bootloader menu" />
<img src="img/menu_uart.png" alt="Zeal Bootloader menu" />
<div align="center">Zeal 8-bit Bootloader using the UART</div>
</p>
<p align="center">
<img src="img/menu_video.png" alt="Zeal Bootloader menu" />
<div align="center">Zeal 8-bit Bootloader using Zeal 8-bit Video Card</div>
</p>

## Features

As you can see from the menu itself, several feature have been implemented:

* Communication over UART (no need for the video board)
* 5 seconds auto-boot on startup
* Communication over UART or over the video board¹
* Auto-boot on startup after after a few seconds¹
* Up to 9 operating systems or programs can be set up to boot from the menu. In the example above, only one entry is present: Zeal 8-bit OS. The numbers between the parenthesis represent the physical address (in ROM) and the virtual address respectively. In the output above, Zeal 8-bit OS is flashed at address **0x4000** in the ROM, it will be mapped at virtual address **0x0000** when booted.
* Program can be sent through UART, and booted **directly**. No need to flash the ROM. This is handy for development when testing a program.
* Program can be sent through UART, and booted **directly**. No need to flash the ROM, handy for development and testing programs.
* New entries can be added as bootable systems, directly from the bootloader itself.
* Symmetrically, entries can be deleted directly from the bootloader. Note that it is not possible to delete all entries, there must at least be one remaining entry at all time.
* Entries can be deleted directly from the bootloader. Note that it is not possible to delete all entries, there must at least be one remaining entry at all time.
* Buffered changes. To prevent mistakes when adding and deleting entries, the changes are first saved to RAM. The changes can then be flushed (**s** option) or discard (reboot the system).
* Baudrate can be changed for the current bootloader session. Handy if there are corrupted data when transferring programs over UART.
* Test Zeal 8-bit Computer hardware. This includes tests for the RAM size, the ROM size, the I2C EEPROM, the I2C RTC, and the PS/2 keyboard.
* Baudrate can be changed for the current bootloader session (not saved after a reboot).
* Test Zeal 8-bit Computer hardware: including RAM size, Flash/ROM size, I2C EEPROM, I2C RTC, and PS/2 keyboard.

¹: These options are configurable via the `config.asm` file.

## Building the project

Expand All @@ -43,16 +52,22 @@ At the moment, the project has only been assembled on Linux (Ubuntu 20.04 and 22

To install z88dk, please [check out their Github project](https://github.com/z88dk/z88dk).

### Configuration

Before building the bootloader, open and modify, if necessary, the configuration file `include/config.asm`.

In this file, any macro that is not set (commented) or set to 0 will be considered disabled.

### Building

To build the bootloader, simply use the command:
After the configuration is saved, you can build the bootloader thanks to the command:
```
make
```

After compiling, the folder `build/` should contain the binary `bootloader.bin` and `bootloader.dump`. The first one is the program itself, whereas the second is a text file containing the disassembled binary with debug symbols.
After compiling, the folder `build/` should contain the binary `bootloader.bin` and `bootloader.map`. The first one is the program itself, whereas the second is a text file containing all the (debug) symbols of the binary.

That dump is only useful when debugging the bootloader (mainly with [Zeal 8-bit Computer emulator](https://github.com/Zeal8bit/Zeal-WebEmulator)).
That map file is only useful when debugging the bootloader, mainly with [Zeal 8-bit Computer emulator](https://github.com/Zeal8bit/Zeal-WebEmulator).

## Transferring data over UART

Expand Down
25 changes: 25 additions & 0 deletions concat.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

usage() {
echo "usage: $0 output_file address_1 file_1 ... address_n file_n" >&2
exit 1
}

# Check if the number of arguments is odd
if [ $# -lt 3 ] || [ $(($# % 2)) -ne 1 ]; then
usage
fi

# Create the output file
output_file="$1"
touch "$output_file"
shift

# Loop through the arguments in pairs: (address, file)
while (( "$#" )); do
addr="$1"
file="$2"
printf "0x%04x - %s\n" "$addr" "$file"
dd if="$file" of="$output_file" bs=1 seek="$(($addr))" status="none"
shift 2
done
Binary file removed img/menu.png
Binary file not shown.
Binary file added img/menu_uart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/menu_video.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions include/config.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; SPDX-FileCopyrightText: 2024 Zeal 8-bit Computer <[email protected]>
;
; SPDX-License-Identifier: Apache-2.0

IFNDEF CONFIG_H
DEFINE CONFIG_H

; When set, the UART will be used as the standard output. When not set or set to 0, the video driver will
; be used. The UART driver will still be used to receive files.
DEFC CONFIG_UART_AS_STDOUT = 1

; When set, the Zeal logo will be shown on screen, this takes more RAM at runtime but won't affect the
; OS or program running after the bootloader as the modified tiles are saved and restored.
DEFC CONFIG_VIDEO_SHOW_LOGO = 1

; When set, the hardware tester will be available in the menu.
DEFC CONFIG_ENABLE_TESTER = 1

; When set, the user will be asked to press a key before returnig to the menu
DEFC CONFIG_ACK_CONTINUE = 1

; Number of secodns to wait before autoboot
DEFC CONFIG_AUTOBOOT_DELAY_SECONDS = 3

ENDIF ; CONFIG_H
30 changes: 30 additions & 0 deletions include/keyboard_h.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
; SPDX-FileCopyrightText: 2024 Zeal 8-bit Computer <[email protected]>
;
; SPDX-License-Identifier: Apache-2.0

IFNDEF KEYBOARD_H
DEFINE KEYBOARD_H

EXTERN keyboard_get_char
EXTERN keyboard_next_char
EXTERN keyboard_has_char
EXTERN keyboard_set_synchronous

DEFC KB_IO_ADDRESS = 0xe8

DEFC KB_PRINTABLE_CNT = 0x60
DEFC KB_SPECIAL_START = 0x66 ; Between 0x60 and 0x66, nothing special
DEFC KB_EXTENDED_SCAN = 0xe0 ; Extended characters such as keypad or arrows
DEFC KB_RELEASE_SCAN = 0xf0
DEFC KB_RIGHT_ALT_SCAN = 0x11
DEFC KB_RIGHT_CTRL_SCAN = 0x14
DEFC KB_LEFT_SUPER_SCAN = 0x1f
DEFC KB_NUMPAD_DIV_SCAN = 0x4a
DEFC KB_NUMPAD_RET_SCAN = 0x5a
DEFC KB_PRT_SCREEN_SCAN = 0x12 ; When Print Screen is received, the scan is 0xE0 0x12
DEFC KB_MAPPED_EXT_SCANS = 0x69 ; Extended characters which scan code is 0xE0 0x69 and above
; are treated with a mapped array

DEFC KB_ESC = 0x80

ENDIF
5 changes: 1 addition & 4 deletions include/pio_h.asm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
DEFC IO_PIO_DATA_B = 0xd1
DEFC IO_PIO_CTRL_A = 0xd2
DEFC IO_PIO_CTRL_B = 0xd3

; PIO Modes
DEFC IO_PIO_MODE0 = 0x0f
DEFC IO_PIO_MODE1 = 0x4f
Expand Down Expand Up @@ -70,7 +70,4 @@
; * Provide a mask
DEFC IO_PIO_SYSTEM_INT_CTRL = 0x90 | IO_PIO_CTRLW_INT

; NOTE: 0 means monitored!
DEFC IO_PIO_SYSTEM_INT_MASK = ~(1 << IO_UART_RX_PIN) & 0xff

ENDIF
83 changes: 83 additions & 0 deletions include/stdout_h.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
; SPDX-FileCopyrightText: 2024 Zeal 8-bit Computer <[email protected]>
;
; SPDX-License-Identifier: Apache-2.0

INCLUDE "config.asm"

IFNDEF STDOUT_H
DEFINE STDOUT_H

; It is possible to choose either the UART or video board as the standard output
IF CONFIG_UART_AS_STDOUT
INCLUDE "uart_h.asm"

DEFC stdout_initialize = uart_initialize
DEFC stdout_autoboot = uart_autoboot
DEFC stdout_write = uart_send_bytes
DEFC stdout_put_char = uart_send_one_byte
DEFC stdout_newline = uart_newline
DEFC stdin_get_char = uart_receive_one_byte
DEFC stdin_has_char = uart_available_read
DEFC stdin_set_synchronous = uart_disable_fifo
DEFC stdout_prepare_menu = uart_clear_screen

MACRO YELLOW_COLOR _
DEFM 0x1b, "[1;33m"
ENDM
MACRO GREEN_COLOR _
DEFM 0x1b, "[1;32m"
ENDM
MACRO RED_COLOR _
DEFM 0x1b, "[1;31m"
ENDM

MACRO END_COLOR _
DEFM 0x1b, "[0m"
ENDM

ELSE ; !CONFIG_UART_AS_STDOUT

INCLUDE "video_h.asm"
INCLUDE "keyboard_h.asm"

DEFC stdout_initialize = video_initialize
DEFC stdout_autoboot = video_autoboot
DEFC stdout_write = video_write
DEFC stdout_put_char = video_put_char
DEFC stdout_newline = video_newline
DEFC stdin_get_char = keyboard_next_char
DEFC stdin_has_char = keyboard_has_char
DEFC stdin_set_synchronous = keyboard_set_synchronous
DEFC stdout_prepare_menu = video_clear_screen

; Use a prefix for the colors
MACRO YELLOW_COLOR _
DEFM 0xFE
ENDM
MACRO GREEN_COLOR _
DEFM 0xF2
ENDM
MACRO RED_COLOR _
DEFM 0xF4
ENDM

MACRO END_COLOR _
DEFM 0xff
ENDM

ENDIF


MACRO PRINT_STR label
ld hl, label
ld bc, label ## _end - label
call stdout_write
ENDM

MACRO PRINT_STR_UART label
ld hl, label
ld bc, label ## _end - label
call uart_send_bytes
ENDM

ENDIF
10 changes: 3 additions & 7 deletions include/uart_h.asm
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,10 @@
; Default baudrate for UART
DEFC UART_BAUDRATE_DEFAULT = UART_BAUDRATE_57600

MACRO PRINT_STR label
ld hl, label
ld bc, label ## _end - label
call uart_send_bytes
ENDM

; Public routines
EXTERN uart_initialize
EXTERN uart_autoboot
EXTERN uart_clear_screen
EXTERN uart_send_bytes
EXTERN uart_send_one_byte
EXTERN uart_available_read
Expand All @@ -31,6 +27,6 @@
EXTERN uart_receive_one_byte
EXTERN uart_receive_big_file
EXTERN uart_set_baudrate
EXTERN newline
EXTERN uart_newline

ENDIF
Loading

0 comments on commit cd82532

Please sign in to comment.