1
0

Added Cpmtris

This commit is contained in:
acn 2019-10-24 11:48:18 +02:00
parent 36f5f5207d
commit 2ca3187553
23 changed files with 7408 additions and 0 deletions

14
cpmtris/Makefile Normal file
View File

@ -0,0 +1,14 @@
# makefile for cpmtris
all: cpmtris.com
SRC=cpmtris.z rand.z conio.z
cpmtris.com: $(SRC)
cat $(SRC) >out.z
zmac/zmac out.z
mv out.bin cpmtris.com
clean:
$(RM) *~ *.lst *.bin out.z

45
cpmtris/README.md Normal file
View File

@ -0,0 +1,45 @@
# cpmtris
A Tetris clone for Z80-based CP/M machines
(c) 1996,1999 Russell Marks, GPLv2
Originally part of the ZCN repository: https://github.com/jamesots/zcn
I modified cpmtris so that "vt100" and "8 MHz" are the default values.
``cpmtris.com`` is the assembled binary that uses these settings.
See README.orig for full documentation.
## Commands
| Action | Key |
| ---------- | --- |
| Rotate | s |
| Left/Right | k/l |
| Drop | d |
## Command-Line Options
``cpmtris [termtype [mhz*10]]``
``termtype`` specifies the terminal type:
| Type | Terminal |
| ---- | --------------------------- |
| 0 | as defined in patch area |
| 1 | VT100 (default) |
| 2 | VT52 (PCW, +3, etc.) |
| 3 | ZCN (this is auto-detected) |
| 4 | VC404 |
``mhz*10`` defines the speed of the machine "times 10", e.g. for a
3.5 MHz machine, use "35" or for 8 MHz (default) use "80".
E.g.: ``cpmtris 1 80`` for a VT100 8 MHz machine, which is the default.
## ZMAC
The ZMAC Z80 macro assembler, which is used for cpmtris, is also available in the ``zmac/`` folder.
When assembling cpmtris using the Makefile, zmac is used (but needs to be compiled first)

101
cpmtris/README.orig Normal file
View File

@ -0,0 +1,101 @@
* -*- outline -*-
Cpmtris v1.1 - (c) 1996,1999 Russell Marks
A tetris clone for Z80-based CP/M machines.
* License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
[The GNU GPL is in the file 'COPYING'.]
* About cpmtris
Cpmtris is a free tetris clone for CP/M machines. It works as is on
VT52s (PCW and +3) and ZCN boxes, works with VT100s with 'cpmtris 1',
and is patchable for other machines and terminals.
It's a conversion of my Psion series 3 OPL tetris program, via my ZX81
tetris. Both are free like cpmtris, and available on request.
* Playing cpmtris
It's tetris. Surely you've played tetris!?
Ok, the basics. Blocks fall from the top of the screen. You have to
fit them together to make solid horizontal lines, as a horizontal line
of blocks disappears to make room for more blocks. And why is this the
case? Well, if the pile of blocks reaches the top of the screen, it's
game over. So it quickly gets important to fit the shapes together
well, and not leave any gaps.
You can rotate the blocks with 's', move them left or right with 'k'
and 'l', and 'drop' them with 'd'.
Cpmtris does not (yet) speed up. It starts pretty fast and stays that
way. If you want to play it faster, specify a MHz rating on the
command-line (see below) lower than your machine's actually is.
* Command-Line Options
In Unix terms, the synopsis (usage) is 'cpmtris [termtype [mhz10]]'.
If 'termtype' is specified, it must be a single digit corresponding to
a terminal type. If 'mhz10' is specified, it should be ten times the
speed (in MHz) of the Z80 the machine has. For example, on a 3.5MHz
machine you'd use '35'. You must have a 'termtype' specified to use
'mhz10'.
To explain this 'terminal type' stuff: It's traditional for
full-screen CP/M programs to either include a configuration program,
or (more usually) document patches which need to be made to support
different terminals. Cpmtris does have a patch area (100h-17fh), but
also has built-in support for a few terminals. These are:
Type Terminal
0 as defined in patch area
1 VT100
2 VT52 (PCW, +3, etc.) - this is the default
3 ZCN (this is auto-detected)
4 VC404
The idea behind being able to specify both terminal type and speed
when you run cpmtris is that it's more convenient if you sometimes use
your machine via a terminal or terminal emulator. With most programs
you have to devise some method of patching them when you want to use
something other than the default configuration. With cpmtris, if (for
example) I'm using my ZCN box via kermit on my Linux box - not
uncommon - then it's just a matter of using 'cpmtris 1'.
See the source (cpmtris.z) for details of the patch area.
* Acknowledgements
The original text-mode PC tetris game (which a surprising number of
people have never played, it seems). It's inspired more clones than
any other game since space invaders, I think. :-)
Rush's "Presto" album. I listened to it constantly while hacking up
cpmtris.
* Contacting the Author
You can email me at russell.marks@ntlworld.com.

65
cpmtris/conio.z Normal file
View File

@ -0,0 +1,65 @@
;conio - console I/O routines
;mostly just repackaged BDOS stuff
;for cpm zmac:
;ZZglobal putchar
;ZZglobal putbyte
;ZZglobal getchar
;ZZglobal getch
;ZZglobal kbhit
;putchar - put char in a
;puts CR before any LF output
;f corrupt, others preserved
putchar:
cp 10
jr nz,putbyte
ld a,13
call putbyte
ld a,10
;FALLS THROUGH
;putbyte - put char in a without translation
;preserves all regs
putbyte:
push af
push bc
push de
push hl
ld e,a
ld c,2
call 5
pop hl
pop de
pop bc
pop af
ret
;getchar - get char into a (without echo)
;preserves all but f
getch: ;same
getchar:
push bc
push de
push hl
getchlp:
call kbhit
jr nc,getchlp
ld e,0ffh
ld c,6
call 5
pop hl
pop de
pop bc
ret
;kbhit - like the common DOS C function
;returns c if key pressed, nc if not
kbhit:
ld c,11
call 5
rra
ret

BIN
cpmtris/cpmtris.com Normal file

Binary file not shown.

1379
cpmtris/cpmtris.z Normal file

File diff suppressed because it is too large Load Diff

96
cpmtris/rand.z Normal file
View File

@ -0,0 +1,96 @@
;rand - simple random number generator
;requires maths.z
;algorithm adapted from the one I used for 8086 kirsten.
;for cpm zmac:
;ZZglobal seed
;ZZglobal srand
;ZZglobal rand16
;ZZglobal rand
;uses these:
;ZZglobal multiply
;ZZglobal divide
seed: defb 'ZX81' ;don't ask :-)
;set random number seed from R
;entry: none, exit: none
;af/hl corrupt
srand:
ld a,r
ld h,a
ld a,r
ld l,a
ld (seed),hl
ld a,r
ld h,a
ld a,r
ld l,a
ld (seed+2),hl
ret
;get random number in range 0 to hl-1 inclusive
;entry: hl=range size
;exit: hl=random number in range 0 to range_size-1
;af/bc/de corrupt
;this is equivalent to 'rand()%range_size' in C; the Linux 'rand'
;man page suggests this alternative if you need a better distribution,
;which may be a good idea for numbers bigger than a few thousand:
;
; > To ensure a good distribution for a subrange of values,
; > use code like the below:
; > i = RAND_MAX / my_range
; > i *= my_range
; > while ((j = rand()) >= i) continue;
; > return j % i;
; > (code example based on code from Karl Lehenbauer's fortune
; > cookie program, which credits Ken Arnold, Unix Review,
; > October 1987).
;
;replace rand() above with a call to rand16, and RAND_MAX with FFFFh.
;there are multiply/divide/mod routines in maths.z. Note that using the
;above algorithm will be significantly slower than calling this
;routine, probably half the speed at best.
rand:
push hl
call rand16
pop de
call divide
ex de,hl
ret
;get random number between 0 and 65535 inclusive
;entry: none
;exit: hl=random number
;af/bc/de corrupt
rand16:
ld hl,(seed+2)
ld d,l
add hl,hl
add hl,hl
ld c,h
ld hl,(seed)
ld b,h
rl b
ld e,h
rl e
rl d
add hl,bc
ld (seed),hl
ld hl,(seed+2)
adc hl,de
res 7,h
ld a,h
and 080h
jr nz,rand16a
inc h
rand16a:
ld (seed+2),hl
ld hl,(seed) ;now hl=16-bit rand. num.
ret

