Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
tnylpo(1)		    General Commands Manual		     tnylpo(1)

NAME
       tnylpo -	a utility to run programs written for CP/M-80

SYNOPSIS
       tnylpo  [-abnrsw]  [-c  (<n>  |	@)]  [-d  <drive>] [-e [h][ b<bytes> |
       p<pages>	| r<addr>-<addr> ] :<file> ] [-f <config-file>]	[-l (<n> | @)]
       [-o(n|y|[y,] <fg>,<bg> )]  [-t  (<n>  |	@)]  [-v  <level>]  [-y	 (n  |
       <count>,<nanoseconds>)] [-z{a|e|i|n|s|x}] <command> [<arg> ...]

       tnylpo -h

DESCRIPTION
       tnylpo allows the execution of programs written for the CP/M-80 operat-
       ing  system in a	Unix environment. To accomplish	this task, tnylpo com-
       bines an	emulation of the Zilog Z80 eight-bit CPU with a	software layer
       translating calls to the	CP/M application  programming  interface  (the
       BDOS  and  BIOS	calls  of CP/M-80 version 2.2 plus a few BDOS calls of
       CP/M 3) to Unix library and system calls.

       tnylpo doesn't even try to re-create the	look-and-feel of  the  CP/M-80
       operating  system  by  emulating	its Console Command Processor (CCP) or
       providing implementations of utility programs  like  PIP	 or  STAT;  in
       fact,  its  aim	is  to integrate CP/M-80 applications and compilers as
       much as possible	into the Unix command line interface  to  allow	 their
       use  in combination with	the much more capable utilities	and editors of
       the host	operating system; tnylpo users are supposed to use  cp(1)  and
       dd(1)  instead  of PIP, chmod(1), df(1),	and ls(1) instead of STAT, and
       shell scripts, here-documents, and redirections instead of  SUBMIT  and
       XSUB.

       Files  in the CP/M environment are directly mapped to Unix files; while
       this comes at the cost of some  minor  incompatibilities	 with  CP/M-80
       (see  below  under NOTES), it vastly simplifies the interaction between
       CP/M and	Unix programs compared to the alternative  approach  of	 using
       disk images.

       Thanks  to  its	system call translation	layer, tnylpo neither contains
       any code	from the CP/M operating	system nor needs any additional	 soft-
       ware apart from the actual applications it is meant to run.

       Since  CP/M-80  programs	 can use eight-bit characters at best (many of
       them even share the firm	belief of CP/M in a  seven-bit	ASCII  world),
       another	translation  layer mediates between the	internal one-byte-per-
       character text representation and the almost universal multibyte	 char-
       acter  (most  commonly  UTF-8 based) approach of	contemporary Unix sys-
       tems. This translation layer affects the	character orientated I/O chan-
       nels of CP/M only and may be  disabled  for  the	 printer,  punch,  and
       reader devices.

       All  screen-orientated  CP/M-80	programs  are  unable to cope with the
       ability of graphical user interfaces to resize text windows  (in	 fact,
       even  the  ability of the DEC VT100 to switch between 80	and 132	column
       mode overtaxes them); to	alleviate this problem (and to provide the ca-
       pability	of running the same CP/M application on	different terminal em-
       ulations	or on serial terminals without reconfiguring  the  CP/M	 bina-
       ries),  tnylpo includes a curses	based emulation	of the DEC VT52	termi-
       nal (with certain extensions in functionality) for use as CP/M  console
       device.	tnylpo	gives the user the choice between this terminal	emula-
       tion and	a line orientated console device more  suitable	 for  programs
       like assemblers and compilers.

       True  to	 its aim of allowing the integration of	CP/M programs into the
       Unix environment, tnylpo	happily	does away with certain	non-essential,
       rarely  used,  or extremely un-Unixy features of	CP/M-80	(some of which
       --to be frank-- would be	disproportionately hard	to implement or	 inte-
       grate under Unix), among	them user areas, the rudimentary character de-
       vice  redirection implemented by	the I/O	byte, file attributes, and the
       printer echo. Whereever some functionality has been left	out, care  has
       been  taken  not	 to offend CP/M	programs unduly	(programs may e.g. set
       the user	area, and on query tnylpo will report the current  value  back
       to them,	but will ignore	it otherwise). As a rule, tnylpo or Unix offer
       better  solutions  to replace the omitted CP/M features,	e.g. different
       tnylpo configurations (and drives/directories) for  different  applica-
       tions  or  users	 (user	areas),	 shell	output redirection (I/O	byte),
       chmod(1)	(file attributes), or script(1)	(console protocol).

   CPU emulation
       tnylpo strives to provide a full	implementation of both documented  and
       undocumented  features  of  the	Z80 CPU; undocumented instructions and
       side effects are	supported to the best of the author's knowledge.

       I/O instructions	are available, but are dummies;	writing	to  I/O	 ports
       has  no	direct	effect,	 and  reading them always returns a null byte.
       Same is true for	all interrupt related instructions (while the I	regis-
       ter may be set and read and the EI and DI  instructions	have  the  ex-
       pected  side  effects, no interrupt will	ever occur).  Executing	a HALT
       instruction will	end program execution (and thereby  the	 execution  of
       tnylpo)	and  is	considered an error situation (see below under Program
       termination). Well-behaved CP/M applications should never  use  any  of
       these instructions anyway.

       Note  that  the behaviour of the	HALT instruction has changed from ear-
       lier versions of	tnylpo,	where it was simply ignored (resp. acted as if
       a NMI had been received immediately after  entering  the	 halt  state).
       This  change allows unused memory areas to be initialized with HALT in-
       structions, which increases the chances of  detecting  and  stopping  a
       runaway application program early.

       The  R  register	 will be increased as expected;	since application pro-
       grams may use the current value of the R	register for the generation of
       random numbers (the Randomize procedure of Turbo	 Pascal	 seems	to  do
       this),  the  R  register	is initialized with a random value (otherwise,
       repeated	runs of	the same program would always generate	the  same  se-
       quence of random	numbers).

       At  the start of	program	execution, all unused memory (i.e. the part of
       the TPA not occupied by the loaded executable as	 well  as  the	unused
       parts of	the zero page and the BIOS area) are initialized with the byte
       value  0x76  (the  HALT instruction).  All registers apart from PC, SP,
       and R are set to	zero, PC is set	to 0x100, and SP  points  to  a	 stack
       area at the top of the TPA.

   File	name translation
       In translating CP/M disk	operations to Unix disk	operations, tnylpo has
       to  translate  CP/M file	names to Unix file names and vice versa; since
       CP/M de facto allows almost arbitrary seven-bit characters in its  file
       names  (including  null bytes and slashes), and Unix file names are not
       bound to	the 8+3	character restriction of CP/M, tnylpo enforces a  com-
       mon  subset:  only  decimal digits, the 26 letters of the alphabet, the
       minus (-), at (@), dollar ($), and hash (#) signs are allowed  in  file
       names,  which  are restricted to	one to eight characters	in length. The
       name may	have an	extension of up	to three characters from the same set;
       the dot between name and	extension may only be present if there	is  at
       least one extension character.  On the Unix side, all letters appear in
       lower  case, while tnylpo accepts (and returns) only upper case letters
       in CP/M FCBs. Unix files	with names containing upper  case  letters  or
       otherwise not conforming	to tnylpo's restrictions are not accessible to
       CP/M programs. (Dollar signs in Unix file names are a nuisance in shell
       scripts,	 but  since  they  are	habitually used	in CP/M	temporary file
       names, tnylpo could not forbid them; fortunately, CP/M programs	creat-
       ing  files  with	file names containing dollar signs usually remove them
       before exiting.)

OPTIONS
       Many of tnylpo's	command	line options have corresponding	entries	in the
       configuration file, so they will	be discussed  in  this	context	 below
       (see Configuration options).  Four options have no counterparts:

       -a     selects  the alternate character set from	the configuration file
	      before starting execution	(see Character sets).

       -e [h][b<bytes>|p<pages>|r[<addr>]-<addr>]:<filename>
	      causes tnylpo to write (parts of)	the CP/M memory	to the	speci-
	      fied file	after program termination (see Saving a	memory image).

       -f <config-file>
	      tells tnylpo to read its configuration from the named file.

       -h     asks  tnylpo to show a short command line	synopsis (-h cannot be
	      used in combination with any other command line option).

   Command line	arguments
       tnylpo interprets its first positional command  line  argument  as  the
       name  of	 the  CP/M  program (.com file)	it is supposed to execute.  If
       this argument contains a	slash (/), it is interpreted as	 a  Unix  path
       name,  otherwise	it is treated as a CP/M	file name, i.e.	it may be pre-
       fixed by	a drive	specification and is interpreted as  relative  to  the
       path  corresponding  to	this  drive  or	the default drive according to
       tnylpo's	configuration (see below). In both cases, the suffix  .com  is
       appended	if the file name does not already end in .com.

       All  further  positional	arguments are passed as	command	line arguments
       to the CP/M program (i.e. they are converted to upper case  and	copied
       to  the	default	 DMA  area at 0x0080; additionally, the	default	FCB at
       0x005c is initialized according to the second and third positional  ar-
       guments).

   Configuration files
       While  some  features  of  tnylpo can be	controlled by command line op-
       tions, the most convenient way to configure it is by using a configura-
       tion file; if a configuration file is explicitly	specified on the  com-
       mand  line  (option -f),	it will	be used; otherwise, tnylpo looks for a
       file named .tnylpo.conf in the current working directory.  If  none  is
       found, tnylpo looks for .tnylpo.conf in the user's home directory. As a
       last  resort, tnylpo uses its built-in defaults.	If conflicting options
       are specified in	the configuration file and on the  command  line,  the
       command line takes precedence.

       A  tnylpo  configuration	 file  is a regular text file; empty lines and
       lines starting with a hash sign (#) or a	semicolon (;) are ignored. All
       other lines have	the form

	      <keyword>	[<token> ...]  = <token> [<token> ...]

       <token> is either a keyword  (a	sequence  of  alphanumeric  characters
       starting	 with a	letter), a number (hexadecimal,	octal or decimal using
       the usual Unix convention of being prefixed by 0x, 0, resp. some	 other
       digit), a string	in double quotes, or a comma.

   Configuration options
       drive <drive letter> = [readonly	,] <path>

	      Up  to 16	drives can be defined by repeated use of this configu-
	      ration option; <drive letter> is a single	lower case  letter  in
	      the  range  a-p, and <path> is a string containing the name of a
	      directory	on the host computer system. CP/M programs  trying  to
	      create  or  access  a  file on the corresponding disk drive will
	      create or	access a file in this directory.  Only	regular	 files
	      up  to  8MB in size with names corresponding to tnylpo's idea of
	      well-behaved file	names suitable for both	 CP/M  and  Unix  (see
	      above)  are  visible to CP/M programs. If	<path> is preceeded by
	      the optional keyword readonly, programs running on  tnylpo  will
	      not be able to create new	files on this drive or rename, delete,
	      or  modify  existing  files  (any	 attempt to modify a read-only
	      drive will terminate the offending CP/M program).

	      There is no corresponding	command	line option. If	no  drive  has
	      been  defined  in	the configuration file (or if there is no con-
	      figuration file),	tnylpo will use

		     drive a = "."

	      as default, i.e. the current  working  directory	will  be  made
	      available	as CP/M	drive A.

       default drive = <drive letter>
       command line option -d <drive letter>

	      define  the  drive  identified by	<drive letter> (a single lower
	      case letter in the range a-p) as default drive, i.e.  the	 drive
	      all file specifications not including an explicit	drive name re-
	      fer  to. This drive must be assigned to a	host system directory,
	      either implicitly	or by the drive	configuration option.  If  de-
	      fault  drive is not specified, tnylpo assumes drive A as default
	      drive.

       close files = (true | false)
       command line option -n

	      If close files is	set to false (or if the	-n command line	option
	      is present), files closed	by the CP/M program are	kept  open  by
	      tnylpo, i.e. the corresponding FCBs are not invalidated. This is
	      required by some CP/M programs (see File closing), but should be
	      avoided  if  possible,  since  otherwise tnylpo might run	out of
	      file descriptors.	 By  default,  tnylpo  actually	 closes	 files
	      closed by	the CP/M program.

       logfile = <path>

	      <path> is	a quoted string	containing the path of a file to which
	      tnylpo appends error messages and	other logging information (fa-
	      tal  error messages are also written to stderr).	If the logfile
	      configuration option is not used,	no logging information will be
	      written.	There is no corresponding command line option.

       loglevel	= <level>
       command line option -v <level>

	      The amount of data written to the	logfile	is controlled  by  the
	      loglevel	configuration option resp. its command line equivalent
	      -v.  Both	take a numeric argument; the higher  the  number,  the
	      more  information	 is written (causing the emulation to run pro-
	      gressively slower).  Valid log levels are:

	      0	     write error messages only.

	      1	     additionally, count the machine instructions executed  by
		     the  emulator; at program termination, tnylpo will	output
		     tables showing which instructions have been executed  how
		     often.

	      2	     additionally,  trace  FDOS	functions (i.e.	BDOS functions
		     related to	file I/O).

	      3	     additionally, dump	FCBs for FDOS functions	using a	FCB.

	      4	     additionally, dump	file records read and written  by  the
		     FDOS functions.

	      5	     additionally, trace all other system calls	(BDOS and BIOS
		     functions); since all character I/O functions are traced,
		     this will produce a lot of	output.

	      The  logging  facility  is  a  leftover from the development and
	      testing of tnylpo	itself;	since it may provide  important	 clues
	      if applications do not work as expected, it has been retained.

       console = (full | line)
       command line options -s or -b

	      tell  tnylpo to use the full screen VT52 emulation (full,	-s) or
	      the line orientated (line, -b)  console  interface.  Some	 other
	      configuration options, e.g.  lines, columns, application cursor,
	      and  screen delay	are only effective in the full screen mode. By
	      default, tnylpo uses the line orientated console interface.

       screen delay = (<number>	| key)
       command line option -t (<number>	| @)

	      define the number	of seconds tnylpo should wait between  program
	      termination  and	resetting  the	display.  If key (resp.	 @) is
	      specified, tnylpo	waits for a key	being pressed  before  exiting
	      the VT52 emulation. This option allows the user to see the final
	      display  of  the	CP/M application even if resetting the display
	      restores the original screen contents or clears the screen.  De-
	      fault value is 0 (don't wait).

       lines = (<number> | current)
       columns = (<number> | current)
       command line options -l (<number> | @) and -c (<number> | @)

	      define the display size used by the terminal emulation; the num-
	      ber of lines must	be between 5 and 95, the number	of columns be-
	      tween 20 and 95.	Using the keyword current (resp.  @ in case of
	      the  command  line options) tells	tnylpo to use the current size
	      of the display device. If	no display size	is  specified  in  the
	      configuration file or on the command line, tnylpo	defaults to 24
	      lines of 80 columns.

       application cursor = (true | false)
       command line option -w

	      If application cursor is set to true (or the command line	option
	      -w  is  present),	 pressing  the cursor keys up, left, right, or
	      down will	send the control characters ^E (0x05), ^S  (0x13),  ^D
	      (0x04),  or  ^X (0x18) to	the running CP/M program (i.e. the ap-
	      propriate	cursor motion commands for programs like  WordStar  or
	      Turbo  Pascal). Otherwise, the cursor keys will generate the de-
	      fault VT52 escape	sequences, <esc> A,  <esc>  D,	<esc>  C,  and
	      <esc>  B.	  This option is only effective	in full	screen console
	      mode.

       exchange	delete = (true | false)
       command line option -r

	      If exchange delete is set	to true	(or the	command	line option -r
	      is present), the backspace (^H, 0x08) key	and the	delete	(0x7f)
	      key are reversed in full screen mode.

       [alt] char <number> = <string>
       [alt] charset = (ascii |	vt52 | latin1 |	tnylpo)
       unprintable = <string>

	      serve to define the primary and alternate	character sets used by
	      tnylpo;  they have no corresponding command line options and are
	      explained	below (see Character sets).

       (printer	| punch	| reader) file = <path>
       (printer	| punch	| reader) mode = (text | raw)

	      define the path and the format of	the  data  files  representing
	      the  CP/M	 character I/O devices LST:, PUN:, and RDR:; there are
	      no corresponding command line options. Details are explained be-
	      low (see Character devices).

       colors =	( false	| true ) [ , <fg> , <bg> ]
       command line options -on, -oy, -oy,<fg>,<bg> and	-o<fg>,<bg>

	      switch color support on or off in	full screen mode;  optionally,
	      the  default  foreground	and  background	 colors	(digits	in the
	      range from 0 to 7) may be	selected (see Color support).

       cpu delay = <count> , <nanoseconds>
       command line options -yn	and -y<count>,<nanoseconds>

	      slow  down  the  emulation  by  adding  a	 delay	(specified  by
	      <nanoseconds>)  after every <count> instructions executed	by the
	      emulated CPU. The	command	line option -yn	disables  this	delay,
	      overriding  a delay specified in the configuration file. Slowing
	      the emulation allows using  software  (e.g.  interactive	games)
	      which  would  otherwise run much too fast	on tnylpo; another ap-
	      plication	is reducing the	high load tnylpo puts on the host CPU.

	      Useful values for	<count>	and <nanoseconds> depend on the	 speed
	      of  the  host CPU, on the	host operating system, and on the par-
	      ticular application program; they	need to	be determined  by  ex-
	      perimentation. Please bear in mind that the minimal useful delay
	      (i.e.  the  minimal value	for <nanoseconds>) depends on the host
	      operating	system and may be as large  as	several	 milliseconds;
	      since  smaller  delays may be rounded up to that minimum implic-
	      itly, specifying e.g.  -y1,1 may give unexpected results.

       dump = none
       dump = all
       dump = (startup | exit |	error |	signal)	[, ...]
       command line options -zn, -za, and -z{s|x|e|i}

	      define if	and when tnylpo	writes a machine dump (including  reg-
	      ister  values  and the contents of main memory) to the log file.
	      The keywords startup, exit, error, and signal (resp. the	subop-
	      tions s, x, e, and i) request a dump at program startup (immedi-
	      ately  before  passing  control to the CP/M command), at program
	      exit, at program exit due	to a fatal execution error, or at  the
	      receipt  of  a  SIGUSR1  signal  and may be arbitrarily combined
	      (only exit and error are mutually	exclusive).  dump = all	(resp.
	      -za) is a	shorthand for dump  =  startup,	 exit,	signal	(resp.
	      -zsxi),  and  dump = none	(resp.	-zn) turns all dumps off (this
	      is also the default setting). Dumps are only written  if	a  log
	      file has been defined by the configuration option	logfile.

   Terminal emulation
       tnylpo  provides	 a  curses  based  emulation of	the DEC	VT52 terminal,
       which can be used instead of the	default	line orientated	console	to ac-
       commodate full-screen applications; this	terminal emulation is selected
       by the command line option -s resp. by the entry	console	= full in  the
       configuration file.

       tnylpo's	terminal emulation mimicks the VT52 fairly accurately, but of-
       fers  a	number of extensions, among them the ability to	support	screen
       sizes of	up to 95 by 95 characters (this	limitation is due to the limi-
       tations of the VT52 direct cursor positioning command), eight-bit oper-
       ation, a	dynamically switchable alternate  character  set,  insert  and
       delete  line  commands,	and  bold,  underlined,	inverted, and blinking
       (i.e. everybody's favourite) character rendition. To protect  the  CP/M
       application  (resp.  its	user) from the effects of screen resizing, the
       terminal	emulation provides a fixed  size  screen  area	(typically  80
       columns by 24 lines, but	this may be changed by command line or config-
       uration	file  options)	within the actual display (a terminal emulator
       like xterm(1) or	the screen of an actual	serial terminal). If the  dis-
       play  device/window  is larger than this	area, there will be blank mar-
       gins to the right and below the VT52 display area; if  it  is  smaller,
       parts  of  the  output from the emulator	will be	invisible to the user,
       but will	(re-)appear as soon as the window is enlarged.

       The terminal emulation (like the	VT52) does not do  an  automatic  line
       wrap  (i.e.  the	 cursor	 will not move to the first column of the next
       line if a character is displayed	in the last column of a	line) and sup-
       ports (or at least tolerates) all of the	VT52 control sequences:

       <bel> (0x07)
	      gives an accustic	(or visual) signal.

       <bs> (0x08)
	      moves the	cursor left, but stops at column 1.

       <tab> (0x09)
	      moves the	cursor to the next tabulator stop if it	is before  the
	      last  tabulator stop on the current line (tabulator stops	are at
	      columns 9, 17, 25, ...); otherwise, it moves the cursor one col-
	      umn to the right (resp.  does nothing if the cursor  is  already
	      in the last column).

       <lf> (0x0a)
	      moves the	cursor down one	line and scrolls up on bottom line.

       <cr> (0x0d)
	      moves the	cursor to the first column of the current line.

       <esc> (0x1b)
	      marks the	start of an escape sequence (see below).

       All  other  characters in the ASCII control character range (0x00-0x1f,
       0x7f) are ignored. The VT52 escape sequences are:

       <esc> ) (0x1b 0x29) and <esc> = (0x1b 0x3d)
	      switch the keypad	to application resp. to	regular	(numeric) mode
	      (no effect in tnylpo).

       <esc> A (0x1b 0x41)
	      moves the	cursor up one line, but	stops at the top line.

       <esc> B (0x1b 0x42)
	      moves the	cursor down one	line, but stops	at the bottom line.

       <esc> C (0x1b 0x43)
	      moves the	cursor right one column, but stops at the last column.

       <esc> D (0x1b 0x44)
	      moves the	cursor left one	column,	but stops at the first column.

       <esc> F (0x1b 0x46) and <esc> G (0x1b 0x47)
	      display character	codes 0x5e-0x7e	as graphical  resp.  as	 ASCII
	      characters (see below).

       <esc> H (0x1b 0x48)
	      moves the	cursor to the left top corner of the display.

       <esc> I (0x1b 0x49)
	      moves the	cursor up one line and scrolls down at the first line.

       <esc> J (0x1b 0x4a)
	      clears  the  display from	the current cursor position to the end
	      of the screen.

       <esc> K (0x1b 0x4b)
	      clears the display from the current cursor position to  the  end
	      of the line.

       <esc> Y <line> <column> (0x1b 0x59 0xYY 0xXX)
	      moves  the cursor	to the specified position on the display; line
	      and column numbers are given  as	graphical  characters  in  the
	      range  of	0x20 (position 1) to 0x7e (position 95). If the	column
	      number is	larger than the	display	width, the horizontal position
	      is not changed; a	line number larger than	the height of the dis-
	      play moves the cursor to the last	line.

       <esc> Z (0x1b 0x5a)
	      identifies the terminal type; the	terminal emulation responds by
	      sending the sequence <esc> / K (0x1b 0x2f	0x4b), i.e. it identi-
	      fies itself as VT52 without hardcopy device.

       <esc> [ (0x1b 0x5b) and <esc> \ (0x1b 0x5c)
	      enter resp. exit "hold screen" mode (see below).

       In addition, the	terminal emulation in tnylpo  supports	the  following
       extensions to the VT52 escape sequences:

       <esc> E (0x1b 0x45)
	      clears  the  display, moves the cursor to	the top	left corner of
	      the display.

       <esc> L (0x1b 0x4c)
	      inserts a	blank line at the cursor position and  moves lines be-
	      low down one line	(the last line is lost).

       <esc> M (0x1b 0x4d)
	      deletes the line at the cursor position and moves	lines below up
	      one line (an empty line will appear at the bottom	 of  the  dis-
	      play).

       <esc> N (0x1b 0x4e)
	      inserts a	blank character	at the cursor position and moves char-
	      acters  to the right one position	to the right (the last charac-
	      ter on the line is lost).

       <esc> O (0x1b 0x4f)
	      deletes the character at the cursor position and	moves  charac-
	      ters  to	the  right one position	to the left (a blank character
	      appears in the last column of the	line).

       <esc> S <color> (0x1b 0x53 0xCC)
	      sets the background color	of subsequent output  characters;  the
	      color code is described below (Color support).

       <esc> T <color> (0x1b 0x54 0xCC)
	      sets  the	 foreground color of subsequent	output characters; the
	      color code is described below (Color support).

       <esc> a (0x1b 0x61) and <esc> b (0x1b 0x62)
	      make the cursor invisible	resp. visible.

       <esc> c (0x1b 0x63) and <esc> d (0x1b 0x64)
	      switch to	the alternate resp. to the primary character set  (see
	      below).

       <esc> e (0x1b 0x65) and <esc> f (0x1b 0x66)
	      switch on	resp. off bold characters.

       <esc> g (0x1b 0x67) and <esc> h (0x1b 0x68)
	      switch on	resp. off underlined characters.

       <esc> i (0x1b 0x69) and <esc> j (0x1b 0x6a)
	      switch on	resp. off inverted characters.

       <esc> k (0x1b 0x6a) and <esc> l (0x1b 0x6c)
	      switch on	(arrgh!) resp. off (phew!) blinking characters.

       <esc> m (0x1b 0x6d)
	      switches off bold, underlined, blinking, and inverted characters
	      as  well as standout mode	(see below); resets the	foreground and
	      background colors	to their defaults.

       <esc> n (0x1b 0x6e) and <esc> o (0x1b 0x6f)
	      switch the cursor	keys to	application mode resp. back to regular
	      (VT52) mode: in regular mode, the	cursor keys send the sequences
	      <esc> A (up), <esc> B (down),  <esc>  C  (right),	 and  <esc>  D
	      (left);  in application mode, they send WordStar-compatible com-
	      mands, namely ^E (0x05, up), ^X (0x18, down), ^D (0x04,  right),
	      and ^S (0x13, left).

       <esc> p (0x1b 0x70) and <esc> q (0x1b 0x71)
	      switch  on  resp.	 off  standout mode; standout mode is the most
	      visible character	attribute provided by curses (this is  usually
	      inverted	video, so using	<esc> p	and <esc> q is usually equiva-
	      lent to using <esc> i and	<esc> j).

       "Hold screen" mode is a feature of the VT52 terminal: it	is entered and
       exited either by	the computer sending the relevant control sequence  or
       by  the	user by	pressing the "hold screen" key (in tnylpo, this	is the
       F5 key).	In "hold screen" mode, trying to scroll	up the	screen	(by  a
       <lf>  on	the bottom line	of the screen) blocks further output until ei-
       ther "hold screen" mode is exited or the	user presses the "scroll page"
       key (F6 in tnylpo) or the "scroll line" key (F7 in tnylpo), which allow
       one more	screenfull resp. one more line of output.

       Displaying graphical characters instead of  ASCII  characters  for  the
       byte  range 0x5e-0x7e is	another	feature	of the VT52 terminal which al-
       lows access to certain additional shapes	like subscripted digits	or the
       +- sign;	in tnylpo, graphical mode allows displaying the	shapes defined
       for the character positions 0x00-0x1f and 0x7f, which  cannot  be  dis-
       played directly.

   Character sets
       Switching between a primary and an alternate character set is an	exten-
       sion  provided  by  tnylpo: two full character sets of 256 shapes (each
       containing  a  separate	graphical  character  set  in  the   positions
       0x00-0x1f  and 0x7f) may	be defined in the configuration	file; programs
       may switch between these	two sets by using  <esc>  c  resp.   <esc>  d.
       Switching  character  sets doesn't change characters already written to
       the display. This feature allows	programs to use	e.g. a national	 vari-
       ant  of	the  ISO  646  seven-bit character set in parallel to standard
       ASCII characters.

       Character set definition	is done	in the configuration file by using the
       option

	      [alt] char <number> = <string>

       which defines  <string>	(a  one-character  string  literal  in	double
       quotes)	as  representation  of	code  <number>	(a number in the range
       0-255) in the primary (or alternate, if the line	is  prefixed  by  alt)
       character  set. Characters not explicitly defined in this way are taken
       from a default character	set, which may be selected by the option

	      [alt] charset = (ascii | vt52 | latin1 | tnylpo)

       The possible values correspond to  the  four  built-in  character  sets
       ASCII,  VT52 (ASCII plus	an approximation of the	VT52 graphical charac-
       ters), the ISO 8859-1 (Latin 1) eight-bit character set,	which  supple-
       ments  the  ASCII code by characters used in Western European languages
       in positions 0xa0-0xff, and finally a homespun superset of Windows code
       page 1252 (and thereby a	superset of ISO	8859-1 and ASCII), which  sup-
       ports block graphics and	the VT100 box drawing characters  as graphical
       character set.

       If no character set is specified, tnylpo	uses the VT52 character	set by
       default.

       By  using the command line option -a, a program may be started with the
       alternate character set selected; the effect is almost identical	to the
       program issuing <esc> c as its very first action. (There	is  a  differ-
       ence  in	full screen console mode: During screen	initialization,	tnylpo
       passes the blank	character from	the  selected  character  set  to  the
       curses  library	for use	as background character. Since the program it-
       self can	select the alternate character set only	after this initializa-
       tion has	been done, curses will receive the blank  character  from  the
       primary character set; with the -a command line option, it will receive
       the  blank  character from the alternate	character set. This difference
       is mostly academic, since it is not recommended to redefine  the	 blank
       character anyway, see below.)

       Output characters which are undefined in	the currently selected charac-
       ter set are ignored by the terminal emulation; the configuration	option

	      unprintable = <string>

       substitutes  undefined  characters  on  output by the value of <string>
       (which must contain a single character).

   Function keys
       Apart from F5, F6, and F7,  which  are  used  to	 implement  the	 "hold
       screen"	function  of the VT52 (see above), tnylpo's terminal emulation
       defines the function keys F1, F2, and F3	as equivalents	of  the	 three
       unlabeled  keys	of  a  VT52  terminal; if pressed, they	return the se-
       quences <esc> P (0x1b 0x50), <esc> Q (0x1b 0x51),  and  <esc>  R	 (0x1b
       0x52). F4 causes	the terminal emulation to redraw its display, which is
       useful  if  some	other program or the host operating system mess	up the
       user's screen. F10 sends	a SIGINT to tnylpo, causing the	 emulation  to
       stop  abruptly, but allowing tnylpo itself to exit gracefully (this key
       is meant	as a last-resort way of	stopping a CP/M	program	gone haywire).

   Color support
       If the underlying software and display  hardware	 allow	color  output,
       tnylpo's	terminal emulation supports the	use of eight different colors,
       which  may  be selected as foreground resp. background colors of	subse-
       quently displayed characters. These colors are identified by  the  fol-
       lowing numeric codes:

	      0	   black
	      1	   blue
	      2	   red
	      3	   magenta
	      4	   green
	      5	   cyan
	      6	   yellow
	      7	   white

       By  default,  color support is disabled even on color-capable displays;
       it must be explicitly enabled either by the configuration option

	      colors = true

       or by the command line option -oy.  Both	colors = true and -oy  may  be
       followed	 by two	comma-separated	color codes, which specify the default
       foreground resp.	background colors of tnylpo's terminal emulation, e.g.

	      colors = true, 6,	1

       (resp.  -oy,6,1)	will select yellow characters on  a  blue  background.
       The default colors may be specified in the configuration	file by	colors
       =  false,  6,  1	 even  if color	support	is disabled (since this	may be
       overridden by -oy).  The	command	line option -o6,1 is a shorthand  form
       of  -oy,6,1, and	-on may	be used	to override the	configuration file and
       disable color support. If no default colors have	been specified	either
       in  the configuration file or on	the command line, tnylpo defaults to 7
       and 0, i.e. to white text on a black background.

       Application programs may	select colors by issuing the escape  sequences
       <esc>  S	 <color>  and  <esc>  T	<color>	to choose the background resp.
       foreground colors of subsequently displayed characters; <color> is  ei-
       ther  a single ASCII digit in the range from 0 to 7 (0x31 to 0x37) cor-
       responding to one of the	colors supported by tnylpo, or the character =
       (0x3d), which will select the respective	default	color. To render  e.g.
       the text	Warning!  in red, a program may	display	the character sequence

	      <esc> T 2	W a r n	i n g !	<esc> T	=

       on  the full-screen console. Both foreground and	background colors will
       also be reset to	their defaults by the escape sequence <esc>  m,	 which
       resets  all text	attributes.  On	monochrome devices or if color support
       has been	disabled, <esc>	S and <esc>  T	will  still  be	 accepted  but
       silently	ignored.

   Character devices
       Besides the bidirectional console device, CP/M supports three unidirec-
       tional  character devices, the output-only printer and paper tape punch
       devices LST: and	PUN: and the input-only	paper tape reader device RDR:.
       tnylpo represents these devices by host system files, to	which the data
       provided	by the CP/M program are	written	resp. from which the data pre-
       sented to the CP/M program are read.

       These files are defined by the configuration options

	      (printer | punch | reader) file =	<path>

       where <path> is a string	in double  quotes  containing  the  Unix  file
       path;  in  case	of the output devices (LST: and	PUN:), data written by
       the CP/M	program	are appended to	the contents of	the named files;  RDR:
       input will start	at the beginning of the	reader file. If	a CP/M program
       reads  past  the	end of the reader file,	tnylpo will continue to	return
       ^Z (0x1a) bytes as end-of-file indication.

       tnylpo's	character devices can operate in two modes, depending  on  the
       configuration options

	      (printer | punch | reader) mode =	(text |	raw)

       In  raw	mode, bytes are	written	to the file exactly as they are	gener-
       ated by the CP/M	program	resp. passed to	the CP/M  program  exactly  as
       they are	read from the file (^Z bytes are still returned	as EOF indica-
       tion).  In  text	 mode, tnylpo will translate the characters read resp.
       written using the translation table used	by the console.	Character  set
       switching  by the console (using	the escape sequences <esc> c and <esc>
       d) will affect this translation,	but switching to graphical  characters
       (<esc> F	and <esc> G) will not.	Moreover, tnylpo will convert the line
       end  markers  from  CP/M	 (^M^J,	0x0d 0x0a) to Unix (^J,	0x0a) and vice
       versa in	this mode.

   Saving a memory image
       The command line	option -e causes tnylpo	to save	parts of the CP/M mem-
       ory to a	file after a regular program termination (i.e. one that	is not
       caused by a fatal error or receipt of a signal);	it takes as argument a
       string of suboptions which specify the name and the format of the  out-
       put  file and the range of CP/M memory addresses	to save. Possible sub-
       options and their parameters are

       h      causes the memory	contents to be written in Intel	Hex format; if
	      this option is absent, a binary file will	be written.

       b<bytes>
	      selects a	number of bytes	(specified as decimal number) starting
	      from address 0x100.

       p<pages>
	      selects a	number of pages	(units of 256 bytes, specified as dec-
	      imal number) starting from address 0x100.

       r[<low-addr>]-<high-addr>
	      selects a	range of addresses to  save  (both  addresses  may  be
	      specified	 as  octal,  hexadecimal, or decimal numbers using the
	      Unix convention of prefixing them	 with  0,  0x,	or  any	 other
	      digit,  respectively);  <high-addr>  may	not be less than <low-
	      addr>, and if <low-addr> is missing, 0x100 will  be  assumed  in
	      its place.

       :<filename>
	      specifies	 the  Unix file	to which the memory contents are writ-
	      ten; this	is mandatory and must be the very last	suboption  (in
	      fact,  everything	 following  the	first colon in the argument of
	      the -e command line option is taken as part of the file name).

       Individual suboptions resp. suboptions and their	parameters may not  be
       separated by whitespace.	The three range	specifications b, p, and r may
       not  exceed  the	range of the CP/M memory space (0x0000-0xffff) and are
       mutually	exclusive; if none of them is specified, the whole TPA (start-
       ing at address 0x100 and	including the last byte	before the BDOS	 area)
       is saved.

       The command line	option -e serves as a replacement for the SAVE command
       of  CP/M, which is most often used to save an executable	file after ap-
       plying patches with a debugger (most CP/M  debuggers  don't  provide  a
       command	for  writing  memory contents to a disk	file). Invoking	tnylpo
       with the	additional option -ep34:new.com	is equivalent to  issuing  the
       command	SAVE 34	NEW.COM	immediately after termination of an executable
       under CP/M.

   Supported system calls
       This subsection gives a list of system calls supported by tnylpo. While
       there are some extensions mainly	taken from the CP/M 3 BDOS  interface,
       tnylpo  prioritizes  compatibilty with CP/M 2.2.	All unimplemented BDOS
       calls (i.e. those not listed in this section) are tolerated and conform
       to the (admittedly suboptimal) CP/M 2.2 convention of  returning	 0  in
       registers A, B, and HL.

	      #0   System Reset
	      #1   Console Input
	      #2   Console Output
	      #3   Reader Input
	      #4   Punch Output
	      #5   List	Output
	      #6   Direct Console I/O
	      #7   Get I/O Byte	(dummy)
	      #8   Set I/O Byte	(dummy)
	      #9   Print String
	      #10  Read	Console	Buffer
	      #11  Get Console Status
	      #12  Return Version Number
	      #13  Reset Disk System
	      #14  Select Disk
	      #15  Open	File
	      #16  Close File
	      #17  Search for First
	      #18  Search for Next
	      #19  Delete File
	      #20  Read	Sequential
	      #21  Write Sequential
	      #22  Make	File
	      #23  Rename File
	      #24  Return Log-In Vector
	      #25  Return Current Disk
	      #26  Set DMA Address
	      #27  Get Addr(Alloc) (dummy)
	      #28  Write Protect Disk
	      #29  Get Read-Only Vector
	      #30  Set File Attributes (dummy)
	      #31  Get Addr(Diskparams)	(dummy)
	      #32  Get/Set User	Code (dummy)
	      #33  Read	Random
	      #34  Write Random
	      #35  Compute File	Size
	      #36  Set Random Record
	      #37  Reset Drive
	      #40  Write Random	with Zero Fill
	      #49  Get/Set System Control Block	(CP/M 3)
	      #101 Return Directory Label Data (CP/M 3)
	      #102 Read	File Date Stamps and Password Mode (CP/M 3)
	      #105 Get Date and	Time (CP/M 3)
	      #108 Get/Set Program Return Code (CP/M 3)
	      #141 Delay (MP/M)

       BDOS  function #49 (Get/Set System Control Block) is only partially im-
       plemented: Attempts to write to the SCB are silently ignored, and  only
       the  SCB	 offsets  0x05	(BDOS  version number, always 0x22), 0x10-0x11
       (program	return code), 0x1a (console columns),  0x1c  (console  lines),
       0x37  (output delimiter,	always 0x24), 0x3c-0x3d	(current DMA address),
       0x3e (current disk), 0x44 (current  user	 number),  and	0x4a  (current
       multi sector count, always 1) provide meaningful	information (all other
       byte offsets return 0).

       BDOS function #102 (Read	File Date Stamps and Password Mode) always re-
       turns  the  access  and	modification timestamps	of the underlying Unix
       file, and function #101 (Return Directory Label	Data)  correspondingly
       always returns a	value of 0x61.

       BDOS  function  #141 (Delay) delays program execution for the number of
       system clock ticks passed in register DE; tnylpo	defines	a tick to last
       20 milliseconds,	i.e. it	emulates a ticker frequency of 50 Hertz.

       In addition to the BDOS calls, tnylpo implements	all BIOS calls of CP/M
       2.2, but	all disk related functions are dummies:

	      BOOT	System Cold Start Initialization
	      WBOOT	Warm Start
	      CONST	Console	Input Status
	      CONIN	Console	Character Input
	      CONOUT	Console	Character Output
	      LIST	Printer	Character Output
	      PUNCH	Paper Tape Punch Output
	      READER	Paper Tape Reader Input
	      HOME	Recalibrate Disk Drive (dummy)
	      SELDSK	Select Disk Drive (dummy)
	      SETTRK	Set Track Number (dummy)
	      SETSEC	Set Sector Number (dummy)
	      SETDMA	Set DMA	Address	(dummy)
	      READ	Read Selected Sector (dummy)
	      WRITE	Write Selected Sector (dummy)
	      LISTST	Printer	Output Status
	      SECTRAN	Sector Number Translation (dummy)

       No additional BIOS calls	from CP/M 3 have been implemented, not even as
       dummies,	i.e. any attempt to call them will result in undefined program
       behaviour.

   Program termination
       tnylpo terminates as soon as the	CP/M program it	executes terminates by
       either calling BDOS function #0 (System Reset) or BIOS function	WBOOT;
       jumping	to address 0x0000 or using the stack area set up by tnylpo and
       ending execution	by a RET instruction is	 equivalent  to	 calling  BIOS
       function	 WBOOT	directly. Finally, the user may	terminate a program by
       pressing	^C (0x03) when prompted	for console input by BDOS function #10
       (Read Console Buffer). All these	forms of program termination are  con-
       sidered	regular	 for  the  purpose of determining the exit status from
       tnylpo (see below, under	EXIT STATUS).

       Furthermore, a CP/M program will	be terminated if it performs an	action
       considered illegal by tnylpo, like executing a HALT instruction,	trying
       to write	to a read-only file or to a file on a disk configured as read-
       only, passing invalid arguments to system calls,	accessing a disk drive
       not configured, or requesting an	illegal	sequence of  operations	 (like
       trying to read from a disk file which has already been closed).

       When  the full screen console is	active,	a program may be terminated by
       the user	pressing the F10 key (see above,  "Function  keys");  this  is
       equivalent to sending a SIGINT to tnylpo	from another terminal/terminal
       window.	Pressing  F10  terminates the CP/M program abruptly and	should
       (like sending a signal to tnylpo) only be used as a  last  resort  when
       dealing with a hung application.

       Both  program  termination  due	to an illegal action and terminating a
       program by pressing F10 (or sending tnylpo a signal) are	considered ir-
       regular forms of	program	termination.

EXIT STATUS
       tnylpo exits with status	1 if it	encountered a fatal error and status 0
       otherwise. Fatal	errors are command line	errors,	configuration file er-
       rors, or	an irregular termination of the	CP/M program (see above).

       CP/M-80 version 2.2 has no concept of a program exit status,  so	 there
       is  no  well-established	way of communicating an	unsuccessful CP/M pro-
       gram execution to the Unix  environment.	 To  alleviate	this  deficit,
       tnylpo implements BDOS function #108 (Get/Put Program Return Code) from
       CP/M  3;	 if a CP/M program sets	its return code	to a value in the "un-
       successful return" range	(0xff00-0xfffe)	prior to  termination,	tnylpo
       will exit with status 1.

FILES
   ./.tnylpo.conf
       The  file .tnylpo.conf in the current working directory is used as con-
       figuration file,	if it is present and no	configuration  file  has  been
       specified on the	command	line.

   ~/.tnylpo.conf
       The file	.tnylpo.conf in	the user's home	directory is used as a config-
       uration file, if	it is present, if no configuration file	has been spec-
       ified  on the command line, and if there	is no file .tnylpo.conf	in the
       current working directory.

       Using configuration informations	from a file in the current working di-
       rectory (./.tnylpo.conf)	is convenient in many situations, but poses  a
       potential  security risk; mainly	for this reason, tnylpo	refuses	to run
       if its effective	user ID	is 0.

NOTES
   Differences between tnylpo and CP/M-80
       By design, there	are some incompatibilities between CP/M-80 and the em-
       ulation provided	by tnylpo:

   Direct access to the	BDOS and BIOS areas
       Since it	doesn't	contain	any actual CP/M	code, all programs  trying  to
       patch  the  BDOS	 or otherwise make assumptions about the layout	of the
       operating system	or its internal	data structures	will fail  while  run-
       ning on tnylpo.

       BDOS  and  BIOS	function  emulations  are  activated  by the simulated
       processor executing a RET instruction fetched from one of the uppermost
       19 addresses of the CP/M	memory space (0xffed for the BDOS entry,  0xf-
       fee to 0xfffe for the 17	BIOS entries of	CP/M-80	2.2 and	0xffff for one
       tnylpo-specific	delay  routine hiding as 18th BIOS entry); this	use of
       "magic addresses" might confuse debuggers trying	to trace system	calls.

       The BIOS	area (starting	three  bytes  before  the  address  stored  at
       0x0001)	is page-aligned	and contains the 17(+1)-element	BIOS jump vec-
       tor, the	dummy disk structures (see below) and the above	 mentioned  19
       RET  instructions.  The	BDOS  area  (starting at the address stored at
       0x0006) is even shorter,	containing only	a jump to 0xffed and the table
       of target addresses for the four	fatal BDOS error  conditions  (non-ex-
       isting  disk, bad sector, read-only disk, and read-only file; these ad-
       dresses may be modified by an application program, but  are  completely
       ignored by tnylpo). Any program expecting the BDOS or the BIOS areas to
       have the	sizes and alignment characteristics of a real CP/M-80 environ-
       ment will be disappointed.

       The  OS	serial	number	stored in the six bytes	immediately before the
       BDOS area is always 0x00	0x16 0x00 0xc0 0xff 0xee, a  (hopefully	 inof-
       fensive)	dummy indicating BDOS version 2.2.

   Direct access to the	disk drives
       All  programs  trying  to access	the CP/M disk structure	directly (e.g.
       disk editors) will not work, since there	is  no	underlying  CP/M  disk
       structure (tnylpo translates FDOS calls into operations on Unix files);
       all  disk  related BIOS calls are implemented as	dummy functions	(those
       few which can return an error indication	--SELDSK,  READ,  and  WRITE--
       will  do	 so).  The BDOS	functions returning disk structure related in-
       formation (#27 and #31) will return dummy structures  containing	 mean-
       ingless (but consistent)	data; for example, all disk drives will	be re-
       ported as having	a block	size of	16KB, 2048 directory entries and a ca-
       pacity  of  8MB,	 of  which 8128KB (8MB less four directory blocks) are
       free (to	save space, all	drives share the same dummy allocation vector,
       which is	of course impossible with real CP/M-80). All block information
       returned	by the BDOS functions #17 and #18 is  meaningless;  regardless
       of the contents of the S2 field (FCB offset 14),	all otherwise matching
       files  are  returned  only once (as opposed to once per physical	extent
       under CP/M-80). Likewise, all block information in  the	FCBs  of  open
       files  (FCB  byte offsets 16 to 31) is meaningless (but may not be dis-
       turbed since tnylpo stores some state information  there,  see  below).
       The  emulation is good enough for programs searching for	file name pat-
       terns or	just listing the disk directory, but will fail for those  try-
       ing  to	analyse	 the block structure of	the emulated disk from the re-
       turned information.

   Console Command Processor
       tnylpo doesn't emulate the CCP, so every	program	using its features (by
       e.g. creating a $$$.SUB file and	expecting the CCP to execute its  con-
       tents) will not work correctly. Ending a	program	by simply returning to
       the  CCP	 is  supported;	tnylpo initializes an 8	level CCP stack	at the
       end of the TPA (below the OS serial number) and pushes the  address  of
       the  WBOOT  entry  in the BIOS vector, so a program trying to return to
       the CCP will terminate correctly.

   File	attributes
       File attributes (read-only and system attribute resp. the four  attrib-
       utes available for user programs) are not supported by tnylpo; the cor-
       responding BDOS function	#30 is a dummy.	File names characters will al-
       ways be returned	with the most significant bits reset.

   User	areas
       The  concept of user areas is not implemented by	tnylpo;	while the user
       code may	be set by  BDOS	 function  #32	(and  will  be	returned  when
       queried), this has no influence on file operations.

   I/O byte
       Likewise,  the I/O byte functionality is	not implemented; while the I/O
       byte may	be queried and set (by BDOS functions #7 and #8) and is	stored
       in address 0x0003, it has no influence on the character devices.

   FCB structures
       FDOS calls are translated into Unix file	operations. For	this to	 work,
       tnylpo  maintains  a  separate list of corresponding Unix files;	refer-
       ences to	the entries of this list are stored in the FCBs	of  open  CP/M
       files  (a 16 bit	reference number is stored at offsets 16 and 17	in the
       FCBs, and the same number XORed by 0xafcb is stored at offsets  18  and
       19).  This  allows  programs to copy the	FCBs of	open files and use the
       copies to further access	the same files (e.g. programs written in Turbo
       Pascal do such things). The drive and file name portions	of a  FCB  are
       only  referenced	 by  BDOS functions #15, #17, #19, #22,	#23, #30, #35,
       and #102, all other functions (especially the read and write functions)
       use the file reference number to	identify the relevant Unix  file.  The
       current record number in	sequential I/O operations is stored in the FCB
       fields EX, S2, and RC (offsets 12, 14, and 32).

   Sparse files
       Since CP/M file operations are directly mapped to Unix file operations,
       some characteristics of Unix files are visible to CP/M programs running
       on  tnylpo:  Trying  to	read a record within an	unwritten block	in the
       middle of a sparse file would result in an  error  indication  (reading
       unwritten  data)	 under	CP/M-80,  but  simply returns a	record of zero
       bytes on	tnylpo,	since unallocated areas	in the middle of a  Unix  file
       read  as	 zero.	Hopefully, few programs	will take offence at this dif-
       ference.

   File	closing
       Normally, closing a file	in a CP/M program  (BDOS  function  #16)  will
       cause tnylpo to close the corresponding Unix file and free its entry in
       the  file  list.	 This causes problems with certain CP/M	software (e.g.
       dBase II), which	continue to use	FCBs for file operations after calling
       BDOS function #16. Since	the close operation just  writes  the  updated
       FCB  data back to the disk directory (but doesn't change	the FCB), this
       is possible in CP/M-80 (though a	little dirty in	my opinion).  Contrar-
       ily,  tnylpo  (in  addition to closing the corresponding	Unix file) re-
       moves its file reference	from the FCB, thereby marking  it  as  invalid
       for  further  I/O, causing subsequent operations	by the CP/M program to
       fail.

       To accommodate such programs, tnylpo provides the -n command  line  op-
       tion  (and the corresponding close files	= false	configuration option),
       which prevent closing the Unix file and	removing  the  file  reference
       from  the FCB (effectively making BDOS function #16 a dummy operation).
       If many files are opened	(sequentially or concurrently) by a CP/M  pro-
       gram,  this  may	cause tnylpo to	run out	of files, since	the closing of
       all Unix	files is deferred until	program	termination.

   Text	file format
       Disk file I/O is	always done untranslated, i.e. the  contents  of  disk
       files written by	programs running on tnylpo are always in the character
       set  used internally by the CP/M	emulation. Likewise, the line end con-
       vention in text files is	that of	CP/M (^M^J, 0x0d 0x0a) and text	 files
       not  ending exactly at the end of a 128 byte CP/M file record will con-
       tain a ^Z (0x1a)	byte as	logical	EOF marker (ideally,  they  should  be
       padded  with  ^Z	 bytes	to the next record border, but in reality they
       usually end in a	single ^Z followed by arbitrary	rubbish). This must be
       taken into account when using Unix utilities to process files generated
       by tnylpo.

       On the other hand, text files generated under Unix should be  converted
       to  the	CP/M  line end convention before processing them with programs
       running on tnylpo (the command set ff=dos might come handy  for	people
       using  Vim!).  The  CP/M	convention for marking the logical end of text
       files is	honoured automatically,	since  tnylpo's	 BDOS  emulation  pads
       Unix files to the CP/M record size of 128 bytes with ^Z bytes.

       Text  file conversion between the Unix and the CP/M formats may be done
       conveniently using the companion	program	tnylpo-convert(1).

   Performance
       tnylpo has been optimized for portability, not  for  performance;  some
       parts of	the processor emulation	(e.g. the addition and subtraction op-
       erations)  may be ridiculously inefficient compared to a	hand-optimized
       assembler version (or even a C version making moderate use of  platform
       specific	 things	like byte order	or number representation). On the plus
       side, tnylpo should compile and run on every Unixy platform  supporting
       ISO  C99	 (for  wide and	multibyte character support), a	wide character
       capable version of the ncurses library and int variables	with more than
       16 bits.	That said, I found tnylpo blindingly fast compared to the real
       thing even on the outdated hardware I used for its development.

   The delay routine
       Since CP/M-80 version 2.2 offers	no functions for time keeping  or  de-
       lays, programs are forced to use	the cycle time of certain instructions
       in  combination with the	CPU clock frequency if they need to delay pro-
       gram execution; this approach is	doomed under an	 emulator,  especially
       if it is	running	on a multiprogramming system.

       To  allow  CP/M	programs to delay execution for	a defined (wall	clock)
       time period, tnylpo supplies a delay routine masquerading as 18th  BIOS
       entry: it expects a single parameter, an	unsigned 16-bit	number in reg-
       ister  BC,  and	waits  this  many milliseconds before returning	to the
       caller.

       The benefit of this routine is at best limited, but most	likely	nonex-
       istent;	since  it  is  an extension, no	existing CP/M application (for
       which tnylpo has	been created in	the first place) uses it, and even  in
       case somebody would develop new CP/M software, employing	tnylpo's delay
       function	would break compatibility with all other CP/M machines or emu-
       lators.

       As  an  alternative,  tnylpo  implements	function #141 (Delay) from the
       MP/M BDOS; while	this function  is  a  little  more  standardized  than
       tnylpo's	 proprietary extension,	it is equally unavailable on real CP/M
       and most	compatible systems and suffers from  the  additional  drawback
       that  it	 measures time in system timer ticks, which are	implementation
       dependent (tnylpo emulates a tick length	of 20 milliseconds, i.e. a  50
       Hertz timer).

   The name of the program
       "tnylpo"	 is  a fantasy word. Neither is	it an acronym nor does it have
       any meaning I know of (which is the main	reason I chose it).   "tnylpo"
       is  pronounced  like  a native speaker of German	(e.g. I) would naively
       pronounce "tnulpo" (or  like  a	speaker	 of  Finnish  would  pronounce
       "tnylpo",  provided she survives	the initial consonant cluster).	In its
       formation, "tnylpo" with	its two	syllables and ending in	 "-po"	aligns
       nicely  with  other  nonsense  words I invented earlier (like "ilpo" or
       "sampo")	--until	I moved	to Finland and discovered that most  of	 these
       supposed	nonsense words have currency here...

BUGS
       See the remarks under NOTES. Most of them may be	interpreted as bugs in
       the implementation, including the program name.

   Character set switching
       A  program  running in full screen mode (VT52 emulation)	may change its
       display character set from the primary character	set to	the  alternate
       set  and	back by	issuing	an appropriate escape sequence.	This switching
       also affects the	character set translation of the other	character  de-
       vices (LST:, PUN:, and RDR:), unless they are operating in raw mode.

   Character redefinition
       It  is  not recommended to redefine any of the characters which may ap-
       pear in CP/M  file  names,  their  Unix	equivalents  or	 in  the  file
       name/file  extension fields of an FCB; these include the	decimal	digits
       (0x30-0x39), the	 upper-	 and  lower  case  characters  (0x41-0x5a  and
       0x61-0x7a),  space  (0x20),  dollar sign	(0x24),	asterisk (0x2a), minus
       (0x2d), dot (0x2e), colon (0x3a), and the question mark (0x3f).

   Host	system locales
       tnylpo has been implemented with	the intention to work with all	possi-
       ble Unix	CTYPE locale settings (other aspects of	the current locale are
       ignored);  unfortunately, only ASCII based systems and locales are sup-
       ported, since there is no character set independent  way	 to  represent
       some  of	 the  control  characters relevant for CP/M (e.g.  ^C and ^Z).
       Currently, tnylpo always	assumes	that the character codes 0x00-0x1f and
       0x7f of the host	operating system single- or  multibyte	character  set
       correspond  to  the  ASCII control characters. Frankly, tnylpo has only
       been extensively	tested to work with UTF-8 based	locales.

   File	namespace clashes
       tnylpo tries to hide unsuitable files in	host directories used as  CP/M
       drives  from CP/M programs; file	searches and open requests will	ignore
       everything but regular files up to 8MB in size  which  have  acceptable
       names.  Unfortunately, this attempt at hiding other objects is far from
       perfect:	a CP/M program trying e.g. to create a file whose name matches
       the name	of a (hidden) directory	will mysteriously fail (a rename oper-
       ation may meet similar problems). It is therefore  recommended  to  re-
       serve directories used as CP/M drives to	conforming regular files or to
       give all	other objects names not	acceptable as CP/M file	names (a lead-
       ing dot may work	wonders!).

   Color limitiations
       The  color support in tnylpo's terminal emulation is constrained	by the
       capabilities of the ncurses library  resp.  of  the  display  hardware.
       These  may  cause  a  limitation	of the number of combinations of fore-
       ground and background colors (color pairs) which	may  be	 used  on  the
       display simultaneously. If tnylpo runs out of color pairs, the affected
       combinations  will revert to the	default	foreground and background col-
       ors. This problem should	only occur  with  pathological	("angry	 fruit
       salad") user interface designs.

EXAMPLES
       tnylpo -f ws.conf ws hugo.txt

       will  use  the  configuration  file ws.conf and run the program ws.com,
       passing it the string hugo.txt as command line parameter.

       If the file ws.conf contains the	following lines

	      #
	      #	WordStar configuration
	      #
	      drive a =	"."
	      printer file = "./printer.txt"
	      printer mode = text
	      logfile =	"./.tnylpo.log"
	      loglevel = 0
	      #
	      #	use German character set
	      #
	      charset =	ascii
	      char 0x40	= "<section>"
	      char 0x5b	= "A"
	      char 0x5c	= "O"
	      char 0x5d	= "U"
	      char 0x7b	= "a"
	      char 0x7c	= "o"
	      char 0x7d	= "u"
	      char 0x7e	= "ss"
	      unprintable = "?"
	      console =	full
	      lines = 24
	      columns =	80
	      application cursor = true
	      screen delay = 2

       tnylpo will search for ws.com (and other	files) in the local directory,
       which will be used as drive A in	the emulation;	console	 I/O  will  be
       handled	in  full screen	mode by	the VT52 emulation which uses a	screen
       of 24 lines of 80 columns.  The cursor keys will	be  translated	to  ^E
       (up),  ^S (left), ^D (right), and ^X (down), and	the character set will
       correspond to the German	ISO/IEC	 646  variant  (umlaut	characters  in
       place  of  the  brackets	 and curly braces of ASCII). Characters	in the
       range of	0x80 to	0xff will be displayed	as  inverted  question	marks.
       Printer output will be written to printer.txt in	the current directory,
       will be in the Unix character set and will follow Unix line end conven-
       tions.	A log will be appended to .tnylpo.log in the current directory
       and will	contain	error messages only. After program termination,	tnylpo
       will wait for two seconds before	resetting the screen.

   Patching a CP/M executable
       Many CP/M applications do not supply installation programs but rely  on
       the user	applying (hopefully well-documented) binary patches to support
       e.g.  the control sequences of a	particular video terminal. Under CP/M,
       this is usually done using a debugger (e.g.  DDT) in  combination  with
       the CCP built-in	command	SAVE.  The following example shall demonstrate
       the process of patching an executable using tnylpo:

	      $	ls -la
	      total 72
	      drwxr-xr-x   7 tnylpo  users   224 Sep  5	13:04 .
	      drwxr-xr-x  39 tnylpo  users  1248 Sep  5	13:04 ..
	      -rw-r--r--   1 tnylpo  users  8192 Sep  5	13:02 asm.com
	      -rw-r--r--   1 tnylpo  users  4864 Sep  5	13:02 ddt.com
	      -rw-r--r--   1 tnylpo  users  2091 Sep  4	13:08 patch.asm
	      -rw-r--r--   1 tnylpo  users  9728 Sep  5	13:02 wm.com
	      -rw-r--r--   1 tnylpo  users  2688 Sep  5	13:02 wm.hlp

       wm.com is the binary to be patched (wm.hlp is an	associated data	file).
       asm.com and ddt.com are the standard CP/M absolute assembler and	debug-
       ger  (ASM and DDT) which	will be	used to	prepare	resp. apply the	patch.
       patch.asm contains the assembler	source file of	the  patch.  Note  the
       size of wm.com, which is	9728 bytes.

       First,  the  patch is assembled,	which creates patch.hex, a file	in the
       Intel Hex format.

	      $	tnylpo asm patch
	      CP/M ASSEMBLER - VER 2.0
	      01D8
	      000H USE FACTOR
	      END OF ASSEMBLY

       Now the debugger	is started, which relocates itself to the top  of  the
       TPA and loads wm.com into the TPA starting at address 0x100. The	option
       -eb9728:wmnew.com  asks	tnylpo to save 9728 bytes (the size of wm.com)
       starting	from address 0x100 to the file wmnew.com after the  CP/M  pro-
       gram (i.e.  DDT)	has terminated.

	      $	tnylpo -eb9728:wmnew.com ddt wm.com
	      DDT VERS 2.2
	      NEXT  PC
	      2700 0100

       DDT  displays  two hexadecimal numbers, the first of which is the first
       free memory address after the loaded program (0x2700 is	decimal	 9984,
       i.e.  0x100  plus  9728,	the size of wm.com).  Now DDT is used to apply
       the patch: The command i	tells DDT the name of the patch	file, and  the
       command	r reads	it into	memory (the Intel Hex format provides the nec-
       essary address information to apply the changes at  the	correct	 loca-
       tions).	 Finally,  g0 directs DDT to jump to adress 0, which causes it
       to terminate.

	      -ipatch.hex
	      -r
	      NEXT  PC
	      2700 0000
	      -g0

       As soon as DDT terminates, tnylpo saves	the  memory  contents  as  di-
       rected,	creating  a  patched  version  of the executable, which	can be
       tested and renamed.

	      $	ls -la wmnew.com
	      -rw-r--r--   1 tnylpo  users  9728 Sep  5	13:06 wmnew.com

AUTHOR
       tnylpo and its manual page were written by Georg	Brein (tnylpo@gmx.at),
       a programmer, IT	systems	administrator and guerrilla egyptologist.

SEE ALSO
       tnylpo-convert(1)

       The implementation of the Z80 processor emulation,  especially  of  the
       features	not covered by the official documentation (Zilog Inc., Z80 CPU
       User  Manual, Revision 11: August 2016 [UM008011-0816]),	is heavily in-
       fluenced	by Sean	Young's	The Undocumented Z80 Documented	(Version 0.91,
       18th September 2005).

       The CP/M-80 2.2 system interface	emulation is based on the CP/M Operat-
       ing System Manual by Digital Research (Third Edition: September 1983).

       Some additional system functions	are based on their descriptions	in the
       CP/M Plus (CP/M Version 3) Operating System Programmer's	Guide by Digi-
       tal Research (Second Edition: April 1983).

				  2021-04-28			     tnylpo(1)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=tnylpo&sektion=1&manpath=FreeBSD+Ports+15.0>

home | help