├── .gitattributes ├── .gitignore ├── AUTHORS ├── ChangeLog ├── LICENSE ├── Makefile ├── Makefile.local ├── README ├── cassette.csh ├── cassette.man ├── cassette.sh ├── cd.ccc ├── cd.cmd ├── cd6.cmd ├── cmd.c ├── cmd.h ├── cmddump.c ├── cmddump.man ├── common.c ├── compile_rom.c ├── config.h ├── cpmutil.dsk ├── cpmutil.html ├── cpmutil.tgz ├── crc.c ├── debug.c ├── dis.c ├── do6.jcl ├── dskspec.html ├── error.c ├── esfrom.z80 ├── expall.bas ├── export.z80 ├── fakerom.z80 ├── hex2cmd.c ├── hex2cmd.man ├── import.z80 ├── keyrepeat.c ├── keyrepeat.h ├── load_cmd.c ├── load_cmd.h ├── load_hex.c ├── m1format.fix ├── main.c ├── mkdisk.c ├── mkdisk.man ├── mount.ccc ├── mount.cmd ├── mount6.cmd ├── pwd.ccc ├── pwd.cmd ├── pwd6.cmd ├── reed.h ├── settime.ccc ├── settime.z80 ├── trs.h ├── trs_cassette.c ├── trs_chars.c ├── trs_disk.c ├── trs_disk.h ├── trs_gtkinterface.c ├── trs_hard.c ├── trs_hard.h ├── trs_imp_exp.c ├── trs_imp_exp.h ├── trs_interrupt.c ├── trs_io.c ├── trs_iodefs.h ├── trs_keyboard.c ├── trs_memory.c ├── trs_printer.c ├── trs_stringy.c ├── trs_stringy.h ├── trs_uart.c ├── trs_uart.h ├── trs_xinterface.c ├── truedam.ccc ├── truedam.cmd ├── truedam6.cmd ├── umount.ccc ├── umount.cmd ├── umount6.cmd ├── unix.ccc ├── unix.cmd ├── unix6.cmd ├── utility.dsk ├── utility.jcl ├── xtrs.glade ├── xtrs.man ├── xtrs8.z80 ├── xtrsemt.ccc ├── xtrsemt.h ├── xtrshard.z80 ├── xtrsmous.z80 ├── xtrsrom4p.README ├── xtrsrom4p.z80 ├── z80.c └── z80.h /.gitattributes: -------------------------------------------------------------------------------- 1 | *.dsk binary 2 | *.tgz binary 3 | *.cmd binary 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CVS default ignores begin 2 | tags 3 | TAGS 4 | .make.state 5 | .nse_depinfo 6 | *~ 7 | #* 8 | .#* 9 | ,* 10 | _$* 11 | *$ 12 | *.old 13 | *.bak 14 | *.BAK 15 | *.orig 16 | *.rej 17 | .del-* 18 | *.a 19 | *.olb 20 | *.o 21 | *.obj 22 | *.so 23 | *.exe 24 | *.Z 25 | *.elc 26 | *.ln 27 | core 28 | cscope.* 29 | # CVS default ignores end 30 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Authors of xtrs 1.0 2 | =================== 3 | David Gingold 4 | Alec Wolman 5 | 6 | Main author of later versions 7 | ============================= 8 | Timothy P. Mann 9 | 10 | Other contributors 11 | ================== 12 | Pete Cervasio 13 | Todd P. Cromwell III 14 | Fabio Ferrari 15 | Roland Gerlach 16 | Jenz Guenther 17 | Jean-Marc Le Peuvedic 18 | Denis Leconte 19 | Ulrich Mueller 20 | Joe Peterson 21 | Al Petrofsky 22 | Branden Robinson 23 | Knut Roll-Lund 24 | Ignatios Souvatzis 25 | Frederic Vecoven 26 | Marcelo Fernandes Vianna 27 | Joseph Wang 28 | 29 | Additonal thanks to the following 30 | ================================= 31 | Jeff Vavasour for the JV1 and JV3 floppy disk file formats. 32 | 33 | David Keil for the DMK floppy disk file format. 34 | 35 | Matthew Reed for the HDV hard disk file format and the ESF Stringy 36 | Floppy file format. 37 | 38 | Mark McDougall for documentation on the Micro Labs Grafyx Solution 39 | card. 40 | 41 | Bruce Norskog, who is thought to be the original author of the public 42 | domain Z80 disassembler zdis, from which xtrs's dis.c is derived. 43 | zdis was a part of the zmac package as early as 12-Mar-1987 when the 44 | package was posted to mod.sources by Colin Kelley. 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 1992 Clarendon Hill Software. 2 | 3 | Permission is granted to any individual or institution to use, copy, 4 | or redistribute this software, provided this copyright notice is retained. 5 | 6 | This software is provided "as is" without any expressed or implied 7 | warranty. If this software brings on any sort of damage -- physical, 8 | monetary, emotional, or brain -- too bad. You've got no one to blame 9 | but yourself. 10 | 11 | The software may be modified for your own purposes, but modified versions 12 | must retain this notice. 13 | 14 | *** 15 | 16 | Copyright (c) 1996-2020, Timothy P. Mann 17 | 18 | Permission is hereby granted, free of charge, to any person 19 | obtaining a copy of this software and associated documentation 20 | files (the "Software"), to deal in the Software without 21 | restriction, including without limitation the rights to use, copy, 22 | modify, merge, publish, distribute, sublicense, and/or sell copies 23 | of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be 27 | included in all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 33 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 34 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 35 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | SOFTWARE. 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for xtrs, the TRS-80 emulator. 3 | # 4 | 5 | OBJECTS = \ 6 | z80.o \ 7 | main.o \ 8 | load_cmd.o \ 9 | load_hex.o \ 10 | trs_memory.o \ 11 | trs_keyboard.o \ 12 | error.o \ 13 | debug.o \ 14 | dis.o \ 15 | trs_io.o \ 16 | trs_cassette.o \ 17 | trs_chars.o \ 18 | trs_printer.o \ 19 | trs_rom1.o \ 20 | trs_rom1x.o \ 21 | trs_rom3.o \ 22 | trs_rom4p.o \ 23 | trs_disk.o \ 24 | trs_interrupt.o \ 25 | trs_imp_exp.o \ 26 | trs_hard.o \ 27 | trs_uart.o \ 28 | trs_stringy.o \ 29 | common.o 30 | 31 | X_OBJECTS = \ 32 | trs_xinterface.o 33 | 34 | GTK_OBJECTS = \ 35 | keyrepeat.o \ 36 | trs_gtkinterface.o 37 | 38 | CR_OBJECTS = \ 39 | compile_rom.o \ 40 | error.o \ 41 | load_cmd.o \ 42 | load_hex.o 43 | 44 | MD_OBJECTS = \ 45 | mkdisk.o \ 46 | common.o \ 47 | error.o 48 | 49 | HC_OBJECTS = \ 50 | cmd.o \ 51 | error.o \ 52 | load_hex.o \ 53 | hex2cmd.o 54 | 55 | CD_OBJECTS = \ 56 | cmddump.o \ 57 | load_cmd.o 58 | 59 | Z80CODE = export.cmd import.cmd settime.cmd xtrsmous.cmd \ 60 | xtrs8.dct xtrshard.dct \ 61 | fakerom.hex xtrsrom4p.hex esfrom.hex 62 | 63 | MANPAGES = xtrs.txt mkdisk.txt cassette.txt cmddump.txt hex2cmd.txt 64 | 65 | PDFMANPAGES = cassette.man.pdf \ 66 | cmddump.man.pdf \ 67 | hex2cmd.man.pdf \ 68 | mkdisk.man.pdf \ 69 | xtrs.man.pdf 70 | 71 | HTMLDOCS = cpmutil.txt \ 72 | dskspec.txt 73 | 74 | PROGS = xtrs mkdisk hex2cmd cmddump 75 | 76 | GXTRS = gxtrs 77 | GLADE = '"$(SHAREDIR)/xtrs.glade"' 78 | 79 | default: $(PROGS) docs 80 | 81 | all: default z80code gxtrs 82 | 83 | docs: $(MANPAGES) $(PDFMANPAGES) $(HTMLDOCS) 84 | 85 | z80code: $(Z80CODE) 86 | 87 | # Local customizations for make variables are done in Makefile.local: 88 | include Makefile.local 89 | 90 | CFLAGS += $(DEBUG) $(ENDIAN) $(DEFAULT_ROM) $(READLINE) $(DISKDIR) $(IFLAGS) \ 91 | $(APPDEFAULTS) $(FASTMEM) -DKBWAIT -D_DARWIN_C_SOURCE 92 | 93 | LIBS = $(XLIB) $(READLINELIBS) $(EXTRALIBS) 94 | 95 | # For original zmac 1.3: 96 | #ZMACFLAGS = -h -l 97 | 98 | # For George Phillips zmac; see https://github.com/gp48k/zmac. The -P 99 | # flag isn't really needed, but it's here so that if someone uses zmac 100 | # 1.3 with these flags, they'll get an error message (because zmac 1.3 101 | # doesn't have that flag) instead of the wrong thing happening. Ugh. 102 | ZMACFLAGS = -P 103 | 104 | .SUFFIXES: .z80 .cmd .dct .man .txt .hex .html 105 | 106 | .z80.cmd: 107 | zmac $(ZMACFLAGS) -o $*.hex $< 108 | hex2cmd $*.hex > $*.cmd 109 | rm -f $*.hex 110 | 111 | .z80.dct: 112 | zmac $(ZMACFLAGS) -o $*.hex $< 113 | hex2cmd $*.hex > $*.dct 114 | rm -f $*.hex 115 | 116 | .z80.hex: 117 | zmac $(ZMACFLAGS) -o $*.hex $< 118 | 119 | .man.txt: 120 | man -l $< > $*.txt 121 | # if needed, you can try this old fashioned alternative: 122 | # nroff -man -c -Tascii $< | colcrt - | cat -s > $*.txt 123 | 124 | .html.txt: 125 | html2text -nobs -style pretty $< >$@ 126 | 127 | %.man.pdf: %.man 128 | groff -man -Tpdf $< > $@ 129 | # if needed, use this workaround for https://savannah.gnu.org/bugs/?67169: 130 | # groff -rU0 -man -Tpdf $< > $@ 131 | 132 | xtrs: $(OBJECTS) $(X_OBJECTS) 133 | $(CC) $(LDFLAGS) -o xtrs $(OBJECTS) $(X_OBJECTS) $(LIBS) 134 | 135 | gxtrs: $(OBJECTS) $(GTK_OBJECTS) 136 | $(CC) $(LDFLAGS) -o gxtrs -rdynamic \ 137 | $(OBJECTS) $(GTK_OBJECTS) $(LIBS) \ 138 | `pkg-config --libs gtk+-2.0` 139 | 140 | compile_rom: $(CR_OBJECTS) 141 | $(CC) $(LDFLAGS) -o compile_rom $(CR_OBJECTS) 142 | 143 | trs_rom1.c: compile_rom $(BUILT_IN_ROM1) 144 | ./compile_rom 1 $(BUILT_IN_ROM1) > trs_rom1.c 145 | 146 | trs_rom1x.c: compile_rom $(BUILT_IN_ROM1X) 147 | ./compile_rom 1x $(BUILT_IN_ROM1X) > trs_rom1x.c 148 | 149 | trs_rom3.c: compile_rom $(BUILT_IN_ROM3) 150 | ./compile_rom 3 $(BUILT_IN_ROM3) > trs_rom3.c 151 | 152 | trs_rom4p.c: compile_rom $(BUILT_IN_ROM4P) 153 | ./compile_rom 4p $(BUILT_IN_ROM4P) > trs_rom4p.c 154 | 155 | trs_gtkinterface.o: trs_gtkinterface.c 156 | $(CC) -c $(CFLAGS) -DGLADE_FILE=$(GLADE) `pkg-config --cflags gtk+-2.0` $< 157 | 158 | keyrepeat.o: keyrepeat.c 159 | $(CC) -c $(CFLAGS) `pkg-config --cflags gtk+-2.0` $< 160 | 161 | mkdisk: $(MD_OBJECTS) 162 | $(CC) $(LDFLAGS) -o mkdisk $(MD_OBJECTS) 163 | 164 | hex2cmd: $(HC_OBJECTS) 165 | $(CC) $(LDFLAGS) -o hex2cmd $(HC_OBJECTS) 166 | 167 | cmddump: $(CD_OBJECTS) 168 | $(CC) $(LDFLAGS) -o cmddump $(CD_OBJECTS) 169 | 170 | clean: 171 | rm -f $(OBJECTS) $(MD_OBJECTS) \ 172 | $(X_OBJECTS) $(GTK_OBJECTS) \ 173 | $(CR_OBJECTS) $(HC_OBJECTS) \ 174 | $(CD_OBJECTS) trs_rom*.c *~ \ 175 | $(PROGS) compile_rom gxtrs \ 176 | $(HTMLDOCS) 177 | 178 | veryclean: clean 179 | rm -f $(Z80CODE) $(MANPAGES) $(PDFMANPAGES) *.lst 180 | 181 | link: 182 | rm -f xtrs 183 | make xtrs 184 | 185 | install: install-progs install-docs 186 | 187 | install-all: install install-gxtrs 188 | 189 | install-progs: $(PROGS) $(SRCDIR)$(CASSETTE) 190 | $(INSTALL) -d -m 755 $(BINDIR) 191 | $(INSTALL) -c -m 755 $(PROGS) $(BINDIR) 192 | $(INSTALL) -c -m 755 $(SRCDIR)$(CASSETTE) $(BINDIR)/cassette 193 | 194 | install-docs: docs 195 | $(INSTALL) -d -m 755 $(MANDIR) 196 | $(INSTALL) -d -m 755 $(MANDIR)/man1 197 | $(INSTALL) -c -m 644 $(SRCDIR)xtrs.man $(MANDIR)/man1/xtrs.1 198 | $(INSTALL) -c -m 644 $(SRCDIR)cassette.man $(MANDIR)/man1/cassette.1 199 | $(INSTALL) -c -m 644 $(SRCDIR)mkdisk.man $(MANDIR)/man1/mkdisk.1 200 | $(INSTALL) -c -m 644 $(SRCDIR)cmddump.man $(MANDIR)/man1/cmddump.1 201 | $(INSTALL) -c -m 644 $(SRCDIR)hex2cmd.man $(MANDIR)/man1/hex2cmd.1 202 | $(INSTALL) -d -m 755 $(DOCDIR) 203 | $(INSTALL) -c -m 644 $(PDFMANPAGES) $(DOCDIR) 204 | $(INSTALL) -c -m 644 $(SRCDIR)cpmutil.html $(DOCDIR) 205 | $(INSTALL) -c -m 644 cpmutil.txt $(DOCDIR) 206 | $(INSTALL) -c -m 644 $(SRCDIR)dskspec.html $(DOCDIR) 207 | $(INSTALL) -c -m 644 dskspec.txt $(DOCDIR) 208 | 209 | install-gxtrs: $(GXTRS) 210 | $(INSTALL) -d -m 755 $(BINDIR) 211 | $(INSTALL) -c -m 755 $(GXTRS) $(BINDIR) 212 | $(INSTALL) -d -m 755 $(SHAREDIR) 213 | $(INSTALL) -c -m 755 xtrs.glade $(SHAREDIR) 214 | 215 | depend: 216 | makedepend -Y -- $(CFLAGS) -- *.c 2>&1 | \ 217 | (egrep -v 'cannot find|not in' || true) 218 | 219 | # DO NOT DELETE THIS LINE -- make depend depends on it. 220 | 221 | cmddump.o: load_cmd.h 222 | common.o: z80.h config.h trs_disk.h trs_hard.h trs_stringy.h reed.h 223 | compile_rom.o: z80.h config.h load_cmd.h 224 | debug.o: z80.h config.h trs.h 225 | dis.o: z80.h config.h 226 | error.o: z80.h config.h 227 | hex2cmd.o: cmd.h z80.h config.h 228 | load_cmd.o: load_cmd.h 229 | load_hex.o: z80.h config.h 230 | main.o: z80.h config.h trs.h trs_disk.h trs_hard.h load_cmd.h 231 | mkdisk.o: trs_disk.h trs_hard.h trs_stringy.h z80.h config.h 232 | trs_cassette.o: trs.h z80.h config.h 233 | trs_chars.o: trs_iodefs.h 234 | trs_disk.o: z80.h config.h trs.h trs_disk.h trs_hard.h crc.c 235 | trs_gtkinterface.o: trs.h z80.h config.h trs_iodefs.h trs_disk.h trs_uart.h 236 | trs_gtkinterface.o: trs_hard.h keyrepeat.h 237 | trs_hard.o: trs.h z80.h config.h trs_hard.h reed.h 238 | trs_imp_exp.o: trs_imp_exp.h z80.h config.h trs.h trs_disk.h trs_hard.h 239 | trs_interrupt.o: z80.h config.h trs.h 240 | trs_io.o: z80.h config.h trs.h trs_disk.h trs_hard.h trs_uart.h 241 | trs_keyboard.o: z80.h config.h trs.h 242 | trs_memory.o: z80.h config.h trs.h trs_disk.h trs_hard.h 243 | trs_printer.o: z80.h config.h trs.h 244 | trs_stringy.o: z80.h config.h trs.h trs_disk.h trs_stringy.h 245 | trs_uart.o: trs.h z80.h config.h trs_uart.h trs_hard.h 246 | trs_xinterface.o: trs_iodefs.h trs.h z80.h config.h trs_disk.h trs_uart.h 247 | trs_xinterface.o: trs_hard.h trs_imp_exp.h 248 | z80.o: z80.h config.h trs.h trs_imp_exp.h 249 | -------------------------------------------------------------------------------- /Makefile.local: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile.local: local customizations for the xtrs Makefile 3 | # 4 | 5 | # Set these to where you want installed stuff to go, if you install 6 | 7 | PREFIX = $(DESTDIR)/usr 8 | BINDIR = $(PREFIX)/bin 9 | MANDIR = $(PREFIX)/share/man 10 | DOCDIR = $(PREFIX)/share/doc/xtrs 11 | SHAREDIR = $(PREFIX)/share/xtrs 12 | 13 | # If your machine is not a sun, vax, or DEC MIPS, uncomment the line below 14 | # if the processor has big-endian byte ordering. If you're not sure what 15 | # to do, don't worry -- the program will complain if it's not right. 16 | 17 | # ENDIAN = -Dbig_endian 18 | 19 | # Define this if you would like to use the old "mem_block_transfer"-method 20 | # for LDIR/LDDR-opcodes: faster, but not how it works on the real Z80-CPU! 21 | # FASTMEM = -DFASTMEM 22 | 23 | # If you want the C-shell version of the cassette script: 24 | #CASSETTE = cassette.csh 25 | # If you want the POSIX-shell version of the cassette script: 26 | CASSETTE = cassette.sh 27 | 28 | # If you would like the TRS-80 ROM to be built into the application, 29 | # use the following lines (with the appropriate file names). You can 30 | # get a ROM image from a real TRS-80 with moderate effort, if you have 31 | # one. There are also Web sites with TRS-80 ROMs that can be 32 | # downloaded, but none are included with this package due to copyright 33 | # concerns. As another alternative, for -model III or 4, you can 34 | # export the MODELA/III file from a Model III or 4 TRSDOS or 35 | # LDOS/LS-DOS diskette and use it as BUILT_IN_ROM3. 36 | 37 | # The default ROM for -model I, III and 4 (fakerom.hex) just prints a 38 | # message saying that you don't have a ROM. The default ROM for 39 | # -model 4P (xtrsrom4p.hex) is a free minimal ROM that can boot a 40 | # Model 4 mode operating system (such as TRSDOS/LDOS 6); source code 41 | # is included in this package. This ROM cannot boot a Model III mode 42 | # operating system. 43 | 44 | # for -model I 45 | BUILT_IN_ROM1 = fakerom.hex 46 | BUILT_IN_ROM1X = esfrom.hex 47 | # for -model III and -model 4 48 | BUILT_IN_ROM3 = fakerom.hex 49 | # for -model 4P 50 | BUILT_IN_ROM4P = xtrsrom4p.hex 51 | 52 | # If you would like the application to load a default ROM file at 53 | # startup time, use these lines (with the appropriate file names). If 54 | # a ROM file is present, it takes precedence over the corresponding 55 | # built-in ROM. 56 | 57 | DEFAULT_ROM = -DDEFAULT_ROM1='"$(SHAREDIR)/level2rom.hex"' \ 58 | -DDEFAULT_ROM1X='"$(SHAREDIR)/esfrom.hex"' \ 59 | -DDEFAULT_ROM3='"$(SHAREDIR)/romimage.m3"' \ 60 | -DDEFAULT_ROM4P='"$(SHAREDIR)/romimage.m4p"' 61 | 62 | # If you would like to change where xtrs looks for disk?-? files, edit 63 | # this line. "." of course means the current working directory. 64 | 65 | DISKDIR = -DDISKDIR='"."' 66 | 67 | # If you have the GNU readline package (the README file tells you where to 68 | # get it) and would like to use it with the built-in Z80 debugger, use 69 | # these lines. 70 | 71 | READLINE = -DREADLINE 72 | READLINELIBS = -lreadline 73 | 74 | # Select debugging symbols (-g) and/or optimization (-O2, etc.) 75 | # Annoyingly, it seems that -Wdeprecated-declarations gives a warning 76 | # even if you don't use the deprecated type, and gtk header files 77 | # deprecated some types. 78 | 79 | DEBUG = -O2 -g -Wall -Wextra -Wno-unused-parameter -Wno-deprecated-declarations 80 | #DEBUG = -g -DKBDEBUG -DXDEBUG 81 | #DEBUG = -g 82 | #DEBUG = -Wall 83 | 84 | # If you have gcc, and you want to use it: 85 | 86 | #CC = gcc 87 | 88 | # If you need a different path for libraries: 89 | 90 | LDFLAGS += -L/usr/lib/X11 91 | #LDFLAGS = -non_shared -L/usr/X11/lib 92 | 93 | # If you need a different path for include files: 94 | 95 | IFLAGS = -I/usr/include/X11 96 | 97 | # Re-define this if your X library is strangely named: 98 | 99 | XLIB = -lX11 100 | 101 | # Use this if you need yet more libraries: 102 | 103 | #EXTRALIBS = -ldnet 104 | #EXTRALIBS = -lots 105 | #EXTRALIBS = -ldnet_stub 106 | 107 | # If you want xtrs to look for a global app-defaults file 108 | # at runtime in $APPDEFAULTS/Xtrs: 109 | 110 | APPDEFAULTS = -DAPPDEFAULTS='"/etc/X11/app-defaults"' 111 | 112 | # Change this if you have a BSD-compatible install program that is 113 | # not the first program named "install" on your $PATH 114 | 115 | INSTALL = install 116 | 117 | # If you are building in a subdirectory: 118 | #SRCDIR=../ 119 | #vpath %.c .. 120 | #vpath %.h .. 121 | #vpath %.man .. 122 | #vpath %.html .. 123 | #vpath %.z80 .. 124 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Building xtrs 2 | Tim Mann 3 | 10/27/2020, updated 5/10/2025 4 | 5 | xtrs and gxtrs compile on typical Linux distributions if you install 6 | enough packages, except for one dependency: zmac. zmac is a Z-80 7 | cross-assembler. There is an updated version with lots of features at 8 | https://github.com/gp48k/zmac or http://48k.ca/zmac.html. I've 9 | updated the xtrs Makefile to work with that new version, but by 10 | changing which definition of ZMACFLAGS is commented out, you could go 11 | back to the old zmac 1.3 that I used when developing xtrs, which you 12 | can download from https://tim-mann.org/trs80resources.html. 13 | 14 | ************************************************************************* 15 | 16 | xtrs README 17 | Tim Mann 18 | http://tim-mann.org/ 19 | 1/12/98 20 | 21 | As computer scientists, we always long for something bigger and better 22 | than what we have now. Give us a megabyte, and we want a gigabyte. 23 | Give us an emulated TRS-80 Model I with Level II BASIC and cassette, 24 | and we long for the Expansion Interface and floppy disk drives. Give 25 | us that, and we want a Model III. Give us a Model III, and we want a 26 | Model 4! 27 | 28 | This is a snapshot of the work I've been doing on xtrs to add these 29 | niceties. My main additions over xtrs-1.0 have been floppy disk and 30 | hard disk emulation, timer interrupt emulation, a kludge to import and 31 | export data to the host system, Model III mode, Model 4 mode, a 32 | rewrite of the keyboard handling, support for most of the undocumented 33 | Z-80 instructions, and a bunch of bug fixes and minor improvements. 34 | 35 | This project has been a real (48KB?) trip down memory lane for me. I 36 | worked as a programmer for Logical Systems, the company that produced 37 | LDOS, during 1980-81 before I went to grad school. I no longer own a 38 | TRS-80, but I recently found a box in my storage closet containing all 39 | my Model I hardware manuals, schematics, ROM disassemblies, and even 40 | the assembly listing for a version of the LDOS Percom Doubler driver 41 | that I helped write, giving me enough information to get my additions 42 | to xtrs off the ground. 43 | 44 | Since then I've done much more. Check out my TRS-80 Web page at 45 | http://www.tim-mann.org/trs80.html for details! 46 | 47 | ************************************************************************* 48 | 49 | Below is the original README file from xtrs 1.0. It is outdated, but 50 | I've kept it for historical reasons and to credit the original authors. 51 | 52 | 53 | XTRS 54 | 55 | A TRS-80 Model I Emulator for X Windows 56 | 57 | by David Gingold 58 | and Alec Wolman 59 | 60 | Version 1.0 61 | 62 | April 1, 1992 63 | 64 | 65 | 66 | WHAT IS XTRS? 67 | 68 | As computer scientists, we and our colleagues now and then experience a 69 | strange yet powerful desire to write some BASIC code on the computer system 70 | that was for many of us the first we owned or programmed: the TRS-80 Model 71 | I. In our modern systems of networked workstations and window systems, 72 | this capability has been strangely neglected. Xtrs is our attempt to fill 73 | this important void in our computing environment. 74 | 75 | Xtrs is an X Windows client which runs under Unix and emulates a TRS-80 76 | Model I. Version 1.0 is our first release of this software; it provides a 77 | simple yet powerful Level II BASIC environment and cassette emulation. We 78 | expect to provide some more sophisticated functionality in future releases. 79 | 80 | 81 | OBTAINING XTRS: 82 | 83 | If you have Internet access, you can get a copy of the latest xtrs software 84 | via anonymous FTP: 85 | 86 | Host: think.com 87 | Directory: /users/gingold/xtrs 88 | File: xtrs-1.0.tar.Z 89 | 90 | We will also be posting the sources to alt.sources and perhaps to 91 | comp.sources.x. 92 | 93 | 94 | OBTAINING THE ROM: 95 | 96 | You will need a copy of the Level II ROM software in order to use xtrs. 97 | 98 | The Level II ROM software may be covered by copyrights; for this reason we 99 | are not distributing it with our xtrs software. However, if you already 100 | own the Level II ROM software, then you can make yourself a copy of this 101 | for use with xtrs (as long as you obey the legal restrictions for its fair 102 | use). You can get such a copy via anonymous FTP. 103 | 104 | Please do not make illegal copies of the ROM software. 105 | 106 | You already own a legal copy of the Level II ROM software if: 107 | - You own a TRS-80 Model I with Level II Basic, 108 | - You own a TRSDOS disk which has a copy of the ROM image on it, or 109 | - You own a copy of Farvour's "Microsoft Basic Decoded" which contains the 110 | ROM code listing. 111 | 112 | If you have Internet access, you can get a copy of the ROM software via 113 | anonymous ftp: 114 | 115 | Host: think.com 116 | Directory: /users/gingold/xtrs/rom 117 | File: level2rom.hex 118 | 119 | If you are obtaining the ROM software through other means (such as getting 120 | it directly out of your TRS-80), you'll need to end up with an ASCII file 121 | which is in what we believe to be an "Intel Hex" format -- this is a format 122 | used with PROM programmers. 123 | 124 | Our disclaimer: We have neither sought nor received permission from anybody 125 | to distribute copies of the ROM software. We discourage your making 126 | illegal copies of this or any software. Neither we nor our employers will 127 | accept any sort of responsibility if you illegaly copy the ROM software. 128 | We are not lawyers, and are in no position to advise you on what is legal. 129 | 130 | (For the legally curious: the TRS-80 we own has a copyright notice on the 131 | ROM PC board, but none on the ROMs themselves or within the software. We 132 | don't know if Farvour had permission to publish the ROM code.) 133 | 134 | 135 | BUILDING THE PROGRAM: 136 | 137 | You can uncompress and extract the software from the tar file as follows: 138 | 139 | % uncompress xtrs-1.0.tar.Z 140 | % tar xvf xtrs-1.0.tar 141 | 142 | You can then build the program using "make". You will probably need to 143 | edit the file "Makefile.local" in order to compile the program properly. 144 | Notes in that file explain how to do this. 145 | 146 | It is possible either to compile the ROM image into the program or to keep 147 | the rom file separate, optionally specified on the command line. The 148 | "Makefile.local" describes how to do this. 149 | 150 | If you would like to use the Gnu "readline" facility with the our built-in 151 | Z-80 debugger, you can get this software via anonymous FTP: 152 | 153 | Host: athena-dist.mit.edu 154 | File: /pub/gnu/readline-1.1.tar.Z 155 | 156 | 157 | RUNNING THE PROGRAM: 158 | 159 | See the manual page. 160 | 161 | 162 | DETAILS: 163 | 164 | Xtrs is built on top of a (mostly) full Z-80 emulator, with added routines 165 | to support keyboard and video I/O through an X Windows interface. The 166 | hardware emulation is based on the TRS-80 Model I design. 167 | 168 | Xtrs supports 48K of RAM. There is support for a rudimentary cassette I/O 169 | emulation which uses files for cassette tapes. A printer is emulated by 170 | sending its output to standard output. There is no support (yet) for a 171 | disk or a serial port. 172 | 173 | The speed of the emulator is pretty good. On a decent Sun-4 compiled with 174 | gcc, it computes a little faster than the real thing. Some operations 175 | (such as writing to the screen) will naturally be slower. 176 | 177 | The Z-80 emulator is written to be portable to most C environments. It is 178 | possible to build a faster emulator by sacrificing this portability (such 179 | emulators have been built for 80x86 and 680x0 machines), but that wasn't 180 | our goal. Memory accesses are handled through a function call interface, 181 | allowing us to cleanly emulate memory-mapped devices. 182 | 183 | The Z-80 emulator has a way-cool debugger called zbx. It works sort of 184 | like dbx. If you run with the -debug switch you'll enter the debugger, and 185 | you can type "help" for more information. 186 | 187 | Some Z-80 things are not supported: interrupts other than the non-maskable 188 | interrupt, other esoteric signals not used by the TRS-80, and any of the 189 | "undocumented" Z-80 instructions. Reading the memory refresh register 190 | gives a pseudo-random value. The execution speed of instructions bears no 191 | relationship to actual Z-80 timings. 192 | 193 | Special support in the emulator allows the program to block when waiting 194 | for information from the keyboard. This will only work for programs which 195 | get keyboard input via the standard ROM calls. We do similar tricks to 196 | make the cassette I/O work. 197 | 198 | 199 | BUGS: 200 | 201 | The manual page lists a few known bugs. 202 | 203 | If you discover bugs (or write fixes for any of these), please let us know 204 | (you can send us mail at the above addresses). We expect to incorporate 205 | fixes into future releases. 206 | 207 | 208 | FUTURE ENHANCEMENTS: 209 | 210 | Here are some features we are thinking of adding to xtrs in the future: 211 | 212 | - A better name for the application. We're not too happy with "xtrs". 213 | - An emulator for disk drives. 214 | - A mechanism for digitizing cassette tapes. 215 | - A nicer mechanism for controlling the cassette emulator. 216 | - A cut and paste mechanism in the X window. 217 | - An emulator for the serial port. 218 | - A Macintosh implementation. 219 | 220 | 221 | CREDITS: 222 | 223 | David Gingold wrote the Z-80 emulator, zbx, and much of 224 | the TRS-80 emulation. 225 | 226 | Alec Wolman wrote the X windows interface and some of 227 | the associated routines. 228 | 229 | Bruce Norskog is the suspected author of a program called "zdis" which was 230 | incorporated into the debugger to disassemble Z-80 instructions. 231 | 232 | Rodnay Zach's "Programming the Z-80" was the reference for implementing the 233 | Z-80 emulator. 234 | 235 | James Farvour's "Microsoft Basic Decoded and Other Mysteries" and George 236 | Blank's "Pathways through the ROM" helped us to debug the emulator and 237 | figure out how to make the gnarly keyboard and cassette hacks work. Thanks 238 | go to David Librik and Marty Brilliant for providing these books. 239 | 240 | Jim Cathey, Charlie Gibbs, and Willi Kusche wrote SimCPM, a CPM simulator 241 | for the Amiga. This was used (don't ask how) to help debug our Z-80 242 | emulator. 243 | -------------------------------------------------------------------------------- /cassette.csh: -------------------------------------------------------------------------------- 1 | #!/bin/csh -f 2 | # Try cassette.sh instead if you do not have /bin/csh. 3 | # $Id$ 4 | 5 | set done = 0 6 | set control_file = '.cassette.ctl' 7 | set default_format = '1' 8 | set format_name = ( 'cas' 'cpt' 'wav' 'direct' 'debug' ) 9 | 10 | if(! -e $control_file) then 11 | echo "Creating" $control_file 12 | echo "cassette.$format_name[$default_format] 0 $default_format" \ 13 | > $control_file 14 | endif 15 | 16 | while($done != 1) 17 | set control = `cat $control_file` 18 | set filename = $control[1] 19 | set position = $control[2] 20 | if (${#control} < 3) then 21 | set format = $default_format 22 | else 23 | set format = $control[3] 24 | endif 25 | if ({ test -e $filename }) then 26 | set isnew = "" 27 | else 28 | set isnew = " (new)" 29 | endif 30 | echo "" 31 | echo "Tape loaded: " $filename$isnew 32 | echo "Type: " $format_name[$format] 33 | echo "Position: " $position 34 | echo "" 35 | echo -n "Command: " 36 | set command = "$<" 37 | set command = ( $command ) 38 | 39 | if($#command < 1) then 40 | set command = "help" 41 | endif 42 | switch($command[1]) 43 | 44 | case "pos": 45 | breaksw 46 | 47 | case "load": 48 | case "file": 49 | if($#command != 2) then 50 | echo "Must specify a file name" 51 | else 52 | switch($command[2]) 53 | case *.cas: 54 | case *.bin: 55 | set format = 1 56 | breaksw 57 | case *.cpt: 58 | set format = 2 59 | breaksw 60 | case *.wav: 61 | set format = 3 62 | breaksw 63 | case "/dev/dsp*": 64 | set format = 4 65 | breaksw 66 | case *.debug: 67 | set format = 5 68 | breaksw 69 | default: 70 | set format = $default_format 71 | breaksw 72 | endsw 73 | echo $command[2] 0 $format > $control_file 74 | endif 75 | breaksw 76 | 77 | case "type": 78 | if($#command != 2) then 79 | echo "Types are:" 80 | echo " " $format_name 81 | else 82 | switch($command[2]) 83 | case "cas": 84 | set format = 1 85 | breaksw 86 | case "cpt": 87 | set format = 2 88 | breaksw 89 | case "wav": 90 | set format = 3 91 | breaksw 92 | case "direct": 93 | set format = 4 94 | set filename = "/dev/dsp" 95 | set position = 0 96 | breaksw 97 | case "debug": 98 | set format = 5 99 | breaksw 100 | default: 101 | echo "Types are:" 102 | echo " " $format_name 103 | breaksw 104 | endsw 105 | echo $filename $position $format > $control_file 106 | endif 107 | breaksw 108 | 109 | case "rew": 110 | if($#command == 2) then 111 | @ position = $command[2] 112 | else 113 | @ position = 0 114 | endif 115 | 116 | echo $filename $position $format > $control_file 117 | breaksw 118 | 119 | case "ff": 120 | if($#command == 2) then 121 | @ position = $command[2] 122 | else 123 | set wcout = `wc -c $filename` 124 | @ position = $wcout[1] 125 | endif 126 | 127 | echo $filename $position $format > $control_file 128 | breaksw 129 | 130 | case "quit": 131 | case "exit": 132 | case "done": 133 | set done = 1 134 | breaksw 135 | 136 | case "help": 137 | default: 138 | echo "Commands are:" 139 | echo " pos" 140 | echo " load filename" 141 | echo " type {$format_name}" 142 | echo " rew [position]" 143 | echo " ff [position]" 144 | echo " quit" 145 | breaksw 146 | 147 | endsw 148 | end 149 | 150 | exit 0 151 | -------------------------------------------------------------------------------- /cassette.man: -------------------------------------------------------------------------------- 1 | .\" in Michael Kerrisk's man-pages(7) and GNU's groff_man(7), and groff(7). 2 | .\" 3 | .\" The following macro definitions come from groff's an-ext.tmac. 4 | .\" 5 | .\" Copyright (C) 2007-2014 Free Software Foundation, Inc. 6 | .\" 7 | .\" Written by Eric S. Raymond 8 | .\" Werner Lemberg 9 | .\" 10 | .\" You may freely use, modify and/or distribute this file. 11 | .\" 12 | .\" If _not_ GNU roff, define UR and UE macros to handle URLs. 13 | .if !\n[.g] \{\ 14 | .\" Start URL. 15 | .de UR 16 | . ds m1 \\$1\" 17 | . nh 18 | . if \\n(mH \{\ 19 | . \" Start diversion in a new environment. 20 | . do ev URL-div 21 | . do di URL-div 22 | . \} 23 | .. 24 | . 25 | . 26 | .\" End URL. 27 | .de UE 28 | . ie \\n(mH \{\ 29 | . br 30 | . di 31 | . ev 32 | . 33 | . \" Has there been one or more input lines for the link text? 34 | . ie \\n(dn \{\ 35 | . do HTML-NS "" 36 | . \" Yes, strip off final newline of diversion and emit it. 37 | . do chop URL-div 38 | . do URL-div 39 | \c 40 | . do HTML-NS 41 | . \} 42 | . el \ 43 | . do HTML-NS "\\*(m1" 44 | \&\\$*\" 45 | . \} 46 | . el \ 47 | \\*(la\\*(m1\\*(ra\\$*\" 48 | . 49 | . hy \\n(HY 50 | .. 51 | .\} \" not GNU roff 52 | .\" End of Free Software Foundation copyrighted material. 53 | .\" 54 | .\" Copyright (C) 1999-2018 Timothy P. Mann 55 | .\" 56 | .\" Permission is hereby granted, free of charge, to any person 57 | .\" obtaining a copy of this software and associated documentation 58 | .\" files (the "Software"), to deal in the Software without 59 | .\" restriction, including without limitation the rights to use, copy, 60 | .\" modify, merge, publish, distribute, sublicense, and/or sell copies 61 | .\" of the Software, and to permit persons to whom the Software is 62 | .\" furnished to do so, subject to the following conditions: 63 | .\" 64 | .\" The above copyright notice and this permission notice shall be 65 | .\" included in all copies or substantial portions of the Software. 66 | .\" 67 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 68 | .\" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 69 | .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 70 | .\" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 71 | .\" HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 72 | .\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 73 | .\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 74 | .\" DEALINGS IN THE SOFTWARE. 75 | .\" 76 | .TH cassette 1 2008-06-26 xtrs 77 | .SH Name 78 | cassette \- data cassette image manipulator for xtrs TRS-80 emulator 79 | .SH Synopsis 80 | .B cassette 81 | .SH Description 82 | To control the emulated cassette used by 83 | .BR xtrs , 84 | a file called 85 | .I .cassette.ctl 86 | in the current directory keeps track of what file is currently \(lqloaded\(rq as 87 | the cassette tape and the current position within that file. 88 | The 89 | .B cassette 90 | shell script provides a way to manipulate 91 | this file. 92 | You can use this script to load and position cassette tape files. 93 | The operation works very much like an actual tape recorder. 94 | .PP 95 | This manual page also describes the image formats that the emulator supports and 96 | their limitations. 97 | . 98 | .SS Commands 99 | .TP 100 | .B help 101 | lists the available commands. 102 | .TP 103 | .B pos 104 | generates a status message including the filename being used as the 105 | cassette image and the current position within the image, in bytes. 106 | .TP 107 | .BI load " filename" 108 | changes the cassette image currently being used to the file specified, and 109 | resets the position counter to zero. 110 | .TP 111 | .BI type " \fR[\fPformat\fR]\fP" 112 | tells the emulator what type of image is loaded. 113 | Usually 114 | .I format 115 | is detected from the file extension, but you can override the detected value 116 | with this command. 117 | Omitting 118 | .I format 119 | from the command lists the supported format types. 120 | .TP 121 | .BI rew " \fR[\fPposition\fR]\fP" 122 | changes the position counter to the position specified. 123 | If no position is given, the counter is reset to zero. 124 | .TP 125 | .BI ff " \fR[\fPposition\fR]\fP" 126 | changes the position counter to the position specified. 127 | If no position is given, the counter is set to the end of the file. 128 | .TP 129 | .B quit 130 | exits 131 | .BR cassette . 132 | .SS Format Types 133 | .B xtrs 134 | supports several different types of cassette images, each of which represents 135 | cassette data in a different format. 136 | .TP 137 | .B cas 138 | format is fairly compact and is compatible with other TRS-80 emulators 139 | that have cassette support. 140 | This format represents the bit stream that (the emulator thinks) the TRS-80 141 | cassette routines were trying to save to the tape, not the actual electrical 142 | signals on the tape. 143 | .IP "" 144 | On writing, the emulator monitors the values that the TRS-80 software is 145 | sending to the cassette port and their timing, auto-recognizes whether 146 | a 250-bps, 500-bps, or 1500-bps format is being written, decodes the 147 | signals into a string of 0 and 1 bits, packs the bits into bytes, and 148 | writes them to the 149 | .B cas 150 | file. 151 | On reading, the emulator auto-detects whether software is trying to read at 250, 152 | 500, or 1500 bps and encodes the \(lq0\(rqs and \(lq1\(rqs back into the signals 153 | that the TRS-80 software is expecting. 154 | This somewhat roundabout method should work with most TRS-80 cassette routines 155 | that read and write signals compatible with the ROM cassette routines, but it 156 | may fail with custom routines that are too different. 157 | .IP "" 158 | Note that generally nothing useful will happen if you try to write a 159 | .B cas 160 | image at one speed and read it at another. 161 | There are differences in the actual bit streams that standard TRS-80 software 162 | records at each of the three different speeds, not just differences in encoding 163 | the electrical signals on the tape. 164 | Thus an incoming bit stream that was originally recorded at one speed will not 165 | be understood when read back in at a different speed. 166 | For example, Level II BASIC programs are tokenized, while Level I BASIC programs 167 | are not, and the two BASIC implementations record different binary information 168 | at the start of the program and between lines. 169 | Also, when a file is saved at 1500 bps, standard TRS-80 software puts an extra 0 170 | bit after every 8 data bits, and these extra bits are packed into the 171 | .B cas 172 | file along with the data bits. 173 | .TP 174 | .B cpt 175 | format (for \(lqcassette pulse train\(rq) encodes the exact values and timing of 176 | the signals that the TRS-80 cassette routine sends to the cassette output port 177 | to be recorded on the tape. 178 | Timing is to the nearest microsecond. 179 | This format emulates a perfect, noise-free cassette, so any cassette routines 180 | that even halfway worked on real hardware should work with it. 181 | .TP 182 | .B wav 183 | format refers to WAVE, a standard sound file format developed by IBM and 184 | Microsoft. 185 | The 186 | .B wav 187 | format is intermediate in emulation accuracy between 188 | .B cas 189 | and 190 | .BR cpt . 191 | It does represent actual signals, not decoded bits, but its timing precision is 192 | limited by the sample rate used. 193 | The default rate for new 194 | .B wav 195 | files is 11,025 Hz; you can change this with the 196 | .B -samplerate 197 | command-line option to 198 | .BR xtrs . 199 | .IP "" 200 | You can play 201 | .B wav 202 | files written by 203 | .B xtrs 204 | through your sound card and hear roughly what a real TRS-80 cassette sounds 205 | like. 206 | A real TRS-80 should be able to read 207 | .B wav 208 | files written by 209 | .B xtrs 210 | if you copy them to a cassette or connect the TRS-80 directly to the sound 211 | card's output. 212 | This feature has not been tested extensively, but it does seem to work, at least 213 | for short programs. 214 | .IP "" 215 | .B xtrs 216 | can also read 217 | .B wav 218 | files. 219 | It can read back the 220 | .B wav 221 | files that it writes without error. 222 | Reading 223 | .B wav 224 | files sampled from real cassettes is more difficult because of the noise 225 | introduced, but in brief testing it does seem to work. 226 | The signal processing algorithms used are crude, and better ones could 227 | probably do a better job of reading old, noisy cassettes. 228 | Help in this area would be welcome. 229 | .IP "" 230 | The 231 | .B wav 232 | file parsing code has several limitations. 233 | Samples must be 234 | 8-bit monophonic PCM, and the 235 | .B wav 236 | file must contain only one data chunk and no extra optional RIFF chunks in the 237 | header. 238 | If you have a 239 | .B wav 240 | file whose header 241 | .B xtrs 242 | rejects, try using a tool like 243 | .BR sox (1) 244 | to convert it to the required format. 245 | .TP 246 | .B direct 247 | format is similar to 248 | .B wav 249 | format, except that the samples go to (or come from) your sound card directly, 250 | not a WAVE file. 251 | The 252 | .B direct 253 | format requires the Open Sound System 254 | .I /dev/dsp 255 | device. 256 | .TP 257 | .B debug 258 | format is the same as 259 | .B cpt 260 | format except that the data is written in human-readable ASCII. 261 | The cassette output is assumed to be 0 initially. 262 | Each line of output gives a new value (0, 1, or 2), and the amount of time (in 263 | microseconds) to wait before changing the output to this value. 264 | .SH See also 265 | .BR xtrs (1) 266 | .\" $Id$ 267 | .\" vim:set et ft=nroff tw=80: 268 | -------------------------------------------------------------------------------- /cassette.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # $Id$ 3 | 4 | arrayitem () { 5 | INDEX=$1 6 | shift 7 | eval echo \$$INDEX; 8 | } 9 | 10 | arraycount () { 11 | echo $#; 12 | } 13 | 14 | DONE=no 15 | CONTROL_FILE=.cassette.ctl 16 | DEFAULT_FORMAT=1 17 | FORMAT_NAME='cas cpt wav direct debug' 18 | 19 | if [ ! -e "$CONTROL_FILE" ]; then 20 | echo Creating $CONTROL_FILE 21 | echo "cassette.$(arrayitem $DEFAULT_FORMAT $FORMAT_NAME) 0 $DEFAULT_FORMAT" > \ 22 | $CONTROL_FILE 23 | fi 24 | 25 | while [ "$DONE" != "yes" ]; do 26 | CONTROL=$(cat $CONTROL_FILE) 27 | FILENAME=$(arrayitem 1 $CONTROL) 28 | POSITION=$(arrayitem 2 $CONTROL) 29 | if [ $(arraycount $CONTROL) -lt 3 ]; then 30 | FORMAT=$DEFAULT_FORMAT 31 | else 32 | FORMAT=$(arrayitem 3 $CONTROL) 33 | fi 34 | if [ -e "$FILENAME" ]; then 35 | ISNEW= 36 | else 37 | ISNEW=" (new)" 38 | fi 39 | echo 40 | echo "Tape loaded: $FILENAME$ISNEW" 41 | echo 'Type: '$(arrayitem $FORMAT $FORMAT_NAME) 42 | echo 'Position: '$POSITION 43 | echo 44 | echo -n 'Command: ' 45 | read COMMAND 46 | 47 | if [ $(arraycount $COMMAND) -lt 1 ]; then 48 | COMMAND=help 49 | fi 50 | 51 | TOKEN1="$(arrayitem 1 $COMMAND)" 52 | 53 | case $TOKEN1 in 54 | pos) ;; 55 | load|file) 56 | if [ $(arraycount $COMMAND) -ne 2 ]; then 57 | echo "Must specify a file name" 58 | else 59 | TOKEN2="$(arrayitem 2 $COMMAND)" 60 | case $TOKEN2 in 61 | *.cas|*.bin) 62 | FORMAT=1 ;; 63 | *.cpt) 64 | FORMAT=2 ;; 65 | *.wav) 66 | FORMAT=3 ;; 67 | /dev/dsp*) 68 | FORMAT=4 ;; 69 | *.debug) 70 | FORMAT=5 ;; 71 | *) 72 | FORMAT=1 ;; 73 | esac 74 | echo "$(arrayitem 2 $COMMAND) 0 $FORMAT" > $CONTROL_FILE 75 | fi ;; 76 | type) 77 | if [ $(arraycount $COMMAND) -ne 2 ]; then 78 | echo Types are: 79 | echo ' '$FORMAT_NAME 80 | else 81 | TOKEN2="$(arrayitem 2 $COMMAND)" 82 | case $TOKEN2 in 83 | cas) 84 | FORMAT=1 ;; 85 | cpt) 86 | FORMAT=2 ;; 87 | wav) 88 | FORMAT=3 ;; 89 | direct) 90 | FORMAT=4 91 | FILENAME=/dev/dsp 92 | POSITION=0 ;; 93 | debug) 94 | FORMAT=5 ;; 95 | *) 96 | echo Types are: 97 | echo ' '$FORMAT_NAME ;; 98 | esac 99 | echo "$FILENAME $POSITION $FORMAT" > $CONTROL_FILE 100 | fi ;; 101 | rew) 102 | if [ $(arraycount $COMMAND) -lt 2 ]; then 103 | POSITION=0 104 | else 105 | POSITION=$(arrayitem 2 $COMMAND) 106 | fi 107 | echo "$FILENAME $POSITION $FORMAT" > $CONTROL_FILE ;; 108 | ff) 109 | if [ $(arraycount $COMMAND) -lt 2 ]; then 110 | POSITION=$(wc -c $FILENAME) 111 | else 112 | POSITION=$(arrayitem 2 $COMMAND) 113 | fi 114 | echo "$FILENAME $POSITION $FORMAT" > $CONTROL_FILE ;; 115 | quit|exit|done) 116 | DONE=yes ;; 117 | *) 118 | echo Commands are: 119 | echo ' 'pos 120 | echo ' 'load filename 121 | echo ' 'type {$FORMAT_NAME} 122 | echo ' 'rew [position] 123 | echo ' 'ff [position] 124 | echo ' 'quit ;; 125 | esac 126 | done 127 | 128 | exit 129 | -------------------------------------------------------------------------------- /cd.ccc: -------------------------------------------------------------------------------- 1 | /* cd.ccc -- Misosys C program to change Unix working directory on xtrs */ 2 | 3 | /* 4 | * Copyright (c) 1998-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #option redirect 0 28 | #include "xtrsemt.h" 29 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 30 | 31 | usage() 32 | { 33 | fprintf(stderr, "usage: cd [-l] unixdir\n"); 34 | exit(1); 35 | } 36 | 37 | #define ERRBUFSIZE 256 38 | #define NAMEBUFSIZE 256 39 | 40 | int main(argc, argv) 41 | int argc; 42 | char **argv; 43 | { 44 | int ret, lower, i; 45 | char errbuf[ERRBUFSIZE]; 46 | char namebuf[NAMEBUFSIZE]; 47 | char *p, *q; 48 | 49 | if (argc < 2) { 50 | usage(); 51 | } 52 | i = 1; 53 | if (argv[i][0] == '-') { 54 | if (tolower(argv[i][1]) != 'l') { 55 | usage(); 56 | } 57 | i++; 58 | lower = 1; 59 | } else { 60 | lower = 0; 61 | } 62 | if (argc - i != 1) { 63 | usage(); 64 | } 65 | 66 | p = namebuf; 67 | q = argv[i]; 68 | if (lower) { 69 | while (*q) { 70 | if (*q == '[' && *(q+1)) { 71 | q++; 72 | *p++ = *q++; 73 | } else if (isalpha(*q)) { 74 | *p++ = tolower(*q++); 75 | } else { 76 | *p++ = *q++; 77 | } 78 | } 79 | } else { 80 | while (*q) *p++ = *q++; 81 | } 82 | *p = '\000'; 83 | 84 | ret = emt_chdir(namebuf); 85 | if (ret != 0) { 86 | emt_strerror(errno, errbuf, ERRBUFSIZE); 87 | fprintf(stderr, "%s: %s\n", namebuf, errbuf); 88 | exit(1); 89 | } 90 | exit(0); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /cd.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/cd.cmd -------------------------------------------------------------------------------- /cd6.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/cd6.cmd -------------------------------------------------------------------------------- /cmd.c: -------------------------------------------------------------------------------- 1 | /* Routines to write a TRS-80 DOS "/cmd" file */ 2 | 3 | /* 4 | * Copyright (c) 1996-2020, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | static int last_address, block_address; 30 | static int block_size, got_transfer; 31 | static unsigned char block[256]; 32 | static FILE* file; 33 | 34 | void 35 | cmd_init(FILE* f) 36 | { 37 | last_address = block_address = -2; 38 | block_size = 0; 39 | got_transfer = 0; 40 | file = f; 41 | } 42 | 43 | void 44 | cmd_data(int address, int value) 45 | { 46 | unsigned char* p; 47 | 48 | if (value < 0 || address != last_address + 1 || block_size >= 256) { 49 | if (block_size > 0) { 50 | /* close off current block */ 51 | putc(1, file); 52 | putc((block_size + 2) & 0xff, file); 53 | putc(block_address & 0xff, file); 54 | putc((block_address >> 8) & 0xff, file); 55 | p = block; 56 | while (block_size) { 57 | putc(*p++, file); 58 | block_size--; 59 | } 60 | } 61 | last_address = block_address = address; 62 | if (value == -2) { 63 | /* transfer address */ 64 | putc(2, file); 65 | putc(2, file); 66 | putc(block_address & 0xff, file); 67 | putc((block_address >> 8) & 0xff, file); 68 | return; 69 | } 70 | if (value == -3) { 71 | /* eof, no transfer address */ 72 | putc(3, file); 73 | return; 74 | } 75 | } 76 | /* continue current block */ 77 | block[block_size++] = value; 78 | last_address = address; 79 | return; 80 | } 81 | 82 | void 83 | cmd_transfer_address(int address) 84 | { 85 | cmd_data(address, -2); 86 | got_transfer = 1; 87 | } 88 | 89 | void 90 | cmd_end_of_file(void) 91 | { 92 | if (!got_transfer) cmd_data(0, -3); 93 | } 94 | -------------------------------------------------------------------------------- /cmd.h: -------------------------------------------------------------------------------- 1 | /* Routines to write a TRS-80 DOS "/cmd" file */ 2 | 3 | /* 4 | * Copyright (c) 1996-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | extern void cmd_init(FILE *outf); 28 | extern void cmd_data(int address, int value); 29 | extern void cmd_transfer_address(int address); 30 | extern void cmd_end_of_file(void); 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cmddump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996-2020, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* Simulated TRS-80 DOS /cmd file loader. 26 | * 27 | * See the LDOS Quarterly, April 1, 1982 (Vol 1, No 4), for documentation 28 | * of the TRS-80 DOS /cmd file format. 29 | * 30 | * Usage: cmddump [-flags] infile [outfile startbyte nbytes] 31 | * If the optional arguments are given, the given byte range is dumped 32 | * from the simulated memory after loading. 33 | * 34 | * Flags: -q quiet: turn off -t, -m, -d, -s (later flags can override). 35 | * -t print text of module headers, pds headers, 36 | * patch names, and copyright notices. 37 | * -m print running load map as file is parsed, 38 | * coalescing adjacent blocks (implies -t). (default) 39 | * -d print detailed map; same as -m, but don't coalesce. 40 | * -s print summary load map after file is parsed. 41 | * -i n select ISAM entry n (0x notation OK) 42 | * -p foo select PDS entry "foo" (padded to 8 bytes with spaces) 43 | * -x ignore anything after the first xfer address 44 | */ 45 | 46 | #define _XOPEN_SOURCE /* unistd.h: getopt(), optarg, optind, opterr */ 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include "load_cmd.h" 53 | 54 | unsigned char memory[64*1024] = { 0 }; 55 | unsigned char loadmap[64*1024]; 56 | 57 | #define ARGS "qtmdsi:p:x" 58 | 59 | int 60 | main(int argc, char* argv[]) 61 | { 62 | FILE* f; 63 | int verbosity = VERBOSITY_MAP; 64 | int isam = -1; 65 | char *pds = NULL; 66 | int xferaddr, stopxfer = 0; 67 | int print_summary = 0; 68 | char pdsbuf[9]; 69 | int res; 70 | int c, errflg = 0; 71 | 72 | optarg = NULL; 73 | while (!errflg && (c = getopt(argc, argv, ARGS)) != -1) { 74 | switch (c) { 75 | case 'q': 76 | verbosity = VERBOSITY_QUIET; 77 | break; 78 | case 't': 79 | verbosity = VERBOSITY_TEXT; 80 | break; 81 | case 'm': 82 | verbosity = VERBOSITY_MAP; 83 | break; 84 | case 'd': 85 | verbosity = VERBOSITY_DETAILED; 86 | break; 87 | case 's': 88 | print_summary = 1; 89 | break; 90 | case 'i': 91 | isam = strtol(optarg, NULL, 0); 92 | break; 93 | case 'p': 94 | snprintf(pdsbuf, sizeof(pdsbuf), "%s%8s", optarg, ""); 95 | pds = pdsbuf; 96 | break; 97 | case 'x': 98 | stopxfer = 1; 99 | break; 100 | default: 101 | errflg++; 102 | break; 103 | } 104 | } 105 | 106 | if (errflg || !(argc == optind + 1 || argc == optind + 4)) { 107 | fprintf(stderr, 108 | "Usage: %s [-%s] infile [outfile startbyte nbytes]\n", 109 | argv[0], ARGS); 110 | exit(1); 111 | } 112 | 113 | f = fopen(argv[optind], "r"); 114 | if (f == NULL) { 115 | perror(argv[optind]); 116 | exit(1); 117 | } 118 | 119 | res = load_cmd(f, memory, print_summary ? loadmap : NULL, 120 | verbosity, stdout, isam, pds, &xferaddr, stopxfer); 121 | 122 | switch (res) { 123 | case LOAD_CMD_OK: 124 | if (isam != -1) { 125 | fprintf(stderr, "warning: not ISAM file but -i flag given\n"); 126 | } else if (pds) { 127 | fprintf(stderr, "warning: not PDS file but -p flag given\n"); 128 | } 129 | break; 130 | case LOAD_CMD_EOF: 131 | fprintf(stderr, "premature end of file\n"); 132 | exit(1); 133 | case LOAD_CMD_NOT_FOUND: 134 | if (pds) { 135 | fprintf(stderr, "PDS entry \"%s\" not found\n", pds); 136 | } else { 137 | fprintf(stderr, "ISAM entry 0x%02x not found\n", isam); 138 | } 139 | exit(1); 140 | case LOAD_CMD_ISAM: 141 | if (isam == -1) { 142 | fprintf(stderr, "warning: ISAM file but -i flag not given\n"); 143 | } 144 | break; 145 | case LOAD_CMD_PDS: 146 | if (pds == NULL) { 147 | fprintf(stderr, "warning: PDS file but -p flag not given\n"); 148 | } 149 | break; 150 | default: 151 | fprintf(stderr, "load file format error, bad block type 0x%02x\n", res); 152 | break; 153 | } 154 | 155 | if (print_summary) { 156 | /* Print load map */ 157 | int lastaddr = -1; 158 | int lastcount = -1; 159 | int addr; 160 | for (addr = 0; addr < (int)sizeof(memory); addr++) { 161 | if (loadmap[addr] != lastcount) { 162 | if (lastcount == 1) { 163 | printf("loaded 0x%04x - 0x%04x\n", 164 | lastaddr, addr-1); 165 | } else if (lastcount > 1) { 166 | printf("loaded 0x%04x - 0x%04x (%d times!)\n", 167 | lastaddr, addr-1, lastcount); 168 | } 169 | lastaddr = addr; 170 | lastcount = loadmap[addr]; 171 | } 172 | } 173 | printf("transfer address = 0x%04x\n", xferaddr); 174 | } 175 | 176 | /* Dump memory - optional */ 177 | if (argc == optind + 4) { 178 | FILE* outf; 179 | int addr, count; 180 | outf = fopen(argv[optind + 1], "w"); 181 | if (outf == NULL) { 182 | perror(argv[optind + 1]); 183 | exit(1); 184 | } 185 | addr = strtol(argv[optind + 2], (char**)NULL, 0); 186 | count = strtol(argv[optind + 3], (char**)NULL, 0); 187 | 188 | while (count-- > 0) { 189 | putc(memory[addr++], outf); 190 | } 191 | fclose(outf); 192 | } 193 | return 0; 194 | } 195 | -------------------------------------------------------------------------------- /cmddump.man: -------------------------------------------------------------------------------- 1 | .\" This man page attempts to follow the conventions and recommendations found 2 | .\" in Michael Kerrisk's man-pages(7) and GNU's groff_man(7), and groff(7). 3 | .\" 4 | .\" The following macro definitions come from groff's an-ext.tmac. 5 | .\" 6 | .\" Copyright (C) 2007-2014 Free Software Foundation, Inc. 7 | .\" 8 | .\" Written by Eric S. Raymond 9 | .\" Werner Lemberg 10 | .\" 11 | .\" You may freely use, modify and/or distribute this file. 12 | .\" 13 | .\" If _not_ GNU roff, define macros to handle synopsis and URLs. 14 | .if !\n[.g] \{\ 15 | .\" Declare start of command synopsis. Sets up hanging indentation. 16 | .de SY 17 | . ie !\\n(mS \{\ 18 | . nh 19 | . nr mS 1 20 | . nr mA \\n(.j 21 | . ad l 22 | . nr mI \\n(.i 23 | . \} 24 | . el \{\ 25 | . br 26 | . ns 27 | . \} 28 | . 29 | . nr mT \w'\fB\\$1\fP\ ' 30 | . HP \\n(mTu 31 | . B "\\$1" 32 | .. 33 | . 34 | . 35 | .\" End of command synopsis. Restores adjustment. 36 | .de YS 37 | . in \\n(mIu 38 | . ad \\n(mA 39 | . hy \\n(HY 40 | . nr mS 0 41 | .. 42 | . 43 | . 44 | .\" Declare optional option. 45 | .de OP 46 | . ie \\n(.$-1 \ 47 | . RI "[\fB\\$1\fP" "\ \\$2" "]" 48 | . el \ 49 | . RB "[" "\\$1" "]" 50 | .. 51 | . 52 | . 53 | .\" Start URL. 54 | .de UR 55 | . ds m1 \\$1\" 56 | . nh 57 | . if \\n(mH \{\ 58 | . \" Start diversion in a new environment. 59 | . do ev URL-div 60 | . do di URL-div 61 | . \} 62 | .. 63 | . 64 | . 65 | .\" End URL. 66 | .de UE 67 | . ie \\n(mH \{\ 68 | . br 69 | . di 70 | . ev 71 | . 72 | . \" Has there been one or more input lines for the link text? 73 | . ie \\n(dn \{\ 74 | . do HTML-NS "" 75 | . \" Yes, strip off final newline of diversion and emit it. 76 | . do chop URL-div 77 | . do URL-div 78 | \c 79 | . do HTML-NS 80 | . \} 81 | . el \ 82 | . do HTML-NS "\\*(m1" 83 | \&\\$*\" 84 | . \} 85 | . el \ 86 | \\*(la\\*(m1\\*(ra\\$*\" 87 | . 88 | . hy \\n(HY 89 | .. 90 | .\} \" not GNU roff 91 | .\" End of Free Software Foundation copyrighted material. 92 | .\" 93 | .\" Copyright 2001, 2017 Branden Robinson 94 | .\" 95 | .\" Permission is hereby granted, free of charge, to any person 96 | .\" obtaining a copy of this software and associated documentation 97 | .\" files (the "Software"), to deal in the Software without 98 | .\" restriction, including without limitation the rights to use, copy, 99 | .\" modify, merge, publish, distribute, sublicense, and/or sell copies 100 | .\" of the Software, and to permit persons to whom the Software is 101 | .\" furnished to do so, subject to the following conditions: 102 | .\" 103 | .\" The above copyright notice and this permission notice shall be 104 | .\" included in all copies or substantial portions of the Software. 105 | .\" 106 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 107 | .\" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 108 | .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 109 | .\" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 110 | .\" HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 111 | .\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 112 | .\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 113 | .\" DEALINGS IN THE SOFTWARE. 114 | .\" 115 | .TH cmddump 1 2017-04-04 xtrs 116 | .SH Name 117 | cmddump \- simulated TRS-80 CMD file loader 118 | .SH Synopsis 119 | .SY cmddump 120 | .OP \-d 121 | .OP \-i n 122 | .OP \-m 123 | .OP \-p entry 124 | .OP \-q 125 | .OP \-s 126 | .OP \-t 127 | .OP \-x 128 | .I infile 129 | .RI [ "outfile startbyte nbytes" ] 130 | .SH Description 131 | .B cmddump 132 | displays information about TRS-80 DOS CMD (binary executable) files. 133 | It takes a mandatory input CMD file 134 | .IR infile, 135 | and an optional triplet of arguments: an output file 136 | .IR outfile , 137 | a starting offset of 138 | .I startbyte 139 | into the CMD file 140 | .IR infile , 141 | and a number of bytes to dump, 142 | .IR nbytes . 143 | If 144 | .IR "outfile, startbyte, " and " nbytes " 145 | are specified, the given byte range is dumped from the simulated memory after 146 | loading. 147 | .PP 148 | The numeric arguments, including that to the option 149 | .BR \-i , 150 | may be given in any format recognized by 151 | .BR strtol (3); 152 | in other words, traditional C literals for decimal, octal, and hexadecimal. 153 | .SH Options 154 | The optional arguments and their parameters direct 155 | .B cmddump 156 | as follows. 157 | .TP 158 | .B \-d 159 | print detailed map; same as 160 | .BR \-m , 161 | but do not coalesce adjacent blocks 162 | .TP 163 | .BI "\-i " n 164 | select ISAM entry \fIn\fP 165 | .TP 166 | .B \-m 167 | print running load map as file is parsed, coalescing adjacent blocks (implies 168 | .BR \-t ); 169 | default 170 | .TP 171 | .BI "\-p " entry 172 | select PDS entry 173 | .IR entry ; 174 | .B cmddump 175 | will truncate or right-pad 176 | .I entry 177 | with spaces, as needed, to the required fixed field width 178 | .TP 179 | .B \-q 180 | quiet; turns off 181 | .BR \-d , 182 | .BR \-m , 183 | .BR \-s , 184 | and 185 | .B \-t 186 | (later flags can override) 187 | .TP 188 | .B \-s 189 | print summary load map after file is parsed 190 | .TP 191 | .B \-t 192 | print text of module headers, PDS headers, patch names, and copyright notices 193 | .TP 194 | .B \-x 195 | ignore anything after the first transfer address 196 | .SH See also 197 | .BR xtrs (1) 198 | .PP 199 | The 200 | .\" If GNU roff, use hyphenless breakpoints. 201 | .ie \n[.g] .UR http://\:www.tim-mann.org/\:misosys.html 202 | .el .UR http://www.tim-mann.org/misosys.html 203 | .IR "LDOS Quarterly" , 204 | April 1, 1982 (Vol 1, No 4) 205 | .UE , 206 | has documentation of the TRS-80 DOS CMD file format. 207 | .\" $Id$ 208 | .\" vim:set et ft=nroff tw=80: 209 | -------------------------------------------------------------------------------- /compile_rom.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2008, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #include "z80.h" 41 | #include "load_cmd.h" 42 | 43 | char *program_name; 44 | static int lowest_address = Z80_ADDRESS_LIMIT; 45 | static int highest_address = 0; 46 | static Uchar memory[Z80_ADDRESS_LIMIT]; 47 | static Uchar loadmap[Z80_ADDRESS_LIMIT]; 48 | 49 | /* Called by load_hex */ 50 | void hex_data(int address, int value) 51 | { 52 | address &= 0xffff; 53 | 54 | memory[address] = value; 55 | if (lowest_address > address) 56 | lowest_address = address; 57 | if (highest_address < address) 58 | highest_address = address; 59 | } 60 | 61 | void hex_transfer_address(int address) 62 | { 63 | /* Ignore */ 64 | } 65 | 66 | static void load_rom(char *filename) 67 | { 68 | FILE *program; 69 | int c, a; 70 | 71 | if ((program = fopen(filename, "r")) == NULL) { 72 | char message[100]; 73 | sprintf(message, "could not read %s", filename); 74 | fatal(message); 75 | } 76 | c = getc(program); 77 | if (c == ':') { 78 | /* Assume Intel hex format */ 79 | rewind(program); 80 | load_hex(program); 81 | fclose(program); 82 | return; 83 | } else if (c == 1 || c == 5) { 84 | /* Assume MODELA/III file (load module format) */ 85 | int res; 86 | rewind(program); 87 | res = load_cmd(program, memory, loadmap, 0, NULL, -1, NULL, NULL, 1); 88 | if (res == LOAD_CMD_OK) { 89 | lowest_address = 0; 90 | while (lowest_address < Z80_ADDRESS_LIMIT) { 91 | if (loadmap[lowest_address] != 0) { 92 | break; 93 | } 94 | lowest_address++; 95 | } 96 | highest_address = Z80_ADDRESS_LIMIT; 97 | while (highest_address > 0) { 98 | if (loadmap[--highest_address] != 0) { 99 | break; 100 | } 101 | } 102 | fclose(program); 103 | return; 104 | } else { 105 | /* Guess it wasn't a load module; prepare to fall into raw 106 | * binary case */ 107 | rewind(program); 108 | c = getc(program); 109 | } 110 | } 111 | /* Assume raw binary at address 0 */ 112 | a = 0; 113 | while (c != EOF) { 114 | hex_data(a++, c); 115 | c = getc(program); 116 | } 117 | fclose(program); 118 | } 119 | 120 | static void write_output(char *which) 121 | { 122 | int address = 0; 123 | int i; 124 | int size = highest_address - lowest_address + 1; 125 | 126 | printf("int trs_rom%s_start = %d;\n", which, lowest_address); 127 | printf("int trs_rom%s_size = %d;\n", which, size); 128 | printf("unsigned char trs_rom%s[%d] = \n{\n", which, size); 129 | 130 | address = lowest_address; 131 | while (address <= highest_address) { 132 | printf(" "); 133 | for (i = 0; i < 8; ++i) { 134 | printf("0x%.2x,", memory[address++]); 135 | if (address > highest_address) 136 | break; 137 | } 138 | printf("\n"); 139 | } 140 | printf("};\n"); 141 | } 142 | 143 | static void write_norom_output(char *which) 144 | { 145 | printf("int trs_rom%s_start = -1;\n", which); 146 | printf("int trs_rom%s_size = -1;\n", which); 147 | printf("unsigned char trs_rom%s[1];\n", which); 148 | } 149 | 150 | int main(int argc, char *argv[]) 151 | { 152 | program_name = argv[0]; 153 | if (argc == 2) { 154 | fprintf(stderr, 155 | "%s: no specified ROM file, ROM %s will not be built into program.\n", 156 | program_name, argv[1]); 157 | write_norom_output(argv[1]); 158 | } else if(argc != 3) { 159 | fprintf(stderr, "Usage: %s model hexfile\n", program_name); 160 | } else { 161 | load_rom(argv[2]); 162 | write_output(argv[1]); 163 | } 164 | return 0; 165 | } 166 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | #if defined(sun) && !defined(i386) 17 | #define big_endian 18 | #endif 19 | 20 | #ifdef vax 21 | #undef big_endian 22 | #endif 23 | 24 | #if defined(mips) && defined(ultrix) 25 | #undef big_endian 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /cpmutil.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/cpmutil.dsk -------------------------------------------------------------------------------- /cpmutil.html: -------------------------------------------------------------------------------- 1 | Roland Gerlach : TRS-80 : CP/M Utilities for the xtrs Emulator 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 |
21 | UP 22 | HOME 23 |
24 | 25 | 26 |