76
cpmtris/zmac/COPYRIGHT Normal file
View File

@ -0,0 +1,76 @@
The copyright situation regarding zmac is not totally clear.
This is what Russell Marks had to say when I asked him:
"
> [...] I would
> like to make double sure that zmac is indeed public domain and so
> freely distributable and modifyable. Can you confirm this? Have the
> various authors of zmac over the years agreed to give away their
> copyright?
This is a difficult area, partly because I'm not a lawyer. :-) None of
them seemed to explicitly give away their copyright, but equally, none
of them asserted it either. If you really want to be sure that it's
all entirely public domain, the sort of thing that would definitely
stand up in court, you'll have to try and contact all three previous
contributors (my changes are definitely PD, you wouldn't have to worry
about that). I have vague memories of seeing both Colin Kelley and
John Providenza's names mentioned in more recent things than zmac, but
I don't know any contact addresses for them (nor for Bruce Norskog).
OTOH, if you're just after some general reassurance that it's ok to
distribute a hacked version, I'd say it's fine - if nothing else,
Colin Kelley posted it to comp.sources.unix in 1987, so he must have
thought it freely distributable and modifiable (the latter because he
made changes himself). I think an earlier version had featured in
simtel's "UNIX-C" directory too.
Also, this point from the copyright FAQ may be relevant:
> 2.2) What is "public domain?"
>
> In contrast to copyright is "public domain." A work in the public domain
> is one that can be freely used by anyone for any purpose.
>
> It used to be that if a work was published without notice, it lost all
> copyright, and entered the public domain. That's no longer true, and now
> public domain is more the exception than the rule.
>
> There are still a number of ways that a work may be public domain.
[...]
> - The copyright might have been forfeited. For example, the work
> may have been published without notice prior to the change in
> the law that eliminated the notice requirement (March 1, 1988,
> the effective date of the Berne Convention Implementation Act,
> PL 100-568, 102 Stat. 2853).
zmac was published without a copyright notice in 1987 (and, one
assumes, long before then as well). This is the main reason I describe
zmac as public domain - the 1987 posting was published source with no
copyright notice and no license being distributed for free by one of
the authors. That smells of PD to me, even without the above. :-) I
just don't see what else it could really be. But getting real,
legally-sound confirmation of this would be a challenge.
I know this isn't the "yep, no problem, and here are all the authors'
current addresses so you can check for yourself" you may have been
looking for, but there it is.
FWIW, I distribute zmac with ZCN (my GPL'd CP/M-like OS for the
Amstrad NC100). In case that contributes anything to this. :-)
"
[Needless to say, I too forfeit any copyright claim on my changes!]
I am therefore assuming that zmac is public domain (note, however,
that the Act above is probably an American one and different
conditions may apply in e.g. the European Union). I am not a
lawyer, though, and I would strongly suggest you don't abuse this.
In particular, I wouldn't use zmac or portions thereof in any
commercial product.
If any of the authors of zmac requests so, I will immediately
withdraw this release.
Mark RISON, <mrison@hotmail.com>, 1999-07-19

336
cpmtris/zmac/ChangeLog Normal file
View File

