.TF     Target File

Syntax:

        .TF  [filename.ext [,format [,expression]]]

See also:

.CP   .EF   .LF   .LI   .SF   .TW  

Function:

With the .TF directive you can open a target file in any of the available formats. This target file will be filled with the generated object code of your program.

Boundary Sync:

In Version 3 of the SB-Assembler this directive will perform a boundary sync.

Explanation:

The .TF directive, without parameters, will close an already open target file. Nothing will happen if no target file is open at that time.
If you want to include a comment behind an empty .TF directive a semicolon should precede this comment.

If a filename does follow the .TF directive an already open target file will also be closed. Then a new target file is created with the name filename. If that file already exists its length will be reduced to zero, effectively overwriting the file without prior notice!
As usual the filename may be preceded by a drive letter and legal path name, obeying the file name rules of your operating system. The SB-Assembler will NOT provide a default extension with target files if you don't provide one. If you omit the extension .ext the created filename will simply not have an extension.

Some target file formats have only a 16 bit address range. Therefore you can not create programs that are larger than 64k bytes. This means that if you start your program at $F000 your program can't be any bigger than 4 k bytes!
There is no limit to the number of target files used during one assembly run. You can have as many target files filled with part of your program as you like. Only one of those target files will be open at any given time. Every time you open a new target file the previous one is closed.

Other target file formats allow you to create programs of up to 4G bytes, which will be sufficient for the next few years from now ;-)
The unformatted files BIN and HEX don't have an address field and can grow as large as your file system allows it.
Motorola has designed 3 different file formats, each with their own limit to file size. The address range for the S19 format is only 64k bytes and so is the maximum file size. For format S28 the maximum address range is 16M bytes (24 bits address). Finally the maximum file size for the S37 format is 4G bytes (32 bits address).
The FPC file format is standard equipped with a 32 bit address range, so that file format is automatically capable of handling file sizes of 4G bytes.
The Intel Hex file format originally has an address range of only 64k bytes. When Intel noticed that this was not enough they invented some extensions to overcome this 64k limit.
The first method of having larger file sizes was the use of segments, like in 80x86 processors. Every segment still can hold up to 64k bytes. But at every 16 byte interval you can start a new segment of 64k again. This could be quite useful for 80x86 processors, but is particularly difficult to handle for other processors because program counter and target address will be out of sync without obvious relation. The maximum target file size for segmented Intel Hex files is 1M bytes.
The second solution they came up with at Intel is somewhat easier to comprehend. This solution uses linear segments. Again every segment is still 64k bytes long. But at the end of this segment a new linear segment is started. Up to 64k segments of 64k bytes each can be used, which in fact is a 32 bit addressing range resulting in a maximum target file size of 4G bytes.
The SB-Assembler can handle linear segmented Intel Hex files. Every time a segment boundary is crossed a new segment is started automatically.

Please note that all bytes generated by the program will be lost when no target file is open yet.

Warning: If the file filename already exists its contents will be erased and overwritten without prior notice.

In Version 2 of the SB-Assembler it is also possible to send the target file to a device, instead of to a file. That way you can send your object code directly to a programmer or EPROM simulator. A device name should always end in a colon. All MS-DOS device names are allowed like PRN:, LPT1:, COM1:, NUL:. Avoid sending the object file to the screen (CON:) however, it will only cause a lot of gibberish to be displayed there.

The file format following the filename is optional. If it is not provided the default BIN format is used.

Please note: The .OR directive will close the unformatted file types BIN and plain HEX immediately because they don't support an address field. Please specify the start of the program before opening the target file if you intend to use one of these two file formats. If, for any reason, you do have to change the start address of the next code you can always use the .NO directive in stead.
With all other file formats you may change the program address as often as you like.

These are the possible file format names:

AP1Apple 1 format
BINBinary format
E52Elektor EMON52 format (not a standard format!)
HEXHexadecimal format (every byte is translated to 2 hexadecimal digits coded in ASCII)
S19Motorola S19 format (64 kb range)
S28Motorola S28 format (16 Mb range)
S37Motorola S37 format (4 Gb range)
INTIntel Hex format (No opening segment if segment 0)
INSIntel Hex format (Always opening segment included)
SIGSignetics format
TEKTektronix format
MOSMOS Technology format (as of version V3.03.02)
FPCFour Packed Code format

