Switch from ackbuilder to bazel.
This commit is contained in:
parent
c12cf80bff
commit
a4739d5e8d
78 changed files with 1442 additions and 3527 deletions
5
BUILD
Normal file
5
BUILD
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([ "diskdefs" ])
|
||||
|
||||
|
||||
24
Makefile
24
Makefile
|
|
@ -1,22 +1,6 @@
|
|||
OBJDIR = $(PWD)/.obj
|
||||
LUA_5_1 = lua5.1
|
||||
all:
|
||||
bazel build -c opt //...
|
||||
|
||||
all: $(OBJDIR)/build.ninja
|
||||
@ninja -f $(OBJDIR)/build.ninja
|
||||
verbose:
|
||||
bazel build -s -c opt //...
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR)
|
||||
|
||||
lua-files = $(shell find . -name 'build*.lua')
|
||||
$(OBJDIR)/build.ninja: build/ackbuilder.lua build/cpm.lua Makefile $(lua-files)
|
||||
@mkdir -p $(OBJDIR)
|
||||
@$(LUA_5_1) \
|
||||
build/ackbuilder.lua \
|
||||
build/build.lua \
|
||||
build/cpm.lua \
|
||||
build.lua \
|
||||
--ninja \
|
||||
OBJDIR=$(OBJDIR) \
|
||||
CC=gcc \
|
||||
AR=ar \
|
||||
> $@
|
||||
|
|
|
|||
106
arch/brotherop2/BUILD
Normal file
106
arch/brotherop2/BUILD
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
load("//build:cpm.bzl", "diskimage")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//utils:build.bzl", "unix2cpm")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
genrule(
|
||||
name = "font_inc",
|
||||
tools = [ "//arch/brotherop2/utils:fontconvert" ],
|
||||
srcs = [ "//utils:6x7font.bdf" ],
|
||||
outs = [ "font.inc" ],
|
||||
cmd = "$(location //arch/brotherop2/utils:fontconvert) $< > $@"
|
||||
)
|
||||
|
||||
zmac(
|
||||
name = "boot_o",
|
||||
srcs = [
|
||||
"boot.z80",
|
||||
"//arch/brotherop2/include:brotherop2.lib",
|
||||
"//arch/common/utils:tty.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
":font_inc",
|
||||
],
|
||||
)
|
||||
|
||||
ld80(
|
||||
name = "boot",
|
||||
address = 0x5000,
|
||||
objs = {
|
||||
0x5000: [ ":boot_o" ]
|
||||
}
|
||||
)
|
||||
|
||||
[
|
||||
zmac(
|
||||
name = n,
|
||||
srcs = [
|
||||
n + ".z80",
|
||||
"//arch/brotherop2/include:brotherop2.lib",
|
||||
"//arch/common/utils:print.lib",
|
||||
"//arch/common/utils:tty.lib",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
]
|
||||
)
|
||||
for n in [ "bios", "floppy", "tty" ]
|
||||
]
|
||||
|
||||
# This is the bit which CP/M reloads on warm boot (well, some of it).
|
||||
ld80(
|
||||
name = "cpmfile",
|
||||
address = 0x9300,
|
||||
objs = {
|
||||
0x9300: [ "//third_party/zcpr1" ],
|
||||
0x9b00: [ "//third_party/zsdos" ],
|
||||
0xa900: [
|
||||
":bios",
|
||||
":floppy",
|
||||
":tty",
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# Produces the FAT bit of the disk image.
|
||||
zmac(
|
||||
name = "fat",
|
||||
srcs = [
|
||||
"fat.z80",
|
||||
":boot",
|
||||
":cpmfile"
|
||||
]
|
||||
)
|
||||
|
||||
ld80(
|
||||
name = "bootfile",
|
||||
objs = {
|
||||
0x0000: [ ":fat" ]
|
||||
}
|
||||
)
|
||||
|
||||
unix2cpm(
|
||||
name = "readme",
|
||||
src = "README.md"
|
||||
)
|
||||
|
||||
diskimage(
|
||||
name = "diskimage",
|
||||
format = "brother-op2",
|
||||
bootfile = ":bootfile",
|
||||
map = {
|
||||
"-readme.txt": ":readme",
|
||||
"dump.com": "//cpmtools:dump",
|
||||
"stat.com": "//cpmtools:stat",
|
||||
"asm.com": "//cpmtools:asm",
|
||||
"copy.com": "//cpmtools:copy",
|
||||
"submit.com": "//cpmtools:submit",
|
||||
"rawdisk.com": "//cpmtools:rawdisk",
|
||||
"bbcbasic.com": "//third_party/bbcbasic:bbcbasic_ADM3A",
|
||||
"camel80.com": "//third_party/camelforth",
|
||||
"qe.com": "//cpmtools:qe_BROTHEROP2",
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "utils/build.lua"
|
||||
|
||||
normalrule {
|
||||
name = "font_inc",
|
||||
ins = {
|
||||
"arch/brotherop2/utils+fontconvert",
|
||||
"utils/6x7font.bdf",
|
||||
},
|
||||
outleaves = { "font.inc" },
|
||||
commands = {
|
||||
"%{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "boot_o",
|
||||
srcs = { "./boot.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
"+font_inc"
|
||||
},
|
||||
}
|
||||
|
||||
ld80 {
|
||||
name = "boot",
|
||||
address = 0x5000,
|
||||
srcs = {
|
||||
"-P5000",
|
||||
"+boot_o"
|
||||
}
|
||||
}
|
||||
|
||||
for _, n in pairs({"bios", "floppy", "tty"}) do
|
||||
zmac {
|
||||
name = n,
|
||||
srcs = { "./"..n..".z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
-- This is the bit which CP/M reloads on warm boot (well, some of it).
|
||||
ld80 {
|
||||
name = "cpmfile",
|
||||
address = 0x9300,
|
||||
srcs = {
|
||||
"-P9300", "third_party/zcpr1+zcpr",
|
||||
"-P9b00", "third_party/zsdos+zsdos",
|
||||
"-Pa900",
|
||||
"+bios",
|
||||
"+floppy",
|
||||
"+tty",
|
||||
}
|
||||
}
|
||||
|
||||
-- Produces the FAT bit of the disk image.
|
||||
zmac {
|
||||
name = "fat",
|
||||
srcs = { "./fat.z80" },
|
||||
deps = {
|
||||
"+boot",
|
||||
"+cpmfile"
|
||||
}
|
||||
}
|
||||
|
||||
ld80 {
|
||||
name = "bootfile",
|
||||
srcs = { "+fat" }
|
||||
}
|
||||
|
||||
unix2cpm {
|
||||
name = "readme",
|
||||
srcs = { "README.md" }
|
||||
}
|
||||
|
||||
diskimage {
|
||||
name = "diskimage",
|
||||
format = "brother-op2",
|
||||
bootfile = { "+bootfile" },
|
||||
map = {
|
||||
["dump.com"] = "cpmtools+dump",
|
||||
["stat.com"] = "cpmtools+stat",
|
||||
["asm.com"] = "cpmtools+asm",
|
||||
["copy.com"] = "cpmtools+copy",
|
||||
["submit.com"] = "cpmtools+submit",
|
||||
["bbcbasic.com"] = "third_party/bbcbasic+bbcbasic_ADM3A",
|
||||
["qe.com"] = "cpmtools+qe_BROTHEROP2",
|
||||
["mkfs.com"] = "cpmtools+mkfs",
|
||||
["rawdisk.com"] = "cpmtools+rawdisk",
|
||||
["-readme.txt"] = "+readme",
|
||||
},
|
||||
}
|
||||
|
||||
5
arch/brotherop2/include/BUILD
Normal file
5
arch/brotherop2/include/BUILD
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
||||
8
arch/brotherop2/utils/BUILD
Normal file
8
arch/brotherop2/utils/BUILD
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_binary(
|
||||
name = "fontconvert",
|
||||
srcs = [ "fontconvert.c" ],
|
||||
deps = [ "//utils:libbdf" ],
|
||||
)
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
cprogram {
|
||||
name = "fontconvert",
|
||||
srcs = { "./fontconvert.c" },
|
||||
deps = { "utils+libbdf" },
|
||||
}
|
||||
145
arch/brotherwp1/BUILD
Normal file
145
arch/brotherwp1/BUILD
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
load("//build:cpm.bzl", "cpm_addresses", "binslice", "diskimage")
|
||||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
load("//utils:build.bzl", "unix2cpm")
|
||||
|
||||
# Memory layout configuration -----------------------------------------------
|
||||
|
||||
# Configure the BIOS size here; this will then emit an addresses.lib file
|
||||
# which contains the position of the BDOS and CCP.
|
||||
|
||||
top_of_memory = 0x9000
|
||||
(cbase, fbase, bbase) = cpm_addresses(
|
||||
name = "addresses",
|
||||
top_of_memory = top_of_memory,
|
||||
bios_size = 0x0a00
|
||||
)
|
||||
|
||||
# Bootstrapper --------------------------------------------------------------
|
||||
|
||||
# This is the .APL file which the Brother OS loads. It's responsible for
|
||||
# remapping the memory, doing some device setup, and loading the BIOS into
|
||||
# the top of memory.
|
||||
|
||||
zmac(
|
||||
name = "boot_img",
|
||||
srcs = [
|
||||
"boot.z80",
|
||||
"//include:z180.lib",
|
||||
":addresses",
|
||||
],
|
||||
relocatable = False
|
||||
)
|
||||
|
||||
# BIOS ----------------------------------------------------------------------
|
||||
|
||||
BIOS_SRCS = [
|
||||
"bios",
|
||||
"floppy",
|
||||
"keyboard",
|
||||
"tty",
|
||||
]
|
||||
|
||||
[
|
||||
zmac(
|
||||
name = name + "_o",
|
||||
srcs = [
|
||||
name + ".z80",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
"//arch/brotherwp1/include:brotherwp1.lib",
|
||||
"//arch/common/utils:tty.lib",
|
||||
"//arch/common/utils:print.lib",
|
||||
":addresses",
|
||||
":keytab",
|
||||
]
|
||||
)
|
||||
for name in BIOS_SRCS
|
||||
]
|
||||
|
||||
genrule(
|
||||
name = "keytab",
|
||||
tools = [ "//arch/brotherwp1/utils:mkkeytab" ],
|
||||
srcs = [],
|
||||
outs = [ "keytab.inc" ],
|
||||
cmd = "$(location //arch/brotherwp1/utils:mkkeytab) > $@"
|
||||
)
|
||||
|
||||
# This is a 64kB file containing the entire CP/M memory image.
|
||||
|
||||
ld80(
|
||||
name = "memory_img",
|
||||
address = 0,
|
||||
objs = {
|
||||
cbase: [ "//third_party/zcpr1" ],
|
||||
fbase: [ "//third_party/zsdos" ],
|
||||
bbase: [
|
||||
":bios_o",
|
||||
":tty_o",
|
||||
":floppy_o",
|
||||
":keyboard_o",
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# We now chop it up to remove the BIOS and the combined CCP/BDOS (which
|
||||
# go into the system track).
|
||||
|
||||
binslice(
|
||||
name = "bios_img",
|
||||
src = ":memory_img",
|
||||
start = bbase,
|
||||
length = top_of_memory - bbase
|
||||
)
|
||||
|
||||
binslice(
|
||||
name = "ccpbdos_img",
|
||||
src = ":memory_img",
|
||||
start = cbase,
|
||||
length = bbase - cbase
|
||||
)
|
||||
|
||||
# Brother file system -------------------------------------------------------
|
||||
|
||||
# Produces the fake Brother file system image
|
||||
|
||||
zmac(
|
||||
name = "bootfile_img",
|
||||
srcs = [
|
||||
"fs.z80",
|
||||
":boot_img",
|
||||
":bios_img",
|
||||
":ccpbdos_img",
|
||||
],
|
||||
relocatable = False
|
||||
)
|
||||
|
||||
# Disk image ----------------------------------------------------------------
|
||||
|
||||
# Assembles the bootable disk which you can actually run.
|
||||
|
||||
unix2cpm(
|
||||
name = "readme",
|
||||
src = "README.md"
|
||||
)
|
||||
|
||||
diskimage(
|
||||
name = "diskimage",
|
||||
format = "brother-wp1",
|
||||
bootfile = ":bootfile_img",
|
||||
map = {
|
||||
"-readme.txt": ":readme",
|
||||
"dump.com": "//cpmtools:dump",
|
||||
"stat.com": "//cpmtools:stat",
|
||||
"asm.com": "//cpmtools:asm",
|
||||
"copy.com": "//cpmtools:copy",
|
||||
"submit.com": "//cpmtools:submit",
|
||||
"bbcbasic.com": "//third_party/bbcbasic:bbcbasic_ADM3A",
|
||||
"camel80.com": "//third_party/camelforth",
|
||||
"qe.com": "//cpmtools:qe_BROTHER_WP1",
|
||||
},
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
|
|
@ -1,181 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "utils/build.lua"
|
||||
|
||||
--- Memory layout configuration ---------------------------------------------
|
||||
|
||||
-- Configure the BIOS size here; this will then emit an addresses.lib file
|
||||
-- which contains the position of the BDOS and CCP.
|
||||
|
||||
local BIOS_SIZE = 0x0a00
|
||||
local BDOS_SIZE = 3584 -- fixed
|
||||
local CCP_SIZE = 2048 -- fixed
|
||||
local BBASE = 0x9000 - BIOS_SIZE
|
||||
local FBASE = BBASE - BDOS_SIZE
|
||||
local CBASE = FBASE - CCP_SIZE
|
||||
|
||||
normalrule {
|
||||
name = "addresses_lib",
|
||||
ins = {},
|
||||
outleaves = { "addresses.lib" },
|
||||
commands = {
|
||||
"echo BIOS_SIZE = "..BIOS_SIZE.." > %{outs[1]}",
|
||||
"echo BDOS_SIZE = "..BDOS_SIZE.." >> %{outs[1]}",
|
||||
"echo CCP_SIZE = "..CCP_SIZE.." >> %{outs[1]}",
|
||||
"echo BBASE = "..BBASE.." >> %{outs[1]}",
|
||||
"echo FBASE = "..FBASE.." >> %{outs[1]}",
|
||||
"echo CBASE = "..CBASE.." >> %{outs[1]}",
|
||||
}
|
||||
}
|
||||
|
||||
--- Bootstrapper ------------------------------------------------------------
|
||||
|
||||
-- This is the .APL file which the Brother OS loads. It's responsible for
|
||||
-- remapping the memory, doing some device setup, and loading the BIOS into
|
||||
-- the top of memory.
|
||||
|
||||
zmac {
|
||||
name = "boot_img",
|
||||
srcs = { "./boot.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"+addresses_lib"
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
--- BIOS --------------------------------------------------------------------
|
||||
|
||||
-- The keyboard map.
|
||||
|
||||
normalrule {
|
||||
name = "keytab_inc",
|
||||
ins = { "arch/brotherwp1/utils+mkkeytab" },
|
||||
outleaves = { "keytab.inc" },
|
||||
commands = {
|
||||
"%{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
-- The CP/M BIOS itself.
|
||||
|
||||
zmac {
|
||||
name = "bios_o",
|
||||
srcs = { "./bios.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
"arch/common/utils/deblocker.lib",
|
||||
"+addresses_lib",
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "tty_o",
|
||||
srcs = { "./tty.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "floppy_o",
|
||||
srcs = { "./floppy.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/deblocker.lib",
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "keyboard_o",
|
||||
srcs = { "./keyboard.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"+keytab_inc",
|
||||
},
|
||||
}
|
||||
|
||||
-- This is a 64kB file containing the entire CP/M memory image.
|
||||
|
||||
ld80 {
|
||||
name = "memory_img",
|
||||
address = 0,
|
||||
srcs = {
|
||||
"-P"..string.format("%x", CBASE), "third_party/zcpr1+zcpr",
|
||||
"-P"..string.format("%x", FBASE), "third_party/zsdos+zsdos",
|
||||
"-P"..string.format("%x", BBASE),
|
||||
"+bios_o",
|
||||
"+tty_o",
|
||||
"+floppy_o",
|
||||
"+keyboard_o",
|
||||
}
|
||||
}
|
||||
|
||||
-- We now chop it up to remove the BIOS and the combined CCP/BDOS (which
|
||||
-- go into the system track).
|
||||
|
||||
binslice {
|
||||
name = "bios_img",
|
||||
src = { "+memory_img" },
|
||||
start = BBASE,
|
||||
length = BIOS_SIZE
|
||||
}
|
||||
|
||||
binslice {
|
||||
name = "ccpbdos_img",
|
||||
src = { "+memory_img" },
|
||||
start = CBASE,
|
||||
length = BBASE - CBASE
|
||||
}
|
||||
|
||||
--- Brother file system -----------------------------------------------------
|
||||
|
||||
-- Produces the fake Brother file system image
|
||||
|
||||
zmac {
|
||||
name = "bootfile_img",
|
||||
srcs = { "./fs.z80" },
|
||||
deps = {
|
||||
"+boot_img",
|
||||
"+bios_img",
|
||||
"+ccpbdos_img",
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
--- Disk image --------------------------------------------------------------
|
||||
|
||||
-- Assembles the bootable disk which you can actually run.
|
||||
|
||||
unix2cpm {
|
||||
name = "readme",
|
||||
srcs = { "README.md" }
|
||||
}
|
||||
|
||||
diskimage {
|
||||
name = "diskimage",
|
||||
format = "brother-wp1",
|
||||
bootfile = { "+bootfile_img" },
|
||||
map = {
|
||||
["-readme.txt"] = "+readme",
|
||||
["dump.com"] = "cpmtools+dump",
|
||||
["stat.com"] = "cpmtools+stat",
|
||||
["asm.com"] = "cpmtools+asm",
|
||||
["copy.com"] = "cpmtools+copy",
|
||||
["submit.com"] = "cpmtools+submit",
|
||||
["bbcbasic.com"] = "third_party/bbcbasic+bbcbasic_ADM3A",
|
||||
["camel80.com"] = "third_party/camelforth+camelforth",
|
||||
["qe.com"] = "cpmtools+qe_BROTHER_WP1",
|
||||
["pterm.com"] = "arch/brotherwp1/tools+pterm",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
5
arch/brotherwp1/include/BUILD
Normal file
5
arch/brotherwp1/include/BUILD
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
zmac {
|
||||
name = "pterm",
|
||||
srcs = { "./pterm.z80" },
|
||||
deps = {
|
||||
"arch/brotherwp1+addresses_lib"
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
9
arch/brotherwp1/utils/BUILD
Normal file
9
arch/brotherwp1/utils/BUILD
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_binary(
|
||||
name = "mkkeytab",
|
||||
srcs = [ "mkkeytab.c" ]
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
cprogram {
|
||||
name = "mkkeytab",
|
||||
srcs = { "./mkkeytab.c" }
|
||||
}
|
||||
4
arch/common/utils/BUILD
Normal file
4
arch/common/utils/BUILD
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "build/z80test.lua"
|
||||
|
||||
local deblocker_tests = {
|
||||
"deblocker_calculate_physical",
|
||||
"deblocker_change_block",
|
||||
"deblocker_calculate_buffer_address",
|
||||
"deblocker_capacity",
|
||||
}
|
||||
|
||||
for _, n in pairs(deblocker_tests) do
|
||||
z80test {
|
||||
name = n,
|
||||
srcs = { "./tests/"..n..".z80" },
|
||||
deps = {
|
||||
"./deblocker.lib",
|
||||
"include/cpm.lib"
|
||||
}
|
||||
}
|
||||
end
|
||||
88
arch/kayproii/BUILD
Normal file
88
arch/kayproii/BUILD
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
load("//build:cpm.bzl", "diskimage")
|
||||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
load("//utils:build.bzl", "unix2cpm")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
zmac(
|
||||
name = "boot",
|
||||
srcs = [ "boot.z80" ],
|
||||
relocatable = False
|
||||
)
|
||||
|
||||
zmac(
|
||||
name = "bios",
|
||||
srcs = [
|
||||
"bios.z80",
|
||||
"//arch/kayproii/include:kayproii.lib",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
],
|
||||
)
|
||||
|
||||
# Builds the memory image.
|
||||
ld80(
|
||||
name = "bootfile_mem",
|
||||
objs = {
|
||||
0xe400: [ "//third_party/zcpr1" ],
|
||||
0xec00: [ "//third_party/zsdos" ],
|
||||
0xfa00: [ ":bios" ],
|
||||
}
|
||||
)
|
||||
|
||||
# Repackages the memory image as a boot track. This doesn't include the extra
|
||||
# section of boot image which exists above the directory.
|
||||
genrule(
|
||||
name = "bootfile",
|
||||
srcs = [
|
||||
":boot",
|
||||
":bootfile_mem"
|
||||
],
|
||||
outs = [ "bootfile.img" ],
|
||||
cmd = " && ".join([
|
||||
"dd if=$(location :boot) of=$@ bs=128 count=1 2> /dev/null",
|
||||
"dd if=$(location :bootfile_mem) of=$@ bs=128 seek=1 skip=456 count=16 2> /dev/null",
|
||||
"dd if=$(location :bootfile_mem) of=$@ bs=128 seek=17 skip=472 count=23 2> /dev/null",
|
||||
])
|
||||
)
|
||||
|
||||
unix2cpm(
|
||||
name = "readme",
|
||||
src = "README.md"
|
||||
)
|
||||
|
||||
diskimage(
|
||||
name = "partialimg",
|
||||
format = "kpii",
|
||||
bootfile = ":bootfile",
|
||||
map = {
|
||||
"-readme.txt": ":readme",
|
||||
"dump.com": "//cpmtools:dump",
|
||||
"stat.com": "//cpmtools:stat",
|
||||
"asm.com": "//cpmtools:asm",
|
||||
"copy.com": "//cpmtools:copy",
|
||||
"submit.com": "//cpmtools:submit",
|
||||
"bbcbasic.com": "//third_party/bbcbasic:bbcbasic_ADM3A",
|
||||
"camel80.com": "//third_party/camelforth",
|
||||
"qe.com": "//cpmtools:qe_KAYPROII",
|
||||
},
|
||||
)
|
||||
|
||||
# Patches the special extra bit of BDOS/BIOS into the area above the
|
||||
# directory; yuch.
|
||||
genrule(
|
||||
name = "diskimage",
|
||||
srcs = [
|
||||
":partialimg",
|
||||
":bootfile_mem"
|
||||
],
|
||||
outs = [ "diskimage.img" ],
|
||||
cmd = " && ".join([
|
||||
"cp $(location :partialimg) $@",
|
||||
"chmod +w $@",
|
||||
"truncate -s 204800 $@",
|
||||
"dd if=$(location :bootfile_mem) of=$@ bs=128 seek=56 skip=495 count=9 conv=notrunc 2> /dev/null"
|
||||
])
|
||||
)
|
||||
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "utils/build.lua"
|
||||
|
||||
zmac {
|
||||
name = "boot",
|
||||
srcs = { "./boot.z80" },
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "bios",
|
||||
srcs = { "./bios.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib"
|
||||
},
|
||||
}
|
||||
|
||||
-- Builds the memory image.
|
||||
ld80 {
|
||||
name = "bootfile_mem",
|
||||
srcs = {
|
||||
"-Pe400", "third_party/zcpr1+zcpr",
|
||||
"-Pec00", "third_party/zsdos+zsdos",
|
||||
"-Pfa00", "+bios",
|
||||
}
|
||||
}
|
||||
|
||||
-- Repackages the memory image as a boot track. This doesn't include the extra
|
||||
-- section of boot image which exists above the directory.
|
||||
normalrule {
|
||||
name = "bootfile",
|
||||
ins = {
|
||||
"+boot",
|
||||
"+bootfile_mem"
|
||||
},
|
||||
outleaves = { "bootfile.img" },
|
||||
commands = {
|
||||
"dd if=%{ins[1]} of=%{outs} bs=128 count=1 2> /dev/null",
|
||||
"dd if=%{ins[3]} of=%{outs} bs=128 seek=1 skip=456 count=16 2> /dev/null",
|
||||
"dd if=%{ins[3]} of=%{outs} bs=128 seek=17 skip=472 count=23 2> /dev/null",
|
||||
}
|
||||
}
|
||||
|
||||
diskimage {
|
||||
name = "partialimg",
|
||||
format = "kpii",
|
||||
bootfile = { "arch/kayproii+bootfile" },
|
||||
map = {
|
||||
["dump.com"] = "cpmtools+dump",
|
||||
["stat.com"] = "cpmtools+stat",
|
||||
["asm.com"] = "cpmtools+asm",
|
||||
["copy.com"] = "cpmtools+copy",
|
||||
["submit.com"] = "cpmtools+submit",
|
||||
["bbcbasic.com"] = "third_party/bbcbasic+bbcbasic_ADM3A",
|
||||
["qe.com"] = "cpmtools+qe_KAYPROII",
|
||||
["camel80.com"] = "third_party/camelforth+camelforth",
|
||||
},
|
||||
}
|
||||
|
||||
-- Patches the special extra bit of BDOS/BIOS into the area above the
|
||||
-- directory; yuch.
|
||||
normalrule {
|
||||
name = "diskimage",
|
||||
ins = {
|
||||
"+partialimg",
|
||||
"+bootfile_mem"
|
||||
},
|
||||
outleaves = { "diskimage.img" },
|
||||
commands = {
|
||||
"cp %{ins[1]} %{outs}",
|
||||
"truncate -s 204800 %{outs}",
|
||||
"dd if=%{ins[2]} of=%{outs} bs=128 seek=56 skip=495 count=9 conv=notrunc 2> /dev/null"
|
||||
}
|
||||
}
|
||||
5
arch/kayproii/include/BUILD
Normal file
5
arch/kayproii/include/BUILD
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
||||
87
arch/nc200/BUILD
Normal file
87
arch/nc200/BUILD
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
load("//build:cpm.bzl", "cpm_addresses", "diskimage")
|
||||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
load("//utils:build.bzl", "objectify", "unix2cpm")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
# Memory layout configuration -----------------------------------------------
|
||||
|
||||
# Configure the BIOS size here; this will then emit an addresses.lib file
|
||||
# which contains the position of the BDOS and CCP.
|
||||
|
||||
(cbase, fbase, bbase) = cpm_addresses(
|
||||
name = "addresses",
|
||||
bios_size = 0x0300
|
||||
)
|
||||
|
||||
# Bootstrap -----------------------------------------------------------------
|
||||
|
||||
# The program the NC200 runs on startup.
|
||||
|
||||
zmac(
|
||||
name = "auto",
|
||||
srcs = [
|
||||
"auto.z80",
|
||||
"//arch/nc200/include:nc200.lib",
|
||||
],
|
||||
relocatable = False
|
||||
)
|
||||
|
||||
objectify(
|
||||
name = "auto_inc",
|
||||
src = ":auto"
|
||||
)
|
||||
|
||||
# FAT boot data -------------------------------------------------------------
|
||||
|
||||
[
|
||||
zmac(
|
||||
name = f.replace(".z80", ""),
|
||||
srcs = [
|
||||
f,
|
||||
":auto_inc",
|
||||
]
|
||||
)
|
||||
for f in glob(["boot/*.z80"])
|
||||
]
|
||||
|
||||
# BIOS ----------------------------------------------------------------------
|
||||
|
||||
# The CP/M BIOS itself.
|
||||
|
||||
zmac(
|
||||
name = "bios",
|
||||
srcs = [
|
||||
"bios.z80",
|
||||
"//arch/nc200/include:nc200.lib",
|
||||
"//arch/nc200/include:supervisor.lib",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
":addresses",
|
||||
]
|
||||
)
|
||||
|
||||
# Builds the memory image. This is a 64kB file containing the entire CP/M
|
||||
# memory image, including the supervisor at the bottom.
|
||||
|
||||
ld80(
|
||||
name = "memory_img",
|
||||
address = 0,
|
||||
objs = {
|
||||
0x0000: [ ":boot/startup", ],
|
||||
0x000b: [ ":boot/bpb1", ],
|
||||
0x0038: [ ":boot/sirq", ],
|
||||
0x01fe: [ ":boot/bootsig", ],
|
||||
0x020b: [ ":boot/bpb2", ],
|
||||
0x0400: [ ":boot/fat", "//arch/nc200/supervisor:variables" ],
|
||||
0x1000: [ ":boot/rootdir", "//arch/nc200/supervisor" ],
|
||||
0x1e00: [ ":boot/relauto", ],
|
||||
cbase: [ "//third_party/zcpr1" ],
|
||||
fbase: [ "//third_party/zsdos" ],
|
||||
bbase: [ ":bios" ],
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "utils/build.lua"
|
||||
|
||||
--- Memory layout configuration ------------------------------------------
|
||||
|
||||
-- Configure the BIOS size here; this will then emit an addresses.lib file
|
||||
-- which contains the position of the BDOS and CCP.
|
||||
|
||||
local BIOS_SIZE = 0x0300
|
||||
local BDOS_SIZE = 3584 -- fixed
|
||||
local CCP_SIZE = 2048 -- fixed
|
||||
local CPM_SIZE = BIOS_SIZE + BDOS_SIZE + CCP_SIZE
|
||||
local BBASE = 0x10000 - BIOS_SIZE
|
||||
local FBASE = BBASE - BDOS_SIZE
|
||||
local CBASE = FBASE - CCP_SIZE
|
||||
|
||||
normalrule {
|
||||
name = "addresses_lib",
|
||||
ins = {},
|
||||
outleaves = { "addresses.lib" },
|
||||
commands = {
|
||||
"echo BIOS_SIZE = "..BIOS_SIZE.." > %{outs[1]}",
|
||||
"echo BDOS_SIZE = "..BDOS_SIZE.." >> %{outs[1]}",
|
||||
"echo CCP_SIZE = "..CCP_SIZE.." >> %{outs[1]}",
|
||||
"echo CPM_SIZE = "..CPM_SIZE.." >> %{outs[1]}",
|
||||
"echo BBASE = "..BBASE.." >> %{outs[1]}",
|
||||
"echo FBASE = "..FBASE.." >> %{outs[1]}",
|
||||
"echo CBASE = "..CBASE.." >> %{outs[1]}",
|
||||
}
|
||||
}
|
||||
|
||||
--- Bootstrap ------------------------------------------------------------
|
||||
|
||||
-- The program the NC200 runs on startup.
|
||||
|
||||
zmac {
|
||||
name = "auto",
|
||||
srcs = { "./auto.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib"
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
objectify {
|
||||
name = "auto_inc",
|
||||
srcs = { "+auto" }
|
||||
}
|
||||
|
||||
--- FAT boot data --------------------------------------------------------
|
||||
|
||||
local bootfiles = filenamesof("./boot/*.z80")
|
||||
for _, f in pairs(bootfiles) do
|
||||
local base = basename(f)
|
||||
zmac {
|
||||
name = base,
|
||||
srcs = { f },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"+auto_inc"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
--- BIOS -----------------------------------------------------------------
|
||||
|
||||
-- The CP/M BIOS itself.
|
||||
|
||||
zmac {
|
||||
name = "bios",
|
||||
srcs = { "./bios.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"+addresses_lib",
|
||||
},
|
||||
}
|
||||
|
||||
-- Builds the memory image. This is a 64kB file containing the entire CP/M
|
||||
-- memory image, including the supervisor at the bottom.
|
||||
|
||||
ld80 {
|
||||
name = "memory_img",
|
||||
address = 0,
|
||||
srcs = {
|
||||
"-P0000", "+startup.z80",
|
||||
"-P000b", "+bpb1.z80",
|
||||
"-P0038", "+sirq.z80",
|
||||
"-P01fe", "+bootsig.z80",
|
||||
"-P020b", "+bpb2.z80",
|
||||
"-P0400", "+fat.z80",
|
||||
"arch/nc200/supervisor+variables",
|
||||
"-P1000", "+rootdir.z80",
|
||||
"arch/nc200/supervisor+supervisor",
|
||||
"-P1e00", "+relauto.z80",
|
||||
"-P"..string.format("%x", CBASE), "third_party/zcpr1+zcpr",
|
||||
"-P"..string.format("%x", FBASE), "third_party/zsdos+zsdos",
|
||||
"-P"..string.format("%x", BBASE), "+bios",
|
||||
}
|
||||
}
|
||||
|
||||
-- We now chop it up to remove the supervisor and the CCP/BDOS/BIOS, which go into
|
||||
-- the system tracks.
|
||||
|
||||
binslice {
|
||||
name = "cpm_img",
|
||||
src = { "+memory_img" },
|
||||
start = CBASE,
|
||||
length = CPM_SIZE
|
||||
}
|
||||
|
||||
binslice {
|
||||
name = "supervisor_img",
|
||||
src = { "+memory_img" },
|
||||
start = 0,
|
||||
length = 9*1024
|
||||
}
|
||||
|
||||
-- And combine them into the system track image.
|
||||
|
||||
normalrule {
|
||||
name = "systemtrack_img",
|
||||
ins = {
|
||||
"+supervisor_img",
|
||||
"+cpm_img",
|
||||
},
|
||||
outleaves = { "systemtrack.img" },
|
||||
commands = {
|
||||
"cat %{ins} > %{outs[1]}"
|
||||
}
|
||||
}
|
||||
|
||||
unix2cpm {
|
||||
name = "readme",
|
||||
srcs = { "README.md" }
|
||||
}
|
||||
|
||||
diskimage {
|
||||
name = "diskimage",
|
||||
format = "nc200cpm",
|
||||
bootfile = { "arch/nc200+systemtrack_img" },
|
||||
map = {
|
||||
["dump.com"] = "cpmtools+dump",
|
||||
["stat.com"] = "cpmtools+stat",
|
||||
["asm.com"] = "cpmtools+asm",
|
||||
["copy.com"] = "cpmtools+copy",
|
||||
["submit.com"] = "cpmtools+submit",
|
||||
["bbcbasic.com"] = "third_party/bbcbasic+bbcbasic_ADM3A",
|
||||
["qe.com"] = "cpmtools+qe_NC200",
|
||||
["flash.com"] = "arch/nc200/tools+flash",
|
||||
["flipdisk.com"] = "arch/nc200/tools+flipdisk",
|
||||
["mkfs.com"] = "cpmtools+mkfs",
|
||||
["rawdisk.com"] = "cpmtools+rawdisk",
|
||||
["z8e.com"] = "third_party/z8e+z8e_NC200",
|
||||
["ted.com"] = "third_party/ted+ted_NC200",
|
||||
["camel80.com"] = "third_party/camelforth+camelforth",
|
||||
["-readme.txt"] = "+readme",
|
||||
},
|
||||
}
|
||||
|
||||
5
arch/nc200/include/BUILD
Normal file
5
arch/nc200/include/BUILD
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
||||
45
arch/nc200/supervisor/BUILD
Normal file
45
arch/nc200/supervisor/BUILD
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
genrule(
|
||||
name = "keytab_inc",
|
||||
tools = [ "//arch/nc200/utils:mkkeytab" ],
|
||||
outs = [ "keytab.inc" ],
|
||||
cmd = "$(location //arch/nc200/utils:mkkeytab) > $@"
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "font_inc",
|
||||
tools = [ "//arch/nc200/utils:fontconvert" ],
|
||||
srcs = [ "//utils:6x7font.bdf" ],
|
||||
outs = [ "font.inc" ],
|
||||
cmd = "$(location //arch/nc200/utils:fontconvert) $< > $@"
|
||||
)
|
||||
|
||||
zmac(
|
||||
name = "supervisor",
|
||||
srcs = [
|
||||
"supervisor.z80",
|
||||
"//arch/common/utils:deblocker.lib",
|
||||
"//arch/nc200/include:nc200.lib",
|
||||
"//arch/nc200/include:supervisor.lib",
|
||||
"//arch/nc200:addresses",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
":keytab_inc",
|
||||
] + glob(["*.inc"]),
|
||||
)
|
||||
|
||||
zmac(
|
||||
name = "variables",
|
||||
srcs = [
|
||||
"variables.z80",
|
||||
"//arch/nc200/include:nc200.lib",
|
||||
"//arch/nc200/include:supervisor.lib",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
":font_inc",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
include "third_party/zmac/build.lua"
|
||||
|
||||
normalrule {
|
||||
name = "keytab_inc",
|
||||
ins = { "arch/nc200/utils+mkkeytab" },
|
||||
outleaves = { "keytab.inc" },
|
||||
commands = {
|
||||
"%{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
normalrule {
|
||||
name = "font_inc",
|
||||
ins = {
|
||||
"arch/nc200/utils+fontconvert",
|
||||
"utils/6x7font.bdf"
|
||||
},
|
||||
outleaves = { "font.inc" },
|
||||
commands = {
|
||||
"%{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "supervisor",
|
||||
srcs = { "./supervisor.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"arch/common/utils/deblocker.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
"arch/nc200/include/*.lib",
|
||||
"arch/nc200+addresses_lib",
|
||||
"./*.inc",
|
||||
"+keytab_inc",
|
||||
"+font_inc",
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "variables",
|
||||
srcs = { "./variables.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"arch/nc200/include/*.lib",
|
||||
"+font_inc",
|
||||
},
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
include "cpmtools/libcuss/build.lua"
|
||||
|
||||
ackprogram {
|
||||
name = "flash",
|
||||
srcs = {
|
||||
"./flash.c",
|
||||
"./pcmcia-tools.s"
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "flipdisk_o",
|
||||
srcs = { "./flipdisk.z80" },
|
||||
deps = { "arch/nc200+addresses_lib" }
|
||||
}
|
||||
|
||||
ld80 {
|
||||
name = "flipdisk",
|
||||
address = 0x100,
|
||||
srcs = {
|
||||
"-P0100",
|
||||
"+flipdisk_o"
|
||||
}
|
||||
}
|
||||
|
||||
15
arch/nc200/utils/BUILD
Normal file
15
arch/nc200/utils/BUILD
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_binary(
|
||||
name = "fontconvert",
|
||||
srcs = [ "fontconvert.c" ],
|
||||
deps = [
|
||||
"//utils:libbdf"
|
||||
]
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "mkkeytab",
|
||||
srcs = [ "mkkeytab.c" ]
|
||||
)
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
cprogram {
|
||||
name = "mkkeytab",
|
||||
srcs = { "./mkkeytab.c" }
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = "fontconvert",
|
||||
srcs = { "./fontconvert.c" },
|
||||
deps = {
|
||||
"utils+libbdf"
|
||||
},
|
||||
}
|
||||
|
|
@ -68,3 +68,6 @@ int main(int argc, const char* argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: ts=4 sw=4 et
|
||||
|
||||
|
|
|
|||
203
arch/wp2450ds/BUILD
Normal file
203
arch/wp2450ds/BUILD
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
load("//build:cpm.bzl", "binslice", "cpm_addresses", "diskimage")
|
||||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
load("//utils:build.bzl", "objectify", "unix2cpm")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
# Memory layout configuration -----------------------------------------------
|
||||
|
||||
# Configure the BIOS size here; this will then emit an addresses.lib file
|
||||
# which contains the position of the BDOS and CCP.
|
||||
|
||||
(cbase, fbase, bbase) = cpm_addresses(
|
||||
name = "addresses",
|
||||
bios_size = 0x0f00
|
||||
)
|
||||
|
||||
# Generated tables ----------------------------------------------------------
|
||||
|
||||
# Font and keyboard table.
|
||||
|
||||
genrule(
|
||||
name = "keytab_inc",
|
||||
tools = [ "//arch/wp2450ds/utils:mkkeytab" ],
|
||||
outs = [ "keytab.inc" ],
|
||||
cmd = "$(location //arch/wp2450ds/utils:mkkeytab) > $@"
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "font_inc",
|
||||
tools = [ "//arch/wp2450ds/utils:fontconvert" ],
|
||||
srcs = [ "//utils:6x7font.bdf" ],
|
||||
outs = [ "font.inc" ],
|
||||
cmd = "$(location //arch/wp2450ds/utils:fontconvert) $< > $@"
|
||||
)
|
||||
|
||||
# Libraries -----------------------------------------------------------------
|
||||
|
||||
# These may be used by both the BIOS proper and the bootstrap program.
|
||||
|
||||
zmac(
|
||||
name = "tty_o",
|
||||
srcs = [
|
||||
"tty.z80",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
"//arch/common/utils:tty.lib",
|
||||
"//arch/common/utils:print.lib",
|
||||
"//arch/wp2450ds/include:wp2450ds.lib",
|
||||
":font_inc"
|
||||
],
|
||||
)
|
||||
|
||||
zmac(
|
||||
name = "upd765_o",
|
||||
srcs = [
|
||||
"upd765.z80",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
"//arch/common/utils:upd765.lib",
|
||||
"//arch/common/utils:deblocker.lib",
|
||||
"//arch/wp2450ds/include:wp2450ds.lib",
|
||||
],
|
||||
)
|
||||
|
||||
zmac(
|
||||
name = "keyboard_o",
|
||||
srcs = [
|
||||
"keyboard.z80",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
"//arch/wp2450ds/include:wp2450ds.lib",
|
||||
":keytab_inc",
|
||||
]
|
||||
)
|
||||
|
||||
# Bootstrapper --------------------------------------------------------------
|
||||
|
||||
# This is the .APL file which the Brother OS loads. It's responsible for
|
||||
# remapping the memory, doing some device setup, and loading the BIOS into
|
||||
# the top of memory.
|
||||
|
||||
zmac(
|
||||
name = "boot_o",
|
||||
srcs = [
|
||||
"boot.z80",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
"//arch/wp2450ds/include:wp2450ds.lib",
|
||||
":addresses",
|
||||
],
|
||||
)
|
||||
|
||||
ld80(
|
||||
name = "boot_img",
|
||||
address = 0x5000,
|
||||
objs = {
|
||||
0x5000: [ ":boot_o", ":upd765_o" ]
|
||||
}
|
||||
)
|
||||
|
||||
# BIOS ----------------------------------------------------------------------
|
||||
|
||||
# The CP/M BIOS itself.
|
||||
|
||||
zmac(
|
||||
name = "bios_o",
|
||||
srcs = [
|
||||
"bios.z80",
|
||||
"//include:cpm.lib",
|
||||
"//include:cpmish.lib",
|
||||
"//include:z180.lib",
|
||||
"//arch/wp2450ds/include:wp2450ds.lib",
|
||||
":addresses",
|
||||
],
|
||||
)
|
||||
|
||||
# This is a 64kB file containing the entire CP/M memory image.
|
||||
|
||||
ld80(
|
||||
name = "memory_img",
|
||||
address = 0,
|
||||
objs = {
|
||||
cbase: [ "//third_party/zcpr1" ],
|
||||
fbase: [ "//third_party/zsdos" ],
|
||||
bbase: [
|
||||
":bios_o",
|
||||
":upd765_o",
|
||||
":tty_o",
|
||||
":keyboard_o",
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# We now chop it up to remove the BIOS and the combined CCP/BDOS (which
|
||||
# go into the system track).
|
||||
|
||||
binslice(
|
||||
name = "bios_img",
|
||||
src = ":memory_img",
|
||||
start = bbase,
|
||||
length = 0x10000 - bbase
|
||||
)
|
||||
|
||||
binslice(
|
||||
name = "systemtrack_img",
|
||||
src = ":memory_img",
|
||||
start = cbase,
|
||||
length = bbase - cbase
|
||||
)
|
||||
|
||||
# FAT file system -----------------------------------------------------------
|
||||
|
||||
# Produces the FAT bit of the disk image.
|
||||
|
||||
zmac(
|
||||
name = "bootfile_img",
|
||||
srcs = [
|
||||
"fat.z80",
|
||||
":boot_img",
|
||||
":bios_img",
|
||||
":systemtrack_img",
|
||||
],
|
||||
relocatable = False
|
||||
)
|
||||
|
||||
# Disk image ----------------------------------------------------------------
|
||||
|
||||
# Assembles the bootable disk which you can actually run.
|
||||
|
||||
unix2cpm(
|
||||
name = "readme",
|
||||
src = "README.md"
|
||||
)
|
||||
|
||||
diskimage(
|
||||
name = "diskimage",
|
||||
format = "brother-wp2450ds",
|
||||
bootfile = ":bootfile_img",
|
||||
map = {
|
||||
"-readme.txt": ":readme",
|
||||
"asm.com": "//cpmtools:asm",
|
||||
"bbcbasic.com": "//third_party/bbcbasic:bbcbasic_ADM3A",
|
||||
"camel80.com": "//third_party/camelforth",
|
||||
"copy.com": "//cpmtools:copy",
|
||||
"mkfs.com": "//cpmtools:mkfs",
|
||||
"rawdisk.com": "//cpmtools:rawdisk",
|
||||
"dump.com": "//cpmtools:dump",
|
||||
"qe.com": "//cpmtools:qe_BROTHER_WP2450DS",
|
||||
"ted.com": "//third_party/ted:ted_WP2450DS",
|
||||
"z8e.com": "//third_party/z8e:z8e_WP2450DS",
|
||||
"stat.com": "//cpmtools:stat",
|
||||
"submit.com": "//cpmtools:submit",
|
||||
"startrek.com": "//third_party/startrek",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,216 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "utils/build.lua"
|
||||
|
||||
--- Memory layout configuration ---------------------------------------------
|
||||
|
||||
-- Configure the BIOS size here; this will then emit an addresses.lib file
|
||||
-- which contains the position of the BDOS and CCP.
|
||||
|
||||
local BIOS_SIZE = 0x0f00
|
||||
local BDOS_SIZE = 3584 -- fixed
|
||||
local CCP_SIZE = 2048 -- fixed
|
||||
local BBASE = 0x10000 - BIOS_SIZE
|
||||
local FBASE = BBASE - BDOS_SIZE
|
||||
local CBASE = FBASE - CCP_SIZE
|
||||
|
||||
normalrule {
|
||||
name = "addresses_lib",
|
||||
ins = {},
|
||||
outleaves = { "addresses.lib" },
|
||||
commands = {
|
||||
"echo BIOS_SIZE = "..BIOS_SIZE.." > %{outs[1]}",
|
||||
"echo BDOS_SIZE = "..BDOS_SIZE.." >> %{outs[1]}",
|
||||
"echo CCP_SIZE = "..CCP_SIZE.." >> %{outs[1]}",
|
||||
"echo BBASE = "..BBASE.." >> %{outs[1]}",
|
||||
"echo FBASE = "..FBASE.." >> %{outs[1]}",
|
||||
"echo CBASE = "..CBASE.." >> %{outs[1]}",
|
||||
}
|
||||
}
|
||||
|
||||
--- Generated tables --------------------------------------------------------
|
||||
|
||||
-- Font and keyboard table.
|
||||
|
||||
normalrule {
|
||||
name = "font_inc",
|
||||
ins = {
|
||||
"arch/wp2450ds/utils+fontconvert",
|
||||
"utils/6x7font.bdf",
|
||||
},
|
||||
outleaves = { "font.inc" },
|
||||
commands = {
|
||||
"%{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
normalrule {
|
||||
name = "keytab_inc",
|
||||
ins = { "arch/wp2450ds/utils+mkkeytab" },
|
||||
outleaves = { "keytab.inc" },
|
||||
commands = {
|
||||
"%{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
--- Libraries ---------------------------------------------------------------
|
||||
|
||||
-- These may be used by both the BIOS proper and the bootstrap program.
|
||||
|
||||
zmac {
|
||||
name = "tty_o",
|
||||
srcs = { "./tty.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
"+font_inc"
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "upd765_o",
|
||||
srcs = { "./upd765.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/upd765.lib",
|
||||
"arch/common/utils/deblocker.lib",
|
||||
},
|
||||
}
|
||||
|
||||
zmac {
|
||||
name = "keyboard_o",
|
||||
srcs = { "./keyboard.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"+keytab_inc",
|
||||
},
|
||||
}
|
||||
|
||||
--- Bootstrapper ------------------------------------------------------------
|
||||
|
||||
-- This is the .APL file which the Brother OS loads. It's responsible for
|
||||
-- remapping the memory, doing some device setup, and loading the BIOS into
|
||||
-- the top of memory.
|
||||
|
||||
zmac {
|
||||
name = "boot_o",
|
||||
srcs = { "./boot.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/upd765.lib",
|
||||
"arch/common/utils/deblocker.lib",
|
||||
"+addresses_lib"
|
||||
},
|
||||
}
|
||||
|
||||
ld80 {
|
||||
name = "boot_img",
|
||||
address = 0x5000,
|
||||
srcs = {
|
||||
"-P5000",
|
||||
"+boot_o",
|
||||
"+upd765_o",
|
||||
}
|
||||
}
|
||||
|
||||
--- BIOS --------------------------------------------------------------------
|
||||
|
||||
-- The CP/M BIOS itself.
|
||||
|
||||
zmac {
|
||||
name = "bios_o",
|
||||
srcs = { "./bios.z80" },
|
||||
deps = {
|
||||
"include/*.lib",
|
||||
"./include/*.lib",
|
||||
"arch/common/utils/tty.lib",
|
||||
"arch/common/utils/upd765.lib",
|
||||
"arch/common/utils/deblocker.lib",
|
||||
"+font_inc",
|
||||
"+addresses_lib",
|
||||
},
|
||||
}
|
||||
|
||||
-- This is a 64kB file containing the entire CP/M memory image.
|
||||
|
||||
ld80 {
|
||||
name = "memory_img",
|
||||
address = 0,
|
||||
srcs = {
|
||||
"-P"..string.format("%x", CBASE), "third_party/zcpr1+zcpr",
|
||||
"-P"..string.format("%x", FBASE), "third_party/zsdos+zsdos",
|
||||
"-P"..string.format("%x", BBASE),
|
||||
"+bios_o",
|
||||
"+upd765_o",
|
||||
"+tty_o",
|
||||
"+keyboard_o",
|
||||
}
|
||||
}
|
||||
|
||||
-- We now chop it up to remove the BIOS and the combined CCP/BDOS (which
|
||||
-- go into the system track).
|
||||
|
||||
binslice {
|
||||
name = "bios_img",
|
||||
src = { "+memory_img" },
|
||||
start = BBASE,
|
||||
length = BIOS_SIZE
|
||||
}
|
||||
|
||||
binslice {
|
||||
name = "systemtrack_img",
|
||||
src = { "+memory_img" },
|
||||
start = CBASE,
|
||||
length = BBASE - CBASE
|
||||
}
|
||||
|
||||
--- FAT file system ---------------------------------------------------------
|
||||
|
||||
-- Produces the FAT bit of the disk image.
|
||||
|
||||
zmac {
|
||||
name = "bootfile_img",
|
||||
srcs = { "./fat.z80" },
|
||||
deps = {
|
||||
"+boot_img",
|
||||
"+bios_img",
|
||||
"+systemtrack_img"
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
--- Disk image --------------------------------------------------------------
|
||||
|
||||
-- Assembles the bootable disk which you can actually run.
|
||||
|
||||
unix2cpm {
|
||||
name = "readme",
|
||||
srcs = { "README.md" }
|
||||
}
|
||||
|
||||
diskimage {
|
||||
name = "diskimage",
|
||||
format = "brother-wp2450ds",
|
||||
bootfile = { "+bootfile_img" },
|
||||
map = {
|
||||
["asm.com"] = "cpmtools+asm",
|
||||
["copy.com"] = "cpmtools+copy",
|
||||
["dump.com"] = "cpmtools+dump",
|
||||
["mkfs.com"] = "cpmtools+mkfs",
|
||||
["rawdisk.com"] = "cpmtools+rawdisk",
|
||||
["stat.com"] = "cpmtools+stat",
|
||||
["submit.com"] = "cpmtools+submit",
|
||||
["-readme.txt"] = "+readme",
|
||||
["bbcbasic.com"] = "third_party/bbcbasic+bbcbasic_ADM3A",
|
||||
["qe.com"] = "cpmtools+qe_BROTHER_WP2450DS",
|
||||
["z8e.com"] = "third_party/z8e+z8e_WP2450DS",
|
||||
["ted.com"] = "third_party/ted+ted_WP2450DS",
|
||||
["camel80.com"] = "third_party/camelforth+camelforth",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
5
arch/wp2450ds/include/BUILD
Normal file
5
arch/wp2450ds/include/BUILD
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
||||
15
arch/wp2450ds/utils/BUILD
Normal file
15
arch/wp2450ds/utils/BUILD
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_binary(
|
||||
name = "fontconvert",
|
||||
srcs = [ "fontconvert.c" ],
|
||||
deps = [
|
||||
"//utils:libbdf"
|
||||
]
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "mkkeytab",
|
||||
srcs = [ "mkkeytab.c" ]
|
||||
)
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
cprogram {
|
||||
name = "mkkeytab",
|
||||
srcs = { "./mkkeytab.c" }
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = "fontconvert",
|
||||
srcs = { "./fontconvert.c" },
|
||||
deps = { "utils+libbdf" },
|
||||
}
|
||||
|
|
@ -54,3 +54,5 @@ int main(int argc, const char* argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
// vim: ts=4 sw=4 et
|
||||
|
||||
|
|
|
|||
16
build.lua
16
build.lua
|
|
@ -1,16 +0,0 @@
|
|||
vars.cflags = { "-g", "-Og" }
|
||||
vars.ldflags = { "-lm" }
|
||||
vars.cpmcflags = { "-O6" }
|
||||
vars.cpmldflags = {}
|
||||
|
||||
installable {
|
||||
name = "all",
|
||||
map = {
|
||||
["emu"] = "utils/emu+emu",
|
||||
["nc200.img"] = "arch/nc200+diskimage",
|
||||
["kayproii.img"] = "arch/kayproii+diskimage",
|
||||
["brotherop2.img"] = "arch/brotherop2+diskimage",
|
||||
["wp2450ds.img"] = "arch/wp2450ds+diskimage",
|
||||
["brotherwp1.img"] = "arch/brotherwp1+diskimage",
|
||||
}
|
||||
}
|
||||
0
build/BUILD
Normal file
0
build/BUILD
Normal file
127
build/ack.bzl
Normal file
127
build/ack.bzl
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
def _removeextension(s):
|
||||
i = s.rindex(".")
|
||||
return s[:i]
|
||||
|
||||
def _compile_ack_files(ctx, srcfiles, headers):
|
||||
ofiles = []
|
||||
for src in srcfiles:
|
||||
n = src.basename[:src.basename.rindex(".")]
|
||||
o = ctx.actions.declare_file(ctx.label.name + "/" + n + ".o")
|
||||
h = [ header.dirname for header in headers ]
|
||||
|
||||
args = ctx.actions.args()
|
||||
args.add("-m" + ctx.attr.arch)
|
||||
args.add_all(ctx.attr.cflags)
|
||||
args.add_all(h, format_each="-I%s")
|
||||
args.add("-c")
|
||||
args.add("-o", o)
|
||||
args.add(src)
|
||||
|
||||
ctx.actions.run(
|
||||
mnemonic = "AckCompile",
|
||||
executable = "/usr/local/bin/ack",
|
||||
arguments = [args],
|
||||
inputs = [src] + headers,
|
||||
outputs = [o]
|
||||
)
|
||||
|
||||
ofiles += [o]
|
||||
|
||||
return ofiles
|
||||
|
||||
AckLibrary = provider(
|
||||
"Ack Library fields",
|
||||
fields = {
|
||||
"public_headers": "depset of header Files from transitive dependencies.",
|
||||
"files_to_link": "depset of Files from compilation.",
|
||||
}
|
||||
)
|
||||
|
||||
def _ack_library_impl(ctx):
|
||||
sources = [f for f in ctx.files.srcs if f.extension == "c"]
|
||||
private_headers = [f for f in ctx.files.srcs if f.extension == "h"]
|
||||
public_headers = ctx.files.hdrs + [dep[AckLibrary].public_headers for dep in ctx.attr.deps]
|
||||
|
||||
ofiles = _compile_ack_files(ctx, sources, private_headers + public_headers)
|
||||
|
||||
output_file = ctx.actions.declare_file(ctx.label.name + ".a")
|
||||
|
||||
args = ctx.actions.args()
|
||||
args.add("qc")
|
||||
args.add(output_file)
|
||||
args.add_all(ofiles)
|
||||
|
||||
ctx.actions.run(
|
||||
mnemonic = "AckLibrary",
|
||||
executable = "/usr/local/bin/aal",
|
||||
arguments = [args],
|
||||
inputs = ofiles,
|
||||
outputs = [output_file],
|
||||
)
|
||||
|
||||
return [
|
||||
AckLibrary(
|
||||
public_headers = depset(public_headers),
|
||||
files_to_link = depset(
|
||||
[output_file],
|
||||
transitive = [
|
||||
dep[AckLibrary].files_to_link for dep in ctx.attr.deps
|
||||
],
|
||||
),
|
||||
),
|
||||
DefaultInfo(files = depset([output_file])),
|
||||
]
|
||||
|
||||
ack_library = rule(
|
||||
implementation = _ack_library_impl,
|
||||
attrs = {
|
||||
"srcs": attr.label_list(allow_files = True),
|
||||
"cflags": attr.string_list(),
|
||||
"arch": attr.string(default = "cpm"),
|
||||
"deps": attr.label_list(providers = [AckLibrary]),
|
||||
"hdrs": attr.label_list(allow_files = True),
|
||||
}
|
||||
)
|
||||
|
||||
def _ack_binary_impl(ctx):
|
||||
sources = [f for f in ctx.files.srcs if f.extension == ".c"]
|
||||
private_headers = [f for f in ctx.files.srcs if f.extension == ".h"]
|
||||
public_headers = [f for dep in ctx.attr.deps for f in dep[AckLibrary].public_headers.to_list()]
|
||||
files_to_link = [f for dep in ctx.attr.deps for f in dep[AckLibrary].files_to_link.to_list()]
|
||||
|
||||
ofiles = _compile_ack_files(ctx, ctx.files.srcs, private_headers + public_headers)
|
||||
|
||||
output_file = ctx.actions.declare_file(ctx.label.name + ".exe")
|
||||
|
||||
args = ctx.actions.args()
|
||||
args.add("-m" + ctx.attr.arch)
|
||||
args.add("-." + ctx.attr.lang)
|
||||
args.add("-o", output_file)
|
||||
args.add_all(ofiles)
|
||||
args.add_all(files_to_link)
|
||||
|
||||
ctx.actions.run(
|
||||
mnemonic = "AckBinary",
|
||||
executable = "/usr/local/bin/ack",
|
||||
arguments = [args],
|
||||
inputs = ofiles + files_to_link,
|
||||
outputs = [output_file],
|
||||
)
|
||||
|
||||
return [
|
||||
DefaultInfo(files = depset([output_file])),
|
||||
]
|
||||
|
||||
ack_binary = rule(
|
||||
implementation = _ack_binary_impl,
|
||||
attrs = {
|
||||
"srcs": attr.label_list(allow_files = True),
|
||||
"cflags": attr.string_list(),
|
||||
"arch": attr.string(default = "cpm"),
|
||||
"deps": attr.label_list(providers = [AckLibrary]),
|
||||
"lang": attr.string(default = "c"),
|
||||
}
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
|
|
@ -1,951 +0,0 @@
|
|||
-- Targets:
|
||||
--
|
||||
-- {
|
||||
-- fullname = full name of target
|
||||
-- dir = target's build directory
|
||||
-- outs = target's object files
|
||||
-- is = { set of rule types which made the target }
|
||||
-- }
|
||||
|
||||
local emitter = {}
|
||||
local rules = {}
|
||||
local targets = {}
|
||||
local buildfiles = {}
|
||||
local globals
|
||||
local cwd = "."
|
||||
local vars = {}
|
||||
local parente = {}
|
||||
local loadingstack = {}
|
||||
|
||||
local PWD = os.getenv("PWD")
|
||||
|
||||
-- Forward references
|
||||
local loadtarget
|
||||
|
||||
-- Posix replacement
|
||||
|
||||
local function access(filename, mode)
|
||||
local fp = io.open(filename, mode)
|
||||
if not fp then
|
||||
return false
|
||||
end
|
||||
fp:close()
|
||||
return true
|
||||
end
|
||||
|
||||
local function glob(path)
|
||||
local _, _, lhs, rhs = path:find("(.*)/([^/]*)$")
|
||||
if lhs:find("[*?]") then
|
||||
error("directory part of glob may not contain wildcards")
|
||||
end
|
||||
if not rhs:find("[*?]") then
|
||||
return {path}
|
||||
end
|
||||
|
||||
local fp = io.popen("find '"..lhs.."' -name '"..rhs.."' -type f 2> /dev/null", "r")
|
||||
local files = {}
|
||||
for f in fp:lines() do
|
||||
files[#files+1] = f
|
||||
end
|
||||
fp:close()
|
||||
return files
|
||||
end
|
||||
|
||||
local function print(...)
|
||||
local function print_no_nl(list)
|
||||
for _, s in ipairs(list) do
|
||||
if (type(s) == "table") then
|
||||
io.stderr:write("{")
|
||||
for k, v in pairs(s) do
|
||||
print_no_nl({k})
|
||||
io.stderr:write("=")
|
||||
print_no_nl({v})
|
||||
io.stderr:write(" ")
|
||||
end
|
||||
io.stderr:write("}")
|
||||
else
|
||||
io.stderr:write(tostring(s))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print_no_nl({...})
|
||||
io.stderr:write("\n")
|
||||
end
|
||||
|
||||
local function assertString(s, i)
|
||||
if (type(s) ~= "string") then
|
||||
error(string.format("parameter %d must be a string", i))
|
||||
end
|
||||
end
|
||||
|
||||
local function concat(...)
|
||||
local r = {}
|
||||
|
||||
local function process(list)
|
||||
for _, t in ipairs(list) do
|
||||
if (type(t) == "table") and not t.is then
|
||||
process(t)
|
||||
else
|
||||
r[#r+1] = t
|
||||
end
|
||||
end
|
||||
end
|
||||
process({...})
|
||||
|
||||
return r
|
||||
end
|
||||
|
||||
-- Test table membership (crudely).
|
||||
local function contains(needle, haystack)
|
||||
for _, k in ipairs(haystack) do
|
||||
if (k == needle) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function inherit(high, low)
|
||||
local o = {}
|
||||
setmetatable(o, {
|
||||
__index = function(self, k)
|
||||
local x = high[k]
|
||||
if x then
|
||||
return x
|
||||
end
|
||||
return low[k]
|
||||
end
|
||||
})
|
||||
for k, v in pairs(high) do
|
||||
local _, _, kk = k:find("^%+(.*)$")
|
||||
if kk then
|
||||
o[kk] = concat(low[kk], v)
|
||||
end
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
local function asstring(o)
|
||||
local t = type(o)
|
||||
if (t == "nil") then
|
||||
return ""
|
||||
elseif (t == "string") then
|
||||
return o
|
||||
elseif (t == "number") then
|
||||
return o
|
||||
elseif (t == "table") then
|
||||
if o.is then
|
||||
return asstring(o.outs)
|
||||
else
|
||||
local s = {}
|
||||
for _, v in pairs(o) do
|
||||
s[#s+1] = asstring(v)
|
||||
end
|
||||
return table.concat(s, " ")
|
||||
end
|
||||
else
|
||||
error(string.format("can't turn values of type '%s' into strings", t))
|
||||
end
|
||||
end
|
||||
|
||||
local function concatpath(...)
|
||||
local p = table.concat({...}, "/")
|
||||
return (p:gsub("/+", "/"):gsub("^%./", ""):gsub("/%./", "/"))
|
||||
end
|
||||
|
||||
-- Returns a list of the targets within the given collection; the keys of any
|
||||
-- keyed items are lost. Lists and wildcards are expanded.
|
||||
local function targetsof(...)
|
||||
local o = {}
|
||||
|
||||
local function process(items)
|
||||
for _, item in pairs(items) do
|
||||
if (type(item) == "table") then
|
||||
if item.is then
|
||||
-- This is a target.
|
||||
o[#o+1] = item
|
||||
else
|
||||
-- This is a list.
|
||||
process(item)
|
||||
end
|
||||
elseif (type(item) == "string") then
|
||||
-- Filename!
|
||||
if item:find("^%+") then
|
||||
item = cwd..item
|
||||
elseif item:find("^%./") then
|
||||
item = concatpath(cwd, item)
|
||||
end
|
||||
o[#o+1] = loadtarget(item)
|
||||
else
|
||||
error(string.format("member of target list is not a string or a target"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
process({...})
|
||||
return o
|
||||
end
|
||||
|
||||
local function filenamesof(...)
|
||||
local targets = targetsof(...)
|
||||
|
||||
local f = {}
|
||||
for _, r in ipairs(targets) do
|
||||
if (type(r) == "table") and r.is then
|
||||
if r.outs then
|
||||
for _, o in ipairs(r.outs) do
|
||||
f[#f+1] = o
|
||||
end
|
||||
end
|
||||
elseif (type(r) == "string") then
|
||||
f[#f+1] = r
|
||||
else
|
||||
error(string.format("list of targets contains a %s which isn't a target",
|
||||
type(r)))
|
||||
end
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
local function targetnamesof(...)
|
||||
local targets = targetsof(...)
|
||||
|
||||
local f
|
||||
for _, r in pairs(targets) do
|
||||
if (type(r) == "table") and r.is then
|
||||
f[#f+1] = r.fullname
|
||||
elseif (type(r) == "string") then
|
||||
f[#f+1] = r
|
||||
else
|
||||
error(string.format("list of targets contains a %s which isn't a target",
|
||||
type(r)))
|
||||
end
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
local function dotocollection(files, callback)
|
||||
if (#files == 1) and (type(files[1]) == "string") then
|
||||
return callback(files[1])
|
||||
end
|
||||
|
||||
local o = {}
|
||||
local function process(files)
|
||||
for _, s in ipairs(files) do
|
||||
if (type(s) == "table") then
|
||||
if s.is then
|
||||
error("passed target to a filename manipulation function")
|
||||
else
|
||||
process(s)
|
||||
end
|
||||
else
|
||||
local b = callback(s)
|
||||
if (b ~= "") then
|
||||
o[#o+1] = b
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
process(files)
|
||||
return o
|
||||
end
|
||||
|
||||
|
||||
local function abspath(...)
|
||||
return dotocollection({...},
|
||||
function(filename)
|
||||
assertString(filename, 1)
|
||||
if not filename:find("^[/$]") then
|
||||
filename = concatpath(PWD, filename)
|
||||
end
|
||||
return filename
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
local function basename(...)
|
||||
return dotocollection({...},
|
||||
function(filename)
|
||||
assertString(filename, 1)
|
||||
local _, _, b = filename:find("^.*/([^/]*)$")
|
||||
if not b then
|
||||
return filename
|
||||
end
|
||||
return b
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
local function dirname(...)
|
||||
return dotocollection({...},
|
||||
function(filename)
|
||||
assertString(filename, 1)
|
||||
local _, _, b = filename:find("^(.*)/[^/]*$")
|
||||
if not b then
|
||||
return ""
|
||||
end
|
||||
return b
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function replace(files, pattern, repl)
|
||||
return dotocollection({files},
|
||||
function(filename)
|
||||
return filename:gsub(pattern, repl)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function fpairs(...)
|
||||
return ipairs(filenamesof(...))
|
||||
end
|
||||
|
||||
local function matching(collection, pattern)
|
||||
local o = {}
|
||||
dotocollection(collection,
|
||||
function(filename)
|
||||
if filename:find(pattern) then
|
||||
o[#o+1] = filename
|
||||
end
|
||||
end
|
||||
)
|
||||
return o
|
||||
end
|
||||
|
||||
-- Selects all targets containing at least one output file that matches
|
||||
-- the pattern (or all, if the pattern is nil).
|
||||
local function selectof(targets, pattern)
|
||||
local targets = targetsof(targets)
|
||||
local o = {}
|
||||
for k, v in pairs(targets) do
|
||||
if v.is and v.outs then
|
||||
local matches = false
|
||||
for _, f in pairs(v.outs) do
|
||||
if f:find(pattern) then
|
||||
matches = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if matches then
|
||||
o[#o+1] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
local function uniquify(...)
|
||||
local s = {}
|
||||
return dotocollection({...},
|
||||
function(filename)
|
||||
if not s[filename] then
|
||||
s[filename] = true
|
||||
return filename
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function startswith(needle, haystack)
|
||||
return haystack:sub(1, #needle) == needle
|
||||
end
|
||||
|
||||
local function emit(...)
|
||||
local n = select("#", ...)
|
||||
local args = {...}
|
||||
|
||||
for i=1, n do
|
||||
local s = asstring(args[i])
|
||||
io.stdout:write(s)
|
||||
if not s:find("\n$") then
|
||||
io.stdout:write(" ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function templateexpand(list, vars)
|
||||
vars = inherit(vars, globals)
|
||||
|
||||
local o = {}
|
||||
for _, s in ipairs(list) do
|
||||
o[#o+1] = s:gsub("%%%b{}",
|
||||
function(expr)
|
||||
expr = expr:sub(3, -2)
|
||||
local chunk, e = loadstring("return ("..expr..")", expr)
|
||||
if e then
|
||||
error(string.format("error evaluating expression: %s", e))
|
||||
end
|
||||
setfenv(chunk, vars)
|
||||
local value = chunk()
|
||||
if (value == nil) then
|
||||
error(string.format("template expression '%s' expands to nil (probably an undefined variable)", expr))
|
||||
end
|
||||
return asstring(value)
|
||||
end
|
||||
)
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
local function loadbuildfile(filename)
|
||||
if contains(filename, loadingstack) then
|
||||
error(string.format("build file cycle; '%s' refers to itself indirectly; stack is: %s %s",
|
||||
filename, asstring(loadingstack), filename))
|
||||
end
|
||||
|
||||
loadingstack[#loadingstack+1] = filename
|
||||
if not buildfiles[filename] then
|
||||
buildfiles[filename] = true
|
||||
|
||||
local fp, data, chunk, e
|
||||
io.stderr:write("loading ", filename, "\n")
|
||||
fp, e = io.open(filename)
|
||||
if not e then
|
||||
data, e = fp:read("*a")
|
||||
fp:close()
|
||||
if not e then
|
||||
local thisglobals = {}
|
||||
thisglobals._G = thisglobals
|
||||
setmetatable(thisglobals, {__index = globals})
|
||||
chunk, e = loadstring(data, "@"..filename)
|
||||
if not e then
|
||||
setfenv(chunk, thisglobals)
|
||||
end
|
||||
end
|
||||
end
|
||||
if e then
|
||||
error(string.format("couldn't load '%s': %s", filename, e))
|
||||
end
|
||||
|
||||
local oldcwd = cwd
|
||||
cwd = dirname(filename)
|
||||
chunk()
|
||||
cwd = oldcwd
|
||||
end
|
||||
loadingstack[#loadingstack] = nil
|
||||
end
|
||||
|
||||
local function loadbuildfilefor(filepart, targetpart)
|
||||
local normalname = concatpath(filepart, "/build.lua")
|
||||
if access(normalname, "r") then
|
||||
loadbuildfile(normalname)
|
||||
return
|
||||
end
|
||||
|
||||
local extendedname = concatpath(filepart, "/build-"..targetpart..".lua")
|
||||
if access(extendedname, "r") then
|
||||
loadbuildfile(extendedname)
|
||||
return
|
||||
end
|
||||
|
||||
error(string.format("could not access either '%s' or '%s'", normalname, extendedname))
|
||||
end
|
||||
|
||||
loadtarget = function(targetname)
|
||||
if targets[targetname] then
|
||||
return targets[targetname]
|
||||
end
|
||||
|
||||
local target
|
||||
if not targetname:find("%+") then
|
||||
local files
|
||||
if targetname:find("[?*]") then
|
||||
files = glob(targetname)
|
||||
if not files then
|
||||
files = {}
|
||||
end
|
||||
else
|
||||
files = {targetname}
|
||||
end
|
||||
|
||||
target = {
|
||||
outs = files,
|
||||
is = {
|
||||
__implicitfile = true
|
||||
}
|
||||
}
|
||||
targets[targetname] = target
|
||||
else
|
||||
local _, _, filepart, targetpart = targetname:find("^([^+]*)%+([%w-_]+)$")
|
||||
if not filepart or not targetpart then
|
||||
error(string.format("malformed target name '%s'", targetname))
|
||||
end
|
||||
if (filepart == "") then
|
||||
filepart = cwd
|
||||
end
|
||||
loadbuildfilefor(filepart, targetpart)
|
||||
|
||||
target = targets[targetname]
|
||||
if not target then
|
||||
error(string.format("build file '%s' contains no target '%s'",
|
||||
filepart, targetpart))
|
||||
end
|
||||
end
|
||||
|
||||
return target
|
||||
end
|
||||
|
||||
local typeconverters = {
|
||||
targets = function(propname, i)
|
||||
if (type(i) == "string") then
|
||||
i = {i}
|
||||
elseif (type(i) ~= "table") then
|
||||
error(string.format("property '%s' must be a target list", propname))
|
||||
end
|
||||
|
||||
local m = {}
|
||||
for k, v in pairs(i) do
|
||||
local ts = targetsof(v)
|
||||
if (type(k) == "number") then
|
||||
for _, t in ipairs(ts) do
|
||||
m[#m+1] = t
|
||||
end
|
||||
else
|
||||
if (#ts ~= 1) then
|
||||
error(string.format("named target '%s' can only be assigned from a single target", k))
|
||||
else
|
||||
m[k] = ts[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
return m
|
||||
end,
|
||||
|
||||
strings = function(propname, i)
|
||||
if (type(i) == "string") then
|
||||
i = {i}
|
||||
elseif (type(i) ~= "table") then
|
||||
error(string.format("property '%s' must be a string list", propname))
|
||||
end
|
||||
return concat(i)
|
||||
end,
|
||||
|
||||
boolean = function(propname, i)
|
||||
if (type(i) ~= "boolean") then
|
||||
error(string.format("property '%s' must be a boolean", propname))
|
||||
end
|
||||
return i
|
||||
end,
|
||||
|
||||
string = function(propname, i)
|
||||
if (type(i) ~= "string") then
|
||||
error(string.format("property '%s' must be a string", propname))
|
||||
end
|
||||
return i
|
||||
end,
|
||||
|
||||
number = function(propname, i)
|
||||
if (type(i) ~= "number") then
|
||||
error(string.format("property '%s' must be a number", propname))
|
||||
end
|
||||
return i
|
||||
end,
|
||||
|
||||
table = function(propname, i)
|
||||
if (type(i) ~= "table") then
|
||||
error(string.format("property '%s' must be a table", propname))
|
||||
end
|
||||
return i
|
||||
end,
|
||||
|
||||
object = function(propname, i)
|
||||
return i
|
||||
end,
|
||||
}
|
||||
|
||||
local function definerule(rulename, types, cb)
|
||||
if rulename and rules[rulename] then
|
||||
error(string.format("rule '%s' is already defined", rulename))
|
||||
end
|
||||
|
||||
types.name = { type="string" }
|
||||
types.cwd = { type="string", optional=true }
|
||||
types.vars = { type="table", default={} }
|
||||
|
||||
for propname, typespec in pairs(types) do
|
||||
if not typeconverters[typespec.type] then
|
||||
error(string.format("property '%s' has unrecognised type '%s'",
|
||||
propname, typespec.type))
|
||||
end
|
||||
end
|
||||
|
||||
local rulecwd = cwd
|
||||
local rule = function(e)
|
||||
local definedprops = {}
|
||||
for propname, _ in pairs(e) do
|
||||
definedprops[propname] = true
|
||||
end
|
||||
|
||||
local args = {}
|
||||
for propname, typespec in pairs(types) do
|
||||
if e[propname] == nil then
|
||||
if not typespec.optional and (typespec.default == nil) then
|
||||
error(string.format("missing mandatory property '%s'", propname))
|
||||
end
|
||||
|
||||
args[propname] = typespec.default
|
||||
else
|
||||
args[propname] = typeconverters[typespec.type](propname, e[propname])
|
||||
definedprops[propname] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local propname, _ = next(definedprops)
|
||||
if propname then
|
||||
error(string.format("don't know what to do with property '%s'", propname))
|
||||
end
|
||||
|
||||
if not args.cwd then
|
||||
args.cwd = cwd
|
||||
end
|
||||
args.fullname = args.cwd.."+"..args.name
|
||||
|
||||
local oldparente = parente
|
||||
parente = args
|
||||
args.vars = inherit(args.vars, oldparente.vars)
|
||||
local result = cb(args) or {}
|
||||
parente = oldparente
|
||||
|
||||
result.is = result.is or {}
|
||||
if rulename then
|
||||
result.is[rulename] = true
|
||||
end
|
||||
result.fullname = args.fullname
|
||||
|
||||
if targets[arg.fullname] and (targets[arg.fullname] ~= result) then
|
||||
error(string.format("target '%s' is already defined", args.fullname))
|
||||
end
|
||||
targets[result.fullname] = result
|
||||
return result
|
||||
end
|
||||
|
||||
if rulename then
|
||||
if rules[rulename] then
|
||||
error(string.format("rule '%s' is already defined", rulename))
|
||||
end
|
||||
rules[rulename] = rule
|
||||
end
|
||||
return rule
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- DEFAULT RULES --
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
local function install_make_emitter()
|
||||
emit("hide = @\n")
|
||||
|
||||
function emitter:var(name, value)
|
||||
-- Don't let emit insert spaces.
|
||||
emit(name.."="..value.."\n")
|
||||
end
|
||||
|
||||
function emitter:rule(name, ins, outs)
|
||||
if (#outs == 0) then
|
||||
local n = name.."-IMAGINARY-OUT"
|
||||
emit(".INTERMEDIATE:", n, "\n")
|
||||
outs = {n}
|
||||
end
|
||||
|
||||
local impl = name.."-IMPL"
|
||||
emit(".INTERMEDIATE:", name, "\n")
|
||||
emit(".INTERMEDIATE:", impl, "\n")
|
||||
|
||||
for i = 1, #outs do
|
||||
emit(name..":", outs[i], "\n")
|
||||
end
|
||||
for i = 1, #outs do
|
||||
emit(outs[i]..":", impl, ";\n")
|
||||
end
|
||||
|
||||
for i = 1, #ins do
|
||||
emit(impl..":", ins[i], "\n")
|
||||
end
|
||||
|
||||
emit(impl..":", "\n")
|
||||
local dirs = uniquify(dirname(outs))
|
||||
if (#dirs > 0) then
|
||||
emit("\t@mkdir -p", dirs, "\n")
|
||||
end
|
||||
end
|
||||
|
||||
function emitter:phony(name, ins, outs)
|
||||
emit(".PHONY:", name, "\n")
|
||||
self:rule(name, ins, outs)
|
||||
end
|
||||
|
||||
function emitter:label(...)
|
||||
local s = table.concat({...}, " ")
|
||||
emit("\t@echo", s, "\n")
|
||||
end
|
||||
|
||||
function emitter:exec(commands)
|
||||
for _, s in ipairs(commands) do
|
||||
emit("\t$(hide)", s, "\n")
|
||||
end
|
||||
end
|
||||
|
||||
function emitter:endrule()
|
||||
emit("\n")
|
||||
end
|
||||
end
|
||||
|
||||
local function install_ninja_emitter()
|
||||
emit("rule build\n")
|
||||
emit(" command = $command\n")
|
||||
emit("\n")
|
||||
|
||||
local function unmake(collection)
|
||||
return dotocollection({collection},
|
||||
function(s)
|
||||
return s:gsub("%$%b()",
|
||||
function(expr)
|
||||
return "${"..expr:sub(3, -2).."}"
|
||||
end
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function emitter:var(name, value)
|
||||
-- Don't let emit insert spaces.
|
||||
emit(name.."="..unmake(value).."\n")
|
||||
end
|
||||
|
||||
function emitter:rule(name, ins, outs)
|
||||
if (#outs == 0) then
|
||||
emit("build", name, ": phony", unmake(ins), "\n")
|
||||
else
|
||||
emit("build", name, ": phony", unmake(outs), "\n")
|
||||
emit("build", unmake(outs), ": build", unmake(ins), "\n")
|
||||
end
|
||||
end
|
||||
|
||||
function emitter:label(...)
|
||||
end
|
||||
|
||||
function emitter:exec(commands)
|
||||
emit(" command =", table.concat(unmake(commands), " && "), "\n")
|
||||
end
|
||||
|
||||
function emitter:endrule()
|
||||
emit("\n")
|
||||
end
|
||||
end
|
||||
|
||||
definerule("simplerule",
|
||||
{
|
||||
ins = { type="targets" },
|
||||
outs = { type="strings" },
|
||||
deps = { type="targets", default={} },
|
||||
label = { type="string", optional=true },
|
||||
commands = { type="strings" },
|
||||
vars = { type="table", default={} },
|
||||
},
|
||||
function (e)
|
||||
emitter:rule(e.fullname, filenamesof(e.ins, e.deps), e.outs)
|
||||
emitter:label(e.fullname, " ", e.label or "")
|
||||
|
||||
local vars = inherit(e.vars, {
|
||||
ins = filenamesof(e.ins),
|
||||
outs = filenamesof(e.outs)
|
||||
})
|
||||
|
||||
emitter:exec(templateexpand(e.commands, vars))
|
||||
emitter:endrule()
|
||||
|
||||
return {
|
||||
outs = e.outs
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("installable",
|
||||
{
|
||||
map = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
},
|
||||
function (e)
|
||||
local deps = filenamesof(e.deps)
|
||||
local commands = {}
|
||||
local srcs = {}
|
||||
local outs = {}
|
||||
local dests = {}
|
||||
for dest, src in pairs(e.map) do
|
||||
if src.is.installable then
|
||||
if (type(dest) ~= "number") then
|
||||
error("can't specify a destination filename when installing an installable")
|
||||
end
|
||||
deps[#deps+1] = src.fullname
|
||||
outs = concat(outs, filenamesof(src))
|
||||
elseif (type(dest) == "number") then
|
||||
error("only references to other installables can be missing a destination")
|
||||
else
|
||||
local f = filenamesof(src)
|
||||
if (#f ~= 1) then
|
||||
error("installable can only cope with targets emitting single files")
|
||||
end
|
||||
|
||||
deps[#deps+1] = f
|
||||
dests[#dests+1] = dest
|
||||
outs[#outs+1] = dest
|
||||
commands[#commands+1] = "cp "..f[1].." "..dest
|
||||
end
|
||||
end
|
||||
|
||||
emitter:rule(e.fullname, deps, dests)
|
||||
emitter:label(e.fullname, " ", e.label or "")
|
||||
if (#commands > 0) then
|
||||
emitter:exec(commands)
|
||||
end
|
||||
emitter:endrule()
|
||||
|
||||
return {
|
||||
outs = outs
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- MAIN PROGRAM --
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
local function parse_arguments(argmap, arg)
|
||||
local i = 1
|
||||
local files = {}
|
||||
|
||||
local function unrecognisedarg(arg)
|
||||
argmap[" unrecognised"](arg)
|
||||
end
|
||||
|
||||
while (i <= #arg) do
|
||||
local o = arg[i]
|
||||
local op
|
||||
|
||||
if (o:byte(1) == 45) then
|
||||
-- This is an option.
|
||||
if (o:byte(2) == 45) then
|
||||
-- ...with a -- prefix.
|
||||
o = o:sub(3)
|
||||
local fn = argmap[o]
|
||||
if not fn then
|
||||
unrecognisedarg("--"..o)
|
||||
end
|
||||
i = i + fn(arg[i+1], arg[i+2])
|
||||
else
|
||||
-- ...without a -- prefix.
|
||||
local od = o:sub(2, 2)
|
||||
local fn = argmap[od]
|
||||
if not fn then
|
||||
unrecognisedarg("-"..od)
|
||||
end
|
||||
op = o:sub(3)
|
||||
if (op == "") then
|
||||
i = i + fn(arg[i+1], arg[i+2])
|
||||
else
|
||||
fn(op)
|
||||
end
|
||||
end
|
||||
else
|
||||
files[#files+1] = o
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
argmap[" files"](files)
|
||||
end
|
||||
|
||||
globals = {
|
||||
abspath = abspath,
|
||||
asstring = asstring,
|
||||
basename = basename,
|
||||
concat = concat,
|
||||
concatpath = concatpath,
|
||||
cwd = function() return cwd end,
|
||||
definerule = definerule,
|
||||
dirname = dirname,
|
||||
emit = emit,
|
||||
filenamesof = filenamesof,
|
||||
fpairs = fpairs,
|
||||
include = loadbuildfile,
|
||||
inherit = inherit,
|
||||
print = print,
|
||||
replace = replace,
|
||||
matching = matching,
|
||||
selectof = selectof,
|
||||
startswith = startswith,
|
||||
uniquify = uniquify,
|
||||
vars = vars,
|
||||
}
|
||||
setmetatable(globals,
|
||||
{
|
||||
__index = function(self, k)
|
||||
local rule = rules[k]
|
||||
if rule then
|
||||
return rule
|
||||
else
|
||||
return _G[k]
|
||||
end
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
vars.cflags = {}
|
||||
parente.vars = vars
|
||||
|
||||
setmetatable(_G,
|
||||
{
|
||||
__index = function(self, k)
|
||||
local value = rawget(_G, k)
|
||||
if not value then
|
||||
error(string.format("access of undefined variable '%s'", k))
|
||||
end
|
||||
return value
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
do
|
||||
local emitter_type = install_make_emitter
|
||||
parse_arguments(
|
||||
{
|
||||
["make"] = function()
|
||||
emitter_type = install_make_emitter
|
||||
return 0
|
||||
end,
|
||||
|
||||
["ninja"] = function()
|
||||
emitter_type = install_ninja_emitter
|
||||
return 0
|
||||
end,
|
||||
|
||||
|
||||
[" unrecognised"] = function(arg)
|
||||
error(string.format("unrecognised argument '%s'", arg))
|
||||
end,
|
||||
|
||||
[" files"] = function(files)
|
||||
emitter_type()
|
||||
|
||||
for _, f in ipairs(files) do
|
||||
local _, _, name, value = f:find("^([%w_]+)=(.*)$")
|
||||
if name then
|
||||
emitter:var(name, value)
|
||||
end
|
||||
end
|
||||
|
||||
for _, f in ipairs(files) do
|
||||
if not f:find("=") then
|
||||
loadbuildfile(f)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
{...}
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
# ackbuilder
|
||||
|
||||
## What is it?
|
||||
|
||||
ackbuilder is a very small build tool inspired by [bazel](https://bazel.io/)
|
||||
which uses either make or [ninja](https://ninja-build.org/) as a backend.
|
||||
|
||||
It supports fully parallelisable builds (in both make and ninja), as well as
|
||||
hopefully-robust support for rules which generate more than one output file,
|
||||
which is something make is very, very bad at.
|
||||
|
||||
It was written because the ACK is a really horribly complex thing to build and
|
||||
there wasn't anything else. ackbuilder is pretty rough and ready but it does
|
||||
sort of work. Be prepared for bugs.
|
||||
|
||||
This document is a very rapid brain dump of how the build file works. It
|
||||
doesn't cover actually running the tool (because that bit's pretty nasty) ---
|
||||
go look at the top level Makefile to see that for now.
|
||||
|
||||
## Basic concepts
|
||||
|
||||
Complete example, using the built-in C rules. This should be saved in a file
|
||||
called `build.lua`:
|
||||
|
||||
cprogram {
|
||||
name = 'prog',
|
||||
srcs = { "./*.c" },
|
||||
}
|
||||
|
||||
This defines a rule `prog` which, when built, compiles all the source files in
|
||||
the same directory as the `build.lua` file into an executable.
|
||||
|
||||
Slightly more complex example:
|
||||
|
||||
clibrary {
|
||||
name = "library",
|
||||
srcs = { "./library.c" },
|
||||
hdrs = { "./library.h" },
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = 'prog2',
|
||||
srcs = { "./prog2.c" },
|
||||
deps = { "+library" }
|
||||
}
|
||||
|
||||
If we move the library into another directory, we can invoke it like this:
|
||||
|
||||
cprogram {
|
||||
name = 'prog3',
|
||||
srcs = { "./prog3.c" },
|
||||
deps = { "path/to/library+library" }
|
||||
}
|
||||
|
||||
* Targets starting with `./` are relative to **the current directory** (i.e.
|
||||
the one the build file is in).
|
||||
|
||||
* Targets starting with a path are relative to the top directory of the
|
||||
project.
|
||||
|
||||
* Targets containing a `+` refer to a named target in another build file. So,
|
||||
on encountering the library in `prog3` above, ackbuilder will look for
|
||||
`path/to/library/build.lua`, load it, and then try to find a target in it
|
||||
called `library`.
|
||||
|
||||
**Warning**: files are interpreted from top to bottom; every time a target
|
||||
referring to another build file is seen for the first time, that file is
|
||||
interpreted then and there. You can't have circular dependencies (these are
|
||||
caught and an error is generated). You can't refer to a target defined below
|
||||
you in the same source file (these are not caught, and just won't be found).
|
||||
|
||||
Build files each get their own private global scope. If you randomly set a
|
||||
variable, it won't be seen by other build files. (Use `vars` for that; see
|
||||
below.) Build files are only loaded once.
|
||||
|
||||
The `cprogram` and `clibrary` rules, by the way, are sophisticated enough to
|
||||
automatically handle library and header paths. The exported headers by the
|
||||
library are automatically imported into the program.
|
||||
|
||||
## `simplerule` and `normalrule`
|
||||
|
||||
These are the building blocks out of which all other rules are made. If you
|
||||
want to run your own programs, you will be using these.
|
||||
|
||||
`simplerule` is the simplest. You give it inputs, and outputs, and commands,
|
||||
and it does it.
|
||||
|
||||
simplerule {
|
||||
name = 'sorted-input',
|
||||
ins = { './input.txt' },
|
||||
outs = { './output.txt' },
|
||||
commands = {
|
||||
"sort < %{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
In a command block, `%{...}` will evaluate the Lua expression between the
|
||||
braces; various useful things are in scope, including the list of inputs and
|
||||
outputs.
|
||||
|
||||
However, this ends up leaving the output file lying around in the project
|
||||
directory, which we don't want, so we usually use `normalrule` instead.
|
||||
(`normalrule` is not strictly part of the ackbuilder core; it's in the standard
|
||||
library along with `cprogram` and `clibrary`.)
|
||||
|
||||
normalrule {
|
||||
name = 'sorted-input',
|
||||
ins = { './input.txt' },
|
||||
outleaves = { 'output.txt' },
|
||||
commands = {
|
||||
"sort < %{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
Note `outleaves`; there is no `./`. This is a list of leaf filenames. The rule
|
||||
will create a directory in the object tree and put the files specified in it,
|
||||
somewhere; you don't care where. You can refer to the output file via the
|
||||
target name, so:
|
||||
|
||||
normalrule {
|
||||
name = 'reversed',
|
||||
ins = { '+sorted-input' },
|
||||
outleaves = { 'reversed.txt' },
|
||||
commands = {
|
||||
"rev < %{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
|
||||
One common use for this is to generate C header or source files.
|
||||
|
||||
normalrule {
|
||||
name = 'reversed_h',
|
||||
ins = { '+reversed' },
|
||||
outleaves = { 'reversed.h' },
|
||||
commands = {
|
||||
'xxd -i %{ins} > %{outs}'
|
||||
}
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = 'prog',
|
||||
srcs = { './*.c' },
|
||||
deps = { '+reversed_h' }
|
||||
}
|
||||
|
||||
Now you can refer to `reversed.h` in one of your C files and it'll just work
|
||||
(`+reversed_h`'s output directory gets added to the include path
|
||||
automatically).
|
||||
|
||||
## Defining your own rules
|
||||
|
||||
Like this:
|
||||
|
||||
definerule("sort",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
},
|
||||
function(e)
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
ins = e.srcs,
|
||||
outleaves = { 'sorted.txt' },
|
||||
commands = {
|
||||
"sort < %{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
sort {
|
||||
name = 'sorted',
|
||||
srcs = { './input.txt' }
|
||||
}
|
||||
|
||||
You give `definerule()` the name of the rule you want to define, a description
|
||||
of the properties the rule will take, and a callback that does the work.
|
||||
|
||||
You can do anything you like in the callback, including defining as many
|
||||
targets as you like; but remember that all targets must have unique names, so
|
||||
for any temporary files you probably want something like `name =
|
||||
e.name.."/intermediate"` to ensure uniqueness.
|
||||
|
||||
The callback should end by returning an invocation of another rule, with `name
|
||||
= e.name` as above.
|
||||
|
||||
Rules are defined whenever a build file containing them is seen. Letting this
|
||||
happen automatically doesn't always work so you probably want to explicitly
|
||||
include it:
|
||||
|
||||
include("foo/bar/baz/build.lua")
|
||||
|
||||
Rule properties are typed and can be specified to be required or optional (or
|
||||
have a default value). If you try to invoke a rule with a property which isn't
|
||||
declared, or missing a property which should be declared, you'll get an error.
|
||||
|
||||
definerule("sort",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
numeric = { type="boolean", optional=true, default=false }
|
||||
}
|
||||
...omitted...
|
||||
|
||||
(The `optional=true` part can be omitted if you specify a default which isn't
|
||||
`nil`.)
|
||||
|
||||
Types include:
|
||||
|
||||
* `targets`: the most common one. When the rule is invoked, ackbuilder will
|
||||
resolve these for you so that when your callback fires, the property is a
|
||||
flattened list of target objects.
|
||||
|
||||
* `strings`: a Lua table of strings. If the invoker supplies a single string
|
||||
which isn't a table, it'll get wrapped in one.
|
||||
|
||||
* `string`: a string.
|
||||
|
||||
* `boolean`: a boolean (either `true` or `false`; nothing else is allowed).
|
||||
|
||||
* `table`: a Lua table.
|
||||
|
||||
* `object`: any Lua value.
|
||||
|
||||
## Target objects
|
||||
|
||||
When a rule callback is run, any targets it needs will be resolved into target
|
||||
objects. These are Lua objects with assorted useful stuff in them.
|
||||
|
||||
* `object.is`: contains a set telling you which rules made the object. e.g.
|
||||
`object.is.cprogram` is true if `object` was built with `cprogram`. Bear in
|
||||
mind that `object.is.normalrule` is _also_ going to be true.
|
||||
|
||||
* `object.dir`: the object's build directory. Only exists if the object was
|
||||
built with `normalrule`.
|
||||
|
||||
There are other properties (`fullname` and `outs`). Please don't use these; use
|
||||
`targetnamesof()` and `filenamesof()` as described below.
|
||||
|
||||
## The standard library
|
||||
|
||||
Your build files are supplied a pile of useful functions.
|
||||
|
||||
### Manipulating target lists
|
||||
|
||||
A target list is a possibly nested set of tables containing either target
|
||||
objects or strings. All of these functions will implicitly flatten the list and
|
||||
resolve any strings into target objects before doing anything else to them.
|
||||
Most of these functions can be supplied with varargs parameters.
|
||||
|
||||
e.g. `targetsof(a, b)` is equivalent to `targetsof({a, b})` is equivalent to
|
||||
`targetsof({a, {b}})`.
|
||||
|
||||
* `targetsof(...)`: just flattens the list and resolves any string target
|
||||
names.
|
||||
|
||||
* `filenamesof(...)`: returns a list of output files for all the supplied
|
||||
targets.
|
||||
|
||||
* `targetnamesof(...)`: returns a list of fully qualified target names for
|
||||
all the supplied stargets.
|
||||
|
||||
* `selectof(targets, pattern)`: returns only those targets whose outputs
|
||||
contain at least one file matching the pattern.
|
||||
|
||||
### Manipulating filename lists
|
||||
|
||||
Like the target list functions, all of these implicitly flatten any nested
|
||||
tables. They all return lists; however, as a special exception, if any of the
|
||||
functions which take varargs parameters have a single parameter which is a
|
||||
string, they return just a string.
|
||||
|
||||
e.g. `abspath({f})` returns a table; `abspath(f)` returns a string.
|
||||
|
||||
* `abspath(...)`: attempts to return the absolute path of its arguments. This
|
||||
isn't always possible due to variable references.
|
||||
|
||||
* `basename(...)`: returns the basenames of its arguments (the file part of
|
||||
the path).
|
||||
|
||||
* `dirname(...)`: returns the directory name of its arguments.
|
||||
|
||||
* `matching(files, pattern)`: returns only those files which match a Lua
|
||||
pattern.
|
||||
|
||||
* `replace(files, pattern, repl)`: performs a Lua pattern replace on the list
|
||||
of files.
|
||||
|
||||
* `uniquify(...)`: removes duplicates.
|
||||
|
||||
### Other things
|
||||
|
||||
* `include(file)`: loads another build file, if it hasn't been loaded before.
|
||||
|
||||
## Variables
|
||||
|
||||
There are two types of variable, mostly for hysterical reasons.
|
||||
|
||||
### Makefile variables
|
||||
|
||||
(Despite the name, these work on ninja too.)
|
||||
|
||||
Filenames can contain variable references of the form `$(FOO)`. These are
|
||||
expanded at build time based on definitions supplied on the ackbuilder command
|
||||
line.
|
||||
|
||||
ackbuilder assumes that these are absolute paths and won't attempt to
|
||||
manipulate them much.
|
||||
|
||||
I want to get rid of these at some point.
|
||||
|
||||
### ackbuilder variables
|
||||
|
||||
These are expanded by ackbuilder itself.
|
||||
|
||||
Every rule invocation contains a magic property, `vars`. When a rule's commands
|
||||
are executed, the variables provided in the template expansion are calculated
|
||||
by combining all `vars` settings in the call stack (including the top level
|
||||
build file).
|
||||
|
||||
Easiest to explain with an example:
|
||||
|
||||
cprogram {
|
||||
name = 'another_test',
|
||||
srcs = { './*.c' },
|
||||
vars = {
|
||||
cflags = { '-g', '-O3' }
|
||||
}
|
||||
}
|
||||
|
||||
When `cprogram` builds each C file, the command will refer to `%{cflags}`. The
|
||||
value above will be flattened into a space-separated string and substituted in.
|
||||
|
||||
Setting a variable this way will _override_ any definition further up the call
|
||||
stack. However, you can do this:
|
||||
|
||||
vars.cflags = { '-g' }
|
||||
|
||||
cprogram {
|
||||
name = 'another_test',
|
||||
srcs = { './*.c' },
|
||||
vars = {
|
||||
["+cflags"] = { '-O3' }
|
||||
}
|
||||
}
|
||||
|
||||
Now `cflags` will default to `-g` everywhere, because it's set at the top
|
||||
level; but when `another_test` is built, it'll be `-g -O3`.
|
||||
|
||||
ackbuilder variables are only expanded in command templates, not in filenames.
|
||||
|
||||
<!-- # vim: set ts=2 sw=2 expandtab : -->
|
||||
|
||||
22
build/build.bzl
Normal file
22
build/build.bzl
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
def bison(name, src):
|
||||
CFILE = "%s.c" % name
|
||||
HFILE = "%s.h" % name
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [src],
|
||||
outs = [CFILE, HFILE],
|
||||
cmd = "bison --defines=$(location {}) --output=$(location {}) $<".format(HFILE, CFILE)
|
||||
)
|
||||
|
||||
def gperf(name, src, hash_function_name="hash", lookup_function_name="name"):
|
||||
HFILE = "%s.h" % name
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [src],
|
||||
outs = [HFILE],
|
||||
cmd = "gperf -o -E --constants-prefix={} -H{} -N{} -DptlC --output-file=$@ $<".format(
|
||||
name, hash_function_name, lookup_function_name)
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
262
build/build.lua
262
build/build.lua
|
|
@ -1,262 +0,0 @@
|
|||
local function objdir(e)
|
||||
return concatpath("$(OBJDIR)", e.cwd, e.name)
|
||||
end
|
||||
|
||||
definerule("normalrule",
|
||||
{
|
||||
ins = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
outleaves = { type="strings" },
|
||||
label = { type="string", optional=true },
|
||||
objdir = { type="string", optional=true },
|
||||
commands = { type="strings" },
|
||||
},
|
||||
function (e)
|
||||
local dir = e.objdir or objdir(e)
|
||||
local realouts = {}
|
||||
for _, v in pairs(e.outleaves) do
|
||||
realouts[#realouts+1] = concatpath(dir, v)
|
||||
end
|
||||
|
||||
local vars = inherit(e.vars, {
|
||||
dir = dir
|
||||
})
|
||||
|
||||
local result = simplerule {
|
||||
name = e.name,
|
||||
ins = e.ins,
|
||||
deps = e.deps,
|
||||
outs = realouts,
|
||||
label = e.label,
|
||||
commands = e.commands,
|
||||
vars = vars,
|
||||
}
|
||||
result.dir = dir
|
||||
return result
|
||||
end
|
||||
)
|
||||
|
||||
definerule("cfile",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
suffix = { type="string", default=".o" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"$(CC) -c -o %{outs[1]} %{ins[1]} %{hdrpaths} %{cflags}"
|
||||
},
|
||||
}
|
||||
},
|
||||
function (e)
|
||||
local hdrpaths = {}
|
||||
for _, t in pairs(e.deps) do
|
||||
if t.dir then
|
||||
hdrpaths[#hdrpaths+1] = "-I"..t.dir
|
||||
end
|
||||
end
|
||||
hdrpaths = uniquify(hdrpaths)
|
||||
|
||||
local outleaf = basename(e.name)..e.suffix
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
ins = e.srcs,
|
||||
deps = e.deps,
|
||||
outleaves = {outleaf},
|
||||
label = e.label,
|
||||
commands = e.commands,
|
||||
vars = {
|
||||
hdrpaths = hdrpaths,
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("cppfile",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
outleaf = { type="string" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"$(CC) -E -P -o %{outs[1]} %{hdrpaths} %{cflags} -x c %{ins}"
|
||||
}
|
||||
},
|
||||
},
|
||||
function (e)
|
||||
if (#e.srcs ~= 1) then
|
||||
error("you must have exactly one input file")
|
||||
end
|
||||
|
||||
local hdrpaths = {}
|
||||
for _, t in pairs(e.deps) do
|
||||
if t.dir then
|
||||
hdrpaths[#hdrpaths+1] = "-I"..t.dir
|
||||
end
|
||||
end
|
||||
hdrpaths = uniquify(hdrpaths)
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
ins = e.srcs,
|
||||
deps = e.deps,
|
||||
outleaves = {e.outleaf},
|
||||
label = e.label,
|
||||
commands = e.commands,
|
||||
vars = {
|
||||
hdrpaths = hdrpaths,
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("bundle",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"tar cf - %{ins} | (cd %{dir} && tar xf -)"
|
||||
}
|
||||
}
|
||||
},
|
||||
function (e)
|
||||
local outleaves = {}
|
||||
local commands = {}
|
||||
for _, f in fpairs(e.srcs) do
|
||||
local localf = basename(f)
|
||||
outleaves[#outleaves+1] = localf
|
||||
commands[#commands+1] = "cp "..f.." %{dir}/"..localf
|
||||
end
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
ins = e.srcs,
|
||||
outleaves = outleaves,
|
||||
label = e.label,
|
||||
commands = commands
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("clibrary",
|
||||
{
|
||||
srcs = { type="targets", default={} },
|
||||
hdrs = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
_cfile = { type="object", default=cfile },
|
||||
suffix = { type="string", default=".o" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"rm -f %{outs[1]}",
|
||||
"$(AR) cqs %{outs[1]} %{ins}",
|
||||
},
|
||||
}
|
||||
},
|
||||
function (e)
|
||||
local ins = {}
|
||||
for _, src in fpairs(e.srcs) do
|
||||
local n = basename(src):gsub("%.%w*$", "")
|
||||
ins[#ins+1] = e._cfile {
|
||||
name = e.name.."/"..n,
|
||||
cwd = e.cwd,
|
||||
srcs = {src},
|
||||
deps = e.deps,
|
||||
suffix = e.suffix,
|
||||
vars = {
|
||||
["+cflags"] = { "-I"..e.cwd, },
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local commands = {}
|
||||
local outleaves = {}
|
||||
if (#e.srcs > 0) then
|
||||
for _, s in ipairs(e.commands) do
|
||||
commands[#commands+1] = s
|
||||
end
|
||||
outleaves[#outleaves+1] = e.name..".a"
|
||||
end
|
||||
|
||||
local hdrsin = {}
|
||||
for dest, src in pairs(e.hdrs) do
|
||||
if (type(dest) == "number") then
|
||||
for _, f in ipairs(filenamesof(src)) do
|
||||
hdrsin[#hdrsin+1] = f
|
||||
outleaves[#outleaves+1] = basename(f)
|
||||
commands[#commands+1] = "cp "..asstring(f).." %{dir}"
|
||||
end
|
||||
else
|
||||
local fs = filenamesof(src)
|
||||
if (#fs ~= 1) then
|
||||
error(string.format("keyed header '%s' can only be a single file", dest))
|
||||
end
|
||||
local f = fs[1]
|
||||
|
||||
hdrsin[#hdrsin+1] = f
|
||||
outleaves[#outleaves+1] = dest
|
||||
commands[#commands+1] = "cp "..asstring(f).." %{dir}/"..dest
|
||||
end
|
||||
end
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
ins = ins,
|
||||
deps = {hdrsin, e.deps},
|
||||
outleaves = outleaves,
|
||||
label = e.label,
|
||||
commands = commands,
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("cprogram",
|
||||
{
|
||||
srcs = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
_clibrary = { type="object", default=clibrary },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"$(CC) -o %{outs[1]} %{ins} %{ins} %{ldflags}"
|
||||
},
|
||||
}
|
||||
},
|
||||
function (e)
|
||||
local libs = matching(filenamesof(e.deps), "%.a$")
|
||||
local srcs = {}
|
||||
if (#e.srcs > 0) then
|
||||
for _, f in pairs(
|
||||
matching(
|
||||
filenamesof(
|
||||
e._clibrary {
|
||||
name = e.name .. "/main",
|
||||
cwd = e.cwd,
|
||||
srcs = e.srcs,
|
||||
deps = e.deps,
|
||||
}
|
||||
),
|
||||
"%.a$"
|
||||
)
|
||||
) do
|
||||
srcs[#srcs+1] = f
|
||||
end
|
||||
end
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
deps = e.deps,
|
||||
ins = { srcs, libs },
|
||||
outleaves = { e.name },
|
||||
commands = e.commands,
|
||||
}
|
||||
end
|
||||
)
|
||||
59
build/cpm.bzl
Normal file
59
build/cpm.bzl
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
def cpm_addresses(name, top_of_memory=0x10000, bios_size=None):
|
||||
bdos_size = 3584 # fixed
|
||||
ccp_size = 2048 # fixed
|
||||
bbase = top_of_memory - bios_size
|
||||
fbase = bbase - bdos_size
|
||||
cbase = fbase - ccp_size
|
||||
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [],
|
||||
outs = [ name + ".lib" ],
|
||||
cmd = " && ".join([
|
||||
"echo BIOS_SIZE = %d > $@" % bios_size,
|
||||
"echo BDOS_SIZE = %d >> $@" % bdos_size,
|
||||
"echo CCP_SIZE = %d >> $@" % ccp_size,
|
||||
"echo CPM_SIZE = %d >> $@" % (bios_size + bdos_size + ccp_size),
|
||||
"echo BBASE = %d >> $@" % bbase,
|
||||
"echo FBASE = %d >> $@" % fbase,
|
||||
"echo CBASE = %d >> $@" % cbase,
|
||||
])
|
||||
)
|
||||
|
||||
return (cbase, fbase, bbase)
|
||||
|
||||
def binslice(name, src, start, length=None):
|
||||
if length == None:
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [ src ],
|
||||
outs = [ name + ".img" ],
|
||||
cmd = "tail -c+%d $< > $@" % start
|
||||
)
|
||||
else:
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [ src ],
|
||||
outs = [ name + ".img" ],
|
||||
cmd = "tail -c+%d $< | head -c%d > $@" % (start, length)
|
||||
)
|
||||
|
||||
def diskimage(name, format, bootfile, map):
|
||||
out = name + ".img"
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [ bootfile, "//:diskdefs" ] + map.values(),
|
||||
outs = [ out ],
|
||||
cmd = " && ".join([
|
||||
"mkfs.cpm -f {} -b $(location {}) $@".format(format, bootfile)
|
||||
] + [
|
||||
"cpmcp -f {} $@ $(location {}) 0:{}".format(format, map[name], name)
|
||||
for name in map
|
||||
] + [
|
||||
"(cpmcp -f {} $@ /dev/zero 0:padding 2> /dev/null) || true".format(format),
|
||||
"cpmrm -f {} $@ 0:padding".format(format)
|
||||
])
|
||||
)
|
||||
|
||||
# vim: sw=4 ts=4 et
|
||||
|
||||
135
build/cpm.lua
135
build/cpm.lua
|
|
@ -1,135 +0,0 @@
|
|||
definerule("ackfile",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
suffix = { type="string", default=".o" },
|
||||
},
|
||||
function (e)
|
||||
return cfile {
|
||||
name = e.name,
|
||||
srcs = e.srcs,
|
||||
deps = e.deps,
|
||||
suffix = e.suffix,
|
||||
commands = {
|
||||
"ack -mcpm -c -o %{outs} %{ins} %{hdrpaths} %{cpmcflags}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("acklibrary",
|
||||
{
|
||||
srcs = { type="targets", default={} },
|
||||
hdrs = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
suffix = { type="string", default=".o" },
|
||||
},
|
||||
function (e)
|
||||
return clibrary {
|
||||
name = e.name,
|
||||
srcs = e.srcs,
|
||||
hdrs = e.hdrs,
|
||||
deps = e.deps,
|
||||
suffix = e.suffix,
|
||||
_cfile = ackfile,
|
||||
commands = {
|
||||
"rm -f %{outs[1]}",
|
||||
"aal qc %{outs[1]} %{ins}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("ackprogram",
|
||||
{
|
||||
srcs = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
},
|
||||
function (e)
|
||||
return cprogram {
|
||||
name = e.name,
|
||||
srcs = e.srcs,
|
||||
deps = e.deps,
|
||||
_clibrary = acklibrary,
|
||||
commands = {
|
||||
"ack -mcpm -.c -o %{outs} %{ins} %{cpmldflags}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("diskimage",
|
||||
{
|
||||
diskdefs = { type="targets", default={ "diskdefs" } },
|
||||
format = { type="string" },
|
||||
bootfile = { type="targets" },
|
||||
map = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
},
|
||||
function (e)
|
||||
local bootfile = filenamesof(e.bootfile)[1]
|
||||
local deps = { e.deps, e.diskdefs, e.bootfile }
|
||||
local commands = {}
|
||||
local outs = {}
|
||||
for dest, src in pairs(e.map) do
|
||||
if (type(dest) == "number") then
|
||||
error("all references must have a destination")
|
||||
else
|
||||
local f = filenamesof(src)
|
||||
if not f[1] then
|
||||
error("target must return at least one file (only the first of which will be installed)")
|
||||
end
|
||||
|
||||
deps[#deps+1] = {f[1]}
|
||||
commands[#commands+1] = "cpmcp -f "..e.format.." %{outs} "..f[1].." 0:"..dest
|
||||
end
|
||||
end
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
outleaves = { e.name..".img" },
|
||||
ins = deps,
|
||||
commands = {
|
||||
"mkfs.cpm -f "..e.format.." -b "..bootfile.." %{outs}",
|
||||
commands,
|
||||
"(cpmcp -f "..e.format.." %{outs} /dev/zero 0:padding 2> /dev/null) || true",
|
||||
"cpmrm -f "..e.format.." %{outs} 0:padding"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("binslice",
|
||||
{
|
||||
src = { type="targets" },
|
||||
start = { type="number" },
|
||||
length = { type="number", optional=true },
|
||||
},
|
||||
function (e)
|
||||
local f = filenamesof(e.src)
|
||||
if #f ~= 1 then
|
||||
error("binslice can only operate on a single file")
|
||||
end
|
||||
|
||||
if e.length == nil then
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
outleaves = { e.name..".img" },
|
||||
ins = e.src,
|
||||
commands = {
|
||||
"tail -c+"..(e.start+1).." %{ins} > %{outs}"
|
||||
}
|
||||
}
|
||||
else
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
outleaves = { e.name..".img" },
|
||||
ins = e.src,
|
||||
commands = {
|
||||
"tail -c+"..(e.start+1).." %{ins} | head -c"..e.length.." > %{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
definerule("yacc",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"yacc -t -b %{dir}/y -d %{ins}"
|
||||
}
|
||||
},
|
||||
},
|
||||
function (e)
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
ins = e.srcs,
|
||||
outleaves = { "y.tab.c", "y.tab.h" },
|
||||
label = e.label,
|
||||
commands = e.commands,
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("flex",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
commands = {
|
||||
type="strings",
|
||||
default={
|
||||
"flex -s -t %{ins} > %{outs[1]}"
|
||||
}
|
||||
}
|
||||
},
|
||||
function (e)
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
cwd = e.cwd,
|
||||
ins = e.srcs,
|
||||
outleaves = { "lex.yy.c" },
|
||||
label = e.label,
|
||||
commands = e.commands
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
35
cpmtools/BUILD
Normal file
35
cpmtools/BUILD
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
load("//build:ack.bzl", "ack_binary")
|
||||
load("//cpmtools/libcuss:libcuss.bzl", "libcuss_ack_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
SIMPLE_TOOLS = [
|
||||
"asm",
|
||||
"copy",
|
||||
"dump",
|
||||
"mkfs",
|
||||
"rawdisk",
|
||||
"stat",
|
||||
"submit"
|
||||
]
|
||||
|
||||
LIBCUSS_TOOLS = [
|
||||
"qe",
|
||||
]
|
||||
|
||||
[
|
||||
ack_binary(
|
||||
name = tool,
|
||||
srcs = [tool + ".c"]
|
||||
)
|
||||
for tool in SIMPLE_TOOLS
|
||||
]
|
||||
|
||||
[
|
||||
libcuss_ack_binary(
|
||||
name = tool,
|
||||
srcs = [tool + ".c"]
|
||||
)
|
||||
for tool in LIBCUSS_TOOLS
|
||||
]
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
include "cpmtools/libcuss/build.lua"
|
||||
|
||||
ackprogram {
|
||||
name = "dump",
|
||||
srcs = { "./dump.c" },
|
||||
}
|
||||
|
||||
ackprogram {
|
||||
name = "stat",
|
||||
srcs = { "./stat.c" },
|
||||
}
|
||||
|
||||
ackprogram {
|
||||
name = "asm",
|
||||
srcs = { "./asm.c" },
|
||||
}
|
||||
|
||||
ackprogram {
|
||||
name = "copy",
|
||||
srcs = { "./copy.c" },
|
||||
}
|
||||
|
||||
ackprogram {
|
||||
name = "submit",
|
||||
srcs = { "./submit.c" },
|
||||
}
|
||||
|
||||
ackprogram {
|
||||
name = "mkfs",
|
||||
srcs = { "./mkfs.c" },
|
||||
}
|
||||
|
||||
ackprogram {
|
||||
name = "rawdisk",
|
||||
srcs = { "./rawdisk.c" },
|
||||
}
|
||||
|
||||
libcussprogram {
|
||||
name = "qe",
|
||||
srcs = { "./qe.c" },
|
||||
}
|
||||
17
cpmtools/libcuss/BUILD
Normal file
17
cpmtools/libcuss/BUILD
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
load("//build:ack.bzl", "ack_library")
|
||||
load("libcuss.bzl", "libcuss_terminals")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
[
|
||||
ack_library(
|
||||
name = "libcuss_" + terminal,
|
||||
cflags = ["-DLIBCUSS_" + terminal],
|
||||
srcs = glob(["*.c"]),
|
||||
hdrs = ["libcuss.h"],
|
||||
)
|
||||
for terminal in libcuss_terminals
|
||||
]
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
local libcuss_terminals = {
|
||||
"KAYPROII",
|
||||
"NC200",
|
||||
"BROTHEROP2",
|
||||
"BROTHER_WP1",
|
||||
"BROTHER_WP2450DS",
|
||||
"SPECTRUM_PLUS_THREE",
|
||||
"SPECTRUM_NEXT",
|
||||
}
|
||||
|
||||
for _, terminal in ipairs(libcuss_terminals) do
|
||||
acklibrary {
|
||||
name = "libcuss_"..terminal,
|
||||
srcs = { "./*.c" },
|
||||
hdrs = { "./*.h" },
|
||||
vars = {
|
||||
["+cpmcflags"] = "-DLIBCUSS_"..terminal
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
definerule("libcussprogram",
|
||||
{
|
||||
srcs = { type="targets", default={} },
|
||||
deps = { type="targets", default={} },
|
||||
},
|
||||
function (e)
|
||||
for _, terminal in ipairs(libcuss_terminals) do
|
||||
ackprogram {
|
||||
name = e.name.."_"..terminal,
|
||||
srcs = e.srcs,
|
||||
deps = { e.deps, "cpmtools/libcuss+libcuss_"..terminal },
|
||||
vars = {
|
||||
["+cpmcflags"] = "-DLIBCUSS_"..terminal
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
)
|
||||
38
cpmtools/libcuss/libcuss.bzl
Normal file
38
cpmtools/libcuss/libcuss.bzl
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
load("//build:ack.bzl", "ack_binary")
|
||||
|
||||
libcuss_terminals = [
|
||||
"KAYPROII",
|
||||
"NC200",
|
||||
"BROTHEROP2",
|
||||
"BROTHER_WP1",
|
||||
"BROTHER_WP2450DS",
|
||||
"SPECTRUM_PLUS_THREE",
|
||||
"SPECTRUM_NEXT",
|
||||
]
|
||||
|
||||
def libcuss_ack_binary(**kwargs):
|
||||
name = kwargs["name"]
|
||||
kwargs.pop("name")
|
||||
|
||||
deps = kwargs.get("deps")
|
||||
if not deps:
|
||||
deps = []
|
||||
else:
|
||||
kwargs.pop("deps")
|
||||
|
||||
cflags = kwargs.get("cflags")
|
||||
if not cflags:
|
||||
cflags = []
|
||||
else:
|
||||
kwargs.pop("cflags")
|
||||
|
||||
for terminal in libcuss_terminals:
|
||||
ack_binary(
|
||||
name = name + "_" + terminal,
|
||||
deps = deps + ["//cpmtools/libcuss:libcuss_" + terminal],
|
||||
cflags = ["-DLIBCUSS_" + terminal] + cflags,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
4
include/BUILD
Normal file
4
include/BUILD
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob(["*.lib"]))
|
||||
|
||||
|
|
@ -143,13 +143,5 @@ otimr macro
|
|||
dw 0x93ed
|
||||
endm
|
||||
|
||||
tsthl macro
|
||||
db 0xed, 0x34
|
||||
endm
|
||||
|
||||
tstio macro const
|
||||
db 0xed, 0x24, const
|
||||
endm
|
||||
|
||||
; vim: ts=4 sw=4 et ft=asm
|
||||
|
||||
|
|
|
|||
43
third_party/bbcbasic/BUILD
vendored
Normal file
43
third_party/bbcbasic/BUILD
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
VERSIONS = [
|
||||
"ADM3A"
|
||||
]
|
||||
|
||||
[
|
||||
zmac(
|
||||
name = f,
|
||||
srcs = [ f+".z80" ]
|
||||
)
|
||||
for f in [
|
||||
"cmos",
|
||||
"eval",
|
||||
"exec",
|
||||
"fpp",
|
||||
"main",
|
||||
"ram",
|
||||
"sorry"
|
||||
]
|
||||
]
|
||||
|
||||
[
|
||||
[
|
||||
zmac(
|
||||
name = "boot_" + v,
|
||||
srcs = [ v.lower() + "/boot.z80" ]
|
||||
),
|
||||
ld80(
|
||||
name = "bbcbasic_" + v,
|
||||
objs = {
|
||||
0x0100: [ ":boot_" + v ],
|
||||
0x0200: [ ":main", ":exec", ":eval", ":fpp", ":sorry", ":cmos" ],
|
||||
0x3b00: [ ":ram" ]
|
||||
}
|
||||
)
|
||||
]
|
||||
for v in VERSIONS
|
||||
]
|
||||
|
||||
40
third_party/bbcbasic/build.lua
vendored
40
third_party/bbcbasic/build.lua
vendored
|
|
@ -1,40 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
|
||||
local VERSIONS = {
|
||||
"ADM3A",
|
||||
}
|
||||
|
||||
local srcs = {"cmos", "eval", "exec", "fpp", "main", "ram", "sorry"}
|
||||
local generated = {}
|
||||
for _, f in pairs(srcs) do
|
||||
generated[#generated+1] = zmac {
|
||||
name = f,
|
||||
srcs = { "./"..f..".z80" }
|
||||
}
|
||||
end
|
||||
|
||||
for _, version in ipairs(VERSIONS) do
|
||||
zmac {
|
||||
name = "boot_"..version,
|
||||
srcs = { "./"..version:lower().."/boot.z80" }
|
||||
}
|
||||
|
||||
ld80 {
|
||||
name = "bbcbasic_"..version,
|
||||
address = 0x100,
|
||||
srcs = {
|
||||
"+boot_"..version,
|
||||
"-P0200",
|
||||
"+main",
|
||||
"+exec",
|
||||
"+eval",
|
||||
"+fpp",
|
||||
"+sorry",
|
||||
"+cmos",
|
||||
"-P3b00",
|
||||
"+ram"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
10
third_party/camelforth/BUILD
vendored
Normal file
10
third_party/camelforth/BUILD
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
zmac(
|
||||
name = "camelforth",
|
||||
srcs = ["camel80.z80"] + glob(["*.inc"]),
|
||||
relocatable = False
|
||||
)
|
||||
|
||||
12
third_party/camelforth/build.lua
vendored
12
third_party/camelforth/build.lua
vendored
|
|
@ -1,12 +0,0 @@
|
|||
zmac {
|
||||
name = "camelforth",
|
||||
srcs = {
|
||||
"./camel80.z80",
|
||||
"./camel80.inc",
|
||||
"./camel80d.inc",
|
||||
"./camel80h.inc",
|
||||
"./camel80i.inc",
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
|
||||
12
third_party/ld80/BUILD
vendored
Normal file
12
third_party/ld80/BUILD
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_binary(
|
||||
name = "ld80",
|
||||
srcs = glob(["*.c", "*.h"]),
|
||||
copts = [
|
||||
"-Wno-main",
|
||||
"-Wno-stringop-truncation",
|
||||
"-Wno-format-overflow",
|
||||
]
|
||||
)
|
||||
|
||||
26
third_party/ld80/build.bzl
vendored
Normal file
26
third_party/ld80/build.bzl
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
def ld80(name, address=0x0100, objs={}):
|
||||
args = []
|
||||
targets = []
|
||||
for addr in objs:
|
||||
args += ["-P$$(printf '%%x' %d)" % addr]
|
||||
for obj in objs[addr]:
|
||||
args += ["$(location "+obj+")"]
|
||||
targets += [obj]
|
||||
|
||||
out_file = name + ".cim"
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = targets,
|
||||
outs = [out_file],
|
||||
tools = ["//third_party/ld80"],
|
||||
cmd = " && ".join([
|
||||
"$(location //third_party/ld80) -m -O bin -o $(location "+out_file+").all -s /dev/null "+
|
||||
(" ".join(args)),
|
||||
"tail -c+{address} $(location {out_file}).all > $(location {out_file})".format(
|
||||
address=address+1, out_file=out_file),
|
||||
"rm $(location {}).all".format(out_file)
|
||||
])
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
60
third_party/ld80/build.lua
vendored
60
third_party/ld80/build.lua
vendored
|
|
@ -1,60 +0,0 @@
|
|||
cprogram {
|
||||
name = "ld80",
|
||||
srcs = {
|
||||
"./main.c",
|
||||
"./readobj.c",
|
||||
"./section.c",
|
||||
"./symbol.c",
|
||||
"./fixup.c",
|
||||
"./do_out.c",
|
||||
"./optget.c"
|
||||
}
|
||||
}
|
||||
|
||||
definerule("ld80",
|
||||
{
|
||||
srcs = { type="table" },
|
||||
address = { type="number", default=0 },
|
||||
},
|
||||
function (e)
|
||||
local args = {}
|
||||
local deps = {}
|
||||
|
||||
for _, src in ipairs(e.srcs) do
|
||||
if (type(src) == "string") and src:find("^%-") then
|
||||
args[#args+1] = src
|
||||
else
|
||||
deps[#deps+1] = src
|
||||
args[#args+1] = filenamesof(src)[1]
|
||||
end
|
||||
end
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
outleaves = {
|
||||
e.name..".cim",
|
||||
},
|
||||
ins = {
|
||||
"third_party/ld80+ld80",
|
||||
deps,
|
||||
},
|
||||
commands = {
|
||||
"%{ins[1]} -m -O bin -o %{outs[1]}.all -s %{outs[1]}.sym "..table.concat(args, " "),
|
||||
"tail -c+"..(e.address+1).." %{outs[1]}.all > %{outs[1]}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
definerule("bintocom",
|
||||
{
|
||||
srcs = { type="table" },
|
||||
},
|
||||
function (e)
|
||||
return binrule {
|
||||
name = e.name,
|
||||
src = { e.ins[1] },
|
||||
start = 0x100
|
||||
}
|
||||
end
|
||||
)
|
||||
285
third_party/ld80/hsearch.c
vendored
285
third_party/ld80/hsearch.c
vendored
|
|
@ -1,285 +0,0 @@
|
|||
/* Copyright (C) 1993,1995-1997,2002,2005,2007,2008,2009
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1993.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ld80.h"
|
||||
|
||||
#define __set_errno(x)
|
||||
|
||||
struct hsearch_data
|
||||
{
|
||||
struct _ENTRY *table;
|
||||
unsigned int size;
|
||||
unsigned int filled;
|
||||
};
|
||||
|
||||
/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
||||
[Knuth] The Art of Computer Programming, part 3 (6.4) */
|
||||
|
||||
|
||||
/* The reentrant version has no static variables to maintain the state.
|
||||
Instead the interface of all functions is extended to take an argument
|
||||
which describes the current status. */
|
||||
typedef struct _ENTRY
|
||||
{
|
||||
unsigned int used;
|
||||
ENTRY entry;
|
||||
}
|
||||
_ENTRY;
|
||||
|
||||
|
||||
/* For the used double hash method the table size has to be a prime. To
|
||||
correct the user given table size we need a prime test. This trivial
|
||||
algorithm is adequate because
|
||||
a) the code is (most probably) called a few times per program run and
|
||||
b) the number is small because the table must fit in the core */
|
||||
static int
|
||||
isprime (unsigned int number)
|
||||
{
|
||||
/* no even number will be passed */
|
||||
unsigned int div = 3;
|
||||
|
||||
while (div * div < number && number % div != 0)
|
||||
div += 2;
|
||||
|
||||
return number % div != 0;
|
||||
}
|
||||
|
||||
|
||||
/* Before using the hash table we must allocate memory for it.
|
||||
Test for an existing table are done. We allocate one element
|
||||
more as the found prime number says. This is done for more effective
|
||||
indexing as explained in the comment for the hsearch function.
|
||||
The contents of the table is zeroed, especially the field used
|
||||
becomes zero. */
|
||||
int
|
||||
hcreate_r (nel, htab)
|
||||
size_t nel;
|
||||
struct hsearch_data *htab;
|
||||
{
|
||||
/* Test for correct arguments. */
|
||||
if (htab == NULL)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* There is still another table active. Return with error. */
|
||||
if (htab->table != NULL)
|
||||
return 0;
|
||||
|
||||
/* We need a size of at least 3. Otherwise the hash functions we
|
||||
use will not work. */
|
||||
if (nel < 3)
|
||||
nel = 3;
|
||||
/* Change nel to the first prime number not smaller as nel. */
|
||||
nel |= 1; /* make odd */
|
||||
while (!isprime (nel))
|
||||
nel += 2;
|
||||
|
||||
htab->size = nel;
|
||||
htab->filled = 0;
|
||||
|
||||
/* allocate memory and zero out */
|
||||
htab->table = (_ENTRY *) calloc (htab->size + 1, sizeof (_ENTRY));
|
||||
if (htab->table == NULL)
|
||||
return 0;
|
||||
|
||||
/* everything went alright */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* After using the hash table it has to be destroyed. The used memory can
|
||||
be freed and the local static variable can be marked as not used. */
|
||||
void
|
||||
hdestroy_r (htab)
|
||||
struct hsearch_data *htab;
|
||||
{
|
||||
/* Test for correct arguments. */
|
||||
if (htab == NULL)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Free used memory. */
|
||||
free (htab->table);
|
||||
|
||||
/* the sign for an existing table is an value != NULL in htable */
|
||||
htab->table = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* This is the search function. It uses double hashing with open addressing.
|
||||
The argument item.key has to be a pointer to an zero terminated, most
|
||||
probably strings of chars. The function for generating a number of the
|
||||
strings is simple but fast. It can be replaced by a more complex function
|
||||
like ajw (see [Aho,Sethi,Ullman]) if the needs are shown.
|
||||
|
||||
We use an trick to speed up the lookup. The table is created by hcreate
|
||||
with one more element available. This enables us to use the index zero
|
||||
special. This index will never be used because we store the first hash
|
||||
index in the field used where zero means not used. Every other value
|
||||
means used. The used field can be used as a first fast comparison for
|
||||
equality of the stored and the parameter value. This helps to prevent
|
||||
unnecessary expensive calls of strcmp. */
|
||||
int
|
||||
hsearch_r (item, action, retval, htab)
|
||||
ENTRY item;
|
||||
ACTION action;
|
||||
ENTRY **retval;
|
||||
struct hsearch_data *htab;
|
||||
{
|
||||
unsigned int hval, hval2, first_idx;
|
||||
unsigned int count;
|
||||
unsigned int len = strlen (item.key);
|
||||
unsigned int idx;
|
||||
|
||||
/* Compute an value for the given string. Perhaps use a better method. */
|
||||
hval = len;
|
||||
count = len;
|
||||
while (count-- > 0)
|
||||
{
|
||||
hval <<= 4;
|
||||
hval += item.key[count];
|
||||
}
|
||||
if (hval == 0)
|
||||
++hval;
|
||||
|
||||
/* First hash function: simply take the modul but prevent zero. */
|
||||
idx = hval % htab->size + 1;
|
||||
|
||||
if (htab->table[idx].used)
|
||||
{
|
||||
/* Further action might be required according to the action value. */
|
||||
if (htab->table[idx].used == hval
|
||||
&& strcmp (item.key, htab->table[idx].entry.key) == 0)
|
||||
{
|
||||
*retval = &htab->table[idx].entry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Second hash function, as suggested in [Knuth] */
|
||||
hval2 = 1 + hval % (htab->size - 2);
|
||||
first_idx = idx;
|
||||
|
||||
do
|
||||
{
|
||||
/* Because SIZE is prime this guarantees to step through all
|
||||
available indeces. */
|
||||
if (idx <= hval2)
|
||||
idx = htab->size + idx - hval2;
|
||||
else
|
||||
idx -= hval2;
|
||||
|
||||
/* If we visited all entries leave the loop unsuccessfully. */
|
||||
if (idx == first_idx)
|
||||
break;
|
||||
|
||||
/* If entry is found use it. */
|
||||
if (htab->table[idx].used == hval
|
||||
&& strcmp (item.key, htab->table[idx].entry.key) == 0)
|
||||
{
|
||||
*retval = &htab->table[idx].entry;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
while (htab->table[idx].used);
|
||||
}
|
||||
|
||||
/* An empty bucket has been found. */
|
||||
if (action == ENTER)
|
||||
{
|
||||
/* If table is full and another entry should be entered return
|
||||
with error. */
|
||||
if (htab->filled == htab->size)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
htab->table[idx].used = hval;
|
||||
htab->table[idx].entry = item;
|
||||
|
||||
++htab->filled;
|
||||
|
||||
*retval = &htab->table[idx].entry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__set_errno (ESRCH);
|
||||
*retval = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
/* The non-reentrant version use a global space for storing the table. */
|
||||
static struct hsearch_data htab;
|
||||
|
||||
|
||||
/* Define the non-reentrant function using the reentrant counterparts. */
|
||||
ENTRY *
|
||||
hsearch (item, action)
|
||||
ENTRY item;
|
||||
ACTION action;
|
||||
{
|
||||
ENTRY *result;
|
||||
|
||||
(void) hsearch_r (item, action, &result, &htab);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hcreate (nel)
|
||||
size_t nel;
|
||||
{
|
||||
return hcreate_r (nel, &htab);
|
||||
}
|
||||
|
||||
void
|
||||
hdestroy()
|
||||
{
|
||||
hdestroy_r(&htab);
|
||||
}
|
||||
4
third_party/libstb/build.lua
vendored
4
third_party/libstb/build.lua
vendored
|
|
@ -1,4 +0,0 @@
|
|||
clibrary {
|
||||
name = "libstb",
|
||||
hdrs = { "./*.h" }
|
||||
}
|
||||
24
third_party/libz80ex/build.lua
vendored
24
third_party/libz80ex/build.lua
vendored
|
|
@ -1,24 +0,0 @@
|
|||
clibrary {
|
||||
name = "libz80ex",
|
||||
srcs = {
|
||||
"./z80ex.c",
|
||||
"./z80ex_dasm.c",
|
||||
},
|
||||
deps = {
|
||||
"./include/z80ex.h",
|
||||
"./include/z80ex_dasm.h",
|
||||
},
|
||||
hdrs = { "./include/*.h" },
|
||||
vars = {
|
||||
["+cflags"] = {
|
||||
"-DENDIANNESS=WORDS_LITTLE_ENDIAN",
|
||||
"-DZ80EX_API_REVISION=1",
|
||||
"-DZ80EX_VERSION_MAJOR=1",
|
||||
"-DZ80EX_VERSION_MINOR=21",
|
||||
"-DZ80EX_RELEASE_TYPE=cpmish",
|
||||
"-DZ80EX_VERSION_STR=1.1.21-cpmish",
|
||||
"-Ithird_party/libz80ex/include",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
9
third_party/startrek/BUILD
vendored
Normal file
9
third_party/startrek/BUILD
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
load("//build:ack.bzl", "ack_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
ack_binary(
|
||||
name = "startrek",
|
||||
srcs = ["startrek.c"]
|
||||
)
|
||||
|
||||
62
third_party/ted/BUILD
vendored
Normal file
62
third_party/ted/BUILD
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
VERSIONS = [
|
||||
"NC200",
|
||||
"WP2450DS",
|
||||
]
|
||||
|
||||
[
|
||||
zmac(
|
||||
name = f,
|
||||
srcs = [
|
||||
f + ".mac",
|
||||
"ted.inc",
|
||||
]
|
||||
)
|
||||
for f in [
|
||||
"cpmio",
|
||||
"main",
|
||||
"fileio",
|
||||
"cmds",
|
||||
]
|
||||
]
|
||||
|
||||
[
|
||||
[
|
||||
zmac(
|
||||
name = "termdef_" + v,
|
||||
srcs = [
|
||||
"termdef.mac",
|
||||
v.lower() + "/config.inc",
|
||||
"ted.inc",
|
||||
]
|
||||
),
|
||||
zmac(
|
||||
name = "scrn_" + v,
|
||||
srcs = [
|
||||
"scrn.mac",
|
||||
v.lower() + "/config.inc",
|
||||
"ted.inc",
|
||||
]
|
||||
),
|
||||
ld80(
|
||||
name = "ted_" + v,
|
||||
address = 0x0100,
|
||||
objs = {
|
||||
0x0100: [
|
||||
":main",
|
||||
":termdef_" + v,
|
||||
":fileio",
|
||||
":scrn_" + v,
|
||||
":cmds",
|
||||
":cpmio"
|
||||
]
|
||||
}
|
||||
)
|
||||
]
|
||||
for v in VERSIONS
|
||||
]
|
||||
|
||||
52
third_party/ted/build.lua
vendored
52
third_party/ted/build.lua
vendored
|
|
@ -1,52 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
|
||||
local PLATFORMS = {
|
||||
"NC200",
|
||||
"WP2450DS",
|
||||
}
|
||||
|
||||
-- These files are the same for all platforms.
|
||||
|
||||
for _, f in ipairs({ "cpmio", "main", "fileio", "cmds" }) do
|
||||
zmac {
|
||||
name = f,
|
||||
srcs = { "./"..f..".mac" }
|
||||
}
|
||||
end
|
||||
|
||||
local srcs = {
|
||||
"cpmio",
|
||||
"main",
|
||||
"termdef",
|
||||
"fileio",
|
||||
"scrn",
|
||||
"cmds"
|
||||
}
|
||||
|
||||
for _, platform in ipairs(PLATFORMS) do
|
||||
-- These need to be compiled individually per platform.
|
||||
--
|
||||
for _, f in ipairs({ "termdef", "scrn" }) do
|
||||
zmac {
|
||||
name = f.."_"..platform,
|
||||
srcs = { "./"..f..".mac" },
|
||||
deps = { "./"..platform:lower().."/config.inc" }
|
||||
}
|
||||
end
|
||||
|
||||
ld80 {
|
||||
name = "ted_"..platform,
|
||||
address = 0x100,
|
||||
srcs = {
|
||||
"-P0100",
|
||||
"+main",
|
||||
"+termdef_"..platform,
|
||||
"+fileio",
|
||||
"+scrn_"..platform,
|
||||
"+cmds",
|
||||
"+cpmio"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
25
third_party/z8e/BUILD
vendored
Normal file
25
third_party/z8e/BUILD
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
load("//build:cpm.bzl", "binslice", "cpm_addresses", "diskimage")
|
||||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
load("//third_party/ld80:build.bzl", "ld80")
|
||||
load("//utils:build.bzl", "objectify", "unix2cpm")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
VERSIONS = [
|
||||
"NC200",
|
||||
"WP2450DS",
|
||||
]
|
||||
|
||||
[
|
||||
zmac(
|
||||
name = "z8e_" + version,
|
||||
srcs = [
|
||||
"src/z8e.z80",
|
||||
"src/terminal.inc",
|
||||
version.lower() + "/config.inc",
|
||||
] + glob(["src/*.tty"]),
|
||||
relocatable = False
|
||||
)
|
||||
for version in VERSIONS
|
||||
]
|
||||
|
||||
22
third_party/z8e/build.lua
vendored
22
third_party/z8e/build.lua
vendored
|
|
@ -1,22 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
|
||||
local VERSIONS = {
|
||||
"NC200",
|
||||
"WP2450DS",
|
||||
}
|
||||
|
||||
for _, version in ipairs(VERSIONS) do
|
||||
zmac {
|
||||
name = "z8e_"..version,
|
||||
srcs = { "./src/z8e.z80" },
|
||||
deps = {
|
||||
"./"..version:lower().."/config.inc",
|
||||
"./src/terminal.inc",
|
||||
"./src/*.tty",
|
||||
},
|
||||
relocatable = false
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
12
third_party/zcpr1/BUILD
vendored
Normal file
12
third_party/zcpr1/BUILD
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
zmac(
|
||||
name = "zcpr1",
|
||||
srcs = [
|
||||
"zcpr.asm"
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
6
third_party/zcpr1/build.lua
vendored
6
third_party/zcpr1/build.lua
vendored
|
|
@ -1,6 +0,0 @@
|
|||
include("third_party/zmac/build.lua")
|
||||
|
||||
zmac {
|
||||
name = "zcpr",
|
||||
srcs = { "./zcpr.asm" }
|
||||
}
|
||||
43
third_party/zmac/BUILD
vendored
Normal file
43
third_party/zmac/BUILD
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
load("//build:build.bzl", "bison")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
bison(
|
||||
name = "parser",
|
||||
src = "zmac.y"
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "doc",
|
||||
srcs = ["doc.c"],
|
||||
defines = ["DOC_DEBUG", "doc=main"],
|
||||
copts = ["-Wno-main"],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "doc_inl",
|
||||
tools = [":doc"],
|
||||
outs = ["doc.inl"],
|
||||
srcs = ["doc.txt"],
|
||||
cmd = "EXE=$$PWD/$(execpath :doc) && cp $(execpath doc.txt) $(RULEDIR) && (cd $(@D) && $$EXE) >/dev/null && rm $(RULEDIR)/doc.txt",
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "zmac",
|
||||
copts = [
|
||||
"-Wno-unused-result"
|
||||
],
|
||||
srcs = [
|
||||
":doc.inl",
|
||||
":parser.c",
|
||||
":parser.h",
|
||||
"doc.c",
|
||||
"mio.c",
|
||||
"mio.h",
|
||||
"zi80dis.cpp",
|
||||
"zi80dis.h",
|
||||
],
|
||||
includes = [
|
||||
":doc.inl/.."
|
||||
],
|
||||
)
|
||||
26
third_party/zmac/build.bzl
vendored
Normal file
26
third_party/zmac/build.bzl
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
def zmac(name, srcs, relocatable=True):
|
||||
srcfiles = [f for f in srcs if f.endswith(".z80") or f.endswith(".asm") or f.endswith(".mac")]
|
||||
if len(srcfiles) != 1:
|
||||
fail("you may only have one .z80 or .asm file")
|
||||
depfiles = [f for f in srcs if f not in srcfiles]
|
||||
|
||||
ext = ".rel" if relocatable else ".cim"
|
||||
relflag = "--rel7" if relocatable else ""
|
||||
archflag = "-z" if srcfiles[0].endswith(".z80") else "-8"
|
||||
outfile = name + ext
|
||||
|
||||
hdrflags = ""
|
||||
for f in depfiles:
|
||||
hdrflags += "-I$$(dirname $(location {})) ".format(f)
|
||||
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = srcfiles + depfiles,
|
||||
outs = [outfile],
|
||||
tools = ["//third_party/zmac"],
|
||||
cmd = "$(execpath //third_party/zmac) --zmac -m {} {} {} -o $(execpath {}) $(execpath {})".format(
|
||||
relflag, archflag, hdrflags, outfile, srcfiles[0])
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
76
third_party/zmac/build.lua
vendored
76
third_party/zmac/build.lua
vendored
|
|
@ -1,76 +0,0 @@
|
|||
include("build/yacc.lua")
|
||||
|
||||
yacc {
|
||||
name = "zmacparser",
|
||||
srcs = { "./zmac.y" }
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = "doc",
|
||||
srcs = { "./doc.c" },
|
||||
vars = {
|
||||
["+cflags"] = { "-DDOC_DEBUG", "-Ddoc=main" }
|
||||
}
|
||||
}
|
||||
|
||||
normalrule {
|
||||
name = "doc_inl",
|
||||
ins = {
|
||||
"+doc",
|
||||
"./doc.txt"
|
||||
},
|
||||
outleaves = { "doc.inl" },
|
||||
commands = { "cd %{dirname(ins[2])} && (%{abspath(ins[1])} > /dev/null) && mv doc.inl %{outs}" }
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = "zmac",
|
||||
srcs = {
|
||||
"./mio.c",
|
||||
"./zi80dis.cpp",
|
||||
"./doc.c",
|
||||
matching(filenamesof("+zmacparser"), "%.c$"),
|
||||
},
|
||||
deps = {
|
||||
"./zi80dis.h",
|
||||
"+zmacparser",
|
||||
"+doc_inl",
|
||||
}
|
||||
}
|
||||
|
||||
definerule("zmac",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
deps = { type="targets", default={} },
|
||||
relocatable = { type="boolean", default=true },
|
||||
},
|
||||
function (e)
|
||||
local firstfilename = filenamesof(e.srcs)[1]
|
||||
local _, _, ext = firstfilename:find("%.(%w+)$")
|
||||
|
||||
local archflag = (ext == "z80") and "-z" or "-8"
|
||||
local relflag = e.relocatable and "--rel7" or ""
|
||||
local ext = e.relocatable and ".rel" or ".cim"
|
||||
|
||||
local hdrpaths = {}
|
||||
for _, t in pairs(uniquify(dirname(filenamesof(e.deps)))) do
|
||||
hdrpaths[#hdrpaths+1] = "-I"..t
|
||||
end
|
||||
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
ins = {
|
||||
"third_party/zmac+zmac",
|
||||
e.srcs
|
||||
},
|
||||
outleaves = { e.name..ext, e.name..".lst" },
|
||||
deps = e.deps,
|
||||
commands = {
|
||||
"%{ins[1]} --zmac -m "..relflag.." "..archflag.." -o %{outs[1]} -o %{outs[2]} %{hdrpaths} %{ins[2]}"
|
||||
},
|
||||
vars = {
|
||||
hdrpaths = hdrpaths,
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
12
third_party/zsdos/BUILD
vendored
Normal file
12
third_party/zsdos/BUILD
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
load("//third_party/zmac:build.bzl", "zmac")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
zmac(
|
||||
name = "zsdos",
|
||||
srcs = [
|
||||
"zsdos-gp.z80",
|
||||
"zsdos.lib"
|
||||
]
|
||||
)
|
||||
|
||||
6
third_party/zsdos/build.lua
vendored
6
third_party/zsdos/build.lua
vendored
|
|
@ -1,6 +0,0 @@
|
|||
include("third_party/zmac/build.lua")
|
||||
|
||||
zmac {
|
||||
name = "zsdos",
|
||||
srcs = { "./zsdos-gp.z80" }
|
||||
}
|
||||
29
utils/BUILD
Normal file
29
utils/BUILD
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([ "6x7font.bdf" ])
|
||||
|
||||
cc_binary(
|
||||
name = "objectify",
|
||||
srcs = [ "objectify.c" ]
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "objectifyc",
|
||||
srcs = [ "objectifyc.c" ]
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "unix2cpm",
|
||||
srcs = [ "unix2cpm.c" ]
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "libbdf",
|
||||
hdrs = [ "libbdf.h" ],
|
||||
srcs = [ "libbdf.c" ],
|
||||
strip_include_prefix = ".",
|
||||
copts = [
|
||||
"-Wno-unused-label"
|
||||
]
|
||||
)
|
||||
|
||||
20
utils/build.bzl
Normal file
20
utils/build.bzl
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
def unix2cpm(name, src):
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [ src ],
|
||||
outs = [ name + ".txt" ],
|
||||
tools = [ "//utils:unix2cpm" ],
|
||||
cmd = "$(location //utils:unix2cpm) $< > $@"
|
||||
)
|
||||
|
||||
def objectify(name, src):
|
||||
native.genrule(
|
||||
name = name,
|
||||
srcs = [ src ],
|
||||
outs = [ name + ".inc" ],
|
||||
tools = [ "//utils:objectify" ],
|
||||
cmd = "$(location //utils:objectify) $< > $@"
|
||||
)
|
||||
|
||||
# vim: ts=4 sw=4 et
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
cprogram {
|
||||
name = "objectify",
|
||||
srcs = { "./objectify.c" }
|
||||
}
|
||||
|
||||
definerule("objectify",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
},
|
||||
function (e)
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
ins = {
|
||||
"utils+objectify",
|
||||
e.srcs,
|
||||
},
|
||||
outleaves = { e.name..".inc" },
|
||||
commands = {
|
||||
"%{ins[1]} < %{ins[2]} > %{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
cprogram {
|
||||
name = "objectifyc",
|
||||
srcs = { "./objectifyc.c" }
|
||||
}
|
||||
|
||||
definerule("objectifyc",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
},
|
||||
function (e)
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
ins = {
|
||||
"utils+objectifyc",
|
||||
e.srcs,
|
||||
},
|
||||
outleaves = { e.name..".h" },
|
||||
commands = {
|
||||
"%{ins[1]} < %{ins[2]} > %{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
cprogram {
|
||||
name = "unix2cpm",
|
||||
srcs = { "./unix2cpm.c" }
|
||||
}
|
||||
|
||||
definerule("unix2cpm",
|
||||
{
|
||||
srcs = { type="targets" },
|
||||
},
|
||||
function (e)
|
||||
return normalrule {
|
||||
name = e.name,
|
||||
ins = {
|
||||
"utils+unix2cpm",
|
||||
e.srcs,
|
||||
},
|
||||
outleaves = { e.name..".txt" },
|
||||
commands = {
|
||||
"%{ins[1]} < %{ins[2]} > %{outs}"
|
||||
}
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
clibrary {
|
||||
name = "libbdf",
|
||||
srcs = { "./libbdf.c" },
|
||||
hdrs = { "./libbdf.h" }
|
||||
}
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
include "third_party/ld80/build.lua"
|
||||
include "third_party/zmac/build.lua"
|
||||
include "utils/build.lua"
|
||||
|
||||
zmac {
|
||||
name = "biosbdos_rel",
|
||||
srcs = { "./biosbdos.z80" }
|
||||
}
|
||||
|
||||
ld80 {
|
||||
name = "biosbdos_memimg",
|
||||
srcs = {
|
||||
"-Pf700", "third_party/zcpr1+zcpr",
|
||||
"-Pff00", "+biosbdos_rel"
|
||||
}
|
||||
}
|
||||
|
||||
binslice {
|
||||
name = "biosbdos_cim",
|
||||
src = "+biosbdos_memimg",
|
||||
start = 0xf700
|
||||
}
|
||||
|
||||
objectifyc {
|
||||
name = "biosbdos_cim_h",
|
||||
srcs = { "+biosbdos_cim" }
|
||||
}
|
||||
|
||||
cprogram {
|
||||
name = "emu",
|
||||
srcs = { "./*.c" },
|
||||
deps = {
|
||||
"+biosbdos_cim_h",
|
||||
"third_party/libz80ex+libz80ex"
|
||||
},
|
||||
vars = {
|
||||
["+ldflags"] = { "-lreadline" }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
OUTPUT_FORMAT(binary)
|
||||
|
||||
SECTIONS {
|
||||
ram : {
|
||||
. = 0x0000;
|
||||
*(.text);
|
||||
|
||||
. = 0xe800;
|
||||
CBASE = .;
|
||||
*(CCP);
|
||||
|
||||
. = 0xf000;
|
||||
FBASE = .;
|
||||
*(BDOS);
|
||||
|
||||
. = 0xfe00;
|
||||
BBASE = .;
|
||||
*(BIOS);
|
||||
}
|
||||
}
|
||||
20
utils/z80.ld
20
utils/z80.ld
|
|
@ -1,20 +0,0 @@
|
|||
OUTPUT_FORMAT(binary)
|
||||
|
||||
MEMORY {
|
||||
supervisor : ORIGIN = 0x0000, LENGTH = 8K
|
||||
splashscreen : ORIGIN = 0x2000, LENGTH = 1K
|
||||
autoprg : ORIGIN = 0x4000, LENGTH = 512
|
||||
|
||||
bios : ORIGIN = 0xfe00, LENGTH = 0x0200
|
||||
bdos : ORIGIN = 0xf000, LENGTH = 0x0e00
|
||||
ccp : ORIGIN = 0xe800, LENGTH = 0x0800
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
autoprg : { *(AUTOPRG) } >autoprg
|
||||
splashscreen : { *(SPLASH) } >splashscreen
|
||||
ccp : { *(CCP) } >ccp
|
||||
bdos : { *(BDOS) } >bdos
|
||||
bios : { *(BIOS) } >bios
|
||||
supervisor : { *(.text) } >supervisor
|
||||
}
|
||||
Loading…
Reference in a new issue