@ -0,0 +1,336 @@
2000-07-02 Mark RISON <mrison@hotmail.com>
* Version 1.3.
* Improve man page (including portability fixes by Tim).
* From Matthew, Tim and Russell: compiler warning avoidance.
2000-06-25 Mark RISON <mrison@hotmail.com>
* Version 1.3b4.
* Allow benign EQU redefinition.
* Cut down on warnings in pass 1.
* Find and (hopefully!) fix nasty bug in error recovery in arglists.
* Allow JP HL/IX/IY syntax. A warning is issued.
* Revamp man page.
* From Tim Mann: resolve r/r conflict for parentheses in expressions.
2000-06-18 Mark RISON <mrison@hotmail.com>
* Version 1.3b3.
* BeOS now supported (just treat as a Un*x variant!).
* Upgrade to bison 1.28 so alloca () no longer a problem.
* Document the operator zoo.
* Allow normal parentheses in expressions.
(FIXME: is there a way to tell bison the r/r conflict is OK?)
* From Tim Mann: sort out operator precedence; make it C-like.
2000-05-25 Mark RISON <mrison@hotmail.com>
* Version 1.3b2.
* Fix error handling fix (with Tim's help!).
* From Tim Mann: add relationals and synonyms for NOT, MOD, SHL, SHR.
2000-03-18 Mark RISON <mrison@hotmail.com>
* Version 1.3b1.
* Fix error handling.
* Allow a leading colon or no special character at all
to introduce a label.
* Allow $ and # to introduce hex constants.
* Allow COND and ENDC as synoyms for IF and ENDIF.
* More ANSI C pedantry.
* From Tim Mann: remove the nasty and buggy hack to allow AND,
OR and XOR to be used as binary operators and do it properly.
* From Tim Mann: fix bug which prevented & from being used as
a binary operator when it was allowed to introduce a hex constant.
* From Matthew Phillips: try filename as given before trying
to add a '.z' extension.
2000-02-27 Mark RISON <mrison@hotmail.com>
* Version 1.2.
* Stop trying to add an extension to INCLUDEd files
(this stupid idea was a misfeature introduced in 1.1.1.1).
Instead, define canonical form, which is automatically
decanonicalised according to the local OS requirements
(see the man page for more details).
* Add support for RISC OS.
* Increase the maximum number of IFs to 1024.
* Issue warning when SLL is used.
* Further ANSI C-ify.
(FIXME: anyone know how to convince bison not to use alloca ()?)
* Tweak command-line error reporting.
* Remove legacy non-ANSI C garbage.
* From Matthew Phillips: add support for outputting AMSDOS header.
* From Matthew Phillips: add support for RISC OS DDE throwback.
2000-02-11 Russell Marks <russell.marks@dtn.ntl.com>
* zmac.1: updated man page.
* zmac.y: changed `-O' warning output to look more like gcc
(`foo.z:N: warning: wibble' rather than `foo.z:N: wibble
warning').
* zmac.y: changed to use my old getoptn() getopt clone instead of
`real' getopt(), as I know Mark likes his portability :-) (and it
probably wouldn't work on DOS otherwise, which even I would like
it to...).
* zmac.y: merged in changes (relative to 1.1) from my current
zmac. These were:
* zmac.y: minor changes to avoid egcs/gcc `ambiguous else'
warnings.
* zmac.y: changes from Chris Smith [slightly changed to fit zmac
1.1.1.x]. `-o' now specifies output file; `-x' specifies listing
file (`-x -' does the same as the old `-o' option); the
undocumented `sll' opcode is now allowed; "Cannot open foo file"
errors now give the filename; a `.z' extension is only added to
source filename if it has no extension; args are now parsed with
getopt().
* Makefile: fix missing dependencies for zmac.
1999-10-03 Mark RISON <mrison@hotmail.com>
* Version 1.1.1.2.
* Fix bug in nested ELSEs.
* Pad .bin file when multiple ORGs are used.
* `-O' option invokes optimisation suggester
for JP, RLC/RRC/RL/RR/SLA A and LD A, 0.
* Reinstate 0x02, 0x0a, 0x12 and 0x1a as valid 8080 opcodes.
* Add zmac.c to .zip file (for those who don't have yacc/bison).
* Make makefile no longer depend on GNU make implicit rules.
1999-07-18 Mark RISON <mrison@hotmail.com>
* Version 1.1.1.1 (nee 1.1.1).
* Extend symbol significance from 15 to 40 chars.
A warning is issued regarding truncated symbols.
* Make continuous listing be the default.
* Add ELSE to IF/ENDIF construct.
* Allow INCLUDE filename to be delimited by " or '.
* Allow labels to be defined using .name (as well as name:).
* Allow ADD/SBC/ADD s syntax (implicit "A, ").
A warning is issued.
* Issue warning for SUB/AND/XOR/OR/CP A, s syntax (explicit "A, ").
* Issue warning for CMP and JMP opcodes, and V and NV condition codes.
* Catch division by zero in expressions.
* Allow hex constants to be specified using a leading '&'.
(FIXME: what's all this testing of nextchar () against '$' for?)
* Add DB, DEFM and TEXT as synonyms for DEFB.
* Add DS and RMEM as synonyms for DEFS.
* Add DW as synonym for DEFW.
* Add READ as synonym for INCLUDE.
* Allow strings to be specified using " too.
* Allow AND, OR and XOR to be used as binary operators.
(FIXME: a bit of a nasty hack; can it be done more cleanly?)
* Make file handing consistent for source and INCLUDE:
for both, try to open with ".z" first, then with no extension.
1998-12-15 Russell Marks <rus@lifeson>
* Version 1.1.
* Added support for --help and --version.
* zmac.1: mentioned `title' pseudo-op.
* Converted revision history from zmac.y into Emacs change log
format (roughly).
* Now outputs errors more like a C compiler (one per line,
prefixed with filename and line-in-file), useful for `M-x compile'
in Emacs. New `-S' option makes it show the error-causing line
like it used to.
* Made it output current file for error reports.
* Added `void' to prototypes for funcs with no args.
* Removed unnecessary `char *ctime()' and `fflush(stderr)'.
* Made it support filenames longer than 14 chars!
1998-02-26 Russell Marks <rus@lifeson>
* Version 1.0 (for the sake of argument).
* Made usage message say what the program is. :-)
1998-02-12 Russell Marks <rus@lifeson>
* Added verbose inline errors in listing and made the original
terse one-letter ones available via new `-t' option.
* Added `-c' option to produce continuous listing (no page breaks
or page headers).
* Corrected plurals in listing so you don't get things like "1
symbols" any more.
* Added `-z' option to output 8080-compatible code only - i.e., to
flag Z80-specific ops as errors.
1998-02-11 Russell Marks <rus@lifeson>
* Fixed LIST-without-args segfault.
* Allowed decimal constants to be up to 65535 (rather than up to
32767 before; I checked and there was no reason for the previous
exception for decimal even on systems with 16-bit ints).
* Removed the `-d' debug option.
* Removed the `-t' option. It did everything as normal *except*
for not reporting errors. I can't imagine any valid reason for
wanting that.
* Made exit status 1 if there were errors in the assembly.
* Fixed `equ' bug - it now detects forward refs to `equ's with
forward refs and flags them as errors (because of course you'd
need three passes to resolve them). The fix is pretty
nasty-looking but it was really the only way I could see to do it.
Some assemblers (e.g. Hisoft's GENS4) don't allow forward refs in
`equ's at all, so count yourselves lucky! :-)
* Changed symbol table listing so it fits in 80 columns.
* Fixed `if' to not depend on internals of yacc parser (which
appear to have changed, anyway).
* Added support for normal `rst' format (0, 8, 10h, 18h...; still
allows the previous 0, 1, 2, 3...).
* Made default output binary (as .bin), added `-h' to get .hex.
* ANSIfied the thing (painful!) and cleaned up a little.
1987-02-05 Colin Kelley
* Added 'cmp' as a synonym for 'cp', 'jmp' as a synonym for 'jp',
and added tolerance of accumulator specification for arithmetic
and logical instructions. (For example, 'or a,12' is now accepted,
same as 'or 12'.)
1987-01-18 Colin Kelley
* Added MIO code to emulate 'mfile' using malloc()'d memory. This
was needed to get the code to work when compiled under MSC 4.0 on
a PC, and it's probably faster anyway.
1986-10-02 Colin Kelley
* Added some more typecasts to keep lint a little happier. Removed
several unused variables. Changed most vars declared as char to
int, since many of them were being compared with -1! I still don't
know what's going on with est[][] being malloc'd and free'd
everywhere...it looks pretty fishy...
1986-09-20 Colin Kelley
* Converted to run on a Pyramid. This meant changing yylval to be
a %union, and then putting in the appropriate typecasts where ints
are pointers are used interchangeably. The current version still
probably won't run on machines where
sizeof(int) != sizeof(char *).
Also changed emit() to use varargs, and got rid of the old
style = in front of yacc action code.
1984-08-27 John Providenza
* Added PHASE/DEPHASE commands.
1984-05-22 John Providenza
* Added include files ala ormac.
1984-05-11 John Providenza
* Added code to print unused labels out with the symbol table.
Also sped up the macro processor by using stdio.
1983-06-07 John Providenza
* Fixed bug in the ADD IX,... instruction.
1983-02-15 John Providenza
* Fixed 'getlocal' to return better local labels. It used to crash
after 6 invocations.
1982-03-15 John Providenza
* Changed maximum number of characters in a label to 15 from 7.
Note that 'putsymtab' uses this value inside of a quoted string,
so we use 15.
* Added underscore as a character type in the lex table 'numpart'
(0x5F).
1982-03-08 John Providenza
* Converted to run on Vax, updated syntax to conform better to the
Zilog standard.
1978-04-?? Bruce Norskog
* Initial version.

43
cpmtris/zmac/MAXAM Normal file
View File