What format you can use best depends on the capabilities of your EPROM programming tools. I prefer the FPC format because it produces the most compact formatted target files. Unfortunately not many EPROM programmers support that format though.
The desired format is entered behind the filename, separated by a comma. Your choice is made by entering one of the 3 letter format names shown above.
The difference between the INT and INS formats applies only to the very first line sent to the target file. If the first address of your target file requires a segment of 0, the INT format will not include a segment definition line in your target file. This is useful for programs that don't grow larger than 64k, no segmentation is required there anyway. If you use the INS format the first line of the target file is always a segment address definition, even if it is segment 0.

The format identifier may also be followed by an expression, separated from the format by an other comma. This expression defines the maximum number of data bytes you want to have on each line in your target file. Only BIN files don't provide for this because they don't consist of lines.
Legal values for expression range from 8 to 32. Lower values will be increased to 8, higher values will be reduced to 32, without warning. If the optional expression is omitted the default line length will be 16 data bytes long.

The syntax of the .TF directive will only be checked during pass 2 of the assembling process. An existing file with the name filename will not be erased and overwritten before pass 2. So if any errors are encountered during pass 1 the old target file(s) will still exist unchanged.

All errors that occur in the parameter field of the .TF directive will result in a fatal error message to be reported. This will stop the assembly process immediately.

Examples:

         .TF   C:\OBJ\TARGET.BIN     Open BIN file (BIN is default)
         .TF   C:\OBJ\TARGET         Open BIN file (no extension)
         .TF   TARGET.BIN,BIN        Open BIN file
         .TF   TARGET.TXT,AP1,8      Open Apple 1 format
         .TF   TARGET.HEX,E52        Open EMON52 file
         .TF   TARGET.HEX,HEX        Open HEX file
         .TF   TARGET.INT,INT,32     Open INT file (32 bytes/line)
         .TF   TARGET.INT,INS        Open INS file
         .TF   TARGET.MOT,S19,8      Open S19 file (8 bytes/line)
         .TF   TARGET.MOT,S28        Open S28 file
         .TF   TARGET.MOT,S37        Open S37 file
         .TF   TARGET.SIG,SIG,0      Open SIG file (8 bytes/line)
         .TF   TARGET.TEK,TEK,100    Open TEK file (32 bytes/line)
         .TF   TARGET.MOS,MOS,       Open MOS Technology file
         .TF   TARGET.FPC,FPC        Open FPC file
         .TF   TARGET.MOT,INT        Confusing, but legal
         .TF   TARGET.BIN,BIN,10     Legal, but length irrelevant
         .TF                         ; Close previous target file
         .TF   COM1:,INT,32          Send object to COM1:

Note on the Apple 1 format:

Vince Briel started some sort of Apple 1 fever around the 30th anniversary of this legendarily computer. The original Apple 1 has only the cassette recorder as mass storage. However it is possible to expand the original Apple 1 with a serial interface and several replica versions are standard equipped with a similar serial interface.
All these serial interfaces have one thing in common: Everything received is literally "typed" to the Apple 1. This behaviour allows us to simply send a file to the Apple 1. And that is exactly what the Apple 1 format is meant for. Each line starts with an address, followed by a colon, which is then followed by the data bytes. Just like you would have done to manually type the code to the Apple 1.

Note for Apple // programmers

Retro computing is really hot again. I can understand that, it's like going back to your youth, and the Apple // was part of my youth too. And the good thing is that you don't need the original hardware anymore to relive those days of your distant past. There are literally dozens of emulators to choose from to take you back in time. One of them can even be run inside your browser, so you don't have to install anything.