CP/M Utilities for the xtrs Emulator

27 | 28 | 29 |

Contents

30 |
31 |
Programs 32 |
33 |
EXPORT 34 |
IMPORT 35 |
XTRS 36 |
37 |
Bug Reports 38 |
Download 39 |
40 | 41 | 42 |

Programs

43 | 44 |

These programs were written for CP/M and make use of the emulator traps in 45 | Tim Mann's xtrs Emulator. 46 |

47 | 48 |

IMPORT and EXPORT also work (with the exception of the -H option) when running CP/M on 49 | David Keil's Model 4/4P Emulator. 50 |

51 | 52 | 53 |

EXPORT

54 | 55 |

Export CP/M file(s) to the host operating system.

56 | 57 |

Usage

58 |
Usage:	EXPORT [-H][-L][-T][-V] cpmfileref [hostfilename]
 59 | 
 60 | Where:	cpmfileref is the local file to export
 61 | 	   (use "?" and "*" to specify multiple files)
 62 | 	hostfilename is the name of the file to create on the host
 63 | 	   (converted to uppercase by default), use -L to convert
 64 | 	   to lowercase and [ to toggle case of next character.
 65 | 	-H switches emulator to high speed and restores speed when done.
 66 | 	-L converts hostfilename to lowercase.
 67 | 	-T export text file (CR LF becomes LF, stop at SUB character).
 68 | 	-V (verbose) display "r" for block read, "w" for block written.
 69 | 
70 | 71 |

Notes

72 | 73 |

CP/M does not keep an accurate file size. Binary files are always 74 | multiples of 128 byte blocks; text files end at the first sub 75 | character. 76 | 77 |

The CP/M CCP converts all command line parameters to uppercase, 78 | hence the need of the -L option and the use of [ to toggle the case of 79 | the next character within the hostfilename. 80 | 81 |

Examples

82 |
83 |
EXPORT -LT HELPFILE.TXT README.TXT 84 |
Export local file "HELPFILE.TXT" as a text file to "readme.txt" on the host. 85 |

86 |

EXPORT RUNME.COM 87 |
Export local file "RUNME.COM" as a binary file to "RUNME.COM" on the host. 88 |
89 | 90 | 91 |

IMPORT

92 | 93 |

Imports a file from the host operating system to CP/M.

94 | 95 |

Usage

96 |
Usage:	IMPORT [-F][-H][-L][-T][-V] hostfilename [cpmfilename]
 97 | 
 98 | Where:	hostfilename is the name of the file on the host
 99 | 	   (converted to uppercase by default), use -L to convert
100 | 	   to lowercase and [ to toggle case of next character.
101 | 	cpmfilename is the name of the CP/M file to create,
102 | 	   existing files will not be overwritten unless -F is used.
103 | 	-F overwrite existing files.
104 | 	-H switches emulator to high speed and restores speed when done.
105 | 	-L convert hostfilename to lowercase.
106 | 	-T import text file (LF becomes CR LF, add SUB at end of file).
107 | 	-V (verbose) display "r" for block read, "w" for block written.
108 | 
109 | 110 |

Notes

111 | 112 |

CP/M does not keep an accurate file size, both binary and text 113 | files will be padded to multiples of 128 byte blocks. 114 | 115 |

The CP/M CCP converts all command line parameters to uppercase, 116 | hence the need of the -L option and the use of [ to toggle the case of 117 | the next character within the hostfilename. 118 | 119 |

Examples

120 |
121 |
IMPORT -LT README.TXT HELPFILE.TXT 122 |
Import "readme.txt" from the host as a text file to "HELPFILE.TXT". 123 |

124 |

IMPORT RUNME.COM 125 |
Import "RUNME.COM" from the host as a binary file to "RUNME.COM". 126 |
127 | 128 | 129 |

XTRS

130 | 131 |

Controls miscellaneous functions of the xtrs emulator.

132 | 133 |

Usage

134 |
Usage:	XTRS action [parameters]
135 | 
136 | Where:	action is one of the following:
137 | 	   BOOT - reboot emulator
138 | 	   CHANGE - signal disk change
139 | 	   DEBUG - enter debugger
140 | 	   EXIT - end emulator
141 | 	   HIGHSPEED - high speed (autodelay off)
142 | 	   MOUNT [-L] hostfilename disknum - mount disk
143 | 	   NORMALSPEED - normal speed (autodelay on)
144 | 	   REPORT - report status
145 | 	   SYSTEM command - execute command on host
146 | 	   UMOUNT disknum - umount disk
147 | 	hostfilename is the name of the virtual disk file on the host
148 | 	   (converted to uppercase by default), use -L to convert to
149 | 	   lowercase and [ to toggle case of next character.
150 | 	command is the command (and parameters) to execute on the host
151 | 	   (converted to lowercase by default), use [ to toggle case.
152 | 	   Note output from command is NOT displayed in the XTRS window.
153 | 	disknum is disk drive number (between 0 and 3 inclusive).
154 | 	-L converts hostfilename to lowercase.
155 | 
156 | 157 | 158 |

Warning

159 | 160 |

The XTRS program assumes that the emulator's virtual disk files - 161 | diskM-U (where M is the TRS-80 model and U is the drive number) - are 162 | symbolic links. For example: 163 |

$ ls -l
164 | -rw-r--r--    1 user  group    213504 Mar 21 15:24 cpmutil.dsk
165 | lrwxrwxrwx    1 user  group        10 Mar  5 12:40 disk4p-0 -> system.dsk
166 | lrwxrwxrwx    1 user  group        11 Mar  7 13:49 disk4p-3 -> cpmutil.dsk
167 | -rw-r--r--    1 user  group    745984 Mar 24 17:38 system.dsk
168 | 
169 | 170 | 171 |

The MOUNT action deletes the diskM-U file, replaces it with a 172 | symbolic link to the given filename and signals a disk change (as if 173 | F7 had been pressed). 174 | 175 |

The UMOUNT action deletes the diskM-U file and signals a disk 176 | change. 177 | 178 |

Notes

179 | 180 |

When changing disks, remember that CP/M must also be told of the 181 | disk change. This is usually done by pressing ctrl-C at the prompt. 182 | 183 |

Examples

184 |
185 |
XTRS MOUNT -L DATA.DSK 1 186 |
Mount the virtual disk file "data.dsk" on drive 1. 187 | The actual command that would be executed on the host is:
188 | rm -f disk4p-1;test -f data.dsk && ln -s data.disk disk4p-1 189 |

190 |

XTRS UMOUNT 1 191 |
Unmount the virtual disk file associated with drive 1. 192 | The actual command that would be executed on the host is:
193 | rm -f disk4p-1 194 | 195 |
196 | 197 |

Bug Reports

198 | 199 |

Send Bug Reports and comments to 200 | Roland Gerlach.

201 | 202 |

Download

203 | 204 |
205 | 206 |
cpmutil.tgz 207 |
Source code and programs in a gzipped tar file. 208 | 209 |

210 |

cpmutil.dsk.gz 211 |
All of these programs (including source code) on a virtual disk 212 | formatted as a "Montezuma Micro Standard DATA disk (40T, SS, DD, 213 | 200K)" with 512-byte sectors. Be careful to configure CP/M with the 214 | proper disk format and drive parameters (40 tracks, not 80 tracks), or 215 | you will have problems reading this disk. 216 | 217 |
218 | 219 |
220 |


Comments and suggestions are welcome, send them to 221 | Roland Gerlach.

222 |
223 | 224 | -------------------------------------------------------------------------------- /cpmutil.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/cpmutil.tgz -------------------------------------------------------------------------------- /crc.c: -------------------------------------------------------------------------------- 1 | /* crc.c 2 | Compute CCITT CRC-16 using the correct bit order for floppy disks. 3 | */ 4 | 5 | /* Accelerator table to compute the CRC eight bits at a time */ 6 | unsigned short const crc16_table[256] = { 7 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 8 | 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 9 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 10 | 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 11 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 12 | 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 13 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 14 | 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 15 | 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 16 | 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 17 | 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 18 | 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 19 | 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 20 | 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 21 | 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 22 | 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 23 | 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 24 | 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 25 | 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 26 | 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 27 | 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 28 | 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 29 | 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 30 | 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 31 | 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 32 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 33 | 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 34 | 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 35 | 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 36 | 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 37 | 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 38 | 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 39 | }; 40 | 41 | /* Slow way, not using table */ 42 | unsigned short CALC_CRC1a(unsigned short crc, unsigned char byte) 43 | { 44 | int i = 8; 45 | unsigned short b = byte << 8; 46 | while (i--) { 47 | crc = (crc << 1) ^ (((crc ^ b) & 0x8000) ? 0x1021 : 0); 48 | b <<= 1; 49 | } 50 | return crc; 51 | } 52 | 53 | /* Fast way, using table */ 54 | #define CALC_CRC1b(crc, c) (((crc) << 8) ^ crc16_table[((crc) >> 8) ^ (c)]) 55 | 56 | #ifndef calc_crc1 57 | #define calc_crc1 CALC_CRC1b 58 | #endif 59 | 60 | /* Recompute the CRC with len bytes appended. */ 61 | unsigned short calc_crc(unsigned short crc, 62 | unsigned char const *buf, int len) 63 | { 64 | while (len--) { 65 | crc = calc_crc1(crc, *buf++); 66 | } 67 | return crc; 68 | } 69 | 70 | #if TEST 71 | #include 72 | int 73 | main(int argc, char **argv) 74 | { 75 | char buf[2048]; 76 | int count, c, res; 77 | unsigned short preset; 78 | 79 | if (argc > 1) { 80 | preset = strtol(argv[1], NULL, 0); 81 | } else { 82 | preset = 0xffff; 83 | } 84 | count = 0; 85 | for (;;) { 86 | res = scanf("%2x", &c); 87 | if (res != 1) break; 88 | buf[count++] = c; 89 | } 90 | printf("\n%04x\n", calc_crc(preset, buf, count)); 91 | return 0; 92 | } 93 | #endif 94 | -------------------------------------------------------------------------------- /do6.jcl: -------------------------------------------------------------------------------- 1 | . Avoid running Model I/III-only xtrs utilities on Model 4 2 | remove cd/cmd:#D# 3 | remove pwd/cmd:#D# 4 | remove unix/cmd:#D# 5 | remove mount/cmd:#D# 6 | remove umount/cmd:#D# 7 | remove truedam/cmd:#D# 8 | rename cd6/cmd:#D# cd/cmd:#D# 9 | rename pwd6/cmd:#D# pwd/cmd:#D# 10 | rename unix6/cmd:#D# unix/cmd:#D# 11 | rename mount6/cmd:#D# mount/cmd:#D# 12 | rename umount6/cmd:#D# umount/cmd:#D# 13 | rename truedam6/cmd:#D# truedam/cmd:#D# 14 | -------------------------------------------------------------------------------- /error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2008, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #include "z80.h" 41 | #include 42 | #include 43 | #include 44 | 45 | extern char *program_name; 46 | 47 | void debug(const char *fmt, ...) 48 | { 49 | va_list args; 50 | char xfmt[2048]; 51 | 52 | strcpy(xfmt, "debug: "); 53 | strcat(xfmt, fmt); 54 | /*strcat(xfmt, "\n");*/ 55 | va_start(args, fmt); 56 | vfprintf(stderr, xfmt, args); 57 | va_end(args); 58 | } 59 | 60 | void warning(const char *fmt, ...) 61 | { 62 | va_list args; 63 | char xfmt[2048]; 64 | 65 | strcpy(xfmt, program_name); 66 | strcat(xfmt, " warning: "); 67 | strcat(xfmt, fmt); 68 | strcat(xfmt, "\n"); 69 | va_start(args, fmt); 70 | vfprintf(stderr, xfmt, args); 71 | va_end(args); 72 | } 73 | 74 | void error(const char *fmt, ...) 75 | { 76 | va_list args; 77 | char xfmt[2048]; 78 | 79 | strcpy(xfmt, program_name); 80 | strcat(xfmt, " error: "); 81 | strcat(xfmt, fmt); 82 | strcat(xfmt, "\n"); 83 | va_start(args, fmt); 84 | vfprintf(stderr, xfmt, args); 85 | va_end(args); 86 | } 87 | 88 | void fatal(const char *fmt, ...) 89 | { 90 | va_list args; 91 | char xfmt[2048]; 92 | 93 | strcpy(xfmt, program_name); 94 | strcat(xfmt, " fatal error: "); 95 | strcat(xfmt, fmt); 96 | strcat(xfmt, "\n"); 97 | va_start(args, fmt); 98 | vfprintf(stderr, xfmt, args); 99 | va_end(args); 100 | exit(1); 101 | } 102 | -------------------------------------------------------------------------------- /expall.bas: -------------------------------------------------------------------------------- 1 | 20 CLEAR 1000 2 | 40 REM-- List an LDOS directory by opening and reading DIR/SYS 3 | 50 REM-- and use the xtrs export program to export all files 4 | 54 REM-- 5 | 55 REM-- 2023/07/23: Fixed a bug where an extended directory entry 6 | 56 REM-- would cause an error and abort further exports. 7 | 57 REM-- 8 | 60 LINE INPUT "Drive? "; DR$ 9 | 80 OPEN "ri", 1, "dir/sys.rs0lt0ff:" + DR$, 32 10 | 100 FIELD 1, 1 AS AT$, 1 AS FL$, 1 AS DT$, 1 AS EF$, 1 AS RL$, 8 AS NM$, 3 AS NX$, 2 AS OP$, 2 AS UP$, 2 AS ER$, 10 AS XT$ 11 | 120 GET 1, 16 12 | 140 N = 0 13 | 160 IF EOF(1) THEN END 14 | 180 N = N + 1 15 | 200 GET 1 16 | 220 IF (ASC(AT$) AND &H90) <> &H10 THEN GOTO 160 17 | 240 I=INSTR(NM$, " ") 18 | 260 IF I THEN NH$ = LEFT$(NM$, I-1) ELSE NH$ = NM$ 19 | 280 I = INSTR(NX$, " ") 20 | 300 IF I THEN NT$ = LEFT$(NX$, I-1) ELSE NT$ = NX$ 21 | 320 REM print n; " "; 22 | 340 NF$ = NH$ + "/" + NT$ 23 | 360 PRINT NF$ 24 | 380 UF$ = NH$ + "." + NT$ 25 | 400 CMD "export -l " + NF$ + ".rs0lt0ff:" + DR$ + " " + UF$ 26 | 420 GOTO 160 27 | -------------------------------------------------------------------------------- /fakerom.z80: -------------------------------------------------------------------------------- 1 | ; 2 | ; Fake ROM for xtrs, initial hack 3 | ; Small improvements 1-Nov-2020 4 | ; 5 | 6 | video equ 3c00h+7*64 7 | 8 | org 0 9 | di 10 | jp start 11 | 12 | org 66h 13 | jp start 14 | 15 | org 100h 16 | start: di 17 | ld hl,fakemsg 18 | ld de,video 19 | 20 | ld a,'a' 21 | ld (de),a 22 | ld a,(de) 23 | cp 'a' 24 | jr z,move 25 | ld hl,ucmsg 26 | 27 | move: ld bc,fmend-fakemsg 28 | ldir 29 | ld a,5 ;query model 30 | defw 3cedh ;emt_misc 31 | ld a,'0' 32 | add a,l 33 | cp '5' 34 | jr z,mod4p 35 | ld (model-fakemsg+video),a 36 | cp '4' 37 | jr z,mod4 38 | jr $ 39 | 40 | mod4: ld hl,m4msg 41 | ld de,video+64 42 | ld bc,m4end-m4msg 43 | ldir 44 | jr $ 45 | 46 | mod4p: ld hl,model-fakemsg+video 47 | ld (hl),'4' 48 | inc hl 49 | ld (hl),'P' 50 | jr $ 51 | 52 | fakemsg:defb 'You do not have a ROM image installed for Model ' 53 | model equ $ 54 | fmend equ $ 55 | ucmsg: defb 'YOU DO NOT HAVE A ROM IMAGE INSTALLED FOR MODEL ' 56 | m4msg: defb '(Model 4 mode requires a Model 3 ROM image)' 57 | m4end equ $ 58 | 59 | end start 60 | -------------------------------------------------------------------------------- /hex2cmd.c: -------------------------------------------------------------------------------- 1 | /* Convert Intel Hex format to TRS-80 CMD format */ 2 | 3 | /* 4 | * Copyright (c) 1996-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include "cmd.h" 31 | #include "z80.h" 32 | 33 | char *program_name; 34 | 35 | /* Called by load_hex */ 36 | void 37 | hex_data(int address, int value) 38 | { 39 | cmd_data(address, value); 40 | } 41 | 42 | void 43 | hex_transfer_address(int address) 44 | { 45 | cmd_transfer_address(address); 46 | } 47 | 48 | int 49 | main(int argc, char *argv[]) 50 | { 51 | FILE *f; 52 | program_name = argv[0]; 53 | cmd_init(stdout); 54 | if (argc == 1) { 55 | f = stdin; 56 | } else if (argc == 2) { 57 | f = fopen(argv[1], "r"); 58 | if (f == NULL) { 59 | perror(argv[1]); 60 | exit(1); 61 | } 62 | } else { 63 | fprintf(stderr, "Usage: %s [<] file.hex > file.cmd\n", 64 | program_name); 65 | exit(2); 66 | } 67 | load_hex(f); 68 | cmd_end_of_file(); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /hex2cmd.man: -------------------------------------------------------------------------------- 1 | .\" This man page attempts to follow the conventions and recommendations found 2 | .\" in Michael Kerrisk's man-pages(7) and GNU's groff_man(7), and groff(7). 3 | .\" 4 | .\" The following macro definitions come from groff's an-ext.tmac. 5 | .\" 6 | .\" Copyright (C) 2007-2014 Free Software Foundation, Inc. 7 | .\" 8 | .\" Written by Eric S. Raymond 9 | .\" Werner Lemberg 10 | .\" 11 | .\" You may freely use, modify and/or distribute this file. 12 | .\" 13 | .\" If _not_ GNU roff, define UR and UE macros to handle URLs. 14 | .if !\n[.g] \{\ 15 | .\" Start URL. 16 | .de UR 17 | . ds m1 \\$1\" 18 | . nh 19 | . if \\n(mH \{\ 20 | . \" Start diversion in a new environment. 21 | . do ev URL-div 22 | . do di URL-div 23 | . \} 24 | .. 25 | . 26 | . 27 | .\" End URL. 28 | .de UE 29 | . ie \\n(mH \{\ 30 | . br 31 | . di 32 | . ev 33 | . 34 | . \" Has there been one or more input lines for the link text? 35 | . ie \\n(dn \{\ 36 | . do HTML-NS "" 37 | . \" Yes, strip off final newline of diversion and emit it. 38 | . do chop URL-div 39 | . do URL-div 40 | \c 41 | . do HTML-NS 42 | . \} 43 | . el \ 44 | . do HTML-NS "\\*(m1" 45 | \&\\$*\" 46 | . \} 47 | . el \ 48 | \\*(la\\*(m1\\*(ra\\$*\" 49 | . 50 | . hy \\n(HY 51 | .. 52 | .\} \" not GNU roff 53 | .\" End of Free Software Foundation copyrighted material. 54 | .\" 55 | .\" Copyright 2001 Branden Robinson 56 | .\" 57 | .\" Permission is hereby granted, free of charge, to any person 58 | .\" obtaining a copy of this software and associated documentation 59 | .\" files (the "Software"), to deal in the Software without 60 | .\" restriction, including without limitation the rights to use, copy, 61 | .\" modify, merge, publish, distribute, sublicense, and/or sell copies 62 | .\" of the Software, and to permit persons to whom the Software is 63 | .\" furnished to do so, subject to the following conditions: 64 | .\" 65 | .\" The above copyright notice and this permission notice shall be 66 | .\" included in all copies or substantial portions of the Software. 67 | .\" 68 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 69 | .\" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 70 | .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 71 | .\" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 72 | .\" HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 73 | .\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 74 | .\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 75 | .\" DEALINGS IN THE SOFTWARE. 76 | .\" 77 | .TH hex2cmd 1 2008-06-26 xtrs 78 | .SH Name 79 | hex2cmd \- convert Intel hex format to TRS-80 CMD format 80 | .SH Synopsis 81 | .B hex2cmd 82 | .RI [ infile ] 83 | .SH Description 84 | .B hex2cmd 85 | reads the specified 86 | .I infile 87 | (or standard input if none is given) in Intel hex format (also known as S-record 88 | format), and writes a TRS-80 CMD file to standard output. 89 | An S-record that asks for 0 bytes to be loaded at address 90 | .I A 91 | sets the transfer address (entry point) of the CMD file to 92 | .IR A ; 93 | otherwise the CMD file is given no transfer address. 94 | .SH See also 95 | .BR xtrs (1) 96 | .PP 97 | The 98 | .\" If GNU roff, use hyphenless breakpoints. 99 | .ie \n[.g] .UR http://\:www.tim-mann.org/\:misosys.html 100 | .el .UR http://www.tim-mann.org/misosys.html 101 | .IR "LDOS Quarterly" , 102 | April 1, 1982 (Vol 1, No 4) 103 | .UE , 104 | has documentation of the TRS-80 DOS CMD file format. 105 | .\" $Id$ 106 | .\" vim:set et ft=nroff tw=80: 107 | -------------------------------------------------------------------------------- /keyrepeat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * These bugs were fixed in 2009, so I've #if'ed out the 22515 3 | * workaround and won't worry about lacking a 21454 workaround. 4 | */ 5 | #if WORKAROUND_X_REPEAT_BUG 6 | /* 7 | * GDK is supposed to either set or emulate the DetectableAutorepeat 8 | * feature, which suppresses the extra key release that X autorepeat 9 | * normally generates. It's then easy for applications to filter out 10 | * the extra key press events if desired, because the same key is 11 | * pressed again without having been released. 12 | * 13 | * Unfortunately, I am still getting the key release events! This 14 | * appears to be a bug in the version of X included in Ubuntu 9.04: 15 | * Calling XkbSetDetectableAutoRepeat reports that the feature is 16 | * supported, but in fact it does not work. GDK would emulate the 17 | * feature if it knew it needed to, but this bug fools it into not 18 | * doing so. I've reported the bug at 19 | * https://bugs.freedesktop.org/show_bug.cgi?id=22515 20 | * 21 | * Because detectable autorepeat is supposed to work, GDK 2.0 does not 22 | * wrap XAutoRepeatOff and friends. Hence this ugly code to reach 23 | * under the covers and invoke them. 24 | */ 25 | 26 | #include "keyrepeat.h" 27 | 28 | /*#define REPEAT_DEBUG 1*/ 29 | 30 | static int repeat_saved = FALSE; 31 | static XKeyboardState repeat_state; 32 | 33 | void 34 | disable_repeat(GdkWindow *window) 35 | { 36 | Display *display = GDK_WINDOW_XDISPLAY(window); 37 | if (!repeat_saved) { 38 | XGetKeyboardControl(display, &repeat_state); 39 | repeat_saved = TRUE; 40 | #if REPEAT_DEBUG 41 | printf("*** saved repeat state %d\n", 42 | repeat_state.global_auto_repeat == AutoRepeatModeOn); 43 | #endif 44 | } 45 | XAutoRepeatOff(display); 46 | XSync(display, False); 47 | #if REPEAT_DEBUG 48 | printf("*** disabled repeat\n"); 49 | #endif 50 | } 51 | 52 | void 53 | restore_repeat(GdkWindow *window) 54 | { 55 | Display *display = GDK_WINDOW_XDISPLAY(window); 56 | if (repeat_saved) { 57 | if (repeat_state.global_auto_repeat == AutoRepeatModeOn) { 58 | XAutoRepeatOn(display); 59 | XSync(display, False); 60 | } 61 | #if REPEAT_DEBUG 62 | printf("*** restored repeat state %d\n", 63 | repeat_state.global_auto_repeat == AutoRepeatModeOn); 64 | #endif 65 | } 66 | } 67 | #endif 68 | -------------------------------------------------------------------------------- /keyrepeat.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void disable_repeat(GdkWindow *window); 4 | void restore_repeat(GdkWindow *window); 5 | -------------------------------------------------------------------------------- /load_cmd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996-2008, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* TRS-80 DOS /cmd file loader */ 26 | 27 | #define LOAD_CMD_OK 0 28 | #define LOAD_CMD_EOF -1 29 | #define LOAD_CMD_NOT_FOUND -2 30 | #define LOAD_CMD_ISAM -3 31 | #define LOAD_CMD_PDS -4 32 | 33 | #define VERBOSITY_QUIET 0 34 | #define VERBOSITY_TEXT 1 35 | #define VERBOSITY_MAP 2 36 | #define VERBOSITY_DETAILED 3 37 | 38 | #define ISAM_NONE -1 39 | 40 | /* Load the /cmd file f into the given memory, optionally selecting 41 | * out an ISAM or PDS member. Return LOAD_CMD_OK for success if f was a 42 | * normal /cmd file, LOAD_CMD_ISAM for success if it was an ISAM file, 43 | * LOAD_CMD_PDS for success if this was a PDS file, LOAD_CMD_EOF for 44 | * failure due to premature end of file, LOAD_CMD_NOT_FOUND for ISAM 45 | * or PDF member not found, or a positive number B for an unknown or 46 | * badly formatted load block of typecode B (load file format error). 47 | * 48 | * Optional flags: 49 | * 50 | * If loadmap is not NULL, it must point to an array of 2**16 51 | * bytes. Each byte in the return value will have a count (mod 256) 52 | * of the number of times that memory location was loaded. Usually each 53 | * count will be 0 or 1, of course. 54 | * 55 | * If verbosity is VERBOSITY_QUIET, print nothing. If verbosity is 56 | * VERBOSITY_TEXT, print module headers, PDS headers, patch names, and 57 | * copyright notices. If verbosity is VERBOSITY_MAP, also print load 58 | * map information as we go along, but coalesce adjacent blocks that 59 | * load contiguously into memory. If verbosity is VERBOSITY_DETAILED, 60 | * don't coalesce. 61 | * 62 | * If isam is not -1, search for the given isam member number and load 63 | * it instead of loading the whole file. 64 | * 65 | * If pds is not NULL, search for the given pds member name and 66 | * load it instead of loading the whole file. isam and pds cannot 67 | * both be used. 68 | * 69 | * If xferaddr is not NULL, return the transfer address there, or if 70 | * there is no transfer address, return -1. 71 | * 72 | * If stopxfer is 1, stop loading when a transfer address is seen; if 73 | * 0, continue loading. stopxfer = 0 is needed if you want to parse 74 | * a PDS file with a front end loader. stopxfer = 1 is useful to deal 75 | * with ordinary /cmd files that have extra garbage at the end, as 76 | * sometimes happens. stopxfer = 0 should be considered the default. 77 | */ 78 | 79 | 80 | int 81 | load_cmd(FILE* f, unsigned char memory[65536], 82 | unsigned char* loadmap, int verbosity, FILE* outf, 83 | int isam, char* pds, int* xferaddr, int stopxfer); 84 | -------------------------------------------------------------------------------- /load_hex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2008, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #include "z80.h" 41 | #include 42 | 43 | #define BUFFER_SIZE 256 44 | 45 | extern void hex_transfer_address(int address); 46 | extern void hex_data(int address, int value); 47 | 48 | static int hex_byte(char *string) 49 | { 50 | char buf[3]; 51 | 52 | buf[0] = string[0]; 53 | buf[1] = string[1]; 54 | buf[2] = '\0'; 55 | 56 | return(strtol(buf, (char **)NULL, 16)); 57 | } 58 | 59 | int load_hex(FILE *file) 60 | { 61 | char buffer[BUFFER_SIZE]; 62 | char *b; 63 | int num_bytes; 64 | int address; 65 | int check; 66 | int value; 67 | int high = 0; 68 | 69 | while(fgets(buffer, BUFFER_SIZE, file)) 70 | { 71 | if(buffer[0] == ':') 72 | { 73 | /* colon */ 74 | b = buffer + 1; 75 | 76 | /* number of bytes on the line */ 77 | num_bytes = hex_byte(b); b += 2; 78 | check = num_bytes; 79 | 80 | /* the starting address */ 81 | address = hex_byte(b) << 8; b += 2; 82 | address |= hex_byte(b); b+= 2; 83 | check += (address >> 8) + (address & 0xff); 84 | 85 | /* a zero? */ 86 | b += 2; 87 | 88 | /* the data */ 89 | if(num_bytes == 0) 90 | { 91 | /* Transfer address */ 92 | hex_transfer_address(address); 93 | } else { 94 | while(num_bytes--) 95 | { 96 | value = hex_byte(b); b += 2; 97 | hex_data(address++, value); 98 | check += value; 99 | } 100 | if (address > high) high = address; 101 | 102 | /* the checksum */ 103 | value = hex_byte(b); 104 | if(((0x100 - check) & 0xff) != value) 105 | { 106 | fatal("bad checksum from hex file"); 107 | } 108 | } 109 | } 110 | } 111 | return high; 112 | } 113 | -------------------------------------------------------------------------------- /m1format.fix: -------------------------------------------------------------------------------- 1 | . M1FORMAT/FIX - 01/24/98 - Tim Mann 2 | . Patch to Model I LDOS 5.3.1 FORMAT to allow formatting a hard 3 | . drive. NOPs out some buggy code that makes it fail. Odd 4 | . that this bug is still present; README/TXT suggests it was 5 | . fixed. This patch is required to format an emulated hard 6 | . drive with XTRSHARD/DCT on an emulated Model I. 7 | . 8 | . Apply with PATCH FORMAT/CMD.RS0LT0FF USING M1FORMAT 9 | . Do not apply to Model III LDOS or Model 4 LS-DOS! 10 | . 11 | X'630B'=00 00 12 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2020, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "z80.h" 47 | #include "trs.h" 48 | #include "trs_disk.h" 49 | #include "trs_hard.h" 50 | #include "load_cmd.h" 51 | 52 | int trs_model = 1; 53 | int trs_paused = 1; 54 | int trs_autodelay = 0; 55 | char *program_name; 56 | char *romfile1 = NULL; 57 | char *romfile1x = NULL; 58 | char *romfile3 = NULL; 59 | char *romfile4p = NULL; 60 | 61 | static void check_endian(void) 62 | { 63 | wordregister x; 64 | x.byte.low = 1; 65 | x.byte.high = 0; 66 | if(x.word != 1) 67 | { 68 | fatal("Program compiled with wrong ENDIAN value -- adjust the Makefile.local, type \"rm *.o\", recompile, and try again."); 69 | } 70 | } 71 | 72 | /* 73 | * Although the ROM loading code supports multiple ROMs, xtrs has an 74 | * overall assumeion that addresses from 0 up to the end of the 75 | * highest-addressed ROM (if any) are all ROM space. So we set 76 | * trs_rom_size to the end of the highest-addressed ROM that has been 77 | * seen. We do now check for loading too large a Model 4P boot ROM, 78 | * which can happen if someone tries to use a Model III/4 ROM in 4P mode. 79 | * 80 | * Moreover, we assume we know where the ROMs start -- address 0 for 81 | * all except the Model I ESF extension ROM, which starts at 0x3000. 82 | * We don't check if this assumption is violated, even in cases where 83 | * it's possible to check because the ROM format carries a starting 84 | * address, such as with Intel hex format or load module format. 85 | */ 86 | 87 | /* 88 | * Load a ROM from an external file. 89 | */ 90 | void trs_load_rom(int address, char *filename) 91 | { 92 | FILE *program; 93 | int c; 94 | int rom_end = 0; 95 | 96 | if((program = fopen(filename, "r")) == NULL) 97 | { 98 | char message[100]; 99 | sprintf(message, "could not read %s", filename); 100 | fatal(message); 101 | } 102 | c = getc(program); 103 | 104 | if (c == ':') { 105 | /* Assume Intel hex format */ 106 | rewind(program); 107 | rom_end = load_hex(program); 108 | goto done; 109 | } 110 | 111 | if (c == 1 || c == 5) { 112 | /* Assume MODELA/III file (load module) */ 113 | int res; 114 | extern Uchar *rom; /*!! fixme*/ 115 | Uchar loadmap[Z80_ADDRESS_LIMIT]; 116 | rewind(program); 117 | res = load_cmd(program, rom, loadmap, 0, NULL, -1, NULL, NULL, 1); 118 | if (res == LOAD_CMD_OK) { 119 | rom_end = Z80_ADDRESS_LIMIT; 120 | while (rom_end > 0) { 121 | if (loadmap[--rom_end] != 0) { 122 | rom_end++; 123 | break; 124 | } 125 | } 126 | goto done; 127 | } else { 128 | /* Apparently it wasn't one; prepare to fall through to 129 | * raw binary case. */ 130 | rewind(program); 131 | c = getc(program); 132 | } 133 | } 134 | 135 | /* Assume raw binary */ 136 | rom_end = address; 137 | while (c != EOF) { 138 | mem_write_rom(rom_end++, c); 139 | c = getc(program); 140 | } 141 | 142 | done: 143 | fclose(program); 144 | if (rom_end > trs_rom_size) { 145 | trs_rom_size = rom_end; 146 | } 147 | } 148 | 149 | /* 150 | * Load a compiled-in ROM. 151 | */ 152 | void trs_load_compiled_rom(int address, int size, unsigned char rom[]) 153 | { 154 | int i; 155 | 156 | for (i = 0; i < size; i++) { 157 | mem_write_rom(address + i, rom[i]); 158 | } 159 | 160 | if (address + size > trs_rom_size) { 161 | trs_rom_size = address + size; 162 | } 163 | } 164 | 165 | void 166 | trs_load_romfiles(void) 167 | { 168 | struct stat statbuf; 169 | 170 | switch (trs_model) { 171 | case 1: 172 | #ifdef DEFAULT_ROM1 173 | if (!romfile1) { 174 | romfile1 = DEFAULT_ROM1; 175 | } 176 | #endif 177 | if (romfile1 != NULL && stat(romfile1, &statbuf) == 0) { 178 | trs_load_rom(0, romfile1); 179 | } else if (trs_rom1_size > 0) { 180 | trs_load_compiled_rom(0, trs_rom1_size, trs_rom1); 181 | } else { 182 | fatal("ROM file not specified!"); 183 | } 184 | 185 | #ifdef DEFAULT_ROM1X 186 | if (!romfile1x) { 187 | romfile1x = DEFAULT_ROM1X; 188 | } 189 | #endif 190 | if (romfile1x != NULL && stat(romfile1x, &statbuf) == 0) { 191 | trs_load_rom(0x3000, romfile1x); 192 | } else if (trs_rom1x_size > 0) { 193 | trs_load_compiled_rom(0x3000, trs_rom1x_size, trs_rom1x); 194 | } 195 | break; 196 | 197 | case 3: 198 | case 4: 199 | #ifdef DEFAULT_ROM3 200 | if (!romfile3) { 201 | romfile3 = DEFAULT_ROM3; 202 | } 203 | #endif 204 | if (romfile3 != NULL && stat(romfile3, &statbuf) == 0) { 205 | trs_load_rom(0, romfile3); 206 | } else if (trs_rom3_size > 0) { 207 | trs_load_compiled_rom(0, trs_rom3_size, trs_rom3); 208 | } else { 209 | fatal("ROM file not specified!"); 210 | } 211 | break; 212 | 213 | default: /* 4P */ 214 | #ifdef DEFAULT_ROM4P 215 | if (!romfile4p) { 216 | romfile4p = DEFAULT_ROM4P; 217 | } 218 | #endif 219 | if (romfile4p != NULL && stat(romfile4p, &statbuf) == 0) { 220 | trs_load_rom(0, romfile4p); 221 | } else if (trs_rom4p_size > 0) { 222 | trs_load_compiled_rom(0, trs_rom4p_size, trs_rom4p); 223 | } else { 224 | fatal("ROM file not specified!"); 225 | } 226 | if (trs_rom_size > 0x1000) { 227 | fatal("Wrong type of ROM; a Model 4P boot ROM is at most 4KB"); 228 | } 229 | break; 230 | } 231 | } 232 | 233 | int main(int argc, char *argv[]) 234 | { 235 | int debug = FALSE; 236 | 237 | /* program_name must be set first because the error 238 | * printing routines use it. */ 239 | program_name = strrchr(argv[0], '/'); 240 | if (program_name == NULL) { 241 | program_name = argv[0]; 242 | } else { 243 | program_name++; 244 | } 245 | 246 | check_endian(); 247 | 248 | argc = trs_parse_command_line(argc, argv, &debug); 249 | if (argc > 1) { 250 | fatal("erroneous argument %s", argv[1]); 251 | } 252 | mem_init(); 253 | trs_screen_init(); 254 | trs_timer_init(); 255 | trs_disk_init(); 256 | trs_hard_init(); 257 | stringy_init(); 258 | 259 | trs_load_romfiles(); 260 | trs_reset(1); 261 | if (!debug) { 262 | /* Run continuously until exit or request to enter debugger */ 263 | z80_run(TRUE); 264 | } 265 | printf("Entering debugger.\n"); 266 | debug_init(); 267 | debug_shell(); 268 | printf("Quitting.\n"); 269 | exit(0); 270 | } 271 | 272 | -------------------------------------------------------------------------------- /mkdisk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996-2020, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * mkdisk.c 27 | * Make a blank (unformatted) emulated floppy or hard drive in a file, 28 | * or write protect/unprotect an existing one. 29 | */ 30 | 31 | #define _XOPEN_SOURCE 500 /* unistd.h: getopt(), ...; sys/stat.h: fchmod() */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "trs_disk.h" 42 | #include "trs_hard.h" 43 | #include "trs_stringy.h" 44 | 45 | char *program_name; 46 | typedef unsigned char Uchar; 47 | 48 | void Usage(char *progname) 49 | { 50 | fprintf(stderr, 51 | "Usage:\t%s -1 [-f] file\n" 52 | "\t%s [-3] [-f] file\n" 53 | "\t%s -k [-s sides] [-d density] [-8] [-i] [-f] file\n" 54 | "\t%s -h [-c cyl] [-s sec] [-g gran] [-d dcyl] [-f] file\n" 55 | "\t%s -w [-s size] [-f] file\n" 56 | "\t%s {-p|-u} {-1|-3|-k|-h|-w} file\n", 57 | progname, progname, progname, progname, progname, progname); 58 | exit(2); 59 | } 60 | 61 | /* 62 | * If overwrite, create or truncate fname and open for writing. If 63 | * !overwrite, create and open fname only if it does not already 64 | * exist. Could use fopen mode "wx" for the latter, but we're still 65 | * making a faint effort to be compatible with older systems that 66 | * don't have that C11 feature. 67 | */ 68 | FILE * 69 | fopen_w(const char *fname, int overwrite) 70 | { 71 | if (overwrite) { 72 | return fopen(fname, "w"); 73 | } else { 74 | int fd; 75 | fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); 76 | if (fd < 0) { 77 | return NULL; 78 | } 79 | return fdopen(fd, "w"); 80 | } 81 | } 82 | 83 | int 84 | main(int argc, char *argv[]) 85 | { 86 | int jv1 = 0, jv3 = 0, dmk = 0, hard = 0, wafer = 0; 87 | int cyl = -1, sec = -1, gran = -1, dir = -1, eight = 0, ignden = 0; 88 | int writeprot = 0, unprot = 0, overwrite = 0; 89 | int c, oumask, res; 90 | char *fname; 91 | FILE *f; 92 | 93 | /* program_name must be set first because the error 94 | * printing routines use it. */ 95 | program_name = strrchr(argv[0], '/'); 96 | if (program_name == NULL) { 97 | program_name = argv[0]; 98 | } else { 99 | program_name++; 100 | } 101 | 102 | opterr = 0; 103 | for (;;) { 104 | c = getopt(argc, argv, "13khwc:s:g:d:8ipuf"); 105 | if (c == -1) break; 106 | switch (c) { 107 | case '1': 108 | jv1 = 1; 109 | break; 110 | case '3': 111 | jv3 = 1; 112 | break; 113 | case 'k': 114 | dmk = 1; 115 | break; 116 | case 'h': 117 | hard = 1; 118 | break; 119 | case 'w': 120 | wafer = 1; 121 | break; 122 | case 'c': 123 | cyl = atoi(optarg); 124 | break; 125 | case 's': 126 | sec = atoi(optarg); // or sides or size 127 | break; 128 | case 'g': 129 | gran = atoi(optarg); 130 | break; 131 | case 'd': 132 | dir = atoi(optarg); // or density 133 | break; 134 | case '8': 135 | eight = 1; 136 | break; 137 | case 'i': 138 | ignden = 1; 139 | break; 140 | case 'p': 141 | writeprot = 1; 142 | break; 143 | case 'u': 144 | unprot = 1; 145 | break; 146 | case 'f': 147 | overwrite = 1; 148 | break; 149 | case '?': 150 | default: 151 | Usage(argv[0]); 152 | break; 153 | } 154 | } 155 | 156 | if (argc - optind != 1) Usage(argv[0]); 157 | 158 | fname = argv[optind]; 159 | 160 | /* 161 | * Media write protect/unprotect. 162 | */ 163 | if (writeprot || unprot) { 164 | struct stat st; 165 | int newmode; 166 | 167 | if (writeprot && unprot) { 168 | error("-p and -u are mutually exclusive"); 169 | exit(2); 170 | } 171 | 172 | if (jv1 + jv3 + dmk + hard + wafer != 1) { 173 | error("%s requires exactly one of -1, -3, -k, -h, or -w", 174 | writeprot ? "-p" : "-u"); 175 | exit(2); 176 | } 177 | 178 | if (stat(fname, &st) < 0) { 179 | perror(fname); 180 | exit(1); 181 | } 182 | 183 | /* Make writable so we can poke inside if need be */ 184 | if (chmod(fname, st.st_mode | (S_IWUSR|S_IWGRP|S_IWOTH)) < 0) { 185 | perror(fname); 186 | exit(1); 187 | } 188 | 189 | f = fopen(fname, "r+"); 190 | if (f == NULL) { 191 | perror(fname); 192 | exit(1); 193 | } 194 | 195 | /* Poke inside */ 196 | if (jv1 || jv3 || dmk) { 197 | res = trs_disk_set_write_prot(f, jv1 ? JV1 : jv3 ? JV3 : DMK, writeprot); 198 | if (res < 0) { 199 | perror(fname); 200 | exit(1); 201 | } 202 | 203 | } else if (hard) { 204 | res = trs_hard_set_write_prot(f, writeprot); 205 | if (res < 0) { 206 | perror(fname); 207 | exit(1); 208 | } 209 | 210 | } else if (wafer) { 211 | /* Set the magic bit */ 212 | res = stringy_set_write_prot(f, STRINGY_FMT_ESF, writeprot); 213 | if (res < 0) { 214 | perror(fname); 215 | exit(1); 216 | } 217 | } 218 | 219 | /* Finish by chmoding the file appropriately */ 220 | if (writeprot) { 221 | newmode = st.st_mode & ~(S_IWUSR|S_IWGRP|S_IWOTH); 222 | } else { 223 | oumask = umask(0); 224 | umask(oumask); 225 | newmode = st.st_mode | 226 | (( (st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH)) >> 1 ) & ~oumask); 227 | } 228 | if (fchmod(fileno(f), newmode)) { 229 | perror(fname); 230 | exit(1); 231 | } 232 | fclose(f); 233 | exit(0); 234 | } 235 | 236 | /* 237 | * Media creation 238 | */ 239 | switch (jv1 + jv3 + dmk + hard + wafer) { 240 | case 0: 241 | jv3 = 1; 242 | break; 243 | case 1: 244 | break; 245 | default: 246 | error("-1, -3, -k, -h, and -w are mutually exclusive"); 247 | exit(2); 248 | } 249 | 250 | if ((jv1 || jv3) && (cyl >= 0 || sec >= 0 || gran >= 0 || dir >= 0)) { 251 | error("-c, -s, -g, -d are not meaningful with -1 or -3"); 252 | exit(2); 253 | } 254 | 255 | if (dmk && (cyl >= 0 || gran >= 0)) { 256 | error("-c and -g are not meaningful with -k"); 257 | exit(2); 258 | } 259 | 260 | if (!dmk && (eight || ignden)) { 261 | error("-8 and -i are only meaningful with -k"); 262 | exit(2); 263 | } 264 | 265 | f = fopen_w(fname, overwrite); 266 | if (f == NULL) { 267 | perror(fname); 268 | exit(1); 269 | } 270 | 271 | if (jv1 || jv3 || dmk) { 272 | /* Reuse flag letters s, d */ 273 | #define sides sec 274 | #define density dir 275 | res = trs_disk_init_with(f, jv1 ? JV1 : jv3 ? JV3 : DMK, 276 | sides, density, eight, ignden); 277 | } else if (hard) { 278 | res = trs_hard_init_with(f, cyl, sec, gran, dir); 279 | 280 | } else /* wafer */ { 281 | /* Reuse flag letter s */ 282 | #define size sec 283 | if (size == -1) { 284 | size = STRINGY_LEN_DEFAULT; 285 | } else { 286 | size = stringy_len_from_kb(size); 287 | } 288 | res = stringy_init_with(f, STRINGY_FMT_DEFAULT, size, 289 | STRINGY_EOT_DEFAULT, FALSE); 290 | } 291 | 292 | if (res < 0) { 293 | perror(fname); 294 | fclose(f); 295 | unlink(fname); 296 | exit(1); 297 | } 298 | 299 | fclose(f); 300 | 301 | return 0; 302 | } 303 | -------------------------------------------------------------------------------- /mount.ccc: -------------------------------------------------------------------------------- 1 | /* mount.ccc -- Misosys C program to switch emulated floppies on xtrs */ 2 | 3 | /* XXX: Assumes the original xtrs method where an emulated floppy 4 | * always has the name "diskM-N" where M is the model and N is the 5 | * unit number. This does not work if gxtrs's dialog has been used to 6 | * mount a floppy with a name of a different format. To fix this will 7 | * at least require adding an emt that calls trs_disk_set_name. */ 8 | 9 | /* 10 | * Copyright (c) 1998-2008, Timothy P. Mann 11 | * 12 | * Permission is hereby granted, free of charge, to any person 13 | * obtaining a copy of this software and associated documentation 14 | * files (the "Software"), to deal in the Software without 15 | * restriction, including without limitation the rights to use, copy, 16 | * modify, merge, publish, distribute, sublicense, and/or sell copies 17 | * of the Software, and to permit persons to whom the Software is 18 | * furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be 21 | * included in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | * SOFTWARE. 31 | */ 32 | 33 | #option redirect 0 34 | #include "xtrsemt.h" 35 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 36 | 37 | usage() 38 | { 39 | fprintf(stderr, "usage: mount [-l] file.dsk unit#\n"); 40 | exit(1); 41 | } 42 | 43 | #define DDIRSIZE 256 44 | #define DNAMESIZE 512 45 | #define FNAMESIZE 256 46 | #define CMDSIZE 512 47 | #define ERRBUFSIZE 512 48 | 49 | int main(argc, argv) 50 | int argc; 51 | char **argv; 52 | { 53 | char ddir[DDIRSIZE]; 54 | char dname[DNAMESIZE], fname[FNAMESIZE], cmd[CMDSIZE]; 55 | char errbuf[ERRBUFSIZE]; 56 | char model[4]; 57 | int hl, bc, de, ret, lower, i; 58 | char *retp, *p, *q; 59 | 60 | if (argc < 2) { 61 | usage(); 62 | } 63 | i = 1; 64 | if (argv[i][0] == '-') { 65 | if (tolower(argv[i][1]) != 'l') { 66 | usage(); 67 | } 68 | i++; 69 | lower = 1; 70 | } else { 71 | lower = 0; 72 | } 73 | if (argc - i != 2 || !isdigit(argv[i+1][0])) { 74 | usage(); 75 | } 76 | retp = emt_gtddir(ddir, DDIRSIZE); 77 | if (retp == NULL) { 78 | emt_strerror(errno, errbuf, ERRBUFSIZE); 79 | fprintf(stderr, "emt_getddir: %s\n", errbuf); 80 | exit(1); 81 | } 82 | emt_4misc(EMT_MISC_QUERY_MODEL, &hl, &bc, &de); 83 | if (hl == 5) { 84 | strcpy(model, "4p"); 85 | } else { 86 | sprintf(model, "%d", hl); 87 | } 88 | sprintf(dname, "%s/disk%s-%s", ddir, model, argv[i+1]); 89 | sprintf(cmd, "rm -f %s", dname); 90 | /*printf("$ %s\n", cmd);*/ 91 | ret = emt_system(cmd); 92 | if (ret != 0) { 93 | emt_strerror(errno, errbuf, ERRBUFSIZE); 94 | fprintf(stderr, "emt_system: %s\n", errbuf); 95 | exit(1); 96 | } 97 | 98 | p = fname; 99 | q = argv[i]; 100 | if (lower) { 101 | while (*q) { 102 | if (*q == '[' && *(q+1)) { 103 | q++; 104 | *p++ = *q++; 105 | } else if (isalpha(*q)) { 106 | *p++ = tolower(*q++); 107 | } else { 108 | *p++ = *q++; 109 | } 110 | } 111 | } else { 112 | while (*q) *p++ = *q++; 113 | } 114 | *p = '\000'; 115 | 116 | sprintf(cmd, "ln -s %s %s", fname, dname); 117 | /*printf("$ %s\n", cmd);*/ 118 | ret = emt_system(cmd); 119 | if (ret != 0) { 120 | emt_strerror(errno, errbuf, ERRBUFSIZE); 121 | fprintf(stderr, "emt_system: %s\n", errbuf); 122 | exit(1); 123 | } 124 | emt_misc(EMT_MISC_DISK_CHANGE); 125 | exit(0); 126 | } 127 | -------------------------------------------------------------------------------- /mount.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/mount.cmd -------------------------------------------------------------------------------- /mount6.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/mount6.cmd -------------------------------------------------------------------------------- /pwd.ccc: -------------------------------------------------------------------------------- 1 | /* pwd.ccc -- Misosys C program to print the Unix working directory of xtrs */ 2 | 3 | /* 4 | * Copyright (c) 1998-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #option redirect 0 28 | #include "xtrsemt.h" 29 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 30 | 31 | usage() 32 | { 33 | fprintf(stderr, "usage: pwd\n"); 34 | exit(1); 35 | } 36 | 37 | #define ERRBUFSIZE 256 38 | #define DIRBUFSIZE 512 39 | 40 | int main(argc, argv) 41 | int argc; 42 | char **argv; 43 | { 44 | int i; 45 | char *ret; 46 | char errbuf[ERRBUFSIZE]; 47 | char dirbuf[DIRBUFSIZE]; 48 | if (argc != 1) { 49 | usage(); 50 | } 51 | ret = emt_getcwd(dirbuf, DIRBUFSIZE); 52 | if (ret == NULL) { 53 | emt_strerror(errno, errbuf, ERRBUFSIZE); 54 | fprintf(stderr, "pwd: %s\n", errbuf); 55 | exit(1); 56 | } 57 | printf("%s\n", dirbuf); 58 | exit(0); 59 | } 60 | -------------------------------------------------------------------------------- /pwd.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/pwd.cmd -------------------------------------------------------------------------------- /pwd6.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/pwd6.cmd -------------------------------------------------------------------------------- /reed.h: -------------------------------------------------------------------------------- 1 | /* Matthew Reed's hard drive format. Thanks to Matthew for providing 2 | documentation. The comments below are copied from his mail 3 | messages, with some additions. */ 4 | 5 | typedef struct { 6 | Uchar id1; /* 0: Identifier #1: 56H */ 7 | Uchar id2; /* 1: Identifier #2: CBH */ 8 | Uchar ver; /* 2: Version of format: 9 | 10H = version 1.0, created by Reed emulator or xtrs. 10 | 11H = version 1.1, created by Keil emulator. 11 | xtrs assumes 1.1 and 1.0 don't differ significantly. */ 12 | Uchar cksum; /* 3: Simple checksum: 13 | To calculate, add together bytes 0 to 31 14 | of header (excepting byte 3), then XOR 15 | result with 4CH */ 16 | Uchar blks; /* 4: Number of 256 byte blocks in header: 17 | should be 1 */ 18 | Uchar mb4; /* 5: Not used, but HDFORMAT sets to 4 */ 19 | Uchar media; /* 6: Media type: 0 for hard disk */ 20 | Uchar flag1; /* 7: Flags #1: 21 | bit 7: Write protected: 0 for no, 1 for 22 | yes [xtrshard/dct ignores for now] 23 | bit 6: Must be 0 24 | bit 5 - 0: reserved */ 25 | Uchar flag2; /* 8: Flags #2: reserved */ 26 | Uchar flag3; /* 9: Flags #3: reserved */ 27 | Uchar crtr; /* 10: Created by: 28 | 14H = HDFORMAT 29 | 42H = xtrs mkdisk 30 | 80H = Cervasio xtrshard port to Vavasour 31 | M4 emulator */ 32 | Uchar dfmt; /* 11: Disk format: 0 = LDOS/LS-DOS */ 33 | Uchar mm; /* 12: Creation month: mm */ 34 | Uchar dd; /* 13: Creation day: dd */ 35 | Uchar yy; /* 14: Creation year: yy (offset from 1900) */ 36 | Uchar res1[12]; /* 15 - 26: reserved */ 37 | Uchar dparm; /* 27: Disk parameters: 38 | (unused with hard drives) 39 | bit 7: Density: 0 = double, 1 = single 40 | bit 6: Sides: 0 = one side, 1 = 2 sides 41 | bit 5: First sector: 0 if sector 0, 42 | 1 if sector 1 43 | bit 4: DAM convention: 0 if normal 44 | (LDOS), 1 if reversed (TRSDOS 1.3) 45 | bit 3 - 0: reserved */ 46 | Uchar cyl; /* 28: Number of cylinders per disk */ 47 | Uchar sec; /* 29: Number of sectors per track (floppy); 48 | cyl (hard) */ 49 | Uchar gran; /* 30: Number of granules per track (floppy); 50 | cyl (hard)*/ 51 | Uchar dcyl; /* 31: Directory cylinder [mkdisk sets to 1; 52 | xtrs ignores]*/ 53 | char label[32]; /* 32: Volume label: 31 bytes terminated by 0 */ 54 | Uchar res2[192]; /* 64 - 255: reserved */ 55 | } ReedHardHeader; 56 | -------------------------------------------------------------------------------- /settime.ccc: -------------------------------------------------------------------------------- 1 | /* settime.ccc -- Misosys C program to set time using xtrs emulator traps */ 2 | 3 | /* 4 | * Copyright (c) 1998-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #option redirect 0 28 | #include "xtrsemt.h" 29 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 30 | 31 | main() 32 | { 33 | time_t now; 34 | struct tm *nowtm; 35 | char cmd[81]; 36 | 37 | now = emt_time(EMT_TIME_LOCAL); 38 | nowtm = localtime(&now); 39 | sprintf(cmd, "date %02d/%02d/%02d", 40 | nowtm->tm_mon + 1, nowtm->tm_mday, nowtm->tm_year % 100); 41 | system(cmd); 42 | sprintf(cmd, "time %02d:%02d:%02d", 43 | nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec); 44 | system(cmd); 45 | system("time"); 46 | } 47 | -------------------------------------------------------------------------------- /settime.z80: -------------------------------------------------------------------------------- 1 | ;; settime.z80 2 | ;; 3 | ;; Read date and time from xtrs emulator trap and set 4 | ;; TRS-80 system date and time. 5 | ;; 6 | ;; Copyright (c) 1998 Ulrich Mueller 7 | ;; 8 | ;; Permission is hereby granted, free of charge, to any person 9 | ;; obtaining a copy of this software and associated documentation 10 | ;; files (the "Software"), to deal in the Software without 11 | ;; restriction, including without limitation the rights to use, copy, 12 | ;; modify, merge, publish, distribute, sublicense, and/or sell copies 13 | ;; of the Software, and to permit persons to whom the Software is 14 | ;; furnished to do so, subject to the following conditions: 15 | ;; 16 | ;; The above copyright notice and this permission notice shall be 17 | ;; included in all copies or substantial portions of the Software. 18 | ;; 19 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | ;; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | ;; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | ;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | ;; SOFTWARE. 27 | 28 | ;; Model I/III addresses 29 | @exit equ 402dh 30 | @abort equ 4030h 31 | 32 | ;; Model 1 and 3 store the last 2 digits of the year in the year byte 33 | time1$ equ 4041h ; seconds/minutes/hours 34 | date1$ equ 4044h ; year/day/month 35 | time3$ equ 4217h 36 | date3$ equ 421ah 37 | 38 | ;; Model 4 SVCs 39 | @svc equ 40 ; rst address for SVCs 40 | ;@svc equ 5 ; older zmac requires 8080-style "rst 5" 41 | @exit6 equ 22 42 | @abort6 equ 21 43 | 44 | ;; Model 4 stores the offset from 1900 in the year byte 45 | time4$ equ 002dh 46 | date4$ equ 0033h 47 | 48 | ;; Emulator trap instructions 49 | emt_time equ 36edh 50 | 51 | org 5200h 52 | settime: 53 | call initj ; init OS-dependent tables 54 | ld bc, 0ffffh 55 | ld a, 1 ; get local time from Unix 56 | defw emt_time ; BCDE: seconds since 1970 57 | ld a, b 58 | and c 59 | inc a 60 | jp z, abort 61 | di 62 | ld hl, (time) 63 | ld a, 60 64 | call divide 65 | ld (hl), a ; seconds 66 | inc hl 67 | ld a, 60 68 | call divide 69 | ld (hl), a ; minutes 70 | inc hl 71 | ld a, 24 72 | call divide 73 | ld (hl), a ; hours 74 | ex de, hl ; HL: days since 1970 75 | ld bc, 19*256+70-1 76 | ld de, 365 77 | year1: inc c ; count years in C 78 | ld a, c 79 | sub 100 80 | jr c, year2 81 | ld c, a 82 | inc b ; centuries 83 | ld a, b 84 | year2: and 3 85 | sub 1 86 | sbc hl, de 87 | jr nc, year1 88 | rlca 89 | adc hl, de ; HL: days since 1 january 90 | push hl 91 | ld hl, (date) 92 | call putyr ; year to (hl) 93 | inc hl 94 | ex (sp), hl 95 | and 1 ; A=1 for leap year, 0 else 96 | add a, 28 97 | ld c, a 98 | ld b, 0 99 | ld d, b 100 | month1: inc b ; count months in B 101 | ld a, b 102 | ld e, c 103 | cp 2 104 | jr z, month2 ; february 105 | ld e, 31 106 | and 9 107 | jp po, month2 ; 31 days 108 | dec e ; 30 days 109 | month2: sbc hl, de ; subtract length of month 110 | jr nc, month1 111 | adc hl, de 112 | ld c, l 113 | pop hl 114 | ld (hl), c ; day 115 | inc hl 116 | ld (hl), b ; month 117 | ei 118 | ld hl,0 ; needed on Model 4 --mann 119 | jr exit 120 | 121 | ;; divide BCDE / A 122 | ;; returns quotient in BCDE, remainder in A 123 | divide: push hl 124 | neg 125 | ld h, a 126 | sub a 127 | ld l, 33 128 | div1: rla 129 | add a, h 130 | jr c, div2 131 | sub h 132 | div2: rl e 133 | rl d 134 | rl c 135 | rl b 136 | dec l 137 | jr nz, div1 138 | pop hl 139 | ret 140 | 141 | ;; Jump tables for OS independence 142 | ;; Model 1 143 | startj: 144 | exit: jp @exit 145 | abort: jp @abort 146 | time: defw time1$ 147 | date: defw date1$ 148 | putyr: jp putyr1 149 | endj: 150 | 151 | ;; Model 3 152 | startj3: 153 | jp @exit 154 | jp @abort 155 | defw time3$ 156 | defw date3$ 157 | jp putyr3 158 | 159 | ;; Model 4 160 | startj4: 161 | ld a, @exit6 162 | rst @svc 163 | ld a, @abort6 164 | rst @svc 165 | defw time4$ 166 | defw date4$ 167 | jp putyr4 168 | 169 | ;; Initialize tables 170 | ;; Changed to work even on a Model III (or Model 4 in III mode) 171 | ;; using MODELA/III as its ROM. Previous version didn't. --mann 172 | ;; 173 | initj: ld hl, startj4 ; model 4? 174 | ld a, (000ah) 175 | cp 40h 176 | jr nz, movej ; go if so 177 | ld hl, startj3 ; model 3? 178 | ld a, (0125h) 179 | cp 'I' 180 | ret nz ; return if not 181 | movej: ld de, startj 182 | ld bc, endj - startj 183 | ldir 184 | ret 185 | 186 | ;; Create year byte. 187 | ;; On entry, c has 2-digit year, b has century. 188 | ;; On exit, (hl) has year byte. 189 | 190 | ;; Model I/III, put 2-digit year 191 | putyr1: 192 | putyr3: ld (hl), c 193 | ret 194 | 195 | ;; Model 4, put offset from 1900 (laboriously recomputed, sigh) 196 | putyr4: push af 197 | push bc 198 | ld a, b 199 | sub 19 200 | ld b, a 201 | ld a, c 202 | jr z, py41 203 | py40: add a, 100 204 | djnz py40 205 | py41: ld (hl), a 206 | pop bc 207 | pop af 208 | ret 209 | 210 | end settime 211 | 212 | 213 | -------------------------------------------------------------------------------- /trs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2020, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | 41 | /* 42 | * trs.h 43 | */ 44 | #ifndef _TRS_H 45 | #define _TRS_H 46 | 47 | #include "z80.h" 48 | #include "time.h" 49 | 50 | #define NORMAL 0 51 | #define EXPANDED 1 52 | #define INVERSE 2 53 | #define ALTERNATE 4 54 | 55 | extern char *program_name; 56 | extern char *romfile1; 57 | extern char *romfile1x; 58 | extern char *romfile3; 59 | extern char *romfile4p; 60 | extern int trs_model; /* 1, 3, 4, 5(=4p) */ 61 | extern int trs_paused; 62 | extern int trs_autodelay; 63 | void trs_suspend_delay(void); 64 | void trs_restore_delay(void); 65 | extern int trs_continuous; /* 1= run continuously, 66 | 0= enter debugger after instruction, 67 | -1= suppress interrupt and enter debugger */ 68 | extern int trs_disk_debug_flags; 69 | extern int trs_io_debug_flags; 70 | extern int trs_emtsafe; 71 | 72 | int trs_parse_command_line(int argc, char **argv, int *debug); 73 | 74 | void trs_screen_init(void); 75 | void trs_screen_write_char(int position, int char_index); 76 | void trs_screen_expanded(int flag); 77 | void trs_screen_alternate(int flag); 78 | void trs_screen_80x24(int flag); 79 | void trs_screen_inverse(int flag); 80 | void trs_screen_scroll(void); 81 | void trs_screen_refresh(void); 82 | extern int trs_lowercase; 83 | 84 | void trs_reset(int poweron); 85 | void trs_exit(void); 86 | 87 | void trs_kb_reset(void); 88 | void trs_kb_bracket(int shifted); 89 | int trs_kb_mem_read(int address); 90 | int trs_next_key(int wait); 91 | void trs_kb_heartbeat(void); 92 | void trs_xlate_keysym(int keysym); 93 | void queue_key(int key); 94 | int dequeue_key(void); 95 | void clear_key_queue(void); 96 | void trs_skip_next_kbwait(void); 97 | extern int stretch_amount; 98 | extern int trs_keydelay; 99 | 100 | void trs_get_event(int wait); 101 | extern volatile int x_poll_count; 102 | 103 | void trs_printer_write(int value); 104 | int trs_printer_read(void); 105 | 106 | void trs_cassette_motor(int value); 107 | void trs_cassette_out(int value); 108 | int trs_cassette_in(void); 109 | void trs_cassette_select(int value); 110 | void trs_sound_out(int value); 111 | 112 | int trs_joystick_in(void); 113 | 114 | extern int trs_rom_size; 115 | extern int trs_rom1_size; 116 | extern int trs_rom1x_size; 117 | extern int trs_rom3_size; 118 | extern int trs_rom4p_size; 119 | extern unsigned char trs_rom1[]; 120 | extern unsigned char trs_rom1x[]; 121 | extern unsigned char trs_rom3[]; 122 | extern unsigned char trs_rom4p[]; 123 | 124 | unsigned char trs_interrupt_latch_read(void); 125 | unsigned char trs_nmi_latch_read(void); 126 | void trs_interrupt_mask_write(unsigned char); 127 | void trs_nmi_mask_write(unsigned char); 128 | void trs_reset_button_interrupt(int state); 129 | void trs_disk_intrq_interrupt(int state); 130 | void trs_disk_drq_interrupt(int state); 131 | void trs_disk_motoroff_interrupt(int state); 132 | void trs_uart_err_interrupt(int state); 133 | void trs_uart_rcv_interrupt(int state); 134 | void trs_uart_snd_interrupt(int state); 135 | void trs_timer_interrupt(int state); 136 | void trs_timer_init(void); 137 | void trs_timer_off(void); 138 | void trs_timer_on(void); 139 | void trs_timer_speed(int flag); 140 | void trs_cassette_rise_interrupt(int dummy); 141 | void trs_cassette_fall_interrupt(int dummy); 142 | void trs_cassette_clear_interrupts(void); 143 | int trs_cassette_interrupts_enabled(void); 144 | void trs_cassette_update(int dummy); 145 | extern int cassette_default_sample_rate; 146 | void trs_orch90_out(int chan, int value); 147 | void trs_cassette_reset(void); 148 | 149 | extern time_t trs_timeoffset; 150 | void trs_inityear(int year); 151 | 152 | const char *trs_disk_get_name(int drive); 153 | int trs_disk_set_name(int drive, const char *newname); 154 | int trs_disk_create(const char *newname); 155 | void trs_disk_change_all(void); 156 | void trs_disk_debug(void); 157 | int trs_disk_motoroff(void); 158 | 159 | void trs_change_all(void); 160 | 161 | void mem_video_page(int which); 162 | void mem_bank(int which); 163 | void mem_map(int which); 164 | void mem_romin(int state); 165 | 166 | void trs_debug(void); 167 | 168 | typedef void (*trs_event_func)(int arg); 169 | void trs_schedule_event(trs_event_func f, int arg, int tstates); 170 | void trs_schedule_event_us(trs_event_func f, int arg, int us); 171 | void trs_do_event(void); 172 | void trs_cancel_event(void); 173 | trs_event_func trs_event_scheduled(void); 174 | 175 | void grafyx_write_x(int value); 176 | void grafyx_write_y(int value); 177 | void grafyx_write_data(int value); 178 | int grafyx_read_data(void); 179 | void grafyx_write_mode(int value); 180 | void grafyx_write_xoffset(int value); 181 | void grafyx_write_yoffset(int value); 182 | void grafyx_write_overlay(int value); 183 | void grafyx_set_microlabs(int on_off); 184 | int grafyx_get_microlabs(void); 185 | void grafyx_m3_reset(); 186 | int grafyx_m3_active(); /* true if currently intercepting video i/o */ 187 | void grafyx_m3_write_mode(int value); 188 | unsigned char grafyx_m3_read_byte(int position); 189 | int grafyx_m3_write_byte(int position, int value); 190 | void hrg_onoff(int enable); 191 | void hrg_write_addr(int addr, int mask); 192 | void hrg_write_data(int data); 193 | int hrg_read_data(void); 194 | 195 | void trs_get_mouse_pos(int *x, int *y, unsigned int *buttons); 196 | void trs_set_mouse_pos(int x, int y); 197 | void trs_get_mouse_max(int *x, int *y, unsigned int *sens); 198 | void trs_set_mouse_max(int x, int y, unsigned int sens); 199 | int trs_get_mouse_type(void); 200 | 201 | void stringy_init(void); 202 | const char *stringy_get_name(int unit); 203 | int stringy_set_name(int unit, const char *name); 204 | int stringy_create(const char *name); 205 | int stringy_in(int unit); 206 | void stringy_out(int unit, int value); 207 | void stringy_reset(void); 208 | void stringy_change_all(void); 209 | 210 | int put_twobyte(Ushort n, FILE* f); 211 | int put_fourbyte(Uint n, FILE* f); 212 | int get_twobyte(Ushort *n, FILE* f); 213 | int get_fourbyte(Uint *n, FILE* f); 214 | 215 | 216 | #endif /*_TRS_H*/ 217 | -------------------------------------------------------------------------------- /trs_disk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1996-2020, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Emulate Model-I or Model-III disk controller 27 | */ 28 | 29 | void trs_disk_init(void); 30 | void trs_disk_reset(void); 31 | void trs_disk_select_write(unsigned char data); 32 | unsigned char trs_disk_track_read(void); 33 | void trs_disk_track_write(unsigned char data); 34 | unsigned char trs_disk_sector_read(void); 35 | void trs_disk_sector_write(unsigned char data); 36 | unsigned char trs_disk_data_read(void); 37 | void trs_disk_data_write(unsigned char data); 38 | unsigned char trs_disk_status_read(void); 39 | void trs_disk_command_write(unsigned char cmd); 40 | unsigned char trs_disk_interrupt_read(void); /* M3 only */ 41 | void trs_disk_interrupt_write(unsigned char mask); /* M3 only */ 42 | 43 | void trs_disk_setstep(int unit, int value); 44 | int trs_disk_getstep(int unit); 45 | void trs_disk_setsize(int unit, int value); 46 | int trs_disk_getsize(int unit); 47 | 48 | int trs_disk_init_with(FILE *f, int emutype, 49 | int sides, int density, int eight, int ignden); 50 | int trs_disk_set_write_prot(FILE *f, int emutype, int writeprot); 51 | 52 | extern int trs_disk_doubler; 53 | extern char* trs_disk_dir; 54 | extern unsigned short trs_changecount; 55 | extern int trs_disk_truedam; 56 | 57 | /* Values for emulated disk image type (emutype) */ 58 | #define JV1 1 /* compatible with Vavasour Model I emulator */ 59 | #define JV3 3 /* compatible with Vavasour Model III/4 emulator */ 60 | #define DMK 4 /* compatible with Keil Model III/4 emulator */ 61 | #define REAL 100 /* real floppy drive, PC controller */ 62 | #define NONE 0 63 | 64 | /* Values for trs_disk_doubler flag word */ 65 | #define TRSDISK_NODOUBLER 0 66 | #define TRSDISK_PERCOM 1 67 | #define TRSDISK_TANDY 2 68 | #define TRSDISK_BOTH 3 69 | 70 | /* Model I drive select register -- address bits 0,1 not decoded */ 71 | #define TRSDISK_SELECT(addr) (((addr)&~3) == 0x37e0) 72 | #define TRSDISK_0 0x1 73 | #define TRSDISK_1 0x2 74 | #define TRSDISK_2 0x4 75 | #define TRSDISK_3 0x8 76 | #define TRSDISK_SIDE 0x8 /* shared on Model I */ 77 | #define TRSDISK_4 0x3 /* fake value for emulator only */ 78 | #define TRSDISK_5 0x5 /* fake value for emulator only */ 79 | #define TRSDISK_6 0x6 /* fake value for emulator only */ 80 | #define TRSDISK_7 0x7 /* fake value for emulator only */ 81 | 82 | /* FDC address space in Model I */ 83 | #define TRSDISK_FDC 0x37ec 84 | #define TRSDISK_FDCLEN 4 /* 4 bytes are mapped, offsets as follows: */ 85 | #define TRSDISK_COMMAND 0x37ec /* writing */ 86 | #define TRSDISK_STATUS 0x37ec /* reading */ 87 | #define TRSDISK_TRACK 0x37ed 88 | #define TRSDISK_SECTOR 0x37ee 89 | #define TRSDISK_DATA 0x37ef 90 | 91 | /* FDC port space in Model III */ 92 | #define TRSDISK3_INTERRUPT 0xe4 93 | #define TRSDISK3_COMMAND 0xf0 /* writing */ 94 | #define TRSDISK3_STATUS 0xf0 /* reading */ 95 | #define TRSDISK3_TRACK 0xf1 96 | #define TRSDISK3_SECTOR 0xf2 97 | #define TRSDISK3_DATA 0xf3 98 | #define TRSDISK3_SELECT 0xf4 /* write-only */ 99 | 100 | /* Interrupt register bits (M3 only) */ 101 | #define TRSDISK3_INTRQ 0x80 102 | #define TRSDISK3_DRQ 0x40 103 | #define TRSDISK3_RESET 0x20 /* reset button, not really disk related */ 104 | 105 | /* Select register bits (M3 only). Drives 0-3 same as model 1. */ 106 | #define TRSDISK3_MFM 0x80 107 | #define TRSDISK3_WAIT 0x40 108 | #define TRSDISK3_PRECOMP 0x20 109 | #define TRSDISK3_SIDE 0x10 /* not shared! */ 110 | 111 | /* Commands */ 112 | #define TRSDISK_CMDMASK 0xf0 /* high nybble selects which command */ 113 | 114 | /* Type I commands: cccchvrr, where 115 | cccc = command number 116 | h = head load 117 | v = verify (i.e., read next address to check we're on the right track) 118 | rr = step rate: 00=6ms, 01=12ms, 10=20ms, 11=40ms 119 | */ 120 | #define TRSDISK_RESTORE 0x00 121 | #define TRSDISK_SEEK 0x10 122 | #define TRSDISK_STEP 0x20 /* don't update track reg */ 123 | #define TRSDISK_STEPU 0x30 /* do update track reg */ 124 | #define TRSDISK_STEPIN 0x40 125 | #define TRSDISK_STEPINU 0x50 126 | #define TRSDISK_STEPOUT 0x60 127 | #define TRSDISK_STEPOUTU 0x70 128 | #define TRSDISK_UBIT 0x10 129 | #define TRSDISK_HBIT 0x08 130 | #define TRSDISK_VBIT 0x04 131 | 132 | /* Type II commands: ccccbecd, where 133 | cccc = command number 134 | e = delay for head engage (10ms) 135 | 1771: 136 | b = 1=IBM format, 0=nonIBM format 137 | cd = select data address mark (writes only, 00 for reads): 138 | 00=FB (normal), 01=FA, 10=F9, 11=F8 (deleted) 139 | 1791: 140 | b = side expected 141 | c = side compare (0=disable, 1=enable) 142 | d = select data address mark (writes only, 0 for reads): 143 | 0=FB (normal), 1=F8 (deleted) 144 | */ 145 | #define TRSDISK_READ 0x80 /* single sector */ 146 | #define TRSDISK_READM 0x90 /* multiple sectors */ 147 | #define TRSDISK_WRITE 0xa0 148 | #define TRSDISK_WRITEM 0xb0 149 | #define TRSDISK_MBIT 0x10 150 | #define TRSDISK_BBIT 0x08 151 | #define TRSDISK_EBIT 0x04 152 | #define TRSDISK_CBIT 0x02 153 | #define TRSDISK_DBIT 0x01 154 | 155 | /* Type III commands: ccccxxxs (?), where 156 | cccc = command number 157 | xxx = ?? (usually 010) 158 | s = 1=READTRK no synchronize; otherwise 0 159 | */ 160 | #define TRSDISK_READADR 0xc0 161 | #define TRSDISK_READTRK 0xe0 162 | #define TRSDISK_WRITETRK 0xf0 163 | /* These commands are peculiar to the Percom Doubler */ 164 | #define TRSDISK_P1771 0xfe /* Select 1771 single density controller */ 165 | #define TRSDISK_P1791 0xff /* Select 1791 double density controller */ 166 | 167 | /* Type IV command: cccciiii, where 168 | cccc = command number 169 | iiii = bitmask of events to terminate and interrupt on (unused on trs80); 170 | 0000 for immediate terminate with no interrupt. 171 | */ 172 | #define TRSDISK_FORCEINT 0xd0 173 | 174 | /* These "commands" are peculiar to the Radio Shack Doubler. They 175 | are written to the sector register, not the command register! 176 | */ 177 | #define TRSDISK_RCMDBITS 0xe0 178 | #define TRSDISK_RSIDE0 0x40 179 | #define TRSDISK_RSIDE1 0x60 180 | #define TRSDISK_R1791 0x80 181 | #define TRSDISK_R1771 0xa0 182 | #define TRSDISK_NOPRECMP 0xc0 183 | #define TRSDISK_PRECMP 0xe0 184 | 185 | /* Type I status bits */ 186 | #define TRSDISK_BUSY 0x01 187 | #define TRSDISK_INDEX 0x02 188 | #define TRSDISK_TRKZERO 0x04 189 | #define TRSDISK_CRCERR 0x08 190 | #define TRSDISK_SEEKERR 0x10 191 | #define TRSDISK_HEADENGD 0x20 192 | #define TRSDISK_WRITEPRT 0x40 193 | #define TRSDISK_NOTRDY 0x80 194 | 195 | /* Read status bits */ 196 | /* TRSDISK_BUSY 0x01*/ 197 | #define TRSDISK_DRQ 0x02 198 | #define TRSDISK_LOSTDATA 0x04 199 | /* TRSDISK_CRCERR 0x08*/ 200 | #define TRSDISK_NOTFOUND 0x10 201 | #define TRSDISK_RECTYPE 0x60 202 | #define TRSDISK_1771_FB 0x00 203 | #define TRSDISK_1771_FA 0x20 204 | #define TRSDISK_1771_F9 0x40 205 | #define TRSDISK_1771_F8 0x60 206 | #define TRSDISK_1791_FB 0x00 207 | #define TRSDISK_1791_F8 0x20 208 | /* TRSDISK_NOTRDY 0x80*/ 209 | 210 | /* Write status bits */ 211 | /* TRSDISK_BUSY 0x01*/ 212 | /* TRSDISK_DRQ 0x02*/ 213 | /* TRSDISK_LOSTDATA 0x04*/ 214 | /* TRSDISK_CRCERR 0x08*/ 215 | /* TRSDISK_NOTFOUND 0x10*/ 216 | #define TRSDISK_WRITEFLT 0x20 217 | /* TRSDISK_WRITEPRT 0x40*/ 218 | /* TRSDISK_NOTRDY 0x80*/ 219 | 220 | /* Read address status bits */ 221 | /* TRSDISK_BUSY 0x01*/ 222 | /* TRSDISK_DRQ 0x02*/ 223 | /* TRSDISK_LOSTDATA 0x04*/ 224 | /* TRSDISK_CRCERR 0x08*/ 225 | /* TRSDISK_NOTFOUND 0x10*/ 226 | /* unused, mbz 0x60*/ 227 | /* TRSDISK_NOTRDY 0x80*/ 228 | 229 | /* Read track status bits */ 230 | /* TRSDISK_BUSY 0x01*/ 231 | /* TRSDISK_DRQ 0x02*/ 232 | /* TRSDISK_LOSTDATA 0x04*/ 233 | /* unused, mbz 0x78*/ 234 | /* TRSDISK_NOTRDY 0x80*/ 235 | 236 | /* Write track status bits */ 237 | /* TRSDISK_BUSY 0x01*/ 238 | /* TRSDISK_DRQ 0x02*/ 239 | /* TRSDISK_LOSTDATA 0x04*/ 240 | /* unused, mbz 0x18*/ 241 | /* TRSDISK_WRITEFLT 0x20*/ 242 | /* TRSDISK_WRITEPRT 0x40*/ 243 | /* TRSDISK_NOTRDY 0x80*/ 244 | 245 | -------------------------------------------------------------------------------- /trs_hard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2020, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Definitions for the Radio Shack TRS-80 Model I/III/4/4P 27 | * hard disk controller. This is a Western Digital WD1000/WD1010 28 | * mapped at ports 0xc8-0xcf, plus control registers at 0xc0-0xc1. 29 | * 30 | * Definitions inferred from various drivers and sketchy documents 31 | * found in odd corners. Anyone have a real WD10xx data sheet? 32 | */ 33 | 34 | void trs_hard_init(void); 35 | void trs_hard_reset(void); 36 | void trs_hard_change_all(void); 37 | const char *trs_hard_get_name(int drive); 38 | int trs_hard_set_name(int drive, const char *name); 39 | int trs_hard_create(const char *name); 40 | int trs_hard_in(int port); 41 | void trs_hard_out(int port, int value); 42 | int trs_hard_init_with(FILE *f, int cyl, int sec, int gran, int dir); 43 | int trs_hard_set_write_prot(FILE *f, int writeprot); 44 | 45 | extern char *trs_disk_dir; 46 | 47 | /* Sector size is always 256 for TRSDOS/LDOS/etc. */ 48 | /* Other sizes currently not emulated */ 49 | #define TRS_HARD_SECSIZE 256 50 | #define TRS_HARD_SECSIZE_CODE 0x0f /* size code for 256 byte sectors?!! */ 51 | 52 | /* RSHARD assumes 32 sectors/track */ 53 | /* Other sizes currently not emulated */ 54 | #define TRS_HARD_SEC_PER_TRK 32 55 | 56 | /* 57 | * Tandy-specific registers 58 | */ 59 | 60 | /* Write protect switch register (read only): 61 | * abcd--pi 62 | * a = drive 0 write protected 63 | * b = drive 1 write protected 64 | * c = drive 2 write protected 65 | * d = drive 3 write protected 66 | * p = at least one drive write protected 67 | * i = interrupt request 68 | */ 69 | #define TRS_HARD_WP 0xc0 70 | #define TRS_HARD_WPBIT(d) (0x80 >> (d)) 71 | #define TRS_HARD_WPSOME 0x02 72 | #define TRS_HARD_INTRQ 0x01 /* not emulated */ 73 | 74 | /* Control register (read(?)/write): 75 | * ---sdw-- 76 | * s = software reset 77 | * d = device enable 78 | * w = wait enable 79 | */ 80 | #define TRS_HARD_CONTROL 0xc1 81 | #define TRS_HARD_SOFTWARE_RESET 0x10 82 | #define TRS_HARD_DEVICE_ENABLE 0x08 83 | #define TRS_HARD_WAIT_ENABLE 0x04 84 | 85 | /* ID register (Model II only!) 86 | */ 87 | #define TRS_HARD_ID0 0xc2 88 | #define TRS_HARD_ID1 0xc3 89 | 90 | /* CTC channels (Model II only!) 91 | */ 92 | #define TRS_HARD_CTC0 0xc4 93 | #define TRS_HARD_CTC1 0xc5 94 | #define TRS_HARD_CTC2 0xc6 95 | #define TRS_HARD_CTC3 0xc7 96 | 97 | /* 98 | * WD1010 registers 99 | */ 100 | 101 | /* Data register (read/write) */ 102 | #define TRS_HARD_DATA 0xc8 103 | 104 | /* Error register (read only): 105 | * bdin-atm 106 | * b = block marked bad 107 | * e = uncorrectable error in data 108 | * i = uncorrectable error in id (unused?) 109 | * n = id not found 110 | * - = unused 111 | * a = command aborted 112 | * t = track 0 not found 113 | * m = bad address mark 114 | */ 115 | #define TRS_HARD_ERROR (TRS_HARD_DATA+1) 116 | #define TRS_HARD_BBDERR 0x80 117 | #define TRS_HARD_DATAERR 0x40 118 | #define TRS_HARD_IDERR 0x20 /* unused? */ 119 | #define TRS_HARD_NFERR 0x10 120 | #define TRS_HARD_MCRERR 0x08 /* unused */ 121 | #define TRS_HARD_ABRTERR 0x04 122 | #define TRS_HARD_TRK0ERR 0x02 123 | #define TRS_HARD_MARKERR 0x01 124 | 125 | /* Write precompensation register (write only) */ 126 | /* Value *4 is the starting cylinder for write precomp */ 127 | #define TRS_HARD_PRECOMP (TRS_HARD_DATA+1) 128 | 129 | /* Sector count register (read/write) */ 130 | /* Used only for multiple sector accesses; otherwise ignored. */ 131 | /* Autodecrements when used. */ 132 | #define TRS_HARD_SECCNT (TRS_HARD_DATA+2) 133 | 134 | /* Sector number register (read/write) */ 135 | #define TRS_HARD_SECNUM (TRS_HARD_DATA+3) 136 | 137 | /* Cylinder low byte register (read/write) */ 138 | #define TRS_HARD_CYLLO (TRS_HARD_DATA+4) 139 | 140 | /* Cylinder high byte register (read/write) */ 141 | #define TRS_HARD_CYLHI (TRS_HARD_DATA+5) 142 | 143 | /* Size/drive/head register (read/write): 144 | * essddhhh 145 | * e = 0 if CRCs used; 1 if ECC used 146 | * ss = sector size; 00=256, 01=512, 10=1024, 11=128 147 | * dd = drive 148 | * hhh = head 149 | */ 150 | #define TRS_HARD_SDH (TRS_HARD_DATA+6) 151 | #define TRS_HARD_ECCMASK 0x80 152 | #define TRS_HARD_ECCSHIFT 7 153 | #define TRS_HARD_SIZEMASK 0x60 154 | #define TRS_HARD_SIZESHIFT 5 155 | #define TRS_HARD_DRIVEMASK 0x18 156 | #define TRS_HARD_DRIVESHIFT 3 157 | #define TRS_HARD_MAXDRIVES 4 158 | #define TRS_HARD_HEADMASK 0x07 159 | #define TRS_HARD_HEADSHIFT 0 160 | #define TRS_HARD_MAXHEADS 8 161 | 162 | /* Status register (read only): 163 | * brwsdcie 164 | * b = busy 165 | * r = drive ready 166 | * w = write error 167 | * s = seek complete 168 | * d = data request 169 | * c = corrected ecc (reserved) 170 | * i = command in progress (=software reset required) 171 | * e = error 172 | */ 173 | #define TRS_HARD_STATUS (TRS_HARD_DATA+7) 174 | #define TRS_HARD_BUSY 0x80 175 | #define TRS_HARD_READY 0x40 176 | #define TRS_HARD_WRERR 0x20 177 | #define TRS_HARD_SEEKDONE 0x10 178 | #define TRS_HARD_DRQ 0x08 179 | #define TRS_HARD_ECC 0x04 180 | #define TRS_HARD_CIP 0x02 181 | #define TRS_HARD_ERR 0x01 182 | 183 | /* Command register (write only) */ 184 | #define TRS_HARD_COMMAND (TRS_HARD_DATA+7) 185 | 186 | /* 187 | * WD1010 commands 188 | */ 189 | 190 | #define TRS_HARD_CMDMASK 0xf0 191 | 192 | /* Restore: 193 | * 0001rrrr 194 | * rrrr = step rate; 0000=35us, else rrrr*0.5ms 195 | */ 196 | #define TRS_HARD_RESTORE 0x10 197 | 198 | /* Read sector: 199 | * 0010dm00 200 | * d = 0 for interrupt on DRQ, 1 for interrupt at end (DMA style) 201 | * TRS-80 always uses programmed I/O, INTRQ not connected, I believe. 202 | * m = multiple sector flag (not emulated!) 203 | */ 204 | #define TRS_HARD_READ 0x20 205 | #define TRS_HARD_DMA 0x08 206 | #define TRS_HARD_MULTI 0x04 207 | 208 | /* Write sector: 209 | * 00110m00 210 | * m = multiple sector flag (not emulated!) 211 | */ 212 | #define TRS_HARD_WRITE 0x30 213 | 214 | /* Verify sector (or "Scan ID"): 215 | * 01000000 216 | */ 217 | #define TRS_HARD_VERIFY 0x40 218 | 219 | /* Format track: 220 | * 01010000 221 | */ 222 | #define TRS_HARD_FORMAT 0x50 223 | 224 | /* Init (??): 225 | * 01100000 226 | */ 227 | #define TRS_HARD_INIT 0x60 228 | 229 | /* Seek to specified sector/head/cylinder: 230 | * 0111rrrr 231 | * rrrr = step rate; 0000=35us, else rrrr*0.5ms 232 | */ 233 | #define TRS_HARD_SEEK 0x70 234 | -------------------------------------------------------------------------------- /trs_iodefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2011, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #define MAXCHARS 256 41 | #define TRS_CHAR_WIDTH 8 42 | #define TRS_CHAR_HEIGHT 12 43 | #define TRS_CHAR_HEIGHT4 10 44 | 45 | extern char trs_char_data[][MAXCHARS][TRS_CHAR_HEIGHT]; 46 | -------------------------------------------------------------------------------- /trs_keyboard.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/trs_keyboard.c -------------------------------------------------------------------------------- /trs_printer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2020, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #include "z80.h" 41 | #include "trs.h" 42 | 43 | void trs_printer_write(int value) 44 | { 45 | if(value == 0x0D) 46 | { 47 | putchar('\n'); 48 | } 49 | else 50 | { 51 | putchar(value); 52 | } 53 | } 54 | 55 | int trs_printer_read(void) 56 | { 57 | return 0x30; /* printer selected, ready, with paper, not busy */ 58 | } 59 | -------------------------------------------------------------------------------- /trs_stringy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011-2020, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Common Stringy Floppy code used by xtrs and mkdisk. 27 | */ 28 | #ifndef _STRINGY_H 29 | #define _STRINGY_H 30 | 31 | #include "z80.h" 32 | 33 | typedef long stringy_pos_t; 34 | 35 | #define STRINGY_CELL_WIDTH 124 // in t-states 36 | 37 | #define STRINGY_FMT_DEBUG 1 38 | #define STRINGY_FMT_ESF 2 39 | #define STRINGY_FMT_DEFAULT STRINGY_FMT_ESF 40 | 41 | #define stringy_len_from_kb(kb) ((kb) * 1024 * 2 * 9 / 8) // allow gaps + leaders (?) 42 | 43 | #define STRINGY_LEN_DEFAULT stringy_len_from_kb(64) 44 | #define STRINGY_EOT_DEFAULT 60 // a good value per MKR 45 | 46 | /* 47 | * .esf file format used by TRS32. 48 | */ 49 | static const char stringy_esf_magic[4] = "ESF\x1a"; 50 | static const Uchar stringy_esf_header_length = 12; 51 | static const Uchar stringy_esf_write_protected = 1; 52 | /* 53 | struct { 54 | char magic[4] = stringy_esf_magic; 55 | Uchar headerLength = 12; // length of this header, in bytes 56 | Uchar flags; // bit 0: write protected; others reserved 57 | Ushort leaderLength = 60; // little endian, in bit cells 58 | Uint length; // little endian, in bytes 59 | Uchar data[length]; 60 | } 61 | */ 62 | 63 | /* 64 | * Debug format 65 | */ 66 | static const char stringy_debug_header[] = "xtrs stringy debug %ld %ld %d\n"; 67 | 68 | int stringy_init_with(FILE *f, 69 | int format, 70 | Uint lengthBytes, // data length in bytes 71 | Uint eotCells, // leader length in bit cells 72 | int writeProt); 73 | 74 | int stringy_set_write_prot(FILE *f, 75 | int format, 76 | int writeProt); 77 | 78 | #endif /* _STRINGY_H */ 79 | -------------------------------------------------------------------------------- /trs_uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2008, Timothy P. Mann 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | /* 26 | * Emulation of the Radio Shack TRS-80 Model I/III/4/4P serial port. 27 | */ 28 | 29 | #include 30 | #include "trs.h" 31 | #include "trs_hard.h" 32 | 33 | extern void trs_uart_init(int reset_button); 34 | extern int trs_uart_check_avail(); 35 | extern int trs_uart_modem_in(); 36 | extern void trs_uart_reset_out(int value); 37 | extern int trs_uart_switches_in(); 38 | extern void trs_uart_baud_out(int value); 39 | extern int trs_uart_status_in(); 40 | extern void trs_uart_control_out(int value); 41 | extern int trs_uart_data_in(); 42 | extern void trs_uart_data_out(int value); 43 | extern char *trs_uart_name; 44 | extern int trs_uart_switches; 45 | 46 | #define TRS_UART_MODEM 0xE8 /* in */ 47 | #define TRS_UART_RESET 0xE8 /* out */ 48 | #define TRS_UART_SWITCHES 0xE9 /* in, model I only */ 49 | #define TRS_UART_BAUD 0xE9 /* out */ 50 | #define TRS_UART_STATUS 0xEA /* in */ 51 | #define TRS_UART_CONTROL 0xEA /* out */ 52 | #define TRS_UART_DATA 0xEB /* in/out */ 53 | 54 | /* Bits in TRS_UART_MODEM port */ 55 | #define TRS_UART_CTS 0x80 56 | #define TRS_UART_DSR 0x40 57 | #define TRS_UART_CD 0x20 58 | #define TRS_UART_RI 0x10 59 | #define TRS_UART_RCVIN 0x02 60 | 61 | /* Bits in TRS_UART_BAUD port */ 62 | #define TRS_UART_SNDBAUD(v) (((v)&0xf0)>>4) 63 | #define TRS_UART_RCVBAUD(v) (((v)&0x0f)>>0) 64 | #define TRS_UART_50 0x00 65 | #define TRS_UART_75 0x01 66 | #define TRS_UART_110 0x02 67 | #define TRS_UART_134 0x03 68 | #define TRS_UART_150 0x04 69 | #define TRS_UART_300 0x05 70 | #define TRS_UART_600 0x06 71 | #define TRS_UART_1200 0x07 72 | #define TRS_UART_1800 0x08 73 | #define TRS_UART_2000 0x09 74 | #define TRS_UART_2400 0x0a 75 | #define TRS_UART_3600 0x0b 76 | #define TRS_UART_4800 0x0c 77 | #define TRS_UART_7200 0x0d 78 | #define TRS_UART_9600 0x0e 79 | #define TRS_UART_19200 0x0f 80 | #define TRS_UART_BAUD_TABLE \ 81 | { 50.0, 75.0, 110.0, 134.5, 150.0, 300.0, 600.0, 1200.0, 1800.0, \ 82 | 2000.0, 2400.0, 3600.0, 4800.0, 7200.0, 9600.0, 19200.0 } 83 | 84 | /* Bits in TRS_UART_STATUS port */ 85 | #define TRS_UART_RCVD 0x80 86 | #define TRS_UART_SENT 0x40 87 | #define TRS_UART_OVRERR 0x20 88 | #define TRS_UART_FRMERR 0x10 89 | #define TRS_UART_PARERR 0x08 90 | 91 | /* Bits in TRS_UART_CONTROL port */ 92 | #define TRS_UART_EVENPAR 0x80 93 | #define TRS_UART_WORDMASK 0x60 94 | #define TRS_UART_WORD5 0x00 95 | #define TRS_UART_WORD6 0x40 96 | #define TRS_UART_WORD7 0x20 97 | #define TRS_UART_WORD8 0x60 98 | #define TRS_UART_WORDBITS(v) (((v)&TRS_UART_WORDMASK)>>5) 99 | #define TRS_UART_WORDBITS_TABLE { 5, 7, 6, 8 } 100 | #define TRS_UART_STOP2 0x10 101 | #define TRS_UART_NOPAR 0x08 102 | #define TRS_UART_NOTBREAK 0x04 103 | #define TRS_UART_DTR 0x02 /* mislabelled as RTS in Model I manual */ 104 | #define TRS_UART_RTS 0x01 /* mislabelled as DTR in Model I manual */ 105 | -------------------------------------------------------------------------------- /truedam.ccc: -------------------------------------------------------------------------------- 1 | /* truedam.ccc -- Misosys C program to query/set truedam flag on xtrs */ 2 | 3 | /* 4 | * Copyright (c) 1998-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #option redirect 0 28 | #include "xtrsemt.h" 29 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 30 | 31 | usage(n) 32 | int n; 33 | { 34 | fprintf(stderr, "usage: truedam [0|1]\n"); 35 | exit(1); 36 | } 37 | 38 | int main(argc, argv) 39 | int argc; 40 | char **argv; 41 | { 42 | int hl, bc, de, ret; 43 | char *retp; 44 | int func; 45 | 46 | if (argc == 1) { 47 | func = EMT_MISC_QUERY_TRUEDAM; 48 | } else if ((argc == 2) && isdigit(argv[1][0])) { 49 | func = EMT_MISC_SET_TRUEDAM; 50 | if (strlen(argv[1]) != 1) usage(); 51 | hl = atoi(argv[1]); 52 | if (hl > 1) usage(); 53 | } else { 54 | usage(); 55 | } 56 | 57 | emt_4misc(func, &hl, &bc, &de); 58 | printf("truedam = %d\n", hl); 59 | 60 | exit(0); 61 | } 62 | -------------------------------------------------------------------------------- /truedam.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/truedam.cmd -------------------------------------------------------------------------------- /truedam6.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/truedam6.cmd -------------------------------------------------------------------------------- /umount.ccc: -------------------------------------------------------------------------------- 1 | /* umount.ccc -- Misosys C program to unmount an emulated floppy on xtrs */ 2 | 3 | /* XXX: Assumes the original xtrs method where an emulated floppy 4 | * always has the name "diskM-N" where M is the model and N is the 5 | * unit number. This does not work if gxtrs's dialog has been used to 6 | * mount a floppy with a name of a different format. To fix this will 7 | * at least require adding an emt that calls trs_disk_set_name. 8 | */ 9 | 10 | /* 11 | * Copyright (c) 1998-2008, Timothy P. Mann 12 | * 13 | * Permission is hereby granted, free of charge, to any person 14 | * obtaining a copy of this software and associated documentation 15 | * files (the "Software"), to deal in the Software without 16 | * restriction, including without limitation the rights to use, copy, 17 | * modify, merge, publish, distribute, sublicense, and/or sell copies 18 | * of the Software, and to permit persons to whom the Software is 19 | * furnished to do so, subject to the following conditions: 20 | * 21 | * The above copyright notice and this permission notice shall be 22 | * included in all copies or substantial portions of the Software. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | * SOFTWARE. 32 | */ 33 | 34 | #option redirect 0 35 | #include "xtrsemt.h" 36 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 37 | 38 | usage() 39 | { 40 | fprintf(stderr, "usage: umount unit#\n"); 41 | exit(1); 42 | } 43 | 44 | #define DDIRSIZE 256 45 | #define DNAMESIZE 512 46 | #define CMDSIZE 512 47 | #define ERRBUFSIZE 512 48 | 49 | int main(argc, argv) 50 | int argc; 51 | char **argv; 52 | { 53 | char ddir[DDIRSIZE]; 54 | char dname[DNAMESIZE], cmd[CMDSIZE]; 55 | char errbuf[ERRBUFSIZE]; 56 | char model[4]; 57 | int hl, bc, de, ret; 58 | char *retp; 59 | 60 | if (argc != 2 || !isdigit(argv[1][0])) { 61 | usage(); 62 | } 63 | retp = emt_gtddir(ddir, DDIRSIZE); 64 | if (retp == NULL) { 65 | emt_strerror(errno, errbuf, ERRBUFSIZE); 66 | fprintf(stderr, "emt_getddir: %s\n", errbuf); 67 | exit(1); 68 | } 69 | emt_4misc(EMT_MISC_QUERY_MODEL, &hl, &bc, &de); 70 | if (hl == 5) { 71 | strcpy(model, "4p"); 72 | } else { 73 | sprintf(model, "%d", hl); 74 | } 75 | sprintf(dname, "%s/disk%s-%s", ddir, model, argv[1]); 76 | sprintf(cmd, "rm -f %s", dname); 77 | /*printf("$ %s\n", cmd);*/ 78 | ret = emt_system(cmd); 79 | if (ret != 0) { 80 | emt_strerror(errno, errbuf, ERRBUFSIZE); 81 | fprintf(stderr, "emt_system: %s\n", errbuf); 82 | exit(1); 83 | } 84 | emt_misc(EMT_MISC_DISK_CHANGE); 85 | exit(0); 86 | } 87 | -------------------------------------------------------------------------------- /umount.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/umount.cmd -------------------------------------------------------------------------------- /umount6.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/umount6.cmd -------------------------------------------------------------------------------- /unix.ccc: -------------------------------------------------------------------------------- 1 | /* unix.ccc -- Misosys C program to execute a Unix shell command from xtrs */ 2 | 3 | /* 4 | * Copyright (c) 1998-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #option redirect 0 28 | #include "xtrsemt.h" 29 | #include "xtrsemt.ccc" /* could use separate compilation instead */ 30 | 31 | usage() 32 | { 33 | fprintf(stderr, "usage: unix [-l] command\n"); 34 | exit(1); 35 | } 36 | 37 | #define ERRBUFSIZE 256 38 | #define CMDBUFSIZE 512 39 | 40 | int main(argc, argv) 41 | int argc; 42 | char **argv; 43 | { 44 | int ret, i, lower; 45 | char errbuf[ERRBUFSIZE]; 46 | char cmdbuf[CMDBUFSIZE]; 47 | char *p, *q; 48 | 49 | if (argc < 2) { 50 | usage(); 51 | } 52 | i = 1; 53 | if (argv[i][0] == '-') { 54 | if (tolower(argv[i][1]) != 'l') { 55 | usage(); 56 | } 57 | i++; 58 | lower = 1; 59 | } else { 60 | lower = 0; 61 | } 62 | 63 | p = cmdbuf; 64 | for (; i> 8, ret & 0xff); 93 | exit(1); 94 | } 95 | exit(0); 96 | } 97 | -------------------------------------------------------------------------------- /unix.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/unix.cmd -------------------------------------------------------------------------------- /unix6.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/unix6.cmd -------------------------------------------------------------------------------- /utility.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TimothyPMann/xtrs/a76c57f3e30d67429bfffef3d5ee47200721cfb1/utility.dsk -------------------------------------------------------------------------------- /utility.jcl: -------------------------------------------------------------------------------- 1 | . Note: Use TRSDOS 6.2.1 to get old-style dates and 2 | . thus avoid password problems with other DOSes. 3 | format :#d#(sden,sides=1,cyl=80,dir=17,name="xtrsutil",q=n,abs) 4 | import export.cmd export/cmd:#D# 5 | import -n export.z80 export/z80:#D# 6 | import import.cmd import/cmd:#D# 7 | import -n import.z80 import/z80:#D# 8 | import -n settime.z80 settime/z80:#D# 9 | import settime.cmd settime/cmd:#D# 10 | import -n xtrsemt.ccc xtrsemt/ccc:#D# 11 | import -n xtrsemt.h xtrsemt/h:#D# 12 | import -n settime.ccc settime/ccc:#D# 13 | import -n m1format.fix m1format/fix:#D# 14 | import xtrshard.dct xtrshard/dct:#D# 15 | import -n xtrshard.z80 xtrshard/z80:#D# 16 | import xtrs8.dct xtrs8/dct:#D# 17 | import -n xtrs8.z80 xtrs8/z80:#D# 18 | import xtrsmous.cmd xtrsmous/cmd:#D# 19 | import -n xtrsmous.z80 xtrsmous/z80:#D# 20 | import -n cd.ccc cd/ccc:#D# 21 | import -n pwd.ccc pwd/ccc:#D# 22 | import -n unix.ccc unix/ccc:#D# 23 | import -n mount.ccc mount/ccc:#D# 24 | import -n umount.ccc umount/ccc:#D# 25 | import cd.cmd cd/cmd:#D# 26 | import pwd.cmd pwd/cmd:#D# 27 | import unix.cmd unix/cmd:#D# 28 | import mount.cmd mount/cmd:#D# 29 | import umount.cmd umount/cmd:#D# 30 | import truedam.cmd truedam/cmd:#D# 31 | import cd6.cmd cd6/cmd:#D# 32 | import pwd6.cmd pwd6/cmd:#D# 33 | import unix6.cmd unix6/cmd:#D# 34 | import mount6.cmd mount6/cmd:#D# 35 | import umount6.cmd umount6/cmd:#D# 36 | import truedam6.cmd truedam6/cmd:#D# 37 | import -n expall.bas expall/bas:#D# 38 | import -n do6.jcl do6/jcl:#D# 39 | -------------------------------------------------------------------------------- /xtrsemt.h: -------------------------------------------------------------------------------- 1 | /* xtrsemt.h -- Misosys C interface to xtrs emulator traps */ 2 | 3 | /* 4 | * Copyright (c) 1997-2008, Timothy P. Mann 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #ifndef _TIME_T 28 | #include 29 | #endif 30 | 31 | /* Some names are changed to keep them unique in the first seven characters */ 32 | extern int emt_system(/* char *cmd */); 33 | extern char* /*emt_getddir*/ emt_gtddir(/* char *buffer, int bytes */); 34 | extern int /*emt_setddir*/ emt_stddir(/* char *fname */); 35 | extern int emt_open(/* char *fname, int oflag, int mode */); 36 | extern int emt_close(/* int fd */); 37 | extern int emt_read(/* int fd, char *buffer, int bytes */); 38 | extern int emt_write(/* int fd, char *buffer, int bytes */); 39 | extern long emt_lseek(/* int fd, long offset, int whence */); 40 | extern int emt_strerror(/* int err, char *buffer, int size */); 41 | extern time_t emt_time(/* int local */); 42 | extern int /*emt_opendir*/ emt_dropen(/* char *fname */); 43 | extern int /*emt_closedir*/ emt_drclose(/* int dirfd */); 44 | extern int /*emt_readdir*/ emt_drread(/*int dirfd, char *buffer, int bytes*/); 45 | extern int emt_chdir(/* char *fname */); 46 | extern char* emt_getcwd(/* char *buffer, int bytes */); 47 | extern int emt_misc(/* int func */); 48 | extern void emt_4misc(/* int func, int *hl, int *bc, int *de */); 49 | extern int emt_ftruncate(/* int fd, long length */); 50 | extern int /*emt_opendisk*/ emt_dkopen(/* char *fname, int oflag, int mode */); 51 | extern int /*emt_closedisk*/ emt_dkclose(/* int fd */); 52 | 53 | /* oflag values for emt_open and emt_opendisk */ 54 | #define EO_ACCMODE 03 55 | #define EO_RDONLY 00 56 | #define EO_WRONLY 01 57 | #define EO_RDWR 02 58 | #define EO_CREAT 0100 59 | #define EO_EXCL 0200 60 | #define EO_TRUNC 01000 61 | #define EO_APPEND 02000 62 | 63 | /* local values for emt_time */ 64 | #define EMT_TIME_GMT 0 65 | #define EMT_TIME_LOCAL 1 66 | 67 | /* func values for emt_misc */ 68 | #define EMT_MISC_DISK_CHANGE 0 69 | #define EMT_MISC_EXIT 1 70 | #define EMT_MISC_DEBUG 2 71 | #define EMT_MISC_RESET_BUTTON 3 72 | #define EMT_MISC_QUERY_DISK_CHANGE 4 73 | #define EMT_MISC_QUERY_MODEL 5 74 | #define EMT_MISC_QUERY_DISK_SIZE 6 75 | #define EMT_MISC_SET_DISK_SIZE 7 76 | #define EMT_MISC_QUERY_DBL_STEP 8 77 | #define EMT_MISC_SET_DBL_STEP 9 78 | #define EMT_MISC_QUERY_MICROLABS 10 79 | #define EMT_MISC_SET_MICROLABS 11 80 | #define EMT_MISC_QUERY_DELAY 12 81 | #define EMT_MISC_SET_DELAY 13 82 | #define EMT_MISC_QUERY_KEYSTRETCH 14 83 | #define EMT_MISC_SET_KEYSTRETCH 15 84 | #define EMT_MISC_QUERY_DOUBLER 16 85 | #define EMT_MISC_SET_DOUBLER 17 86 | #define EMT_MISC_QUERY_VOLUME 18 87 | #define EMT_MISC_SET_VOLUME 19 88 | #define EMT_MISC_QUERY_TRUEDAM 20 89 | #define EMT_MISC_SET_TRUEDAM 21 90 | -------------------------------------------------------------------------------- /xtrsmous.z80: -------------------------------------------------------------------------------- 1 | ;*=*=* 2 | ; xtrsmous/cmd 3 | ; LS-DOS driver for xtrs emulation of mouse 4 | ; 5 | ;; Copyright (c) 1998-2011, Timothy P. Mann 6 | ;; 7 | ;; Permission is hereby granted, free of charge, to any person 8 | ;; obtaining a copy of this software and associated documentation 9 | ;; files (the "Software"), to deal in the Software without 10 | ;; restriction, including without limitation the rights to use, copy, 11 | ;; modify, merge, publish, distribute, sublicense, and/or sell copies 12 | ;; of the Software, and to permit persons to whom the Software is 13 | ;; furnished to do so, subject to the following conditions: 14 | ;; 15 | ;; The above copyright notice and this permission notice shall be 16 | ;; included in all copies or substantial portions of the Software. 17 | ;; 18 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 22 | ;; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 | ;; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | ;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | ;; SOFTWARE. 26 | ; 27 | ; Usage: 28 | ; xtrsmous To load driver in high memory. 29 | ; xtrsmous (low) To load driver in low memory if possible, 30 | ; or in high memory if low memory is full. 31 | ; 32 | ; The default is to use high memory because MDRAW/BAS contains a 33 | ; PEEK in the first line of code that looks for the driver in 34 | ; high memory; if it is in low memory, MDRAW thinks the driver 35 | ; is not installed and exits. If you edit this line of code to 36 | ; remove the test, the driver will work fine in low memory. 37 | ;*=*=* 38 | 39 | 40 | ; ASCII chars 41 | LF equ 10 42 | CR equ 13 43 | ETX equ 3 44 | 45 | ; Model 4 SVC numbers 46 | @high equ 100 47 | @dsply equ 10 48 | @flags equ 101 49 | @logot equ 12 50 | @gtdcb equ 82 51 | @gtmod equ 83 52 | @keyin equ 9 53 | @param equ 17 54 | @mouse equ 120 ;unofficial value 55 | 56 | svcvec equ 100h + 2*@mouse 57 | 58 | ; xtrs emts (byte-reversed) 59 | emt_mouse equ 029edh 60 | 61 | org 3000h 62 | ;*=*=* 63 | ; Relocator for disk driver 64 | ;*=*=* 65 | instal: ld de,prmtab 66 | ld a,@param ;Parse parameters 67 | rst 40 68 | jp nz,prmerr 69 | ld hl,hello_ 70 | ld a,@dsply ;Display hello 71 | rst 40 72 | ;*=*=* 73 | ; Check if driver already loaded 74 | ;*=*=* 75 | ld de,modnam 76 | ld a,@gtmod 77 | rst 40 78 | jp z,loaded ;Already loaded 79 | ;*=*=* 80 | ; Check if OK to use low memory. 81 | ;*=*=* 82 | lparm: ld bc,0 83 | ld a,b 84 | or c 85 | jr z,usehi 86 | ;*=*=* 87 | ; Obtain low memory driver pointer. Bizarre API here! 88 | ;*=*=* 89 | ld e,'K' ;Locate pointer to *KI DCB 90 | ld d,'I' ; via @GTDCB SVC 91 | ld a,@gtdcb 92 | rst 40 93 | jp nz,curdl ;No error unless KI clobbered! 94 | dec hl ;Decrement to driver pointer 95 | ld d,(hl) ;P/u hi-order of pointer, 96 | dec hl ; decrement to and p/u 97 | ld e,(hl) ; lo-order of pointer 98 | ;*=*=* 99 | ; Check if driver will fit into [(LCPTR), X'12FF'] 100 | ;*=*=* 101 | push hl ;Save address of pointer 102 | ld hl,length ;New pointer will be 103 | add hl,de ; pointer + LENGTH 104 | ld d,h ;Save a copy in DE 105 | ld e,l 106 | ld bc,1301h ;If > 1300H, driver won't fit 107 | sub a ;Reset carry flag 108 | sbc hl,bc 109 | pop hl ;Get back address of pointer 110 | jr nc,usehi ;Go if driver won't fit 111 | ld (hl),e ;Store new value of pointer 112 | inc hl 113 | ld (hl),d 114 | dec de ;Last byte of driver goes here 115 | ld (newend),de 116 | jr dorelo 117 | ;*=*=* 118 | ; Put in high memory instead. 119 | ;*=*=* 120 | usehi: ld hl,0 ;Get current HIGH$ 121 | ld b,l 122 | ld a,@high 123 | rst 40 124 | jp nz,nomem 125 | ld (newend),hl ;Last byte of driver goes here 126 | ld de,length 127 | sub a ;Reset carry flag 128 | sbc hl,de ;Compute new HIGH$ 129 | ld a,@high ;Set new HIGH$ into the system 130 | rst 40 131 | ;*=*=* 132 | ; Relocate internal references in driver. 133 | ; HL = address for last byte of driver. 134 | ;*=*=* 135 | dorelo: call relo 136 | ;*=*=* 137 | ; Link to @ICNFG (must follow address relocation and precede movement) 138 | ;*=*=* 139 | ld a,@flags ;Get flags pointer into IY 140 | rst 40 141 | ld a,(iy+28) ;Copy current @ICNFG into LINK 142 | ld l,(iy+29) 143 | ld h,(iy+30) 144 | ld (link),a 145 | ld (link+1),hl 146 | ld hl,dvrcfg ;Get relocated init address 147 | rx01 equ $-2 148 | ld (iy+29),l ;Save in @ICNFG vector 149 | ld (iy+30),h 150 | ld (iy+28),0c3h ;Insert JP opcode 151 | ;*=*=* 152 | ; Move driver into low or high memory. 153 | ;*=*=* 154 | move: 155 | ld de,(newend) ;Destination address 156 | ld hl,dvrend ;Last byte of module 157 | ld bc,length ;Length of filter 158 | lddr 159 | ex de,hl 160 | inc hl ;Bump to driver entry 161 | ;*=*=* 162 | ; Driver is loaded; finish up. 163 | ;*=*=* 164 | call dvrini ;Hook into SVC table 165 | 166 | ld hl,0 ;Successful completion 167 | sub a 168 | ret 169 | 170 | ;*=*=* 171 | ; Error vectors 172 | ;*=*=* 173 | prmerr: ld hl,prmerr_ 174 | defb 0ddh 175 | loaded: ld hl,loaded_ 176 | defb 0ddh 177 | curdl: ld hl,curdl_ 178 | defb 0ddh 179 | nomem: ld hl,nomem_ 180 | logot: ld a,@logot 181 | rst 40 182 | ld hl,-1 ;Unuccessful completion 183 | ret 184 | 185 | ;*=*=* 186 | ; Relocate internal references in driver. 187 | ; HL = address for last byte of driver. 188 | ;*=*=* 189 | relo: ld hl,(newend) 190 | ld iy,reltab ;Point to relocation tbl 191 | ld de,dvrend 192 | sub a ;Clear carry flag 193 | sbc hl,de 194 | ld b,h ;Move to BC 195 | ld c,l 196 | rloop: ld l,(iy) ;Get address to change 197 | ld h,(iy+1) 198 | ld a,h 199 | or l 200 | ret z 201 | ld e,(hl) ;P/U address 202 | inc hl 203 | ld d,(hl) 204 | ex de,hl ;Offset it 205 | add hl,bc 206 | ex de,hl 207 | ld (hl),d ;And put back 208 | dec hl 209 | ld (hl),e 210 | inc iy 211 | inc iy 212 | jr rloop ;Loop till done 213 | 214 | ;*=*=* 215 | ; Messages and globals 216 | ;*=*=* 217 | hello_: defb 'XTRSMOUS - Emulated mouse driver for xtrs - 9/28/98',CR 218 | curdl_: defb 'LS-DOS is curdled!',CR 219 | nomem_: defb 'High memory is not available!',CR 220 | loaded_:defb 'Mouse driver is already loaded!',CR 221 | prmerr_:defb 'Bad parameters!',CR 222 | lcptr: defw 0 223 | newend: defw 0 224 | 225 | ;*=*=* 226 | ; Parameter table 227 | ;*=*=* 228 | prmtab: defb 'LOW ' 229 | defw lparm+1 230 | defb 'L ' 231 | defw lparm+1 232 | defb 0 233 | 234 | ;*=*=* 235 | ; Driver 236 | ;*=*=* 237 | entry: jr begin ;The driver starts with the 238 | defw dvrend ; DOS standard header 239 | rx00 equ $-2 240 | defb modptr-modnam ;Length of name 241 | modnam: defb '$MOUSE' ;Name for @GTMOD requests 242 | modptr: defw 0 ;These pointers are unused, but 1st byte MBZ 243 | defw 0 244 | ;*=*=* 245 | ; Do the real work using an emulator trap 246 | ;*=*=* 247 | begin: defw emt_mouse 248 | ret 249 | ;*=*=* 250 | ; Boot-time initialization 251 | ;*=*=* 252 | dvrcfg: ;@ICNFG chains in here 253 | call dvrini 254 | rx02 equ $-2 255 | link: defb 'Tim' ;Replaced by next link in @ICNFG chain 256 | ;*=*=* 257 | ; Hook into SVC table 258 | ;*=*=* 259 | dvrini: ld hl,entry 260 | rx03 equ $-2 261 | ld (svcvec),hl 262 | ret 263 | 264 | dvrend equ $-1 265 | length equ $-entry 266 | reltab: defw rx00,rx01,rx02,rx03,0 267 | end instal 268 | -------------------------------------------------------------------------------- /xtrsrom4p.README: -------------------------------------------------------------------------------- 1 | Free Model 4P mode boot ROM for xtrs 2 | Copyright 1999, Peter W. Cervasio 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, copy, 8 | modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | This is a freely available Model 4P mode boot ROM which can 25 | be used with Tim Mann's version of xtrs in order to boot up 26 | LS-DOS 6.3.1. 27 | 28 | This code was written with the help of the LS-DOS 6.3.1 source 29 | code, which Roy Soltoff has allowed everyone to download and 30 | freely distribute (though he retains the copyright). The Model 31 | 4/4P technical reference manual proved invaluable, as well, even 32 | if I didn't make this do everything. 33 | 34 | The code was tested with xtrs 3.3 on Linux 2.2.2 using an LS-DOS 35 | 6.3.1 disk image. I got it to the point where xtrs would boot up 36 | LS-DOS 6.3.1 and would reboot it when pressing F10 or typing 37 | "boot" at the LS-DOS command line. 38 | 39 | It is only useful for the Model 4P mode of operation, and it 40 | might not work for all operating systems. The ROM does not 41 | contain any code to access any sector other than track 0, sector 42 | 1. It will not boot a Model III operating system, and is unable 43 | to load in a "MODELA/III" ROM image from disk, like the real 44 | Model 4P ROM does. 45 | 46 | This ROM will not work in plain Model 4 mode. If you want to use 47 | Model 4 mode, boot LS-DOS 6.3.1, export the MODELA/III file to 48 | Unix, and set it up as a Model 3 and 4 ROM. 49 | 50 | Features: 51 | ========= 52 | 53 | Small and simple (and easy to fix). 54 | 55 | To do: 56 | ====== 57 | 58 | Write code for all the RST handlers as in the real 4P ROM, which 59 | would allow xtrs to boot a Model III disk when in Model 4P mode. 60 | This would require considerable work, and isn't planned for any 61 | time in the forseeable future. 62 | 63 | Any questions? 64 | ============== 65 | 66 | Here's my list of IEQ's (Infreqently Expected Questions) about the 67 | xtrsrom4p rom image: 68 | 69 | 1) Does xtrsrom4p handle the special keypresses the 4P uses at boot up 70 | time, such as F1, F2 and F3 to modify the boot sequence? 71 | 72 | Sorry, but it doesn't look at the keyboard. See the answer to #2. 73 | 74 | 2) Will it load MODELA/III from disk so I can boot LDOS/TRSDOS 1.3 or 75 | NewDos/80 for the Model III? 76 | 77 | Sorry. You're welcome to write the code for it, though. 78 | 79 | 3) Can I use it to boot from from a hard disk image? 80 | 81 | Um.... no. See the answer to #2. 82 | 83 | 4) How about Network 4? 84 | 85 | Uh... no, it won't do that either. Also see #2's answer. 86 | 87 | 5) What about booting from RS-232? 88 | 89 | See #2 again. 90 | 91 | 6) How about the diagnostics? 92 | 93 | What diagnostics? Oh, those diagnostics. See the answer to #2. 94 | 95 | 96 | 97 | Along with not doing any of that other stuff, it also doesn't follow 98 | the technical reference as far as RST handlers go, so if you have a 99 | custom 4P setup that uses the RST instructions, that's not going to 100 | work without some additional code. I wrote this so people could get 101 | something up and running with what's in the xtrs distribution. From 102 | there, you can export a MODELA/III image from a disk (or disk image) 103 | to use in booting up Model III mode. 104 | -------------------------------------------------------------------------------- /xtrsrom4p.z80: -------------------------------------------------------------------------------- 1 | ;------------------------------------------------------------------ 2 | ; Free Model 4P mode boot ROM for xtrs - Version 0.06 3 | ;------------------------------------------------------------------ 4 | ; Copyright 1999, Peter W. Cervasio 5 | ; 6 | ; Permission is hereby granted, free of charge, to any person 7 | ; obtaining a copy of this software and associated documentation 8 | ; files (the "Software"), to deal in the Software without 9 | ; restriction, including without limitation the rights to use, copy, 10 | ; modify, merge, publish, distribute, sublicense, and/or sell copies 11 | ; of the Software, and to permit persons to whom the Software is 12 | ; furnished to do so, subject to the following conditions: 13 | ; 14 | ; The above copyright notice and this permission notice shall be 15 | ; included in all copies or substantial portions of the Software. 16 | ; 17 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | ; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | ; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | ; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | ; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | ; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | ; SOFTWARE. 25 | ;------------------------------------------------------------------ 26 | ; Checks to see if a disk image is loaded in emulated drive 0. If 27 | ; so, it reads the boot sector to 0x4300 and jumps to that address. 28 | ; If no disk image loaded, complains and sits in a loop. 29 | ; 30 | ; This is only useful for the Model 4P mode of operation, and it 31 | ; might not work for all programs. Complains if xtrs thinks it's 32 | ; in model 1, 3, or 4 mode. 33 | ; 34 | ; Written with the help of the LS-DOS 6.3.1 source code, which is 35 | ; freely avaliable, though Roy Soltoff holds the copyright to it, 36 | ; and the Model 4/4P technical reference. 37 | ; 38 | ; 3-19-1999, Tim Mann: Improved disk error handling. Ruled out 39 | ; attempts to work in plain Model 4 mode. (v0.03) 40 | ; 4-4-1999, Tim Mann: Made read loop continue until NMI instead of 41 | ; counting 256 bytes; this should let boot sectors of other than 42 | ; 256 bytes work. (v0.04) Fixed bug in sending fdc read command; 43 | ; don't use fdcmd, since that waits for completion. (v0.05) 44 | ; 1-28-2018, Tim Mann: Fixed detection of no disk image loaded (v0.06) 45 | ; 46 | ; TODO: 47 | ; possibly write code for the RST handlers as in the real 4P rom 48 | ;------------------------------------------------------------------ 49 | 50 | ; 51 | ; misc equates needed 52 | ; 53 | video equ 3c00h+7*64 54 | bootram equ 4300h ; load to this address 55 | goboot equ 401ah ; jump here to run boot sec! 56 | ; 57 | ; hardware addresses 58 | ; 59 | opreg equ 084h ; Operation control 60 | romport equ 09ch ; ROM control 61 | wrnmiport equ 0e4h ; NMI mask register 62 | modport equ 0ech ; speed, etc. 63 | ; 64 | fdccmnd equ 0f0h ; FDC Command register (write) 65 | fdcstat equ 0f0h ; FDC Status register (read) 66 | fdctrak equ 0f1h ; FDC Track register (r/w) 67 | fdcsect equ 0f2h ; FDC Sector register (r/w) 68 | fdcdata equ 0f3h ; FDC Data register (r/w) 69 | fdcslct equ 0f4h ; Drive select, SDEN/DDEN, 70 | 71 | org 0 72 | 73 | ; The following three instructions are what you would 74 | ; have in RAM at address 0, which would set up the 75 | ; Model 4/4P to turn the ROM back on (lsdos does this) 76 | ; 77 | start: di ; disable interrupts 78 | ld a,1 ; map in the ROM 79 | out (romport),a ; do it! 80 | ; 81 | ; start of "real" ROM instructions 82 | ; 83 | jp contin ; continue farther up 84 | ; 85 | ; rst 08h through rst 38h jumps (per tech ref) 86 | ; 87 | rst8: jp 4000h 88 | db 0,0,0,0,0 89 | rst10: jp 4003h 90 | db 0,0,0,0,0 91 | rst18: jp 4006h 92 | db 0,0,0,0,0 93 | rst20: jp 4009h 94 | db 0,0,0,0,0 95 | rst28: jp 400ch 96 | db 0,0,0,0,0 97 | rst30: jp 400fh 98 | db 0,0,0,0,0 99 | rst38: jp 4012h 100 | ; 101 | ; Data to load from 4000h to ?? 102 | ; 103 | retdat: ret ; 4000h (rst 8h) 104 | dw 0 105 | ret ; 4003h (rst 10h) 106 | dw 0 107 | ret ; 4006h (rst 18h) 108 | dw 0 109 | ret ; 4009h (rst 20h) 110 | dw 0 111 | ret ; 400ch (rst 28h) 112 | dw 0 113 | ret ; 400fh (rst 30h) 114 | dw 0 115 | ret ; 4012h (rst 38h) 116 | dw 0 117 | jp nmiret ; 4015h (nmi) 118 | ; 119 | db 'MO' ; 4P detect by sysinit 120 | ; 121 | ; code that jumps to the boot sector (401ah) 122 | ; 123 | xor a 124 | out (romport),a ; disable rom 125 | jp bootram ; run boot sector 126 | ; 127 | retlen equ $-retdat ; size of code 128 | ; 129 | ; nmi address 130 | ; 131 | org 66h 132 | ; 133 | jp 4015h ; std M4 point in RAM 134 | ; 135 | ; continue booting the machine 136 | ; 137 | contin: xor a 138 | out (wrnmiport),a ; disable interrupts 139 | ld a,1 140 | out (opreg),a ; set ram mode 141 | ld a,01010000b 142 | out (modport),a ; set speed/vid 143 | ; 144 | ld sp,bootram-100h ; set stack pointer 145 | ; 146 | ld hl,retdat ; code for RAM 147 | ld de,4000h ; move it here 148 | ld bc,retlen 149 | ldir 150 | ; 151 | ld hl,3c00h ; clear video screen 152 | ld de,3c01h 153 | ld bc,1023 154 | ld (hl),' ' 155 | ldir 156 | ; 157 | im 1 158 | ; 159 | call chkmdl ; check for model 4p 160 | call rstdrv ; restore drive 161 | call z,readbt ; read boot sector 162 | jp nz,dskerr ; go on error 163 | ; 164 | jmprom: jp goboot ; jump to boot sector 165 | ; 166 | ; chkmdl - make sure we're in 4P mode 167 | ; 168 | chkmdl: ld a,5 ; model query 169 | dw 3cedh ; emt_misc instr. 170 | ld a,l ; get model in a 171 | cp 5 ; model 4p? 172 | ret z 173 | ; 174 | ; romerr - rom installed in model 1, 3, or 4 mode!! 175 | ; 176 | romerr: push af 177 | ld hl,rommsg ; "invalid rom for model" 178 | ld de,video 179 | ld bc,romlen 180 | ldir ; put msg 181 | add a,'0' ; convert model to ascii 182 | ld (de),a ; stuff onto screen 183 | jr $ ; and hang 184 | ; 185 | ; dskerr - error reading disk 186 | ; 187 | dskerr: ld hl,errtab ; table of error messages 188 | scf ; ensure termination 189 | nxterr: rra ; loop through bits, low first 190 | jr c,goterr ; go if error bit found 191 | inc hl ; no, step to next message 192 | inc hl 193 | jr nxterr 194 | goterr: ld e,(hl) ; get message address 195 | inc hl 196 | ld d,(hl) 197 | ex de,hl 198 | ld de,video ; where to show it 199 | chrout: ld a,(hl) 200 | and a 201 | jr z,$ ; hang in a loop when done 202 | ld (de),a 203 | inc hl 204 | inc de 205 | jr chrout 206 | ; 207 | ; rstdrv - seek track 0 and set up for boot read 208 | ; 209 | rstdrv: ld a,81h ; drive 0, dden (no nmi) 210 | out (fdcslct),a ; select drive 211 | ld a,0d0h ; force interrupt 212 | call fdcmd ; send to fdc 213 | ld b,0 214 | djnz $ ; wait a bit 215 | ld a,0ch ; restore w/verify 216 | call fdcmd ; 217 | 218 | ld b,0 219 | ckidx: bit 1,a ; index set? 220 | jr z,imgok ; if not, a disk is loaded; okay 221 | in a,(fdcstat) ; if so, recheck up to 256 times 222 | djnz ckidx 223 | and 02h ; index always set; no disk 224 | jr dskerr 225 | 226 | imgok: and 99h ; mask error bits 227 | ret z ; return if okay 228 | jr dskerr 229 | ; 230 | ; readbt - read boot sector from drive 0 231 | ; 232 | readbt: ld de,0001h ; trk 0, sec 1 233 | ld hl,bootram ; set buffer 234 | call readsb ; attempt read 235 | and 1ch ; keep RNF,CRC,LOST DATA 236 | ret z ; return if no error 237 | jp dskerr ; go on error 238 | ; 239 | ; readsb - read sector to buffer 240 | ; 241 | readsb: ld b,81h 242 | ld c,fdcslct ; set dden,ds0 243 | out (c),b ; select 244 | dec c ; set to data register 245 | ld a,18h ; fdc seek command 246 | out (c),d ; track # to fdc 247 | call fdcmd ; send command to fdc 248 | ld a,e 249 | out (fdcsect),a ; desired sector 250 | ld a,81h ; dden & ds0 251 | out (fdcslct),a ; reselect drive 252 | ld de,08116h ; D=DS0, dden, wait 253 | ; E=mask to see DRQ or error 254 | ld a,80h ; fdc read command 255 | out (fdccmnd),a ; send command 256 | ld b,100 ; short delay 257 | djnz $ 258 | ld a,0c0h ; enable intrq 259 | out (wrnmiport),a 260 | rdlp1: in a,(fdcstat) ; get status 261 | and e ; test bit 1 262 | jr z,rdlp1 263 | ini 264 | ld a,d 265 | rdlp2: out (fdcslct),a 266 | ini 267 | jr rdlp2 ; tight loop waiting for NMI 268 | ; jr nz,rdlp2 269 | ; in a,(fdcstat) 270 | ; ret 271 | 272 | nmiret: xor a 273 | out (wrnmiport),a ; no interrupts 274 | ld a,81h ; DS 0, dden 275 | out (fdcslct),a 276 | in a,(fdcstat) 277 | ex (sp),hl ; discard one level of return address 278 | pop hl 279 | retn 280 | 281 | ; 282 | ; fdcmd - send command in A to fdc and wait for completion 283 | ; 284 | fdcmd: out (fdccmnd),a ; send command 285 | ld b,100 ; short delay 286 | djnz $ 287 | fdst: in a,(fdcstat) 288 | bit 0,a ; busy? 289 | ret z ; return if not 290 | bit 7,a ; not ready? 291 | ret nz ; return if set 292 | jr fdst ; else loop 293 | 294 | 295 | ;------------------------------------------------------------------ 296 | ; messages 297 | ;------------------------------------------------------------------ 298 | ; 299 | rommsg: db 'This ROM code does NOT work when emulating Model ' 300 | romlen equ $-rommsg 301 | ; 302 | errtab: dw dskmsg,dskmsg,elost,ecrc,ernf,ecant,ecant,dskmsg,ecant 303 | elost: 304 | ecant: db 'Emulator or ROM bug',0 305 | ecrc: db 'Boot sector CRC error',0 306 | ernf: db 'Boot sector not found on disk',0 307 | dskmsg: db 'You do not have a disk image loaded',0 308 | ; 309 | end start 310 | -------------------------------------------------------------------------------- /z80.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1992 Clarendon Hill Software. 3 | * 4 | * Permission is granted to any individual or institution to use, copy, 5 | * or redistribute this software, provided this copyright notice is retained. 6 | * 7 | * This software is provided "as is" without any expressed or implied 8 | * warranty. If this software brings on any sort of damage -- physical, 9 | * monetary, emotional, or brain -- too bad. You've got no one to blame 10 | * but yourself. 11 | * 12 | * The software may be modified for your own purposes, but modified versions 13 | * must retain this notice. 14 | */ 15 | 16 | /* 17 | * Portions copyright (c) 1996-2008, Timothy P. Mann 18 | * 19 | * Permission is hereby granted, free of charge, to any person 20 | * obtaining a copy of this software and associated documentation 21 | * files (the "Software"), to deal in the Software without 22 | * restriction, including without limitation the rights to use, copy, 23 | * modify, merge, publish, distribute, sublicense, and/or sell copies 24 | * of the Software, and to permit persons to whom the Software is 25 | * furnished to do so, subject to the following conditions: 26 | * 27 | * The above copyright notice and this permission notice shall be 28 | * included in all copies or substantial portions of the Software. 29 | * 30 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 34 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 35 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 36 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | #ifndef _Z80_H 41 | #define _Z80_H 42 | 43 | #include "config.h" 44 | #include 45 | #include 46 | #include 47 | 48 | #ifndef TRUE 49 | #define TRUE (1) 50 | #define FALSE (0) 51 | #endif 52 | 53 | typedef unsigned int Uint; /* 4 bytes */ 54 | typedef unsigned short Ushort; /* 2 bytes */ 55 | typedef unsigned char Uchar; /* 1 byte */ 56 | 57 | #if __WORDSIZE == 32 58 | typedef unsigned long long tstate_t; 59 | #define TSTATE_T_MID (((unsigned long long) -1LL)/2ULL) 60 | #define TSTATE_T_LEN "llu" 61 | #else 62 | typedef unsigned long tstate_t; 63 | #define TSTATE_T_MID (((unsigned long) -1L)/2UL) 64 | #define TSTATE_T_LEN "lu" 65 | #endif 66 | 67 | struct twobyte 68 | { 69 | #ifdef big_endian 70 | Uchar high, low; 71 | #else 72 | Uchar low, high; 73 | #endif 74 | }; 75 | 76 | struct fourbyte 77 | { 78 | #ifdef big_endian 79 | Uchar byte3, byte2, byte1, byte0; 80 | #else 81 | Uchar byte0, byte1, byte2, byte3; 82 | #endif 83 | }; 84 | 85 | /* for implementing registers which can be seen as bytes or words: */ 86 | typedef union 87 | { 88 | struct twobyte byte; 89 | Ushort word; 90 | } wordregister; 91 | 92 | struct z80_state_struct 93 | { 94 | wordregister af; 95 | wordregister bc; 96 | wordregister de; 97 | wordregister hl; 98 | wordregister ix; 99 | wordregister iy; 100 | wordregister sp; 101 | wordregister pc; 102 | 103 | wordregister af_prime; 104 | wordregister bc_prime; 105 | wordregister de_prime; 106 | wordregister hl_prime; 107 | 108 | Uchar i; /* interrupt-page address register */ 109 | Uchar r; /* memory-refresh register, bits 0-6 */ 110 | Uchar r7; /* memory-refresh register, bit 7 */ 111 | 112 | Uchar iff1, iff2; 113 | Uchar interrupt_mode; 114 | 115 | /* To signal a maskable interrupt, set irq TRUE. The CPU does not 116 | * turn off irq; the external device must turn it off when 117 | * appropriately tickled by some IO port or memory address that it 118 | * decodes. INT is level triggered, so Z-80 code must tickle the 119 | * device before reenabling interrupts. 120 | * 121 | * There is no support as yet for fetching an interrupt vector or 122 | * RST instruction from the interrupting device, as this gets 123 | * rather complex when there can be more than one device with an 124 | * interrupt pending. So you'd better use interrupt_mode 1 only 125 | * (which is what the TRS-80 does). 126 | */ 127 | int irq; 128 | 129 | /* To signal a nonmaskable interrupt, set nmi to TRUE. The CPU 130 | * does not turn off nmi; the external device must turn it off 131 | * when tickled (or after a timeout). NMI is edge triggered, so 132 | * it has to be turned off and back on again before it can cause 133 | * another interrupt. nmi_seen remembers that an edge has been seen, 134 | * so turn off both nmi and nmi_seen when the interrupt is acknowledged. 135 | */ 136 | int nmi, nmi_seen; 137 | 138 | /* Speed control. 0 = full speed */ 139 | int delay; 140 | int keydelay; /* extra delay while any keys are pressed */ 141 | 142 | /* Cyclic T-state counter */ 143 | tstate_t t_count; 144 | 145 | /* Clock in MHz = T-states per microsecond */ 146 | float clockMHz; 147 | 148 | /* Simple event scheduler. If nonzero, when t_count passes sched, 149 | * trs_do_event() is called and sched is set to zero. */ 150 | tstate_t sched; 151 | }; 152 | 153 | #define Z80_ADDRESS_LIMIT (1 << 16) 154 | 155 | /* 156 | * Register accessors: 157 | */ 158 | 159 | #define REG_A (z80_state.af.byte.high) 160 | #define REG_F (z80_state.af.byte.low) 161 | #define REG_B (z80_state.bc.byte.high) 162 | #define REG_C (z80_state.bc.byte.low) 163 | #define REG_D (z80_state.de.byte.high) 164 | #define REG_E (z80_state.de.byte.low) 165 | #define REG_H (z80_state.hl.byte.high) 166 | #define REG_L (z80_state.hl.byte.low) 167 | #define REG_IX_HIGH (z80_state.ix.byte.high) 168 | #define REG_IX_LOW (z80_state.ix.byte.low) 169 | #define REG_IY_HIGH (z80_state.iy.byte.high) 170 | #define REG_IY_LOW (z80_state.iy.byte.low) 171 | 172 | #define REG_SP (z80_state.sp.word) 173 | #define REG_PC (z80_state.pc.word) 174 | 175 | #define REG_AF (z80_state.af.word) 176 | #define REG_BC (z80_state.bc.word) 177 | #define REG_DE (z80_state.de.word) 178 | #define REG_HL (z80_state.hl.word) 179 | 180 | #define REG_AF_PRIME (z80_state.af_prime.word) 181 | #define REG_BC_PRIME (z80_state.bc_prime.word) 182 | #define REG_DE_PRIME (z80_state.de_prime.word) 183 | #define REG_HL_PRIME (z80_state.hl_prime.word) 184 | 185 | #define REG_IX (z80_state.ix.word) 186 | #define REG_IY (z80_state.iy.word) 187 | 188 | #define REG_I (z80_state.i) 189 | #define REG_R (z80_state.r) 190 | #define REG_R7 (z80_state.r7) 191 | 192 | #define HIGH(p) (((struct twobyte *)(p))->high) 193 | #define LOW(p) (((struct twobyte *)(p))->low) 194 | 195 | #define T_COUNT(n) (z80_state.t_count += (n)) 196 | 197 | /* 198 | * Flag accessors: 199 | * 200 | * Flags are: 201 | * 202 | * 7 6 5 4 3 2 1 0 203 | * S Z - H - P/V N C 204 | * 205 | * C Carry 206 | * N Subtract 207 | * P/V Parity/Overflow 208 | * H Half-carry 209 | * Z Zero 210 | * S Sign 211 | */ 212 | 213 | #define CARRY_MASK (0x1) 214 | #define SUBTRACT_MASK (0x2) 215 | #define PARITY_MASK (0x4) 216 | #define OVERFLOW_MASK (0x4) 217 | #define UNDOC3_MASK (0x8) 218 | #define HALF_CARRY_MASK (0x10) 219 | #define UNDOC5_MASK (0x20) 220 | #define ZERO_MASK (0x40) 221 | #define SIGN_MASK (0x80) 222 | #define ALL_FLAGS_MASK (CARRY_MASK | SUBTRACT_MASK | OVERFLOW_MASK | \ 223 | HALF_CARRY_MASK | ZERO_MASK | SIGN_MASK) 224 | 225 | #define SET_SIGN() (REG_F |= SIGN_MASK) 226 | #define CLEAR_SIGN() (REG_F &= (~SIGN_MASK)) 227 | #define SET_ZERO() (REG_F |= ZERO_MASK) 228 | #define CLEAR_ZERO() (REG_F &= (~ZERO_MASK)) 229 | #define SET_HALF_CARRY() (REG_F |= HALF_CARRY_MASK) 230 | #define CLEAR_HALF_CARRY() (REG_F &= (~HALF_CARRY_MASK)) 231 | #define SET_OVERFLOW() (REG_F |= OVERFLOW_MASK) 232 | #define CLEAR_OVERFLOW() (REG_F &= (~OVERFLOW_MASK)) 233 | #define SET_PARITY() (REG_F |= PARITY_MASK) 234 | #define CLEAR_PARITY() (REG_F &= (~PARITY_MASK)) 235 | #define SET_SUBTRACT() (REG_F |= SUBTRACT_MASK) 236 | #define CLEAR_SUBTRACT() (REG_F &= (~SUBTRACT_MASK)) 237 | #define SET_CARRY() (REG_F |= CARRY_MASK) 238 | #define CLEAR_CARRY() (REG_F &= (~CARRY_MASK)) 239 | 240 | #define SIGN_FLAG (REG_F & SIGN_MASK) 241 | #define ZERO_FLAG (REG_F & ZERO_MASK) 242 | #define HALF_CARRY_FLAG (REG_F & HALF_CARRY_MASK) 243 | #define OVERFLOW_FLAG (REG_F & OVERFLOW_MASK) 244 | #define PARITY_FLAG (REG_F & PARITY_MASK) 245 | #define SUBTRACT_FLAG (REG_F & SUBTRACT_MASK) 246 | #define CARRY_FLAG (REG_F & CARRY_MASK) 247 | 248 | extern struct z80_state_struct z80_state; 249 | 250 | extern void z80_reset(void); 251 | extern int z80_run(int continuous); 252 | extern void mem_init(void); 253 | extern int mem_read(int address); 254 | extern void mem_write(int address, int value); 255 | extern void mem_write_rom(int address, int value); 256 | extern int mem_read_word(int address); 257 | extern void mem_write_word(int address, int value); 258 | Uchar *mem_pointer(int address, int writing); 259 | extern int mem_block_transfer(Ushort dest, Ushort source, int direction, 260 | Ushort count); 261 | extern int load_hex(FILE *file); /* returns highest address loaded + 1 */ 262 | extern void debug(const char *fmt, ...); 263 | extern void error(const char *fmt, ...); 264 | extern void warning(const char *fmt, ...); 265 | extern void fatal(const char *fmt, ...); 266 | extern void z80_out(int port, int value); 267 | extern int z80_in(int port); 268 | extern int disassemble(unsigned short pc); 269 | extern void debug_init(void); 270 | extern void debug_shell(void); 271 | 272 | #endif 273 | --------------------------------------------------------------------------------