@ -0,0 +1,43 @@
Notes on MAXAM compatibility
============================
MAXAM is an assembler for Amstrad CPC machines
(a CP/M version also exists).
zmac tries to be MAXAM-compatible.
Note the following major differences with MAXAM 1.14, though:
- zmac allows ' and " strings to be specified using '''' and """".
MAXAM only allows '"' and "'", which zmac also allows.
- zmac will truncate symbols to 40 characters.
MAXAM has no such restriction.
- MAXAM allows strings to be terminated by end-of-line.
zmac does not.
- When using the READ directive, MAXAM will take the first
non-whitespace character as the filename delimiter. zmac only
allows ' or " as a filename delimiter.
- AMSDOS restrictions prevent MAXAM from supporting nested
READs, which zmac allows. AMSDOS restrictions also prevent
MAXAM from supporting directories.
- zmac has a pretty decent expression parser.
MAXAM does not (no parentheses, no precedence).
- zmac handles multiple ORGs by inserting padding bytes in
the .bin file, but of course this means retrograde ORGs are
not possible.
- MAXAM allows multiple statements on the same line, separated
by colons. zmac does not.
- zmac has many synonyms for operators, directives, labels, hex
constants, etc., which MAXAM does not support. The easiest
thing is not to find out about them!
Mark RISON, <mrison@hotmail.com>, 2000-05-25

47
cpmtris/zmac/Makefile Normal file
View File

@ -0,0 +1,47 @@
# Makefile for zmac
# Edit any defs which are wrong - these should be OK for Linux though.
CC = gcc
YACC = bison -y
MV = mv
ZIP = zip
CFLAGS = -O -Wall
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/man/man1
all: zmac
zmac: zmac.c mio.c getoptn.c
$(CC) $(CFLAGS) -o zmac zmac.c mio.c getoptn.c
zmac.c: zmac.y
$(YACC) zmac.y
$(MV) y.tab.c zmac.c
dev: /tmp/zmac
/tmp/zmac: zmac.c mio.c getoptn.c
$(CC) $(CFLAGS) --ansi --pedantic --extra-warnings --all-warnings -o /tmp/zmac zmac.c mio.c getoptn.c
chmod 777 /tmp/zmac
install: zmac
install -s -m 511 zmac $(BINDIR)
install -m 444 zmac.1 $(MANDIR)
zip:
$(RM) zmac.zip
man -l -7 zmac.1 | sed 's/.//g' >zmac.doc
$(ZIP) zmac.zip zmac.y zmac.c mio.c mio.h getoptn.c getoptn.h zmac.1 \
zmac.doc Makefile README NEWS COPYRIGHT ChangeLog MAXAM RISCOS \
file_id.diz
clean:
$(RM) *.o y.tab.c zmac.c *~ zmac

76
cpmtris/zmac/NEWS Normal file
View File

@ -0,0 +1,76 @@
* Changes between versions -*- mode:indented-text; mode:outline-minor -*-
This file (NEWS) documents the significant changes between all
versions of zmac (since version 1.0), with the newest changes first.
* Changes in zmac 1.3
- Allow ':label' and 'label', and '$' and '#' for hex constants.
- Add relationals.
- Add more synonyms.
- Fix logical operator bugs.
- Fix error handling.
- Make operator precedence C-like.
- Allow normal parentheses in expressions.
- Revamp man page and add plain text version.
* Changes in zmac 1.2
- Make filename handling more portable.
- Introduce -x and new -o options (old -o is now '-x -').
- Improve ANSI C-ness.
- Add support for writing out files with AMSDOS headers.
- Add support for RISC OS throwback.
* Changes in zmac 1.1.1.2
- Fix nested ELSE bug.
- Pad .bin file when multiple ORGs used.
- Add optimisation suggester.
- Tweak list of valid 8080 opcodes.
* Changes in zmac 1.1.1.1
- Add ELSE, READ, DB, DS, DW, DEFM, TEXT and RMEM directives.
- Allow & to introduce a hex constant, " as a string delimiter
and . to introduce labels.
- Allow AND, OR and XOR to be used as binary operators.
- Warn for truncated symbols and non-standard syntax.
* Changes in zmac 1.1
- Fixed the nasty assumption that filenames were never more than 14
chars (which was *never* valid, as filenames can include the path to
the file).
- Error reports now conform to the canonical format for compilers and
the like (as the GNU coding standards put it,
"SOURCE-FILE-NAME:LINENO: MESSAGE"). This is a lot more sensible
than the previous OVERALL-LINENO: MESSAGE\nERROR-LINE\n (and means
you can easily jump to errors when using Emacs' `M-x compile'), but
you can get SOURCE-FILE-NAME:LINENO: MESSAGE\nERROR-LINE\n if you
use the `-S' option.
- Now supports GNU-ish `--help' and `--version' options.

145
cpmtris/zmac/README Normal file
View File

@ -0,0 +1,145 @@
zmac 1.3, a Z80 macro cross-assembler.
Public domain by Bruce Norskog, John Providenza and Colin Kelley.
Cleaned up somewhat and documented by Russell Marks.
Tweaked by Mark RISON, Chris Smith, Matthew Phillips and Tim Mann.
Description
-----------
zmac is a rather good Z80 macro cross-assembler which hardly anyone
seems to know about, but which I've used for about four or five years
now for various things.
I'd taken to, whenever I uploaded any of my Z80 sources, including a
diff to get zmac minimally working (being a relatively old program, it
made some assumptions which were a little odd in a modern context) and
a pointer to where the shar archives could be found. (FWIW, that's
comp.sources.unix volume 9.) But eventually, I decided it'd be a Good
Thing if I got a more reasonable zmac package together, especially
since I couldn't ever remember seeing a Z80 cross-assembler on
sunsite. Honestly, why bother wasting space on junk like the kernel
and gcc when you could be using it for *useful* stuff like Z80
assemblers? :-)
So I made the code ANSI C and got it through gcc's `-Wall', fixed a
couple of obscure bugs I'd found in it, wrote a man page, and added
the option of only accepting 8080-compatible instructions so you can
write programs in Z80 which will also run on the 8080 and 8085 (see
the man page for details), and a couple of other minor features. And
that's essentially what's here.
The documentation is in the file zmac.doc (derived from the Un*x
man page in the file zmac.1 ).
Installation on Un*x
--------------------
You'll need an ANSI C compiler. gcc is fine - so should most other
compilers be, these days. (You'll also need bison or yacc, if you
want to build from scratch, but that shouldn't be a problem.)
Check/edit the Makefile first. (It should be fine, though.) Then do
`make', then (as root) `make install'. This installs the man page
as well as the executable.
Installation on BeOS
--------------------
You'll need an ANSI C compiler. gcc is fine.
You should be able to use the Makefile provided, otherwise just
do whatever you need to do to compile zmac.c, mio.c and getoptn.c
together.
Then put the executable in /boot/home/config/bin/ or
/boot/beos/bin/ .
Installation on DOS
-------------------
You'll need an ANSI C compiler.
You may be able to use the Makefile provided, if you're using
djgpp, otherwise just do whatever you need to do to compile
zmac.c, mio.c and getoptn.c together; in both cases make sure
the preprocessor token MSDOS is defined.
Then put the executable somewhere in your PATH.
Installation on RISC OS
-----------------------
You'll need an ANSI C compiler. Acorn C/C++ is fine, and
so should gcc and lcc be.
You may be able to use the Makefile provided, otherwise just
do whatever you need to do to compile zmac.c, mio.c and getoptn.c
together; in both cases make sure the preprocessor token __riscos
or __riscos__ is defined (this is the case for Acorn C/C++,
gcc and lcc).
Then put the executable somewhere in your Run$Path.
[Also see the file RISCOS.]
Installation on other OSes
--------------------------
You'll need an ANSI C compiler.
You'll probably need to add filename-handling support for
your OS. This involves adding appropriate definitions
of OS_DIR_SEP and OS_EXT_SEP and adding appropriate code
to decanonicalise (). In those cases where directories in
pathnames are syntactically distinct to leafnames (e.g. VMS)
changes will also be needed in suffix () and suffix_if_none ().
You may be able to use the Makefile provided, otherwise just
do whatever you need to do to compile zmac.c, mio.c and getoptn.c
together.
Then put the executable somewhere appropriate, and feed your
changes back to <mrison@hotmail.com> so they can become part
of the source source!
History
-------
Bruce Norskog wrote zmac in 1978, "modeled after the ... macro
cross-assembler for the Intel 8080 by Ken Borgendale."
John Providenza made some changes and bugfixes in the early 80s.
Colin Kelley did much the same in the mid-80s.
And of course, I've just messed about with it in the late 90s,
together with Mark RISON, Chris Smith, Matthew Phillips
and Tim Mann. :-)
I assigned the first version I hacked on the version number 1.0 just
for the sake of argument (previous versions didn't have a version
number). A version number of about 4.0 or 5.0 would probably be a
better reflection of what the code's been through over the years...
Contacting me
-------------
You can email me at <russell.marks@ntlworld.com>. However,
Mark RISON now maintains zmac, so you should generally
email him instead at <mrison@hotmail.com>.
The latest version of zmac is currently available from
http://www.nenie.org/cpcip/index.html#zmac
Share and enjoy!
-Rus (with a few tweaks by Mark).

5
cpmtris/zmac/README.1st Normal file
View File

@ -0,0 +1,5 @@
This copy omits zmac.c to save space, but is otherwise identical
to zmac 1.3 as released. The C is normally built from zmac.y, so
this shouldn't cause any problems.
-Rus.

19
cpmtris/zmac/RISCOS Normal file
View File

@ -0,0 +1,19 @@
Notes for compilation under RISC OS
===================================
zmac 1.2 has been compiled and tested on RISC OS 3.71, using
Acorn C/C++ Release 5. It has not been compiled with gcc, lcc
or Easy C.
To compile with Acorn C/C++ you will need to rename the five
source and header files to place them in directories called
"c" and "h" and create the object directory "o". Ignore
the supplied Makefile -- it is very easy to build a RISC OS
one using Acorn !Make. Do not forget to link in C:o.stubs.
A full RISC OS binary distribution, with desktop front end,
is available for download from
http://users.ox.ac.uk/~chri0264/software/
Matthew Phillips, <matthew.phillips@chch.ox.ac.uk>, 2000-03-12

3
cpmtris/zmac/file_id.diz Normal file
View File

@ -0,0 +1,3 @@
Z80 macro cross-assembler
Cross-assembleur macro Z80

58
cpmtris/zmac/getoptn.c Normal file
View File

@ -0,0 +1,58 @@
/* getoptn.c - a getopt() clone, so that cmdline option parsing will
* work on non-Unix systems.
*
* PD by RJM
*/
#include <stdio.h>
#include <string.h>
#include "getoptn.h"
/* equivalents of optopt, opterr, optind, and optarg */
int optnopt=0,optnerr=0,optnind=1;
char *optnarg=NULL;
/* holds offset in current argv[] value */
static unsigned int optnpos=1;
/* This routine assumes that the caller is pretty sane and doesn't
* try passing an invalid 'optstring' or varying argc/argv.
*/
int getoptn(int argc,char *argv[],char *optstring)
{
char *ptr;
/* check for end of arg list */
if(optnind==argc || *(argv[optnind])!='-' || strlen(argv[optnind])<=1)
return(-1);
if((ptr=strchr(optstring,argv[optnind][optnpos]))==NULL)
return('?'); /* error: unknown option */
else
{
optnopt=*ptr;
if(ptr[1]==':')
{
if(optnind==argc-1) return(':'); /* error: missing option */
optnarg=argv[optnind+1];
optnpos=1;
optnind+=2;
return(optnopt); /* return early, avoiding the normal increment */
}
}
/* now increment position ready for next time.
* no checking is done for the end of args yet - this is done on
* the next call.
*/
optnpos++;
if(optnpos>=strlen(argv[optnind]))
{
optnpos=1;
optnind++;
}
return(optnopt); /* return the found option */
}

5
cpmtris/zmac/getoptn.h Normal file
View File

@ -0,0 +1,5 @@
/* getoptn.h */
extern int optnopt,optnerr,optnind;
extern char *optnarg;
extern int getoptn(int argc,char *argv[],char *optstring);

126
cpmtris/zmac/mio.c Normal file
View File

@ -0,0 +1,126 @@
/*
* mio.c - Colin Kelley 1-18-87
* routines to emulate temporary file handling with memory instead
*
* rjm 980212 - changed to use memcpy rather than bcopy
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define UNUSED(var) ((void) var)
#define MALLOC_SIZE 10000
#define JUNK_FPTR stdin /* junk ptr to return (unused) */
static unsigned char *mhead; /* pointer to start of malloc()d area */
static unsigned char *mend; /* pointer to current (just beyond) EOF*/
static unsigned char *mptr; /* pointer to current position */
static unsigned int msize; /* size of chunk mhead points to */
FILE *mfopen(char *filename,char *mode)
{
UNUSED (filename);
UNUSED (mode);
if ((mhead = malloc(MALLOC_SIZE)) == NULL) {
msize = 0;
return (NULL);
}
msize = MALLOC_SIZE;
mend = mptr = mhead;
return (JUNK_FPTR); /* not used */
}
int mfclose(FILE *f)
{
UNUSED (f);
if (mhead) {
free(mhead);
return (0);
}
else
return (-1);
}
int mfputc(unsigned int c,FILE *f)
{
unsigned char *p;
UNUSED (f);
while (mptr >= mhead + msize) {
if ((p = realloc(mhead,msize+MALLOC_SIZE)) == (unsigned char *)-1) {
fputs("mio: out of memory\n",stderr);
return (-1);
}
else {
msize += MALLOC_SIZE;
mptr = (unsigned char *) (p + (unsigned int)(mptr - mhead));
mhead = p;
}
}
*mptr = c & 255;
mend = ++mptr;
return c;
}
int mfgetc(FILE *f)
{
UNUSED (f);
if (mptr >= mend) /* no characters left */
return (-1);
else
return (*mptr++);
}
int mfseek(FILE *f,long loc,int origin)
{
UNUSED (f);
if (origin != 0) {
fputs("mseek() only implemented with 0 origin",stderr);
return (-1);
}
mptr = mhead + loc;
return (0);
}
int mfread(char *ptr, unsigned int size, unsigned int nitems, FILE *f)
{
unsigned int i = 0;
UNUSED (f);
while (i < nitems) {
if ((mptr + size) > mend)
break;
memcpy(ptr,mptr,size);
ptr += size;
mptr += size;
i++;
}
return (i);
}
int mfwrite(char *ptr, int size, int nitems, FILE *f)
{
int i = 0;
unsigned char *p;
UNUSED (f);
while (i < nitems) {
while (mptr + size >= mhead + msize) {
if ((p = realloc(mhead,msize+MALLOC_SIZE)) == (unsigned char *)-1){
fputs("mio: out of memory\n",stderr);
return (-1);
}
else {
msize += MALLOC_SIZE;
mptr = (unsigned char *) (p + (unsigned int)(mptr - mhead));
mhead = p;
}
}
if ((mptr + size) > mhead + msize)
break;
memcpy(mend,ptr,size);
ptr += size;
mend += size;
mptr = mend;
}
return (i);
}

9
cpmtris/zmac/mio.h Normal file
View File

@ -0,0 +1,9 @@
/* prototypes for mio.h */
extern FILE *mfopen(char *filename,char *mode);
extern int mfclose(FILE *f);
extern int mfputc(unsigned int c,FILE *f);
extern int mfgetc(FILE *f);
extern int mfseek(FILE *f,long loc,int origin);
extern int mfread(char *ptr, unsigned int size, unsigned int nitems, FILE *f);
extern int mfwrite(char *ptr, int size, int nitems, FILE *f);

412
cpmtris/zmac/zmac.1 Normal file
View File

@ -0,0 +1,412 @@
.\" -*- nroff -*-
.\"
.\" zmac - Z80 macro cross-assembler
.\" Public domain by Bruce Norskog and others.
.\"
.\" zmac.1 - man page
.\"
.\" (version number below is purely for the sake of argument;
.\" it's probably about the millionth version IRL :-))
.\"
.TH zmac 1 "2000-07-02" "Version 1.3" "Development Tools"
.\"
.\"------------------------------------------------------------------
.\"
.SH NAME
zmac \- Z80 macro cross-assembler
.\"
.\"------------------------------------------------------------------
.\"
.SH SYNOPSIS
.PD 0
.B zmac
.RB [ --help ]
.RB [ --version ]
.RB [ -AbcdefghilLmnOpsStTz ]
.RB [ -o
.IR outfile ]
.RB [ -x
.IR listfile ]
.RI [ filename ]
.PD 1
.\"
.\"------------------------------------------------------------------
.\"
.SH DESCRIPTION
zmac is a Z80 macro cross-assembler. It has all the features you'd
expect. It assembles the specified input file (with a `.z' extension
if there is no pre-existing extension and the file as given doesn't
exist) and produces raw binary output
in a `.bin' file. (It can optionally produce CP/M-style Intel hex
format - see below.) By default it also produces a nicely-formatted
listing of the m/c alongside the source, in a `.lst' file.
.PP
As well as normal Z80 programs, zmac lets you write 8080 programs in
Z80 assembly. (See the `-z' option below.)
.\"
.\"------------------------------------------------------------------
.\"
.SH OPTIONS
Most of the options control aspects of the listing.
.TP
.I --help
Display a list of options and a terse description of what the options
do.
.TP
.I --version
Print version number.
.TP
.I -A
Add an AMSDOS header to the generated binary file (this option
automatically disables generation of hex output).
.TP
.I -b
Don't generate the m/c output at all.
.TP
.I -c
Make the listing continuous, i.e. don't generate any page breaks or
page headers. Can make things less confusing if you're going to
consult the listing online rather than printing it. This is the default.
.TP
.I -d
Make the listing discontinuous.
.TP
.I -e
Omit the `error report' section in the listing.
.TP
.I -f
List instructions not assembled due to `if' expressions being
false. (Normally these are not shown in the listing.)
.TP
.I -g
List only the first line of equivalent hex for a source line.
.TP
.I -h
Output CP/M-ish Intel hex format (using extension `.hex') rather than
the default of a simple binary file (extension `.bin').
.TP
.I -i
Don't list files included with `include'.
.TP
.I -l
Don't generate a listing at all.
.TP
.I -L
Generate listing no matter what. Overrides any conflicting options.
.TP
.I -m
List macro expansions.
.TP
.I -n
Omit line numbers from listing.
.TP
.I -o
Output assembled code to
.IR outfile .
.TP
.I -O
Suggest possible optimisations. (These are shown as warnings.)
.TP
.I -p
Use a few linefeeds for page break in listing rather than ^L.
.TP
.I -s
Omit the symbol table from the listing.
.TP
.I -S
When reporting an error, show the line which caused it. Without this
option zmac reports errors in the canonical format, one-per-line (but
see the first item in the
.B BUGS
section).
.TP
.I -t
Give terse (single-letter) error codes in listing (with a key at the
end). (Normally the full error message is given.)
.TP
.I -T
Enable DDE throwback for reporting warnings and errors. This option
only exists for RISC OS builds.
.TP
.I -x
Output listing to
.IR listfile .
(It outputs to stdout if you specify the file as `-'.)
This has no effect if used with
.IR -l .
.TP
.I -z
Accept 8080-compatible instructions only; flag any Z80-specific ones
as errors. This lets you write 8080 programs in Z80 assembly, without
having to worry about the deeply nasty 8080 assembly syntax. :-)
.\"
.\"------------------------------------------------------------------
.\"
.SH "INPUT FORMAT"
zmac uses the standard Zilog mnemonics, and the pseudo-ops are also
largely as you'd expect.
.PP
Input can be upper or lowercase.
.PP
Comments start with `;' and carry on
to the end of the line.
.PP
Labels are declared with
`label:', `.label', `:label' or just `label' -
indentation is unimportant. (Labels can be up to 40 chars long.)
.PP
Number constants can take a trailing h or a leading &, $ or # for hex,
a trailing b for binary, a trailing o or q for octal, or a trailing
d for decimal.
.PP
Here is how other things work:
.TP
.B defb 42
A byte. `ascii', `byte', `db', `defm' and `text' are synonyms.
.TP
.B defb 'foobar'
An ASCII character string (not NUL-terminated).
Double quotes can also be used.
.TP
\fBdefb 'Who needs MS-DOG when you have *CP/M*?', 13, 10, '$'\fP
Strings, bytes, and comp.os.msdos.programmer troll. :-)
.TP
.B defw 2112
A word (16 bits). `word' and `dw' are synonyms.
.TP
.B defs 500
Insert 500 zero bytes. `block', `ds' and `rmem' are synonyms.
.TP
.B org
Set the address to assemble to.
.TP
.B equ
Define a symbol to have a fixed value. The symbol can be used before it
is defined. A symbol defined with `equ' or as a label can be defined only
once, except that a symbol defined with `equ' may be redefined to the
same value.
.TP
.B defl
Define a symbol to have a changeable value. The symbol cannot be used
before it is defined, and it can be redefined to a different value later
with another `defl'.
.TP
.B end
Ends the input. Any lines after an `end' are silently ignored.
If an arg is given, it declares the entry address for the program.
This has no effect if zmac is writing a raw binary file. In an Intel
hex file, it generates an S-record directing 0 bytes of data to be loaded
at the given address.
.TP
\fBif\fP ... [ \fBelse\fP ... ] \fBendif\fP
For conditional assembly. If you do `if foo' and foo evaluates to
zero, all the lines up until the next corresponding `else' or `endif'
are completely ignored. Conversely, if foo evaluates to non-zero, any
lines from a corresponding `else' to the `endif' are ignored. Ifs can
be nested. `cond'/`endc' are synonyms for `if'/`endif'.
.TP
\fBrsym\fP and \fBwsym\fP
Read/write a symbol file. These simply load/save the currently defined
symbols from/to the file specified (in a non-portable format). `rsym'
takes place at the point it is encountered in the file (on the first
pass); `wsym' is delayed until assembly has finished.
.TP
.B include
Include a file. Like C's (well, cpp's) #include, but the filename arg
lacks the angle brackets or quotes (though quotes may be used).
`read' is a synonym.
.\"
.\"------------------------------------------------------------------
.\"
.SH "ODDITIES"
There are the following oddities:
.TP
.B cmp
Same as `cp'.
.TP
.B jmp
Same as `jp'.
.TP
.B jp hl
Same as `jp (hl)'. Ditto for ix and iy.
.TP
.B ld hl, 'LH'
Oh, yes! Ditto for bc, de, sp, ix and iy.
.TP
\fBmin\fP and \fBmax\fP
Same as `defl' except that the symbol is defined as the
smaller or bigger of two comma-separated expressions.
.TP
\fBv\fP and \fBnv\fP
These are alternatives to `pe' and `po' respectively in `jp'
and `call' instructions, meaning that tests on the Z80's
(parity/)overflow flag can be written in the same
format (`x'/`nx') as for those on the zero or carry flags.
.\"
.\"------------------------------------------------------------------
.\"
.SH "LISTING PSEUDO-OPS"
There are several pseudo-ops for controlling the listing. None of
these ops appear in the listing themselves:
.TP
.B eject
Start a new listing page.
.TP
.B nolist
Do nothing. This can be used to have a comment in the source but not
the listing, I suppose.
.TP
.B "elist, flist, glist, mlist"
These have the same effect as the similarly-named command-line
options, though possibly with the sense reversed depending on the
default. Use an arg >0 (or no arg) to enable, and an arg <0 to
disable.
.TP
.B list
Sets whether to list or not. You can use this to avoid listing certain
parts of the source. Takes same optional arg as `elist', etc..
.TP
.B title
Set title (used in listing and symbol file).
.TP
.B space
Output arg blank lines in the listing, or one line if no arg is given.
.\"
.\"------------------------------------------------------------------
.\"
.SH "EXPRESSIONS"
Expressions are reasonably full-featured; here is the complete
list of operators, highest-precedence first. Operators separated
only by a space are synonyms; for example, `~' is the same as `not'.
.IP
! (logical), ~ not (bitwise), + (unary), - (unary)
.IP
*, /, % mod
.IP
+, -
.IP
<< shl, >> shr
.IP
< lt, > gt, <= le, >= ge
.IP
== = eq, != <> ne
.IP
& and (bitwise)
.IP
^ xor (bitwise)
.IP
| or (bitwise)
.PP
You can use normal parentheses or square brackets to override
the precedence rules; use square brackets where parentheses would
conflict with Z80 mnemonic syntax.
.\"
.\"------------------------------------------------------------------
.\"
.SH "MACROS"
The following defines a macro named m with zero or more formal parameters
p1, p2, ..., pn, zero or more local symbols ?s1, ?s2, ..., ?sm, and
body b1, b2, ...:
.IP
m macro p1, p2, ..., pn, ?s1, ?s2, ..., ?sm
.IP
b1
.IP
b2
.IP
...
.IP
endm
.PP
The macro is called by writing:
.IP
m v1, v2, ..., vn
.PP
A macro call expands to the text of the macro's body, with each
occurrence of a formal parameter pk replaced by the corresponding
value vk, and with each local symbol ?sk replaced by a new, unique
symbol invented for this call. Invented symbols begin with `?',
so you should avoid using such symbols elsewhere in your program.
.PP
zmac currently does not check that you have provided the right number
of parameters when calling a macro. If you provide too few, unmatched
formals are replaced with the empty string. If you provide too
many, the additional values begin to replace local symbols as if
they were ordinary parameters. (This could be considered a feature.)
After the local symbols are all replaced, additional parameters
are silently ignored.
.\"
.\"------------------------------------------------------------------
.\"
.SH "FILENAMES"
To allow source files to be portable, a canonical format should be
used for filenames in source files (i.e. in include, rsym or wsym
statements). This canonical format is basically the Un*x
format: `/' as the directory separator, `.' as the extension separator,
".." as the parent directory, "." as the current directory,
and a leading `/' as the root directory
(this should be avoided as it makes moving the source non-trivial).
.PP
For maximum portability, no element of such a filename should have
more than 10 characters, contain characters other than 0-9, a-z,
underscore and `.', or contain more than one `.'.
.PP
Filenames passed as command-line arguments (i.e. for the source
specification, or for the
.IR -o
or
.IR -x
options), however, are assumed to
be in the local (non-canonical) format; this includes the
extension separator (whether supplied or added) and any drive specifiers.
.PP
The OSes which are currently supported are Un*x, BeOS, DOS and RISC OS.
.\"
.\"------------------------------------------------------------------
.\"
.SH "MISCELLANEOUS"
In the symbol table listing, the `=' prefix is given for those symbols
defined by `equ' or `defl', and the `+' suffix is given for those
which were not used.
.\"
.\"------------------------------------------------------------------
.\"
.SH "EXIT STATUS"
.TP
.B 0
No errors.
.TP
.B 1
One or more errors were found during assembly, or zmac exited with a
fatal error.
.\"
.\"------------------------------------------------------------------
.\"
.SH BUGS
zmac reports each error in a line separately. This is probably a good
thing, but tends to effectively result in the same overall problem
being reported twice (e.g. a reference to an undefined symbol causes
both an undeclared error and a value error).
.PP
The man page isn't what you'd call extensive. This shouldn't be too
surprising as I had to RTFS to WTFM. :-)
.PP
What do phase/dephase do (they seem to be some way of temporarily
moving the program location -- for overlays?)?
.\"
.\"------------------------------------------------------------------
.\"
.SH "SEE ALSO"
.IR as "(1)"
.\"
.\"------------------------------------------------------------------
.\"
.SH AUTHOR
Bruce Norskog (in 1978!).
.PP
Updates and bugfixes over the years by John Providenza, Colin Kelley,
and more recently by Russell Marks, Mark RISON, Chris Smith,
Matthew Phillips and Tim Mann.
.PP
Russell Marks wrote most of the man page, with tweaks by Mark RISON
and Tim Mann.

462
cpmtris/zmac/zmac.doc Normal file
View File

@ -0,0 +1,462 @@
zmac(1) Development Tools zmac(1)
NAME
zmac - Z80 macro cross-assembler
SYNOPSIS
zmac [--help] [--version] [-AbcdefghilLmnOpsStTz] [-o out-
file] [-x listfile] [filename]
DESCRIPTION
zmac is a Z80 macro cross-assembler. It has all the fea-
tures you'd expect. It assembles the specified input file
(with a `.z' extension if there is no pre-existing exten-
sion and the file as given doesn't exist) and produces raw
binary output in a `.bin' file. (It can optionally produce
CP/M-style Intel hex format - see below.) By default it
also produces a nicely-formatted listing of the m/c along-
side the source, in a `.lst' file.
As well as normal Z80 programs, zmac lets you write 8080
programs in Z80 assembly. (See the `-z' option below.)
OPTIONS
Most of the options control aspects of the listing.
--help Display a list of options and a terse description
of what the options do.
--version
Print version number.
-A Add an AMSDOS header to the generated binary file
(this option automatically disables generation of
hex output).
-b Don't generate the m/c output at all.
-c Make the listing continuous, i.e. don't generate
any page breaks or page headers. Can make things
less confusing if you're going to consult the list-
ing online rather than printing it. This is the
default.
-d Make the listing discontinuous.
-e Omit the `error report' section in the listing.
-f List instructions not assembled due to `if' expres-
sions being false. (Normally these are not shown in
the listing.)
-g List only the first line of equivalent hex for a
source line.
-h Output CP/M-ish Intel hex format (using extension
`.hex') rather than the default of a simple binary
Version 1.3 2000-07-02 1
zmac(1) Development Tools zmac(1)
file (extension `.bin').
-i Don't list files included with `include'.
-l Don't generate a listing at all.
-L Generate listing no matter what. Overrides any con-
flicting options.
-m List macro expansions.
-n Omit line numbers from listing.
-o Output assembled code to outfile.
-O Suggest possible optimisations. (These are shown as
warnings.)
-p Use a few linefeeds for page break in listing
rather than ^L.
-s Omit the symbol table from the listing.
-S When reporting an error, show the line which caused
it. Without this option zmac reports errors in the
canonical format, one-per-line (but see the first
item in the BUGS section).
-t Give terse (single-letter) error codes in listing
(with a key at the end). (Normally the full error
message is given.)
-T Enable DDE throwback for reporting warnings and
errors. This option only exists for RISC OS
builds.
-x Output listing to listfile. (It outputs to stdout
if you specify the file as `-'.) This has no
effect if used with -l.
-z Accept 8080-compatible instructions only; flag any
Z80-specific ones as errors. This lets you write
8080 programs in Z80 assembly, without having to
worry about the deeply nasty 8080 assembly syntax.
:-)
INPUT FORMAT
zmac uses the standard Zilog mnemonics, and the pseudo-ops
are also largely as you'd expect.
Input can be upper or lowercase.
Comments start with `;' and carry on to the end of the
line.
Version 1.3 2000-07-02 2
zmac(1) Development Tools zmac(1)
Labels are declared with `label:', `.label', `:label' or
just `label' - indentation is unimportant. (Labels can be
up to 40 chars long.)
Number constants can take a trailing h or a leading &, $
or # for hex, a trailing b for binary, a trailing o or q
for octal, or a trailing d for decimal.
Here is how other things work:
defb 42
A byte. `ascii', `byte', `db', `defm' and `text'
are synonyms.
defb 'foobar'
An ASCII character string (not NUL-terminated).
Double quotes can also be used.
defb 'Who needs MS-DOG when you have *CP/M*?', 13, 10, '$'
Strings, bytes, and comp.os.msdos.programmer troll.
:-)
defw 2112
A word (16 bits). `word' and `dw' are synonyms.
defs 500
Insert 500 zero bytes. `block', `ds' and `rmem'
are synonyms.
org Set the address to assemble to.
equ Define a symbol to have a fixed value. The symbol
can be used before it is defined. A symbol defined
with `equ' or as a label can be defined only once,
except that a symbol defined with `equ' may be
redefined to the same value.
defl Define a symbol to have a changeable value. The
symbol cannot be used before it is defined, and it
can be redefined to a different value later with
another `defl'.
end Ends the input. Any lines after an `end' are
silently ignored. If an arg is given, it declares
the entry address for the program. This has no
effect if zmac is writing a raw binary file. In an
Intel hex file, it generates an S-record directing
0 bytes of data to be loaded at the given address.
if ... [ else ... ] endif
For conditional assembly. If you do `if foo' and
foo evaluates to zero, all the lines up until the
next corresponding `else' or `endif' are completely
ignored. Conversely, if foo evaluates to non-zero,
Version 1.3 2000-07-02 3
zmac(1) Development Tools zmac(1)
any lines from a corresponding `else' to the
`endif' are ignored. Ifs can be nested.
`cond'/`endc' are synonyms for `if'/`endif'.
rsym and wsym
Read/write a symbol file. These simply load/save
the currently defined symbols from/to the file
specified (in a non-portable format). `rsym' takes
place at the point it is encountered in the file
(on the first pass); `wsym' is delayed until assem-
bly has finished.
include
Include a file. Like C's (well, cpp's) #include,
but the filename arg lacks the angle brackets or
quotes (though quotes may be used). `read' is a
synonym.
ODDITIES
There are the following oddities:
cmp Same as `cp'.
jmp Same as `jp'.
jp hl Same as `jp (hl)'. Ditto for ix and iy.
ld hl, 'LH'
Oh, yes! Ditto for bc, de, sp, ix and iy.
min and max
Same as `defl' except that the symbol is defined as
the smaller or bigger of two comma-separated
expressions.
v and nv
These are alternatives to `pe' and `po' respec-
tively in `jp' and `call' instructions, meaning
that tests on the Z80's (parity/)overflow flag can
be written in the same format (`x'/`nx') as for
those on the zero or carry flags.
LISTING PSEUDO-OPS
There are several pseudo-ops for controlling the listing.
None of these ops appear in the listing themselves:
eject Start a new listing page.
nolist Do nothing. This can be used to have a comment in
the source but not the listing, I suppose.
elist, flist, glist, mlist
These have the same effect as the similarly-named
command-line options, though possibly with the
Version 1.3 2000-07-02 4
zmac(1) Development Tools zmac(1)
sense reversed depending on the default. Use an arg
>0 (or no arg) to enable, and an arg <0 to disable.
list Sets whether to list or not. You can use this to
avoid listing certain parts of the source. Takes
same optional arg as `elist', etc..
title Set title (used in listing and symbol file).
space Output arg blank lines in the listing, or one line
if no arg is given.
EXPRESSIONS
Expressions are reasonably full-featured; here is the com-
plete list of operators, highest-precedence first. Opera-
tors separated only by a space are synonyms; for example,
`~' is the same as `not'.
! (logical), ~ not (bitwise), + (unary), - (unary)
*, /, % mod
+, -
<< shl, >> shr
< lt, > gt, <= le, >= ge
== = eq, != <> ne
& and (bitwise)
^ xor (bitwise)
| or (bitwise)
You can use normal parentheses or square brackets to over-
ride the precedence rules; use square brackets where
parentheses would conflict with Z80 mnemonic syntax.
MACROS
The following defines a macro named m with zero or more
formal parameters p1, p2, ..., pn, zero or more local sym-
bols ?s1, ?s2, ..., ?sm, and body b1, b2, ...:
m macro p1, p2, ..., pn, ?s1, ?s2, ..., ?sm
b1
b2
...
endm
Version 1.3 2000-07-02 5
zmac(1) Development Tools zmac(1)
The macro is called by writing:
m v1, v2, ..., vn
A macro call expands to the text of the macro's body, with
each occurrence of a formal parameter pk replaced by the
corresponding value vk, and with each local symbol ?sk
replaced by a new, unique symbol invented for this call.
Invented symbols begin with `?', so you should avoid using
such symbols elsewhere in your program.
zmac currently does not check that you have provided the
right number of parameters when calling a macro. If you
provide too few, unmatched formals are replaced with the
empty string. If you provide too many, the additional
values begin to replace local symbols as if they were
ordinary parameters. (This could be considered a fea-
ture.) After the local symbols are all replaced, addi-
tional parameters are silently ignored.
FILENAMES
To allow source files to be portable, a canonical format
should be used for filenames in source files (i.e. in
include, rsym or wsym statements). This canonical format
is basically the Un*x format: `/' as the directory separa-
tor, `.' as the extension separator, ".." as the parent
directory, "." as the current directory, and a leading `/'
as the root directory (this should be avoided as it makes
moving the source non-trivial).
For maximum portability, no element of such a filename
should have more than 10 characters, contain characters
other than 0-9, a-z, underscore and `.', or contain more
than one `.'.
Filenames passed as command-line arguments (i.e. for the
source specification, or for the -o or -x options), how-
ever, are assumed to be in the local (non-canonical) for-
mat; this includes the extension separator (whether sup-
plied or added) and any drive specifiers.
The OSes which are currently supported are Un*x, BeOS, DOS
and RISC OS.
MISCELLANEOUS
In the symbol table listing, the `=' prefix is given for
those symbols defined by `equ' or `defl', and the `+' suf-
fix is given for those which were not used.
EXIT STATUS
0 No errors.
1 One or more errors were found during assembly, or
zmac exited with a fatal error.
Version 1.3 2000-07-02 6
zmac(1) Development Tools zmac(1)
BUGS
zmac reports each error in a line separately. This is
probably a good thing, but tends to effectively result in
the same overall problem being reported twice (e.g. a ref-
erence to an undefined symbol causes both an undeclared
error and a value error).
The man page isn't what you'd call extensive. This
shouldn't be too surprising as I had to RTFS to WTFM. :-)
What do phase/dephase do (they seem to be some way of tem-
porarily moving the program location -- for overlays?)?
SEE ALSO
as(1)
AUTHOR
Bruce Norskog (in 1978!).
Updates and bugfixes over the years by John Providenza,
Colin Kelley, and more recently by Russell Marks, Mark
RISON, Chris Smith, Matthew Phillips and Tim Mann.
Russell Marks wrote most of the man page, with tweaks by
Mark RISON and Tim Mann.
Version 1.3 2000-07-02 7

3886
cpmtris/zmac/zmac.y Normal file

File diff suppressed because it is too large Load Diff