Compare commits

..

26 Commits

Author SHA1 Message Date
37c56f30f7 Remove spurious nested make 2025-07-10 11:35:33 +00:00
3b8f72d53c Add skoolkit utilities 2025-07-09 21:56:44 +01:00
3a7cbdf550 Add licence info to README 2025-07-06 14:57:53 +01:00
051aab4695 Add inpaws and speed up building 2025-07-06 14:57:31 +01:00
bd1dbf9e19 Add README info on extensions 2025-06-24 20:29:09 +00:00
e2eefe89c2 Add usage gif to README 2025-06-23 22:29:19 +01:00
c068a870cf Add debug detail to README 2025-06-23 15:37:06 +00:00
765263ab4c more details in README 2025-06-23 15:33:35 +00:00
c795732223 Bah, md 2025-06-23 15:29:46 +00:00
b80c22eaff Add more usage information to README 2025-06-23 15:27:59 +00:00
7154c9bfc8 New barebones project using various tools 2025-06-23 14:34:21 +00:00
55b456ec06 Remove old project 2025-06-23 14:19:38 +00:00
5886da4a77 Add Z80 Assembly Meter extension 2025-06-23 08:43:58 +00:00
6a4be69501 Add makefile recipe to start a new, clean project 2025-06-23 08:36:22 +00:00
c95de03f6a Add BASIC syntax highlighting 2025-06-14 22:24:29 +00:00
17a903338a Oops - missed out z88dk include directory by mistake 2025-05-19 18:50:43 +01:00
a08f0351ed Pin to a stable devcontainer image so I can experiment more freely 2025-04-30 11:13:39 +00:00
90fded9f74 reinstate z88dk by building ourselves 2025-04-29 09:11:57 +00:00
e344cbd0f1 Disable z88dk - presumably this is a musl/glibc thing 2025-04-28 23:01:27 +01:00
ba5ce07264 Add Boriel BASIC 2025-04-28 08:59:46 +00:00
a8a0bde44a typo 2025-04-27 22:42:43 +00:00
45bcd9e8bb Expand the README 2025-04-27 22:06:28 +00:00
9d2322ffcd Move hooks directory to correct place 2025-04-27 12:36:30 +00:00
6cf3420ba2 I don't think there is an automatic way to reach localhost between Linux and Windows, sadly 2025-04-27 12:32:47 +00:00
8e42fe3308 Add z88dk 2025-04-27 12:24:10 +00:00
4f948d6f9f Build container locally 2025-04-27 12:23:58 +00:00
16 changed files with 367 additions and 275 deletions

