The guide to writing WAV-PRG plugins

This archive should contain:

readme.txt    - This file

In directory pascal\

plugindef.pas   - Header file for writing plugins with Delphi
ld_turbotap.dpr - Source for ld_turbotap.dll
ld_zzap.dpr     - Source for ld_zzap.dll

In directory c\

plugindef.h         - Header file for writing plug-ins in C/C++
ld_kernel.dsw       - Visual C++ workspace for ld_kernel.dll and
                      ld_kernelheader.dll
ld_kernel.dsp       - Visual C++ project for ld_kernel.dll
ld_kernelheader.dsp - Visual C++ project for ld_kernelheader.dll
ld_kernel.c         - Source for ld_kernel.dll
ld_kernelheader.c   - Source for ld_kernelheader.dll

A WAV-PRG plug-in is a Win32 DLL which includes plugindef.pas (Pascal) or
plugindef.h (C/C++), and properly initializes the variable symbols. It can be
written in any language and built with any development environment. Included are
examples in Delphi and Visual C++.

The main feature in a WAV-PRG plug-in is the record/structure type ImportedSymbols.
Here are the definitions in Pascal and C:

(Pascal)

ImportedSymbols=record
    ImpulseLength:function:integer;
    FileHasEnded:function:boolean;
    WriteMessage:procedure(m:pchar;w:word=0);cdecl;
    ReadByte:function:byte;
    SeekForHeader:function:entry;cdecl;
    PluginName:pchar;
    ProvidesStartAddress:boolean;
    ProvidesEndAddress:boolean;
end;

(C)

typedef struct{
	int (* ImpulseLength)();
	char (* FileHasEnded)();
	void (* WriteMessage)(char* m,unsigned short int w);
	unsigned char (*ReadByte)();
	void (* SeekForHeader)(struct entry* found);
	char* PluginName;
	char ProvidesStartAddress;
	char ProvidesEndAddress;
} ImportedSymbols;

The type entry is defined as follows:

(Pascal)

entry=record
     startadd:word;
     endadd:word;
     name:array[0..15]of char;
end;

(C)

struct entry{
	unsigned short int startadd;
	unsigned short int endadd;
	char name[16];
};

These functions are provided by WAV-PRG:

ImpulseLength: this function takes no arguments and returns an integer. It reads
the WAV file and gives the number of samples (at 44100 Hz) between a trigger and
the previous one.

FileHasEnded: this function takes no arguments and returns a boolean/char. If it is
False/0, the WAV file has not ended yet, if it is True/1, the WAV file has ended
and the results coming from ImpulseLength are undefined. The plug-in should poll
this function, and quit if it returns True/1, so to avoid endless loops.

WriteMessage: this function takes two arguments, a pchar/char* and a word/short
integer, and returns no value. The string pointed to by the pointer is display in
the "Converting" window. If the integer is not 0, it will displayed at the end of
the string, otherwise it will not be displayed. The function is useful to display
warning messages, inform about checksum errors, show the start and the end address
etc. In Delphi, the second argument can be omitted: it will be assumed to be 0.

These functions should be provided by the plug-in:

ReadByte: this function takes no arguments and returns a byte/unsigned char.
It should read bytes from the WAV file (via the ImpulseLength function), taking in
account the data endianness and parity checks, if any. Subsequent calls to this
functions should return data bytes to be stored in the PRG/P00/T64 file. After a
valid header for the chosen file format has been found with the function SeekForHeader,
WAV-PRG calls this function <end address>-<start address> times, and each time it
writes the byte in the PRG/P00/T64 file being created. Checksums should be performed by
this function, too.

SeekForHeader: in Delphi, this function takes no arguments and returns a record of
type entry. In C/C++, it takes a ponter to a structure entry as the argument and
returns no value.
This function should scan the WAV file (via the ImpulseLength function) and return
when a valid header for the file format has been found, or when the flag FileHasEnded
has become true. After SeekForHeader has exited, a call to ReadByte should return the
first data byte. If a header has been found, the function should
* (Pascal) return a variable of type entry, filled with the file name, the start
  and the end address
* (C) fill the structure of type entry whose pointer has been passed as the
  argument with the file name, the start and the end address
WAV-PRG will read the file name, the start and the end addresses from the record/structure of type entry returned/filled by this function. If the file format does not provide a file name, the name field can be filled with anything: a string of 16 spaces is recommended. If the file format does not provide the start and/or the end addresses, WAV-PRG will ask the user for them, and will use the values provided by the user.

These variables should be initialized by the plug-in:

PluginName: this is a variable of type pchar/char*, which points to the string that
appears in the "Use plug-in" combo box.

ProvidesStartAddress: this is a variable of type boolean/char. It should be set to
True/1 if the file format provides a start address, otherwise to False/0. In the
latter case, the user will be asked for the start address before beginning the
conversion.

ProvidesEndAddress: this is a variable of type boolean/char. It should be set to
True/1 if the file format provides an end address, otherwise to False/0. In the
latter case, the user will be asked for the end address before beginning the
conversion.

In the header files, a variable called symbols, of type ImportedSymbols, is
declared. The author of the plug-in should:
- include the file plugindef.pas/plugindef.h
- implement the ReadByte and SeekForHeader functions
- initialize the variable symbols in the DLL's initialization code, by
 - assigning the correct pointers to functions to the fields ReadByte and
   SeekForHeader
 - setting the plug-in name in the PluginName variable
 - assigning the correct values to the variables ProvidesStartAddress and
   ProvidesEndAddress

WAV-PRG will:
- assign the correct pointers to functions to the fields ImpulseLength,
  FileHasEnded and WriteMessage
- if ProvidesStartAddress and/or ProvidesEndAddress are false, ask the user for the
  start and end addresses
- call the function SeekForHeader
- if the flag FileHasEnded is not true, it will begin the conversion: the name will
  be taken from the name field returned by SeekForHeader. If ProvidesStartAddress
  and/or ProvidesEndAddress are true, the start and/or the end addresses will be
  taken from the startadd/endadd fields returned by SeekForHeader, otherwise the
  values provided by the user will be used.
- call the function ReadByte <end address>-<start address> times, and store the
  resulting bytes in the output file.

This document is by Fabrizio Gennari (fabrizio.ge@tiscalinet.it), 1999.
Suggestions are welcome. If you write a plug-in, notify the author, so it can be
posted to WAV-PRG's page (http://www.geocities.com/SiliconValley/Platform/8224/wavprg.html)