Anyway, I know a few people who are creating new programs for Apple // computers. The SB-Assembler, together with one of the available emulators, are great tools to write these programs making use of all the modern conveniences, like a decent text editor, fast assembler, version control, etc. Probably the easiest way to get your programs across to the emulator is by creating an Apple binary file, copy it to an Apple compatible disk image, mount that image to your emulator and run the program.
Writing an Apple // binary file is quite easy, once you know how. For starters you should write to a BINary target file, what a surprise. However there are few more things you need to know:

  • A 4 byte header must precede the binary data in your binary file.
  • The first two bytes represent the load address of the binary file.
  • The next two bytes represent the file length, i.e. the number of data bytes the file contains.
  • The file length should not exceed 32767 bytes.

Here's an example on how to write your code to a binary file which can directly be copied to an Apple // disk image.

    .CR     6502            Goes without saying, doesn't it?
    .OR     $2000-4         Let's start our example at addess $2000
    .TF     EXAMPLE,bin     No need to define a file extension

    .DA     PROG_BEGIN      Write the target address to the bin file
    .DA     PROG_END-PROG_BEGIN   Write the length to the bin file

PROG_BEGIN  ;               The intended target address of $2000
    LDA     ......
     :                      Your program goes here
     :
     :
    RTS                     Until here
PROG_END

Here's what's happening. At first we define the starting point of our program, minus 4. The -4 is important, because we shouldn't count the loading address and file length bytes to our program. Then we open a normal binary target file. Naming this target file may be a bit tricky due to OS differences and the naming conventions used by the Apple //. Anyway, to keep it simply I deliberately used capital letters and avoided using spaces or other special characters. I also didn't specify a file extension. Normally you would want to add .bin as file extension, but that is purely for us humans, you can name the file anything you like.
And next the magic happens. Two words are written to the binary file. The first word is the target address of the program, you know the place where BLOAD or BRUN start dumping the bytes. The second word is the length of the program. This is simply calculated on the spot by subtracting the end of the program from the beginning of it. No check is made if the program length exceeds 32767 bytes here, but you can add that yourself using an .ER directive together with some conditional assembly, if you really want to guild the lily.
That's it. Then you can start writing your program. By now the program counter is back at the intended starting point of $2000, in our example, because we already wrote the four bytes in the header. And don't forget to add the last label PROG_END, after the last line of code of your program.

Note for the MOS Technologies File Format For KIM-1 And SYM-1 Users

Up until SB-Assembler V3.03.06 the end of file record for the MOS Technologies target files just contained ;00. The SYM-1 monitor's paper tape reader routine was quite satisfied with that, because it simply stops reading from the paper tape as soon as it sees a record byte count of 0. On the other hand the KIM-1 monitor's paper tape reader routine is a bit more strict and would exit with an error when it finds the end of file record which just contains a 0 byte counter.

That's why I've altered the end of file record for the MOS Technologies file format as of SB-Assembler 3.03.07. Officially the 0 byte count of the end of file record should be followed by a 16-bit record counter, entered twice. For instance the official end of file record for a MOS file containing 300 records is ;00012C012C, where $012C is the number of records in the file.
The SYM-1 monitor is quite happy with this change, because it will simply stop interpreting the rest of the record as soon as it finds the byte count of 0. But because of a bug in the KIM-1 monitor it will still exit with an error in some cases. When the file is less than 256 records long, everything's OK. However for longer files things go wrong. Instead of the second record counter, the KIM-1 monitor expects a normal checksum of this record. That means that it expects ;00012C002D in the 300 line long file of our example (the bytes $01 and $2C added together).
B.T.W. the KIM-1 monitor only checks the checksum, it ignores the record counter all together. This means that the KIM-1 would have been quite happy if all files ended in ;0000000000.

As of SB-Assembler V3.03.07 the MOS Technologies file format ends with an end of file record which both the KIM-1 and SYM-1 will accept. After all I expect these are the two most often encountered use cases for the MOS Technologies file format these days. Thus, officially, the end of file record is not according to the specs. But that doesn't matter, as long as the KIM-1 is happy with it.

Please note that the KIM-1 might complain about the contents of the end of file record with the older implementation of the MOS Technologies file format. But in the mean time the data was transferred correctly anyway, despite the error message of the KIM-1.