103
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,103 @@
# syntax=docker/dockerfile:1
FROM ubuntu:24.04 AS build
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
make \
python3-pip \
unzip \
&& rm -rf /var/lib/apt/lists/*
ADD https://github.com/z00m128/sjasmplus.git#v1.21.0 /sjasmplus
RUN cd /sjasmplus && make -j8 && make install
ADD https://boarstone.mcphail.uk/mcphail/spectrum_remload.git /ttttt
RUN cd /ttttt && make ttttt
ADD https://github.com/einar-saukas/ZX0.git /zx0
RUN cd /zx0/src/ \
&& gcc -O2 -o zx0 zx0.c optimize.c compress.c memory.c \
&& gcc -O2 -o dzx0 dzx0.c
ADD https://www.boriel.com/files/zxb/zxbasic-1.18.1-linux64.tar.gz .
RUN tar xf zxbasic*
ADD https://github.com/Mastodon-/inpaws.git /inpaws
RUN cd /inpaws/ \
&& make -j8
RUN python3 -m pip install --break-system-packages skoolkit
FROM build AS z88dk
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bison \
ca-certificates \
ccache \
cpanminus \
curl \
dos2unix \
flex \
gdb \
git \
libboost-all-dev \
libcapture-tiny-perl \
libclone-perl \
libdata-hexdump-perl \
libfile-slurp-perl \
libgmp3-dev \
liblocal-lib-perl \
libmodern-perl-perl \
libpath-tiny-perl \
libregexp-common-perl \
libtext-table-perl \
libxml2-dev \
libyaml-perl \
m4 \
perl \
pkg-config \
ragel \
re2c \
texi2html \
texinfo \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
ENV Z88DK_PATH="/opt/z88dk"
RUN cpanm -l $HOME/perl5 --no-wget local::lib Template::Plugin::YAML \
&& git clone --depth 1 --recursive https://github.com/z88dk/z88dk.git ${Z88DK_PATH} \
&& cd ${Z88DK_PATH} \
&& eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib)" \
&& chmod 777 build.sh \
&& sed -i -e "s/make/make -j8/g" build.sh \
&& BUILD_SDCC=1 BUILD_SDCC_HTTP=1 ./build.sh \
&& make install-clean bins-clean
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
fuse-emulator-utils \
git \
make \
openssh-client \
pasmo \
python3 \
z80asm \
z80dasm \
zmakebas \
&& rm -rf /var/lib/apt/lists/*
COPY --from=build /usr/local/bin/sjasmplus /bin/sjasmplus
COPY --from=build /ttttt/ttttt /bin/ttttt
COPY --from=build /zx0/src/zx0 /bin/zx0
COPY --from=build /zx0/src/dzx0 /bin/dzx0
COPY --from=build /zxbasic/zxbasm.py /opt/zxbasic/zxbasm
COPY --from=build /zxbasic/zxbc.py /opt/zxbasic/zxbc
COPY --from=build /zxbasic/zxbpp.py /opt/zxbasic/zxbpp
COPY --from=build /zxbasic/src /opt/zxbasic/src
COPY --from=build /inpaws/inpaws /bin/inpaws
COPY --from=build /usr/local/bin/ /usr/local/bin/
COPY --from=build /usr/local/lib/python3.12/dist-packages/skoolkit/ /usr/local/lib/python3.12/dist-packages/skoolkit/
COPY --from=z88dk /opt/z88dk/bin /opt/z88dk/bin
COPY --from=z88dk /opt/z88dk/lib /opt/z88dk/lib
COPY --from=z88dk /opt/z88dk/include /opt/z88dk/include
ENV PATH="${PATH}:/opt/z88dk/bin:/opt/zxbasic"
ENV ZCCCFG="/opt/z88dk/lib/config"
USER ubuntu
RUN echo "PATH=$PATH:/opt/z88dk/bin:/opt/zxbasic" >> ~/.profile
RUN echo "export ZCCCFG=/opt/z88dk/lib/config/" >> ~/.profile

View File

@@ -1,6 +1,8 @@
{
"name": "ZX Spectrum dev tools",
"image": "boarstone.mcphail.uk/mcphail/speccydev",
//"build": { "dockerfile": "Dockerfile" },
// The Dockerfile takes an age to build due to z88dk, so pull from prebuilt:
"image": "boarstone.mcphail.uk/mcphail/speccydev:stable",
"remoteUser": "ubuntu",
"runArgs": [
"--network=host"
@@ -14,7 +16,9 @@
"maziac.hex-hover-converter",
"maziac.sna-fileviewer",
"maziac.nex-fileviewer",
"ms-vscode.makefile-tools"
"ms-vscode.makefile-tools",
"jsjlogin.zxbasic",
"thenestruo.z80-asm-meter"
]
}
}

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
.tmp/
*.tap
*.sna
*.sld
*.tzx
*.block
*.zx0
*.bin

6
.vscode/launch.json vendored
View File

@@ -72,12 +72,8 @@
"load": "myprog.sna",
"topOfStack": "0x5d58",
"cspect": {
// Change "host.docker.internal" to "localhost" if running on Linux
"hostname": "host.docker.internal"
},
"linux": {
"cspect": {
"hostname": "localhost"
}
}
},
{

View File

@@ -1,34 +0,0 @@
# syntax=docker/dockerfile:1
FROM ubuntu:24.04 AS build
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
make \
&& rm -rf /var/lib/apt/lists/*
ADD https://github.com/z00m128/sjasmplus.git#v1.21.0 /sjasmplus
RUN cd /sjasmplus && make && make install
ADD https://boarstone.mcphail.uk/mcphail/spectrum_remload.git /ttttt
RUN cd /ttttt && make ttttt
ADD https://github.com/einar-saukas/ZX0.git /zx0
RUN cd /zx0/src/ \
&& gcc -O2 -o zx0 zx0.c optimize.c compress.c memory.c \
&& gcc -O2 -o dzx0 dzx0.c
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
fuse-emulator-utils\
git \
make \
openssh-client\
pasmo \
z80asm \
z80dasm \
zmakebas \
&& rm -rf /var/lib/apt/lists/*
COPY --from=build /usr/local/bin/sjasmplus /bin/sjasmplus
COPY --from=build /ttttt/ttttt /bin/ttttt
COPY --from=build /zx0/src/zx0 /bin/zx0
COPY --from=build /zx0/src/dzx0 /bin/dzx0

View File

@@ -1,10 +1,39 @@
myprog.sna myprog.tap myprog.sld: main.asm loader.asm print.asm
sjasmplus --sld=myprog.sld --fullpath main.asm
speccydev.tzx: speccydev.tap
tapeconv speccydev.tap speccydev.tzx
speccydev.tap: sjasm.tap loader.tap boriel.zx0.block
cat loader.tap sjasm.tap boriel.zx0.block > speccydev.tap
myprog.sna sjasm.tap myprog.sld: speccydev.asm dzx0_standard.asm boriel.zx0
sjasmplus --sld=myprog.sld --fullpath speccydev.asm
loader.tap: loader.bas
zmakebas -a 30 -n SpeccyDev -o loader.tap loader.bas
boriel.bin: boriel.zxb
zxbc -S 40000 -o boriel.bin boriel.zxb
boriel.zx0: boriel.bin
zx0 -f boriel.bin boriel.zx0
boriel.zx0.block: boriel.zx0
ttttt boriel.zx0 data
clean:
rm -f *.tap
rm -f *.sna
rm -f *.sld
rm -f *.block
rm -f *.tzx
rm -f *.bin
rm -f *.zx0
rm -rf .tmp/
.PHONY: clean
start_new_project: clean
rm -rf .git
git init -b main
git add .devcontainer/ .vscode/ .gitignore
git commit -m "New project"
rm -rf *
.PHONY: clean start_new_project

114
README.md
View File

@@ -1,9 +1,115 @@
# Development tools for the ZX Spectrum
The Dockerfile is the basis of the devcontainer.
The Dockerfile is the basis of the devcontainer and can be changed to add or remove tools. It will take a long time to build locally, so by default the devcontainer will pull a prebuilt version. Edit `.devcontainer/devcontainer.json` if you would rather build your own.
The devcontainer contains various assemblers etc.
The devcontainer contains:
- pasmo (assembler)
- sjasmplus (assembler)
- z80asm (assembler)
- z80dasm (disassembler)
- zmakebas (creates BASIC programs)
- z88dk (C compiler and other utilities including assembler)
- utilities from the FUSE emulator:
- audio2tape
- createhdf
- fmfconv
- listbasic
- profile2map
- raw2hdf
- rzxcheck
- rzxdump
- rzxtool
- scl2trd
- snap2tzx
- snapconv
- snapdump
- tape2pulses
- tape2wav
- tapeconv
- tzxlist
- zx0 (binary compressor)
- dzx0 (binary decompressor)
- ZX BASIC (aka Boriel BASIC)
- zxbc (BASIC compiler)
- zxbasm (assembler)
- zxbpp (preprocessor)
- ttttt (converts binaries into .tap blocks)
- inpaws (interactive fiction compiler/extractor for Gilsoft's PAW)
- skoolkit (tools for creating browseable disassemblies of Spectrum games)
- sna2ctl.py
- sna2skool.py
- skool2html.py
- skool2asm.py
- skool2ctl.py
- skool2bin.py
- tap2sna.py
- snapinfo.py
- trace.py
- rzxplay.py
- tapinfo.py
- rzxinfo.py
- bin2tap.py
- bin2sna.py
- snapmod.py
- sna2img.py
- git (version control)
- make (build control)
Build the example project by running `make` from the terminal or the VSCode extension.
Several useful VSCode extentsions will be installed, including a Z80 assembly language server, Z80 and C debugger, Makefile support, BASIC syntax highlighter and more.
Debug in the built in simulator or in CSpect externally (example CSpect invocation on Windows would be `CSpect.exe -w2 -debug -remote`).
Thanks to the many authors of these wonderful tools and extensions; to think what we could have made with these in 1985!
## Install
This devcontainer should work in Windows, Linux and MacOS. It is recommended to install:
- git, then configure user name and email address
- docker, or alternative like podman
- (Windows only, optional) Windows Subsystem for Linux, version 2
- Microsoft's vscode
- the "Dev Containers" extension (from Microsoft) within vscode
Make sure docker (or your alternative) is running before trying to use the devcontainer.
## Usage
![A terminal window running the commands outlined below](res/speccydev.gif)
Open a terminal and navigate to the directory which will contain your Spectrum projects. Run `git clone https://github.com/mcphail/speccydev.git your_project_name` and enter that directory. Start vscode by running `code .` inside the directory.
If you have installed the Dev Containers extension correctly, a popup will offer to reload the project within a devcontainer. Go ahead and allow this. The first time you use this devcontainer, it may take a few minutes to download and start. It should open more quickly on subsequent use.
Open the bottom bar in vscode to expose the terminal or select "Terminal -> New Terminal" from the menu bar. Try running some Linux commands like `ls -lh` or `date`. Build the example project by running `make` from the terminal or the VSCode extension. Experiment with editing some of the source files and running `make` again. Experiment with some of the assemblers, compilers and other tools mentioned above. The `Makefile` contains example usage of tools like sjasmplus, zmakebas, Boriel's BASIC and the FUSE utilities.
When you are ready to start your own project, run `make start_new_project` to wipe out the example code and start afresh.
## Debugging
Debug in the built in simulator or in CSpect externally (example CSpect invocation on Windows would be `CSpect.exe -w2 -debug -remote`). The simulator is set up to expect a binary called `myprog.sna` and a map file called `myprog.sld` but this can be configured in the `.vscode/launch.json` file.
*Note: to use CSpect debugging from a Linux host you will have to edit the file `.vscode/launch.json` to change the `"hostname"` parameter to `"localhost"`*
## Licences
pamso - copyright Julián Albo and released under the GPL
sjasmplus - copyright aprisobal and released under BSD 3-clause
z80asm - copyright Bas Wijnen and released under GPL v3 or later
z80dasm - copyright Jan Panteltje and Tomaz Solc and released under GPL v2
zmakebas - placed under Public Domain by Russell Marks
z88dk - copyright the z88dk authors and released under the Clarified Artistic License
FUSE utilities - copyright Philip Kendall and contributors and released under GPL v2
zx0 and dzx0 - copyright Einar Saukas and released under BSD 3-clause
Boriel BASIC - copyleft Jose Rodriguez-Rosa and released under AGPL v3 and portions under MIT
ttttt - placed under Public Domain by Neil McPhail
inpaws - copyright "Mastodon" and released under GPL v3
skoolkit - copyright Richard Dymond and Philip M Anderson and released under GPL v3 or later

5
boriel.zxb Normal file
View File

@@ -0,0 +1,5 @@
10 CLS
20 FOR i = 0 TO 23
30 PRINT "ZX Spectrum Rules OK!"
40 NEXT i
50 PAUSE 0

61
dzx0_standard.asm Normal file
View File

@@ -0,0 +1,61 @@
; -----------------------------------------------------------------------------
; ZX0 decoder by Einar Saukas & Urusergi
; "Standard" version (68 bytes only)
; -----------------------------------------------------------------------------
; Parameters:
; HL: source address (compressed data)
; DE: destination address (decompressing)
; -----------------------------------------------------------------------------
dzx0_standard:
ld bc, $ffff ; preserve default offset 1
push bc
inc bc
ld a, $80
dzx0s_literals:
call dzx0s_elias ; obtain length
ldir ; copy literals
add a, a ; copy from last offset or new offset?
jr c, dzx0s_new_offset
call dzx0s_elias ; obtain length
dzx0s_copy:
ex (sp), hl ; preserve source, restore offset
push hl ; preserve offset
add hl, de ; calculate destination - offset
ldir ; copy from offset
pop hl ; restore offset
ex (sp), hl ; preserve offset, restore source
add a, a ; copy from literals or new offset?
jr nc, dzx0s_literals
dzx0s_new_offset:
pop bc ; discard last offset
ld c, $fe ; prepare negative offset
call dzx0s_elias_loop ; obtain offset MSB
inc c
ret z ; check end marker
ld b, c
ld c, (hl) ; obtain offset LSB
inc hl
rr b ; last offset bit becomes first length bit
rr c
push bc ; preserve new offset
ld bc, 1 ; obtain length
call nc, dzx0s_elias_backtrack
inc bc
jr dzx0s_copy
dzx0s_elias:
inc c ; interlaced Elias gamma coding
dzx0s_elias_loop:
add a, a
jr nz, dzx0s_elias_skip
ld a, (hl) ; load another group of 8 bits
inc hl
rla
dzx0s_elias_skip:
ret c
dzx0s_elias_backtrack:
add a, a
rl c
rl b
jr dzx0s_elias_loop
; -----------------------------------------------------------------------------

View File

@@ -1,25 +0,0 @@
MODULE basic_loader
ORG #5c00
basic_start:
db 0, 0 ; line number
dw line_length
line_start:
db #fd, '0', #0e, 0, 0 ; CLEAR
dw code_start_addr - 1
db 0, ':'
db #ef, '"' ; LOAD "
db "code"
db '"', #af, ':' ; name"CODE
db #f5, #c0 ; PRINT USR
db '0', #0e, 0, 0
dw code_run_addr
db 0, #0d
line_length EQU $ - line_start
basic_length EQU $ - basic_start
EMPTYTAP "myprog.tap"
SAVETAP "myprog.tap", BASIC, "myprog", basic_start, basic_length, 0
SAVETAP "myprog.tap", CODE, "code", code_start_addr, code_length
ENDMODULE

5
loader.bas Normal file
View File

@@ -0,0 +1,5 @@
10 REM This file was created
20 REM using zmakebas
30 CLEAR 32767
40 LOAD ""CODE
50 RANDOMIZE USR 32768

View File

@@ -1,22 +0,0 @@
code_start_addr EQU #8000
ORG code_start_addr
MODULE main
@code_run_addr:
ld a, 57
ld bc, 64
ld hl, 0
call print_string
db "Hello, world!", 0
ret
ENDMODULE
INCLUDE print.asm
code_length EQU $ - code_start_addr
DEVICE ZXSPECTRUM48
SLDOPT COMMENT WPMEM, LOGPOINT, ASSERTION
SAVESNA "myprog.sna", code_run_addr
INCLUDE loader.asm

180
print.asm
View File

@@ -1,180 +0,0 @@
ink_black EQU 0
ink_blue EQU 1
ink_red EQU 2
ink_magenta EQU 3
ink_green EQU 4
ink_cyan EQU 5
ink_yellow EQU 6
ink_white EQU 7
black EQU ink_black
blue EQU ink_blue
red EQU ink_red
magenta EQU ink_magenta
green EQU ink_green
cyan EQU ink_cyan
yellow EQU ink_yellow
white EQU ink_white
paper_black EQU 0
paper_blue EQU 8
paper_red EQU 16
paper_magenta EQU 24
paper_green EQU 32
paper_cyan EQU 40
paper_yellow EQU 48
paper_white EQU 56
bright EQU 64
flash EQU 128
attr_list_end EQU flash | bright | ink_black | paper_black
MODULE print
bm_start EQU #4000
attr_area EQU #5800
bm_len EQU 6144
attr_len EQU 768
CHARS EQU #5c36
char_posn:
dw #4000
MODULE print_string
; Set HL to be row and column and follow the call with a null-terminated string
; All registers preserved
; char_posn will have been moved to after string, but HL will still have coordinates of string start
@print_string:
call set_char_posn
ex (sp), hl
push af
loop:
ld a, (hl)
inc hl
or a
jr z, exit
call print_char
jr loop
exit:
pop af
ex (sp), hl
ret
ENDMODULE
MODULE print_char
; Prints the single character from the A register
; All registers preserved
; char_posn will point to next square
@print_char:
push hl
push de
push af
ld h, 0
ld l, a
add hl, hl
add hl, hl
add hl, hl
ld d, h
ld e, l
ld hl, (print.CHARS)
add hl, de
ld d, h
ld e, l
ld hl, (print.char_posn)
push bc
ld b, 8
loop:
ld a, (de)
ld (hl), a
inc h
inc de
djnz loop
ld hl, (print.char_posn)
inc l
jr nz, update_char_posn
ld a, #50
cp h
jr nz, next_third
ld hl, print.bm_start
jr update_char_posn
next_third:
ld a, 8
add a, h
ld h, a
update_char_posn:
ld (print.char_posn), hl
pop bc
pop af
pop de
pop hl
ret
ENDMODULE
MODULE set_char_posn
; Pass row and column, in that order, in HL
@set_char_posn:
push hl
push af
ld a, h
; check for top third
ld h, %01000000
sub 8
jr c, set_column
; check for middle third
ld h, %01001000
sub 8
jr c, set_column
; must be bottom third
ld h, %01010000
sub 8
set_column:
; restore the row offset of the third and shift it into upper 3 bits of L
add a, 8
sla a
sla a
sla a
sla a
sla a
or l
ld l, a
ld (print.char_posn), hl
pop af
pop hl
ret
ENDMODULE
MODULE set_attributes
; Row and column in HL
; db list of attributes follows call
; terminate with attr_list_end byte (bright flashing black on black)
@set_attributes:
ex de, hl
ex (sp), hl
push de
push hl
ld h, 0
ld l, d
ld d, h
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, hl
add hl, de
ld de, print.attr_area
add hl, de
pop de
ex de, hl
push af
loop:
ld a, (hl)
inc hl
cp attr_list_end
jr z, exit
ld (de), a
inc de
jr loop
exit:
pop af
pop de
ex (sp), hl
ex de, hl
ret
ENDMODULE
ENDMODULE

BIN
res/speccydev.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

36
speccydev.asm Normal file
View File

@@ -0,0 +1,36 @@
code_start_addr EQU #8000
org code_start_addr
; headerless load
scf
ld a, #ff
ld de, boriel_size
ld ix, compressed_boriel
call #0556
decompress:
ld hl, compressed_boriel
ld de, uncompressed_boriel
call dzx0.dzx0_standard
call uncompressed_boriel
ret
MODULE dzx0
INCLUDE "dzx0_standard.asm"
ENDMODULE
code_length EQU $ - code_start_addr
compressed_boriel:
INCBIN "boriel.zx0"
boriel_size EQU $ - compressed_boriel
uncompressed_boriel EQU 40000
DEVICE ZXSPECTRUM48
SLDOPT COMMENT WPMEM, LOGPOINT, ASSERTION
SAVESNA "myprog.sna", decompress
EMPTYTAP "sjasm.tap"
SAVETAP "sjasm.tap", CODE, "sjasm", code_start_addr, code_length