Initial files
This commit is contained in:
parent
2f34088fc3
commit
a92a2b8dad
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
syntax: glob
|
||||||
|
|
||||||
|
# Project ignores
|
||||||
|
bin
|
||||||
|
bin/**
|
||||||
|
|
||||||
|
# Makefile ignores
|
||||||
|
Makelocal.mk
|
||||||
|
|
||||||
|
# File ignores
|
||||||
|
*.log
|
||||||
|
*.bak
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
|
||||||
|
# Ignore some eclipse files
|
||||||
|
.settings
|
||||||
|
.project
|
||||||
|
|
||||||
|
# Ignore visual studio files
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Ignore intellij files
|
||||||
|
*.iml
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Ignore netbeans directory
|
||||||
|
nbproject
|
||||||
|
|
||||||
|
# Ignore mac finder files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Ignore windows files.
|
||||||
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Ignore kde dolphin files
|
||||||
|
.directory
|
26
Makefile
Normal file
26
Makefile
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
|
||||||
|
INC_LIB := $(call rwildcard, lib, */0module.mk)
|
||||||
|
INC_TEST := $(call rwildcard, test, */0module.mk)
|
||||||
|
PATH_BIN := bin
|
||||||
|
BUILD_ALL := "Use 'make help' for possible targets."
|
||||||
|
BUILD_HELP := "Use one of the following build targets;"
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.PHONY: all
|
||||||
|
all:
|
||||||
|
@echo $(BUILD_ALL)
|
||||||
|
|
||||||
|
BUILD_HELP += \\n\\t* help
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@echo $(BUILD_HELP)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(call mb_clean,$(PATH_BIN))
|
||||||
|
|
||||||
|
-include Makelocal.mk
|
||||||
|
include lib/make/msxbuild.mk
|
||||||
|
include $(INC_LIB)
|
||||||
|
include $(INC_TEST)
|
8
Makelocal.mk.tpl
Normal file
8
Makelocal.mk.tpl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Local included makefile fragment.
|
||||||
|
# Save this file without tpl suffix and custumize it.
|
||||||
|
#
|
||||||
|
# Change to local installations if needed;
|
||||||
|
|
||||||
|
#PATH_SDCC ?= /usr/bin
|
||||||
|
#PATH_HEX2BIN ?= /usr/bin
|
||||||
|
#PATH_OPENMSX ?= /opt/openMSX/bin/
|
38
README.md
38
README.md
|
@ -1,3 +1,39 @@
|
||||||
# msxbuild
|
# MSXBUILD
|
||||||
|
|
||||||
Utils to use openMSX in build pipelines.
|
Utils to use openMSX in build pipelines.
|
||||||
|
|
||||||
|
You can use these scripts as-is. But as always, feel free to extend it
|
||||||
|
for your specific needs or contribute a fix or feature.
|
||||||
|
|
||||||
|
## Makefile features
|
||||||
|
|
||||||
|
* SDCC msx build steps
|
||||||
|
* Headless openMSX buildpipe on max speed.
|
||||||
|
* openMSX safe exit failure guards.
|
||||||
|
* Automatic disk image import + export per build step.
|
||||||
|
* wgets resources from msxhub
|
||||||
|
|
||||||
|
## TCL Scripts
|
||||||
|
|
||||||
|
Tcl scripts for safe openMSX integrations as reliable build step
|
||||||
|
in compiling/packing/testing msx software natively.
|
||||||
|
But managed from external build tool like make or scripts.
|
||||||
|
This means that great care is given to make sure that openMSX
|
||||||
|
exits correctly.
|
||||||
|
|
||||||
|
The use this, pass the one or more scripts on the command line and
|
||||||
|
set the optional environment variables when executing openMSX:
|
||||||
|
|
||||||
|
FAIL_AFTER_BOOT=30 \
|
||||||
|
FAIL_AFTER_PATH=bin/myapp \
|
||||||
|
BOOT_HDD_PATH=bin/myapp/disk \
|
||||||
|
BOOT_HDD_IMAGE=bin/myapp/disk.img \
|
||||||
|
JOYPORTA=mouse \
|
||||||
|
openmsx \
|
||||||
|
-script <path-to>/boot_env.tcl \
|
||||||
|
-script <path-to>/boot_hdd.tcl \
|
||||||
|
-script <path-to>/fail_after.tcl \
|
||||||
|
-machine ...
|
||||||
|
|
||||||
|
Check the scripts source code for more (technical) details.
|
||||||
|
|
||||||
|
|
33
lib/make/mb_assert.mk
Normal file
33
lib/make/mb_assert.mk
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
define _mb_assert_success
|
||||||
|
@echo success: mb_assert_$(1)\; \'$(2)\'
|
||||||
|
endef
|
||||||
|
define _mb_assert_failure
|
||||||
|
@echo failure: mb_assert_$(1)\; \'$(2)\'
|
||||||
|
@exit 1
|
||||||
|
endef
|
||||||
|
define _mb_assert_if
|
||||||
|
$(if $(1),$(call _mb_assert_success,$(2),$(3)),$(call _mb_assert_failure,$(2),$(3)))
|
||||||
|
endef
|
||||||
|
define _mb_assert_if_not
|
||||||
|
$(if $(1),$(call _mb_assert_failure,$(2),$(3)),$(call _mb_assert_success,$(2),$(3)))
|
||||||
|
endef
|
||||||
|
|
||||||
|
# FIXME: Not stable
|
||||||
|
#define mb_assert_file_contains
|
||||||
|
# $(call _mb_assert_if,$(findstring $(2),$(file < $(1))),file_contains,$(2))
|
||||||
|
#endef
|
||||||
|
define mb_assert_file_equals
|
||||||
|
$(call _mb_assert_if_not,$(subst $(2),,$(file < $(1))),file_equals,$(2))
|
||||||
|
endef
|
||||||
|
|
||||||
|
# Assert that the variable(s) are set and doesn't have non-empty values.
|
||||||
|
# Params;
|
||||||
|
# 1. Variable name(s) to validate.
|
||||||
|
# 2. (optional) Error message to user.
|
||||||
|
define mb_assert_defined
|
||||||
|
$(strip $(foreach 1,$1,$(call _mb_assert_defined_error,$1,$(strip $(value 2)))))
|
||||||
|
endef
|
||||||
|
define _mb_assert_defined_error
|
||||||
|
$(if $(value $1),,$(error Undefined $1$(if $2, ($2))))
|
||||||
|
endef
|
68
lib/make/mb_autoexec.mk
Normal file
68
lib/make/mb_autoexec.mk
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
|
||||||
|
MB_AUTOEXEC_BYSELF ?= true
|
||||||
|
MB_AUTOEXEC_BYSELF_MSG ?= Generated by msxbuild Makefile
|
||||||
|
MB_AUTOEXEC_TEXTMODE ?= 80
|
||||||
|
MB_AUTOEXEC_STARTUP_TIMEOUT ?= 60
|
||||||
|
MB_AUTOEXEC_STARTUP_EXITCODE ?= 124
|
||||||
|
MB_AUTOEXEC_TEST_TIMEOUT ?= 120
|
||||||
|
MB_AUTOEXEC_TEST_EXITCODE ?= 1
|
||||||
|
|
||||||
|
define mb_autoexec_append_cmd
|
||||||
|
echo "$(2)\r" >> $(1)/autoexec.bat
|
||||||
|
endef
|
||||||
|
define mb_autoexec_append_echo
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),echo $(2))
|
||||||
|
endef
|
||||||
|
define mb_autoexec_append_rem
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),rem $(2))
|
||||||
|
endef
|
||||||
|
define mb_autoexec_append_gui_mode
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Enabling renderer.)
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),omsxctl set renderer SDL > NUL)
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Enabling throttling.)
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),omsxctl set throttle on > NUL)
|
||||||
|
endef
|
||||||
|
define mb_autoexec_append_stop_fail
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Disabling automatic failure.)
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),omsxctl fail_after 0)
|
||||||
|
endef
|
||||||
|
define mb_autoexec_append_exit
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),omsxctl exit 0)
|
||||||
|
endef
|
||||||
|
define mb_autoexec_write_default
|
||||||
|
echo -n "" > $(1)/autoexec.bat
|
||||||
|
$(if $(filter true,$(MB_AUTOEXEC_BYSELF)),$(call mb_autoexec_append_rem,$(1),$(MB_AUTOEXEC_BYSELF_MSG)))
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),omsxctl fail_after $(MB_AUTOEXEC_STARTUP_TIMEOUT) seconds fail_after_init $(MB_AUTOEXEC_STARTUP_EXITCODE))
|
||||||
|
$(if $(filter 40,$(MB_AUTOEXEC_TEXTMODE)),$(call mb_autoexec_append_cmd,$(1),mode 40))
|
||||||
|
$(if $(filter 40,$(MB_AUTOEXEC_TEXTMODE)),$(call mb_autoexec_append_echo,$(1),Enabled mode 40.))
|
||||||
|
$(if $(filter 80,$(MB_AUTOEXEC_TEXTMODE)),$(call mb_autoexec_append_cmd,$(1),mode 80))
|
||||||
|
$(if $(filter 80,$(MB_AUTOEXEC_TEXTMODE)),$(call mb_autoexec_append_echo,$(1),Enabled mode 80.))
|
||||||
|
endef
|
||||||
|
|
||||||
|
define mb_autoexec_open_gui
|
||||||
|
@echo === Generating autoexec.bat for command with gui
|
||||||
|
$(call mb_autoexec_write_default,$(1))
|
||||||
|
$(call mb_autoexec_append_gui_mode,$(1))
|
||||||
|
$(call mb_autoexec_append_stop_fail,$(1))
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Type 'omsxctl exit' to stop emulation.)
|
||||||
|
endef
|
||||||
|
define mb_autoexec_open_gui_cmd
|
||||||
|
$(call mb_autoexec_open_gui,$(1))
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Running command '$(2)')
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),$(2))
|
||||||
|
endef
|
||||||
|
define mb_autoexec_cmd
|
||||||
|
@echo === Generating autoexec.bat for command
|
||||||
|
$(call mb_autoexec_write_default,$(1))
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Running command '$(2)')
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),$(2))
|
||||||
|
$(call mb_autoexec_append_exit,$(1))
|
||||||
|
endef
|
||||||
|
define mb_autoexec_cmd_test
|
||||||
|
@echo === Generating autoexec.bat for command test
|
||||||
|
$(call mb_autoexec_write_default,$(1))
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),omsxctl fail_after $(MB_AUTOEXEC_TEST_TIMEOUT) seconds fail_after_test $(MB_AUTOEXEC_TEST_EXITCODE))
|
||||||
|
$(call mb_autoexec_append_echo,$(1),Running test '$(2)')
|
||||||
|
$(call mb_autoexec_append_cmd,$(1),$(2))
|
||||||
|
$(call mb_autoexec_append_exit,$(1))
|
||||||
|
endef
|
44
lib/make/mb_base.mk
Normal file
44
lib/make/mb_base.mk
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# TODO: clean up + make working for non-unix systems.
|
||||||
|
|
||||||
|
# OS cmds
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
MB_RM = del /F /Q
|
||||||
|
MB_RMDIR = RMDIR /S /Q
|
||||||
|
MB_MKDIR = mkdir
|
||||||
|
MB_COPY = copy
|
||||||
|
MB_ERRIGNORE = 2>NUL || true
|
||||||
|
MB_SEP=\\
|
||||||
|
else
|
||||||
|
MB_RM = rm -f
|
||||||
|
MB_RMDIR = rm -rf
|
||||||
|
MB_MKDIR = mkdir -p
|
||||||
|
MB_COPY = cp
|
||||||
|
MB_ERRIGNORE = 2>/dev/null
|
||||||
|
MB_SEP=/
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Remove space after separator
|
||||||
|
MB_PSEP = $(strip $(MB_SEP))
|
||||||
|
|
||||||
|
define mb_clean
|
||||||
|
@echo === Cleaning build folder.
|
||||||
|
test $(1) && $(MB_RMDIR) $(1)
|
||||||
|
endef
|
||||||
|
define mb_mkdir
|
||||||
|
@echo === Create module build folder.
|
||||||
|
$(MB_MKDIR) $(1)
|
||||||
|
endef
|
||||||
|
define mb_delete
|
||||||
|
test $(1) && $(MB_RM) $(1)
|
||||||
|
endef
|
||||||
|
define mb_copy
|
||||||
|
$(MB_COPY) $(1) $(2)
|
||||||
|
endef
|
||||||
|
define mb_file_info
|
||||||
|
sha1sum $(1)
|
||||||
|
ls -lah $(1)
|
||||||
|
endef
|
||||||
|
define mb_create_dist
|
||||||
|
tar -czf $(1) -C $(2) `ls $(2)`
|
||||||
|
$(call mb_file_info,$(1))
|
||||||
|
endef
|
62
lib/make/mb_openmsx.mk
Normal file
62
lib/make/mb_openmsx.mk
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
# TODO move to new msxhub native posix+win cmd tool
|
||||||
|
# + local userdir caching like ~/.cache/msxhub/repro/m/s/x/msxdos2
|
||||||
|
CMD_WGET ?= wget
|
||||||
|
|
||||||
|
PATH_OPENMSX ?= /usr/bin
|
||||||
|
|
||||||
|
# Define openmsx defaults
|
||||||
|
MB_OPENMSX_BOOT_TIMEOUT ?= 25
|
||||||
|
MB_OPENMSX_MACHINE ?= Philips_NMS_8250
|
||||||
|
MB_OPENMSX_JOYPORTA ?=
|
||||||
|
MB_OPENMSX_JOYPORTB ?=
|
||||||
|
# Workaround for include msxbuild.mk file and 'older' openmsx segfaults on relative settings path.
|
||||||
|
MB_OPENMSX_SETTING := $(if $(realpath $(PATH_MSXBUILD)),$(realpath $(PATH_MSXBUILD)),$(PATH_MSXBUILD))/lib/openmsx/boot_settings.xml
|
||||||
|
MB_OPENMSX_EXTS_ORG += -ext ide -ext ram4mb
|
||||||
|
MB_OPENMSX_ARGS = \
|
||||||
|
-setting $(MB_OPENMSX_SETTING) \
|
||||||
|
-machine $(MB_OPENMSX_MACHINE) \
|
||||||
|
-ext slotexpander $(MB_OPENMSX_EXTS_ORG) $(MB_OPENMSX_EXTS) \
|
||||||
|
-script $(PATH_MSXBUILD)/lib/openmsx/boot_env.tcl \
|
||||||
|
-script $(PATH_MSXBUILD)/lib/openmsx/boot_hdd.tcl \
|
||||||
|
-script $(PATH_MSXBUILD)/lib/openmsx/fail_after.tcl \
|
||||||
|
-script $(PATH_MSXBUILD)/bin/wget/omsxctl.tcl
|
||||||
|
|
||||||
|
# TODO: add run flag to disable xml output like "-control stdio-boot-only"
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
MB_OPENMSX_CMD = $(PATH_OPENMSX)/openmsx $(MB_OPENMSX_ARGS) -control stdio < $(PATH_MSXBUILD)/lib/openmsx/boot_stdio.xml
|
||||||
|
else
|
||||||
|
MB_OPENMSX_CMD = $(PATH_OPENMSX)/openmsx $(MB_OPENMSX_ARGS) -control stdio < $(PATH_MSXBUILD)/lib/openmsx/boot_stdio.xml | sed -n -e 's/.*>\(.*\)<.*/\1/p' | tail -n+3
|
||||||
|
endif
|
||||||
|
define _mb_openmsx_run
|
||||||
|
@echo === Running openmsx
|
||||||
|
test -f $(PATH_MSXBUILD)/bin/wget/omsxctl.tcl || $(CMD_WGET) -O $(PATH_MSXBUILD)/bin/wget/omsxctl.tcl https://msxhub.com/api/OMSXCTL/1.0-1/get/OMSXCTL/omsxctl.tcl
|
||||||
|
FAIL_AFTER_BOOT=$(MB_OPENMSX_BOOT_TIMEOUT) \
|
||||||
|
FAIL_AFTER_PATH=bin \
|
||||||
|
BOOT_HDD_PATH="$(1)" \
|
||||||
|
BOOT_HDD_IMAGE="$(1)/../dsk.img" \
|
||||||
|
JOYPORTA=$(MB_OPENMSX_JOYPORTA) \
|
||||||
|
JOYPORTB=$(MB_OPENMSX_JOYPORTB) \
|
||||||
|
$(MB_OPENMSX_CMD)
|
||||||
|
endef
|
||||||
|
define _mb_openmsx_run_dos
|
||||||
|
@echo === run openmsx
|
||||||
|
test -f $(PATH_MSXBUILD)/bin/wget/omsxctl.com || $(CMD_WGET) -O $(PATH_MSXBUILD)/bin/wget/omsxctl.com https://msxhub.com/api/OMSXCTL/1.0-1/get/OMSXCTL/omsxctl.com
|
||||||
|
$(call mb_copy,$(PATH_MSXBUILD)/bin/wget/omsxctl.com,$(1))
|
||||||
|
$(call _mb_openmsx_run,$(1))
|
||||||
|
endef
|
||||||
|
# TODO: add msx1+allversions of dos to https://github.com/fr3nd/msxhub-packages/issues/18
|
||||||
|
#define mb_openmsx_dos1
|
||||||
|
# @echo === Run openmsx_dos1
|
||||||
|
# cp build/msxdos1/* $(1)
|
||||||
|
# $(call _mb_openmsx_run_dos,$(1))
|
||||||
|
#endef
|
||||||
|
define mb_openmsx_dos2
|
||||||
|
@echo === Prepare openmsx run with dos2
|
||||||
|
test -f $(PATH_MSXBUILD)/bin/wget/msxdos2.sys || $(MB_MKDIR) $(PATH_MSXBUILD)/bin/wget
|
||||||
|
test -f $(PATH_MSXBUILD)/bin/wget/msxdos2.sys || $(CMD_WGET) -O $(PATH_MSXBUILD)/bin/wget/msxdos2.sys https://msxhub.com/api/MSXDOS2/2.20-1/get/MSXDOS2/MSXDOS2.SYS
|
||||||
|
test -f $(PATH_MSXBUILD)/bin/wget/command2.com || $(CMD_WGET) -O $(PATH_MSXBUILD)/bin/wget/command2.com https://msxhub.com/api/MSXDOS2/2.20-1/get/MSXDOS2/COMMAND2.COM
|
||||||
|
$(call mb_copy,$(PATH_MSXBUILD)/bin/wget/msxdos2.sys,$(1))
|
||||||
|
$(call mb_copy,$(PATH_MSXBUILD)/bin/wget/command2.com,$(1))
|
||||||
|
$(call _mb_openmsx_run_dos, $(1))
|
||||||
|
endef
|
74
lib/make/msxbuild.mk
Normal file
74
lib/make/msxbuild.mk
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# msxbuild.mk - Makefile helper to use with msx projects.
|
||||||
|
#
|
||||||
|
# note: this needs more work.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# Required tools paths
|
||||||
|
PATH_HEX2BIN ?= /usr/bin
|
||||||
|
PATH_SDCC ?= /usr/bin
|
||||||
|
PATH_MSXBUILD ?= $(dir $(lastword $(MAKEFILE_LIST)))../..
|
||||||
|
|
||||||
|
include $(PATH_MSXBUILD)/lib/make/mb_base.mk
|
||||||
|
include $(PATH_MSXBUILD)/lib/make/mb_autoexec.mk
|
||||||
|
include $(PATH_MSXBUILD)/lib/make/mb_openmsx.mk
|
||||||
|
include $(PATH_MSXBUILD)/lib/make/mb_assert.mk
|
||||||
|
|
||||||
|
CMD_H2B ?= $(PATH_HEX2BIN)/hex2bin
|
||||||
|
CMD_SDCC ?= $(PATH_SDCC)/sdcc
|
||||||
|
CMD_SDASM ?= $(PATH_SDCC)/sdasz80
|
||||||
|
CMD_SDAR ?= $(PATH_SDCC)/sdar
|
||||||
|
|
||||||
|
# Define build flags
|
||||||
|
MB_SDCC_FLAG_CPU ?= -mz80
|
||||||
|
MB_SDCC_FLAG_LD ?= --nostdinc
|
||||||
|
MB_SDASM_FLAGS ?= -g -l -c -o
|
||||||
|
MB_SDAR_FLAGS ?= -rc
|
||||||
|
#$(MB_SDASM) -I$(MB_LIBASM_SRC)/include
|
||||||
|
|
||||||
|
define mb_compile_asm
|
||||||
|
@echo === Compile module asm.
|
||||||
|
$(CMD_SDASM) $(MB_SDASM_FLAGS) $(1) $(2)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define mb_link_asm_lib
|
||||||
|
@echo === Link module asm lib.
|
||||||
|
$(CMD_SDAR) $(MB_SDAR_FLAGS) $(1) $(2)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define mb_link_asm
|
||||||
|
@echo === Link asm module at $(3)
|
||||||
|
$(CMD_SDCC) $(MB_SDCC_FLAG_CPU) --no-std-crt0 --code-loc $(3) -o $(1) $(2)
|
||||||
|
endef
|
||||||
|
define mb_link_asm_0000
|
||||||
|
$(call mb_link_asm,$(1),$(2),0x0000)
|
||||||
|
endef
|
||||||
|
define mb_link_asm_dos
|
||||||
|
$(call mb_link_asm,$(1),$(2),0x0100)
|
||||||
|
endef
|
||||||
|
define mb_link_asm_1000
|
||||||
|
$(call mb_link_asm,$(1),$(2),0x1000)
|
||||||
|
endef
|
||||||
|
define mb_link_asm_4000
|
||||||
|
$(call mb_link_asm,$(1),$(2),0x4000)
|
||||||
|
endef
|
||||||
|
define mb_link_asm_8000
|
||||||
|
$(call mb_link_asm,$(1),$(2),0x8000)
|
||||||
|
endef
|
||||||
|
define mb_link_asm_C000
|
||||||
|
$(call mb_link_asm,$(1),$(2),0xC000)
|
||||||
|
endef
|
||||||
|
#-l$(LIBASM_LINK)
|
||||||
|
|
||||||
|
define mb_hex2com
|
||||||
|
@echo === Convert to binary: $(notdir $(1)).com
|
||||||
|
cd $(dir $(1)) && $(CMD_H2B) -e com $(notdir $(1))
|
||||||
|
$(call mb_file_info,$(2))
|
||||||
|
@echo === Done $(notdir $(2))
|
||||||
|
endef
|
||||||
|
define mb_hex2dat
|
||||||
|
@echo === Convert to binary $(notdir $(1)).dat
|
||||||
|
cd $(dir $(1)) && $(CMD_H2B) -e dat $(notdir $(1))
|
||||||
|
$(call mb_file_info,$(2))
|
||||||
|
@echo === Done $(notdir $(2))
|
||||||
|
endef
|
65
lib/openmsx/boot_env.tcl
Normal file
65
lib/openmsx/boot_env.tcl
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# boot_env -- Sets various openMSX settings based from environment variables.
|
||||||
|
#
|
||||||
|
# Typically used in automation tools which run openMSX without human interaction.
|
||||||
|
# Supported environment variables by this script;
|
||||||
|
#
|
||||||
|
# SAVE_SETTINGS_ON_EXIT=false
|
||||||
|
# Disables automatic settings saving.
|
||||||
|
#
|
||||||
|
# RENDERER=none
|
||||||
|
# Disables video output, to enable video use 'SDL' as argument.
|
||||||
|
#
|
||||||
|
# THROTTLE=off
|
||||||
|
# Disables msx speed emulation.
|
||||||
|
#
|
||||||
|
# SPEED=400
|
||||||
|
# Sets msx speed to 4x of original but only when throttle is on.
|
||||||
|
#
|
||||||
|
# JOYPORTA=mouse
|
||||||
|
# Inserts mouse in joyporta.
|
||||||
|
#
|
||||||
|
# JOYPORTB=mouse
|
||||||
|
# Inserts mouse in joyportb.
|
||||||
|
#
|
||||||
|
|
||||||
|
if {[info exists ::env(SAVE_SETTINGS_ON_EXIT)] && ([string trim $::env(SAVE_SETTINGS_ON_EXIT)] != "")} {
|
||||||
|
if {[catch {set save_settings_on_exit [string trim $::env(SAVE_SETTINGS_ON_EXIT)]} err_msg]} {
|
||||||
|
puts stderr "error: env.SAVE_SETTINGS_ON_EXIT value $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[info exists ::env(RENDERER)] && ([string trim $::env(RENDERER)] != "")} {
|
||||||
|
if {[catch {set renderer [string trim $::env(RENDERER)]} err_msg]} {
|
||||||
|
puts stderr "error: env.RENDERER value $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[info exists ::env(THROTTLE)] && ([string trim $::env(THROTTLE)] != "")} {
|
||||||
|
if {[catch {set throttle [string trim $::env(THROTTLE)]} err_msg]} {
|
||||||
|
puts stderr "error: env.THROTTLE value $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[info exists ::env(SPEED)] && ([string trim $::env(SPEED)] != "")} {
|
||||||
|
if {[catch {set speed [string trim $::env(SPEED)]} err_msg]} {
|
||||||
|
puts stderr "error: env.SPEED value $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[info exists ::env(JOYPORTA)] && ([string trim $::env(JOYPORTA)] != "")} {
|
||||||
|
if {[catch {plug joyporta [string trim $::env(JOYPORTA)]} err_msg]} {
|
||||||
|
puts stderr "error: env.JOYPORTA value $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[info exists ::env(JOYPORTB)] && ([string trim $::env(JOYPORTB)] != "")} {
|
||||||
|
if {[catch {plug joyportb [string trim $::env(JOYPORTB)]} err_msg]} {
|
||||||
|
puts stderr "error: env.JOYPORTB value $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
130
lib/openmsx/boot_hdd.tcl
Normal file
130
lib/openmsx/boot_hdd.tcl
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
# boot_hdd -- Create import/export disk images to local folder.
|
||||||
|
#
|
||||||
|
# Typically used in automation tools which run openMSX without human interaction.
|
||||||
|
# This script is basicly is a bit more generic and safe way to run the following code;
|
||||||
|
#
|
||||||
|
# diskmanipulator create disk.img 32m 32m 32m 32m
|
||||||
|
# hda disk.img
|
||||||
|
# diskmanipulator import hda1 ./disk-in/
|
||||||
|
# after quit {diskmanipulator export hda1 ./disk-out/}
|
||||||
|
#
|
||||||
|
# Supported environment variables by this script;
|
||||||
|
#
|
||||||
|
# BOOT_HDD_SIZE=30m
|
||||||
|
# Sets the size of the created partitions, defaults to 15m.
|
||||||
|
#
|
||||||
|
# BOOT_HDD_IMAGE=bin/myapp/dsk.img
|
||||||
|
# Defaults to ./hdd.dsk
|
||||||
|
#
|
||||||
|
# BOOT_HDD_PATH=bin/myapp/dsk
|
||||||
|
# provides the default values for BOOT_HDD_PATH_IMPORT and BOOT_HDD_PATH_EXPORT
|
||||||
|
#
|
||||||
|
# BOOT_HDD_PATH_IMPORT=bin/myapp/dsk
|
||||||
|
# When set enables the import of all files into the first disk partition.
|
||||||
|
#
|
||||||
|
# BOOT_HDD_PATH_EXPORT=bin/myapp/dsk-result
|
||||||
|
# When set enables the export of all files back to the filesystem
|
||||||
|
#
|
||||||
|
# BOOT_HDD_EXPORT_PARTITION=2
|
||||||
|
# When set override the export from 'first' to 'given' partition number.
|
||||||
|
#
|
||||||
|
# BOOT_HDD_EXPORT_DIR=myout
|
||||||
|
# By default export does chdir to root of msx partition override to custom export directory.
|
||||||
|
#
|
||||||
|
# BOOT_HDD_PARTITIONS=2
|
||||||
|
# The number of partitions created in the disk image, defaults to 1.
|
||||||
|
#
|
||||||
|
|
||||||
|
# per default create msxdos1 compatible partition size.
|
||||||
|
set boot_hdd_size 15m
|
||||||
|
set boot_hdd_image hdd.dsk
|
||||||
|
set boot_hdd_path_import 0
|
||||||
|
set boot_hdd_path_export 0
|
||||||
|
set boot_hdd_export_partition 0
|
||||||
|
set boot_hdd_export_dir \\
|
||||||
|
set boot_hdd_partitions 1
|
||||||
|
|
||||||
|
# Parse env settings
|
||||||
|
if {[info exists ::env(BOOT_HDD_SIZE)] && ([string trim $::env(BOOT_HDD_SIZE)] != "")} {
|
||||||
|
set boot_hdd_size [string trim $::env(BOOT_HDD_SIZE)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_IMAGE)] && ([string trim $::env(BOOT_HDD_IMAGE)] != "")} {
|
||||||
|
set boot_hdd_image [string trim $::env(BOOT_HDD_IMAGE)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_PATH)] && ([string trim $::env(BOOT_HDD_PATH)] != "")} {
|
||||||
|
set boot_hdd_path_import [string trim $::env(BOOT_HDD_PATH)]
|
||||||
|
set boot_hdd_path_export [string trim $::env(BOOT_HDD_PATH)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_PATH_IMPORT)] && ([string trim $::env(BOOT_HDD_PATH_IMPORT)] != "")} {
|
||||||
|
set boot_hdd_path_import [string trim $::env(BOOT_HDD_PATH_IMPORT)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_PATH_EXPORT)] && ([string trim $::env(BOOT_HDD_PATH_EXPORT)] != "")} {
|
||||||
|
set boot_hdd_path_export [string trim $::env(BOOT_HDD_PATH_EXPORT)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_EXPORT_PARTITION)] && ([string trim $::env(BOOT_HDD_EXPORT_PARTITION)] != "")} {
|
||||||
|
set boot_hdd_export_partition [string trim $::env(BOOT_HDD_EXPORT_PARTITION)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_EXPORT_DIR)] && ([string trim $::env(BOOT_HDD_EXPORT_DIR)] != "")} {
|
||||||
|
set boot_hdd_export_dir [string trim $::env(BOOT_HDD_EXPORT_DIR)]
|
||||||
|
}
|
||||||
|
if {[info exists ::env(BOOT_HDD_PARTITIONS)] && ([string trim $::env(BOOT_HDD_PARTITIONS)] != "")} {
|
||||||
|
set boot_hdd_partitions [string trim $::env(BOOT_HDD_PARTITIONS)]
|
||||||
|
if {$boot_hdd_partitions == 0 || $boot_hdd_partitions > 4} {
|
||||||
|
puts stderr "error: Invalid env.BOOT_HDD_PARTITIONS value 1-4 allowed: $boot_hdd_partitions"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if {$boot_hdd_path_import != 0} {
|
||||||
|
set boot_hdd_disk_partition "hda"
|
||||||
|
if {$boot_hdd_partitions == 1} {
|
||||||
|
if {[catch {diskmanipulator create $boot_hdd_image $boot_hdd_size} err_msg]} {
|
||||||
|
puts stderr "error: create1 $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {$boot_hdd_partitions > 1} {
|
||||||
|
set boot_hdd_disk_partition "hda1"
|
||||||
|
if {$boot_hdd_partitions == 2} {
|
||||||
|
if {[catch {diskmanipulator create $boot_hdd_image $boot_hdd_size $boot_hdd_size} err_msg]} {
|
||||||
|
puts stderr "error: create2 $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {$boot_hdd_partitions == 3} {
|
||||||
|
if {[catch {diskmanipulator create $boot_hdd_image $boot_hdd_size $boot_hdd_size $boot_hdd_size} err_msg]} {
|
||||||
|
puts stderr "error: create3 $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {$boot_hdd_partitions == 4} {
|
||||||
|
if {[catch {diskmanipulator create $boot_hdd_image $boot_hdd_size $boot_hdd_size $boot_hdd_size $boot_hdd_size} err_msg]} {
|
||||||
|
puts stderr "error: create4 $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {[catch {hda $boot_hdd_image} err_msg]} {
|
||||||
|
puts stderr "error: hda $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if {[catch {diskmanipulator import $boot_hdd_disk_partition $boot_hdd_path_import} err_msg]} {
|
||||||
|
puts stderr "error: import $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if {$boot_hdd_path_export != 0} {
|
||||||
|
if {$boot_hdd_export_partition != 0} {
|
||||||
|
set boot_hdd_disk_partition "hda$boot_hdd_export_partition"
|
||||||
|
}
|
||||||
|
after quit {
|
||||||
|
if {[catch {diskmanipulator chdir $boot_hdd_disk_partition $boot_hdd_export_dir} err_msg]} {
|
||||||
|
puts stderr "error: chdir $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if {[catch {diskmanipulator export $boot_hdd_disk_partition $boot_hdd_path_export} err_msg]} {
|
||||||
|
puts stderr "error: export $err_msg"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
lib/openmsx/boot_settings.xml
Normal file
9
lib/openmsx/boot_settings.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE settings SYSTEM 'settings.dtd'>
|
||||||
|
<settings>
|
||||||
|
<settings>
|
||||||
|
<setting id="save_settings_on_exit">false</setting>
|
||||||
|
<setting id="scale_factor">3</setting>
|
||||||
|
<setting id="speed">333</setting>
|
||||||
|
</settings>
|
||||||
|
<bindings/>
|
||||||
|
</settings>
|
8
lib/openmsx/boot_stdio.xml
Normal file
8
lib/openmsx/boot_stdio.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<openmsx-control>
|
||||||
|
<!--
|
||||||
|
When booting 'openmsx -control stdio < boot_stdio.xml'
|
||||||
|
It starts then in power off mode and without renderer for fast booting.
|
||||||
|
-->
|
||||||
|
<command>set power on</command>
|
||||||
|
<command>set throttle off</command>
|
||||||
|
</openmsx-control>
|
77
lib/openmsx/fail_after.tcl
Normal file
77
lib/openmsx/fail_after.tcl
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# fail_after -- exits openMSX after timeout.
|
||||||
|
#
|
||||||
|
# Typically used in combination with the MSX-DOS 'omsxctl.com' utility.
|
||||||
|
#
|
||||||
|
# Adds two environment variables and two commands to openMSX;
|
||||||
|
#
|
||||||
|
# 'fail_after timeout [timeunit] [fail_id] [fail_code]'
|
||||||
|
# Schedules an openMSX exit after the timeout.
|
||||||
|
# This can be canceled by requesting a timeout of 0 or new timeout.
|
||||||
|
# The timeunit can be selected between (msx)'time' and (host)'realtime'.
|
||||||
|
# The fail_id can be used to differentiate between multiple fail_after commands.
|
||||||
|
# The failure exit code can be given too.
|
||||||
|
#
|
||||||
|
# 'fail_after_exit [fail_id] [fail_code]'
|
||||||
|
# Exits openMSX with an failure exit code and if the FAIL_AFTER_PATH is
|
||||||
|
# set it also creates a screenshot named from the failure id.
|
||||||
|
#
|
||||||
|
# Supported environment variables by this script;
|
||||||
|
#
|
||||||
|
# FAIL_AFTER_PATH=.
|
||||||
|
# Enabled automatic screenshots saving in case of failures in the supplied path.
|
||||||
|
#
|
||||||
|
# FAIL_AFTER_BOOT=30
|
||||||
|
# Enables the boot watchdog timer which will exit openMSX after the timeout(in seconds).
|
||||||
|
# To cancel this timer give an `fail_after 0` or any new fail_after command.
|
||||||
|
#
|
||||||
|
|
||||||
|
proc fail_after_exit {{fail_id "fail_after_exit"} {fail_code 2}} {
|
||||||
|
global fail_after_path
|
||||||
|
if {$fail_after_path != 0} {
|
||||||
|
if {[catch {screenshot $fail_after_path/$fail_id.png} err_msg]} {
|
||||||
|
puts stderr "warning: $err_msg"
|
||||||
|
}
|
||||||
|
# maybe later add; if {is_text_mode} { [get_screen] ?> $fail_after_path/$fail_id.scr }
|
||||||
|
}
|
||||||
|
puts stderr "error: Failure request from $fail_id"
|
||||||
|
exit $fail_code
|
||||||
|
}
|
||||||
|
|
||||||
|
proc fail_after { timeout {time_unit "time"} {fail_id "fail_after"} {fail_code 2}} {
|
||||||
|
global fail_after_prev_timer
|
||||||
|
global fail_after_prev_id
|
||||||
|
set msg ""
|
||||||
|
if {$fail_after_prev_timer != 0} {
|
||||||
|
after cancel $fail_after_prev_timer
|
||||||
|
set msg "$fail_after_prev_id: Stopped attempt."
|
||||||
|
}
|
||||||
|
set fail_after_prev_id $fail_id
|
||||||
|
if {$time_unit != "time"} {
|
||||||
|
set time_unit "realtime"
|
||||||
|
}
|
||||||
|
if {$timeout != 0} {
|
||||||
|
if {[catch {set fail_after_prev_timer [after $time_unit $timeout "fail_after_exit $fail_id $fail_code"]} err_msg]} {
|
||||||
|
puts stderr "error: $err_msg"
|
||||||
|
fail_after_exit fail_after_timer_error 1
|
||||||
|
}
|
||||||
|
set msg "$msg\n$fail_id: Automatic failure in $timeout $time_unit seconds."
|
||||||
|
} else {
|
||||||
|
set fail_after_prev_timer 0
|
||||||
|
}
|
||||||
|
return $msg
|
||||||
|
}
|
||||||
|
|
||||||
|
# Globals
|
||||||
|
set fail_after_prev_timer 0
|
||||||
|
set fail_after_prev_id 0
|
||||||
|
set fail_after_path 0
|
||||||
|
|
||||||
|
# Parse screenshot path env setting
|
||||||
|
if {[info exists ::env(FAIL_AFTER_PATH)] && ([string trim $::env(FAIL_AFTER_PATH)] != "")} {
|
||||||
|
set fail_after_path [string trim $::env(FAIL_AFTER_PATH)]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enables boot watch dog timer when FAIL_AFTER_BOOT env has a value. (124 see `man timeout`)
|
||||||
|
if {[info exists ::env(FAIL_AFTER_BOOT)] && ([string trim $::env(FAIL_AFTER_BOOT)] != "")} {
|
||||||
|
fail_after [string trim $::env(FAIL_AFTER_BOOT)] realtime fail_after_boot 124
|
||||||
|
}
|
33
test/ahello/0module.mk
Normal file
33
test/ahello/0module.mk
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
ASM_HELLO_NAME := ahello
|
||||||
|
ASM_HELLO_RUN := run-$(ASM_HELLO_NAME)
|
||||||
|
ASM_HELLO_TEST := test-$(ASM_HELLO_NAME)
|
||||||
|
ASM_HELLO_SRC := test/$(ASM_HELLO_NAME)
|
||||||
|
ASM_HELLO_BIN := $(PATH_BIN)/test/$(ASM_HELLO_NAME)
|
||||||
|
ASM_HELLO_HEX := $(ASM_HELLO_BIN)/$(ASM_HELLO_NAME).hex
|
||||||
|
ASM_HELLO_COM := $(ASM_HELLO_BIN)/$(ASM_HELLO_NAME).com
|
||||||
|
ASM_HELLO_RELS := $(ASM_HELLO_BIN)/$(ASM_HELLO_NAME).rel
|
||||||
|
ASM_HELLO_CODE := $(ASM_HELLO_SRC)/$(ASM_HELLO_NAME).asm
|
||||||
|
BUILD_HELP += \\n\\t* $(ASM_HELLO_COM)\\n\\t* $(ASM_HELLO_RUN)\\n\\t* $(ASM_HELLO_TEST) \(Change txt in hello.asm and run again\)
|
||||||
|
|
||||||
|
$(ASM_HELLO_BIN):
|
||||||
|
$(call mb_mkdir,$(ASM_HELLO_BIN))
|
||||||
|
|
||||||
|
$(ASM_HELLO_BIN)/%.rel: $(ASM_HELLO_SRC)/%.asm | $(ASM_HELLO_BIN)
|
||||||
|
$(call mb_compile_asm,$@,$<)
|
||||||
|
|
||||||
|
$(ASM_HELLO_HEX): $(ASM_HELLO_RELS)
|
||||||
|
$(call mb_link_asm_dos,$(ASM_HELLO_HEX),$(ASM_HELLO_RELS))
|
||||||
|
|
||||||
|
$(ASM_HELLO_COM): $(ASM_HELLO_HEX)
|
||||||
|
$(call mb_hex2com,$(ASM_HELLO_HEX),$(ASM_HELLO_COM))
|
||||||
|
|
||||||
|
$(ASM_HELLO_RUN): $(ASM_HELLO_COM)
|
||||||
|
$(call mb_autoexec_open_gui,$(ASM_HELLO_BIN))
|
||||||
|
$(call mb_openmsx_dos2,$(ASM_HELLO_BIN))
|
||||||
|
|
||||||
|
$(ASM_HELLO_TEST): $(ASM_HELLO_COM)
|
||||||
|
$(call mb_delete,$(ASM_HELLO_BIN)/test.out)
|
||||||
|
$(call mb_autoexec_cmd_test,$(ASM_HELLO_BIN),$(ASM_HELLO_NAME) > test.out)
|
||||||
|
$(call mb_openmsx_dos2,$(ASM_HELLO_BIN))
|
||||||
|
$(call mb_assert_file_equals,$(ASM_HELLO_BIN)/test.out,Hello world...from asm.)
|
42
test/ahello/ahello.asm
Normal file
42
test/ahello/ahello.asm
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
DOS .equ 0x5
|
||||||
|
_CONOUT .equ 0x02
|
||||||
|
|
||||||
|
.area _CODE
|
||||||
|
JP START
|
||||||
|
|
||||||
|
.db 0x0D ; type hello.com
|
||||||
|
.db 0x0D,0x0A
|
||||||
|
.str "Example hello world executable."
|
||||||
|
.db 0x0D,0x0A
|
||||||
|
.db 0x1A ; end txt
|
||||||
|
|
||||||
|
START:
|
||||||
|
LD HL,#TXT_HELLO
|
||||||
|
CALL PUT_TXT
|
||||||
|
LD HL,#TXT_HELLO_SRC
|
||||||
|
CALL PUT_TXT
|
||||||
|
RET
|
||||||
|
|
||||||
|
PUT_TXT:
|
||||||
|
LD A,(HL)
|
||||||
|
CP #0x1D
|
||||||
|
RET Z
|
||||||
|
LD E,A
|
||||||
|
LD C,#2
|
||||||
|
PUSH HL
|
||||||
|
CALL DOS
|
||||||
|
POP HL
|
||||||
|
INC HL
|
||||||
|
JR PUT_TXT
|
||||||
|
|
||||||
|
TXT_HELLO:
|
||||||
|
.str "Hello world..."
|
||||||
|
.db 0x1D
|
||||||
|
|
||||||
|
TXT_HELLO_SRC:
|
||||||
|
.str "from asm."
|
||||||
|
.db 0x0D,0x0A
|
||||||
|
.db 0x1D
|
||||||
|
|
||||||
|
.area _DATA
|
Loading…
Reference in a new issue