Tunesmith
---------

Quick Reference, last revised 7/98

Version B -- Tunesmith is a major update to the old blahtune.

For latest binaries, documentation, and example tunes, visit
http://stratus.esam.nwu.edu/~judd/fridge/ 

Email: sjudd@nwu.edu

-----

Play saved tune from BASIC: SYS 4102

Warm restart: $6800  (SYS 26624)
		- Don't forget to set device # on a reboot!

Cold restart: $6803

------
Player
------

$1000	MAINPLAY	- The main player routine
$1003	PLAYINIT	- Initialize the player
$1006	SETIRQ		- Wedge player into current IRQ routine
$1009	LOADINST	- Load instrument (inst # in .X)
$100C	GETP		- Get field pointer for current voice (.A,.X = lo,hi)
$100F	SETP		- Set field pointer for current voice
$1012	V1GETP		- Get field pointer for voice 1 (.A,.X)
$1015	V2GETP
$1018	V3GETP
$101B	V1SETP		- Set field pointer for voice 1 (.A,.X)
$101E	V2SETP
$1021	V3SETP
$1024	RETURN		- Macro exit

$103D/E/F		- Voice 1/2/3 lookahead values

--------
Compiler
--------

Keywords
--------

Compiler is no longer case sensitive.

; 	Comment
<-	(Backarrow) Continue on next line (anachronism from when the text
	editor couldn't handle lines longer than 40 columns)

BADD/WADD    SRC > DEST   DEST + SRC -> DEST
BAND/WAND    SRC > DEST   DEST AND SRC -> DEST
BDEC/WDEC    ARG          ARG + 1 -> ARG
BDIV/WDIV    ARG          ARG/2 -> ARG          (think LSR)
BEOR/WEOR    SRC > DEST   DEST EOR SRC -> DEST
BINC/WINC    ARG          ARG - 1 -> ARG
BMOVE/WMOVE  SRC > DEST   SRC -> DEST
BMUL/WMUL    ARG          ARG*2 -> ARG          (think ASL)
BOR/WOR      SRC > DEST   DEST OR SRC -> DEST
BSUB/WSUB    SRC > DEST   DEST - SRC -> DEST
BTEST/WTEST  SRC > DEST   DEST - SRC   nothing is stored, just sets the flags

COMMENT      string       Place STRING directly into the code
DATA                      User defined label (Anachronistic)
DEF	     var string   DEFine a new variable (text substitution)
VAR VAR*n    var	  Create an n-byte variable at this spot
SUB	     var	  SUBroutine
SEND			  End subroutine
JSUB			  Call subroutine

DONE                      Halt macro
EMBED        byte byte ...Places bytes directly into code
ENTRY                     Set initial macro entry point
ILOAD        ARG          Load current voice with instrument number ARG
LOOP                      Repeat following code...
UNTIL        FLAG          ...until FLAG is true (set)
FOREVER                    ...forever (until macro is deactivated or restarted)
WAIT                      Return control to player routine
WHEN/LWHEN   FLAG         Execute block if FLAG is true
ELSE                      Execute block if FLAG is false
WEND                      End WHEN block

GETP         ARG          Place current field data pointer into ARG
SETP         ARG          Set current field pointer to ARG,ARG+1 (lo,hi)
V1GETP       ARG          Load specific field pointer into ARG,ARG+1
V2GETP                    .
V3GETP                    .
V1SETP                    Load ARG,ARG+1 into a specific field pointer
V2SETP                    .
V3SETP                    .

Flags:
        EQU NEQ POS NEG

Arguments:

        # #$ #%              - Immediate value
        $                    - Address
        ,ARG                 - Indexed mode
        + -                  - Offsets (example: SID+#2)
        &ARG                 - Additional destinations
	(ARG1 > ARG2) > ARG3 - "Uninvolved Operand"


Variables:

ATDK       attack/decay register for the current voice (SHADOW+#5,COFFSET)
COFFSET    SID offset (0 7 14) for current voice
CREG       control register for the current voice (SHADOW+#4,COFFSET)
CURFIELD   current field (global macros are field 0)
CURVOICE   current voice (1 2 3)
DATA       user-defined variable (anachronistic)
DUR        (remaining) duration of the current note for the current field
FLOTAB     table of the low bytes of frequencies
FHITAB     table of the high bytes of frequencies
FREQ       frequency of the current voice (word, SHADOW,COFFSET)
INST       instrument for the current field
NOTE       note value for the current field
PWIDTH     pulse width of the current voice (word, SHADOW+#2,COFFSET)
SHADOW     shadow SID maintained by the system
SID        the real SID, $D400
SUREL      sustain/release register for the current voice (SHADOW+#6,COFFSET)
V1STOP     if it is set to a nonzero value, voice will not be processed at all
V2STOP     .
V3STOP     .
G0, G1, ..., G15  Global variables.
L0, L1, ..., L7   Local variables.
M0, M1, ..., M31  Markers.

-------------
SID registers 
-------------

Offsets from $D400

(Voice 1)
$00,$01            Frequency, low/high byte

$02,$03            Pulse width, low/high byte (only bits 0..3 of $03 are used)

$04		   Voice 1 control register
      bits    0    gate bit (turn voice on/off)
              1    hard sync (synchronize to voice 3)
              2    ring modulation (modulate to voice 3)
              3    test bit (reset voice)
              4    triangle (waveforms)
              5    saw
              6    pulse
              7    noise

$05		   Attack/decay
      bits 0..3    decay (0-15)
           7..4    attack (0-15)

$06		   Sustain/release
      bits 0..3    release (0-15)
           7..4    sustain (0-15)

$07 - $0D          Voice 2 (same as above)
$0E - $14          Voice 3 (same as above)

$15-$16		   Filter cutoff
$15   bits 0..2    Low bits of cutoff frequency
           3..7    Unused
$16                High byte of cutoff frequency

$17		   Filter control register
      bits    0    Filter voice 1
              1    Filter voice 2
              2    Filter voice 3
              3    Filter external voice
           4..7    Filter resonance (0-15)

$18   bits 0..3    Main volume (0-15)
              4    Low pass filter
              5    Band pass filter
              6    High pass filter
              7    Disable voice 3 output

Read-only registers:
$19                X potentiometer
$1A                Y potentiometer
$1B                Voice 3 waveform
$1C                Voice 3 envelope


---
NED
---

shift-return        - Insert a new line
cursor keys, return - What you would expect
insert, delete      - Likewise
shift-clear         - Clear all text
home                - Move to top of file
F7                  - Load/save text file
run/stop	    - Quit

CTRL-a    - Delete characters to right of cursor
    -d    - Delete line
    -b/n  - Move to beginning/end of line
    -c/x  - Copy/cut lines to clipboard
    -p    - Paste line from clipboard
    -j/k  - Move 40 columns left/right (max 240 columns)
    -i/m  - Move 25 rows up/down
    -g    - Goto line #
    -z    - Compile to $E000
    - <-  - (Back-arrow) Quit


-----------------
Instrument Editor
-----------------
1,2,3		Select voice 1 2 or 3
a		Move to Attack
f		Move to Frequency
shift-f		Move to filter toggles

tspn		Toggle triangle/sawtooth/pulse/noise bits
gyre		Toggle gate/sync/ring/test bits

CRSR UP/DN	Quite obvious I think
Space		Toggle
+/-		Inc/Dec value
Shift +/-	Inc/Dec value by large amount
< >		Mult/Div value by 2 (pulse width, frequency, and cutoff)
shift-l		Load instrument
shift-s		Save instrument; press RETURN to keep current name
F1		Music editor
F5		Macro manager
(One key, * or Lira or some such, toggles the disable voice 3 output bit)


Macro Manager
-------------
CRSR UP/DN	Delete all files on current drive and reset computer
CRSR RT		Edit macro name
e or Return	Edit macro (NED)
a		Autocompile all macros upon exit from NED
c		Compile all macros
d		Delete macro
Shift-CLR	Delete all macros (may preserve names)
CTRL-p		Play song from beginning/Stop playing song
F1		Music editor
F3		Instrument editor
F7		Load/save macro bundle
F8		Load/save single file


Music Editor
------------

Flags:
  !  Singlekey mode
  "  Field display mode
  #  Raise next note
  $  Hex/decimal mode
  A  Audible mode
  T  Transpose mode
  R  Return mode

CRSR UP/DN,L/R 	Navigate
Return		Insert line and move cursor forward
Space		Accept current value
INST		Insert
DEL		Delete

0-7		Set default octave
Shift-1		Toggle single-keystroke mode
Shift +/-	Inc/dec default duration
+/-		Increment/decrement default octave
]/[		Inc/dec default macro
C=-[ C=-[	Inc/dec by large amount
#		Raise next note (#a same as a#)

Shift-2		Toggle field display mode (instructions or macro names)
Shift-4		Toggle number base (base 10/base 16)
Shift-6		Toggle status window display 
		  mode 0: System information
		  mode 1: Display macro names and default macro
		  mode 2: Display macro names and active macros
Shift-7		Toggle Return mode (insert CR after player instructions)

C=-1 through C=-4 Meta keys
CTRL -m		  Assign meta key

Shift-5		Open/close fold
C=   -f		Set fold block/end fold block
C=   -5 (C=-%)	Dissolve fold

C=   -x		Set block/cut to clipboard
C=   -c		Set block/copy to clipboard
C=   -p		Paste from clipboard

@		Goto line
Shift-@		Goto marker
HOME		Set home (bookmark)
C=   -HOME	Go home
<		Page up
>		Page down
C=   -<		Go to beginning of field
C=   ->		Go to end of field
.		(Play note under cursor/Transpose note under cursor and)
	        advance cursor
Shift-CLR	Clear all data
shift-^ (pi)	Clear SID
*		Toggle gate bit for current voice

a-w,y		Notes 0-24
a-l,a#-l#	Notes 0-24, alternate form
#a-#l		Same as a#-l# 
x		Hold note
0-7		Octave
0-9,A-N 	Duration
<- (backarrow)	Back up one level in note-octave-dur sequence

Other:

C=+, C=-	Double/halve current play speed (temporary, playback only)
=		Toggle border raster 

CTRL- e		Exit to BASIC (RS/RESTORE to re-enter editor)
CTRL- i		Set interrupt
CTRL- d		Edit duration table (Run/Stop or 'e' to exit)
CTRL- n		Edit note table (Run/Stop or 'e' to exit)
CTRL- z		Display instrument table
CTRL- p		Play song
SHIFT-CTRL-p	Play song from current location

CTRL- m		Assign meta key
CTRL- a		Audible (play notes as they are entered)
CTRL- t		Enable transpose
shift-CTRL-t	Set transpose values (negative values allowed)
.		Play note under cursor (if audible),
	        transpose under cursor (if transpose active),
	        and advance cursor
CTRL- s		Single step - space, (s)kip, (c)hange skip value, return=exit
SHIFT-CTRL-s	Single step from current location

F3		Instrument editor
F5		Macro manager
F7		Disk menu
F8		Load old version data disk menu
		-- DON'T forget to recompile! :)

Player directives:

Shift-w		Set volume (The nuclear wessel displaces a large wolume)

Shift-l		Activate local macro (0-23)
C=   -l		Deactivate local (0-23)
Shift-g		Activate global macro (0-23)
C=   -g		Deactivate global (0-23)
Shift-v		Load local variable with value (0-7, 0-255)
C=   -v		Load global variable (0-15, 0-255)
Shift-m		Set marker (0-31)
C=   -m		Clear marker (0-31)
Shift-i		Load instrument (0-13)

C=   -s		SYNC
C=   -w		WAIT for sync

Shift-j		Jump to marker
C=   -j		Jump to subroutine at marker
C=   -t		reTurn from Subroutine

Shift-r		Repeat begin (0-255 repetitions)
C=   -r		End repeat
Shift-o		Gate on
C=   -o		Gate off
Shift-c		Cycle Test bit
Shift-u		Slur mode
C=   -u		Deactivate slur mode
Shift-s		Stop voice
Shift-z		Restart player


Pressing Run/Stop-RESTORE resets Tunesmith.

R/S-RESTORE will get you out of a jam in most cases.  Everything -- music,
instruments, tables, macros, etc. -- is preserved as best as can be.

----------------
Things that bite
----------------

	- Calling uncompiled macros can lead to disaster.  The Macro
	  pointer in the status box is highlighted when macros have
	  not been compiled.

	- Missing macro ENTRY points can lead to disaster.

	- Saving music does not save macro text, and vice versa.

	- Instruments must be saved before being used.

	- If no volume is set then no volume will be heard.

	- SID is read only, so use the Shadow SID for modifications

	- Macros _always_ preserve .Y -- if they jump to an outside program,
	  make sure it preserves .Y as well!

-------------
Memory layout
-------------

$0800	Editor stuff
$1000-$19xx or so	Player
$19xx
	Compiled macros
	Field 1 data
	Field 2 data
	Field 3 data
FIELDEND
	Fold stuff
FREBOT  Free memory
	...
	Clipboard
FRETOP	End of free memory
	Macro text
$667E	Macro names and addresses (hot date tonight!)
$6800	Beginning of main program
$CD18	End of main program
$CD00-$CFFF	Used by compiler (variables, stack, queue)
$E000	Free mem, NED clip/compile buffer

Macro text builds downwards from the top of memory; folds, fields and compiled
macros build upwards.  The clipboard is stored in the top of free memory.
Memory is a little tighter now; macro text may be deleted to save memory.


-------------------------------
Converting between PAL and NTSC
-------------------------------

	The player uses a default timer setting of $42C6, which synchronizes
the player with an NTSC screen.  PAL users (and some NTSC users) will need
to set a different value using CTRL-i.  The values are:

100% screen sync:

6567R56A: 64*262-1      $417F   NTSC (rare)
6567R8+:  65*263-1	$42C6   NTSC (default)
6569:     63*312-1      $4CC7	PAL

The player is synchronized with the screen when the border raster does
not move.
	PAL and NTSC machines run at slightly different frequencies.
Therefore to hear PAL tunes at PAL speeds on an NTSC machine the timer
value should be multiplied by approximately 0.963353.  Similarly, PAL
users should multiply by 1.03804 to hear NTSC tunes at NTSC speeds.
It's not MUCH of a difference, but it's a difference :).
	Finally, since the machines run at different speeds, the PAL note 
values are different than the (default) NTSC values -- using NTSC frequency
settings on a PAL machine is like playing a 1.02MHz sample at 0.99MHz.
The exact pitch formula is

	FREQUENCY = (REGISTER VALUE * CLOCK)/16777216 Hz

where CLOCK=1022730 for NTSC systems and CLOCK=985250 for PAL systems.
Again, you can multiply the register settings by 1.03804 or 0.96335
to convert between systems if you really want to (the difference is
pretty trivial, and the modification is not necessary -- it's just
a point of interest :).
