home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 4: Demo 1
/
almathera_demo1.bin
/
sourcecode
/
noisetracker1.1
/
noise.s
< prev
next >
Wrap
Text File
|
1995-03-17
|
146KB
|
6,709 lines
*--------------------------------------------------------------*
* *
* NOISETRACKER 1.1 SOURCE CODE *
* *
* Program (C)1989 Mahoney & Kaktus *
* *
* Disassembled and Commented by JMP in Nov 89 *
* *
* A program worth using is a program worth documenting ! *
* *
*---------------------------------------------------------------*
*------------------------------
* JMP'S ALTERATIONS AND EXTENSIONS
* 1) Noisetracker has a bug in the installation of the keyboard interrupt.
* The interrupt handler is patched into the input-device vector of the
* cia interrupt structure rather than the irq-structure vector.
* These vectors have the same value on an unexpanded system but with
* a A590 hard disk attached the input-device vector is re-directed,
* hence Noisetracker corrupts the hard disk driver and crashes as soon
* as the first disk access occurs !
A590_version equ 1 0=original/1=hard disk compatibility
* 2) This patch alters the 'select drive' request when loading a sample so
* that clicking DF1: selects ST-01: instead, which is my hard disk
* samples directory.
ST01_version equ 1 0=original/1=use ST-01: instead of DF1:
*------------------------------
* MACROS
align macro
cnop 0,4 MUST ensure DOS info blocks are divisible by 4
endm
*------------------------------
* EQUATES
* hardware
_custom EQU $DFF000
vposr EQU $04
joy0dat EQU $0A
adkconr EQU $10
potinp EQU $16
intenar EQU $1C
intreqr EQU $1E
cop1lch EQU $80
copjmp1 EQU $88
diwstrt EQU $8E
diwstop EQU $90
ddfstrt EQU $92
ddfstop EQU $94
dmacon EQU $96
aud0 EQU $A0
aud1 EQU $B0
aud2 EQU $C0
aud3 EQU $D0
bpl1pth EQU $E0
bpl1ptl EQU $E2
bpl2pth EQU $E4
bpl2ptl EQU $E6
bpl3pth EQU $E8
bpl3ptl EQU $EA
bplcon0 EQU $100
bplcon1 EQU $102
bplcon2 EQU $104
bpl1mod EQU $108
bpl2mod EQU $10A
spr0pth EQU $120
spr0ptl EQU $122
spr1pth EQU $124
spr1ptl EQU $126
spr2pth EQU $128
spr2ptl EQU $12A
spr3pth EQU $12C
spr3ptl EQU $12E
spr4pth EQU $130
spr4ptl EQU $132
spr5pth EQU $134
spr5ptl EQU $136
spr6pth EQU $138
spr6ptl EQU $13A
spr7pth EQU $13C
spr7ptl EQU $13E
color0 EQU $180
ac_ptr EQU 0
ac_len EQU 4
ac_per EQU 6
ac_vol EQU 8
ac_dat EQU 10
* memory
MEMF_CLEAR EQU $10000
MEMF_FAST EQU 4
MEMF_CHIP EQU 2
* exec library
_LVOExitIntr EQU -36
_LVOForbid EQU -132
_LVOOldOpenLibrary EQU -408
_LVOWaitPort EQU -384
_LVOGetMsg EQU -372
_LVOFreeMem EQU -210
_LVOCloseLibrary EQU -414
_LVOAvailMem EQU -216
_LVOAllocMem EQU -198
_LVOReplyMsg EQU -378
_LVOFindTask EQU -294
* vectors
tv_Lev2IntVect EQU $68
tv_Lev3IntVect EQU $6C
* dos library
_LVOOpen EQU -30
_LVOClose EQU -36
_LVORead EQU -42
_LVOWrite EQU -48
_LVOSeek EQU -66
_LVODeleteFile EQU -72
_LVOLock EQU -84
_LVOUnLock EQU -90
_LVOExamine EQU -102
_LVOExNext EQU -108
* gfx library
gb_copinit EQU $26
* intuition library
_LVOAutoRequest EQU -348
* process structure
pr_CLI EQU $AC
pr_MsgPort EQU $5C
*------------------------------
* SONG/MODULE format
*
* offset size meaning
*
* 0 20 song name (ascii padded with $00)
* $14 31*30 info for 31 instruments
* 30 bytes each:
* 0 22 character name padded with $00
* 22 w length of sample in words
* 24 w volume 0..64
* 26 w repeat offset
* 28 w repeat length in words (1=single)
* $03B6 1 no. of parts
* $03B7 1 restart = 120
* $03B8 128 pattern no. for each part (up to 128)
* $0438 4 identifier = 'M.K.'
* $043C n*1024 pattern definitions
* 1024 bytes each consisting of 64 16-byte rows
* each row contains 4 longs (1 per voice):
* $spppsfnn
* where: ppp = note (period value)
* ss = instrument no. (0 or $01..$1F)
* f = special function (0..$F)
* nn = parameter for function
*
* followed by sample data (contiguous)
sf_instr equ $14 song file offsets
sf_length equ $3B6
sf_restart equ $3B7
sf_parts equ $3B8
sf_ident equ $438
sf_patterns equ $43C
sf_size equ sf_patterns+68*1024
in_length equ 22 instrument offsets
in_volume equ 24
in_repeat equ 26
in_replen equ 28
in_size equ 30
*------------------------------
* CODE
SECTION noisetracker1.1,CODE_C
BRA.S start
dc.b ' Noisetracker V1.1 by Mahoney & Kaktus. '
start CLR.L _WBenchMsg
MOVE.L 4.w,a6 start from cli/workbench
SUB.L A1,A1
JSR _LVOFindTask(A6) get self
MOVE.L D0,A4
TST.L pr_CLI(A4)
BEQ.S wb_start
BRA cli_start
wb_start
LEA pr_MsgPort(A4),A0 if started from workbench
MOVE.L 4.w,a6
JSR _LVOWaitPort(A6) get message
LEA pr_MsgPort(A4),A0
JSR _LVOGetMsg(A6)
MOVE.L D0,_WBenchMsg
cli_start
BSR main call main program
MOVE.L D0,-(SP)
TST.L _WBenchMsg if started from workbench
BEQ.S exit
MOVE.L 4.w,a6
JSR _LVOForbid(A6) reply to message
MOVE.L _WBenchMsg,A1
JSR _LVOReplyMsg(A6)
exit MOVE.L (SP)+,D0 exit to cli/workbench
RTS
* main program
main MOVE.L SP,initialSP save stack
CLR.L 0.w no break in
BSET #1,$BFE001 led off
BSR save_irq2_3 setup irqs/memory/screen
BSR setup
BSR backup_edit_icons make copy of edit functions
BSR use_normal_colours
MOVE.L clist_ptr,_custom+cop1lch
TST.L alloc7k_ptr ] UNUSED
BEQ.S .no7k ]
MOVE.L 4.w,a6 ]
MOVE.L #7000,D0 ]
MOVE.L alloc7k_ptr,A1 ]
JSR _LVOFreeMem(A6) ]
.no7k
BSR set_play_scroller draw pattern scroller
BSR arrow_is_grey
BSR refresh_on_off refresh channel on/off icons
BSR print_allright
BSR plst_scan_search flag plst files in current disks
main_loop
BSR check_escape escape quits diskops/plst
BSR check_capslock capslock changes colour scheme
BSR refresh_memory_usage
CMP.W #1,fscroll_pending diskop file list scrolling
BNE.S .dscr2
BSR scroll_up_files
.dscr2 CMP.W #2,fscroll_pending
BNE.S .pscr
BSR scroll_down_files
.pscr MOVE.W pscroll_pending,D0 plst file list scrolling
BEQ.S .pscr3
MOVE.W #1,alter_dir
CMPI.W #1,D0
BNE.S .pscr2
MOVE.W #$FFFF,alter_dir
.pscr2 BSR scroll_plst
CLR.W pscroll_pending
.pscr3 BSR check_play_edit_keys check key functions
BSR check_instr_keys
BSR check_transpose_keys
BSR check_pat_or_pos
BSR check_edit_pattern
BSR check_octave_keys
BSR check_cut_paste
BSR check_f6_to_f10
BSR check_help
CMP.L #'patp',play_mode if play mode then
BNE.S .noplay
BSR refresh_song_position update position
TST.W new_pat_flag if new pattern then
BEQ.S .noplay
MOVE.L new_pat_no,pattern_no update pattern
BSR refresh_pattern_display
.noplay BTST #6,$BFE001 loop until left button pressed
BNE main_loop
TST.W mode if mode=entry then
BNE.S .not1st
BSR goto_editor_mode goto editor
.not1st BRA check_arrow_and_cursor check arrow/cursor functions
check_escape
CMP.B #$45,key_code if key = ESC then
BNE return
CLR.B key_code clear key
MOVE.W mode,D0
CMPI.W #3,D0 if mode=diskops then
BEQ goto_editor_mode goto editor
CMPI.W #4,D0 if mode= then
BEQ cancel_plst_mode
RTS else ignore
check_capslock
MOVE.B key_code,D0 if no key then return
BEQ return
CMPI.B #$62,D0
BEQ.S use_other_colours
CMPI.B #$E2,D0 if caps lock then colour set 2
BNE return
use_normal_colours
MOVE.L #chaneq_colours2,chaneq_colours_ptr
MOVE.L #spect_colours2,spect_colours_ptr
MOVE.W #$444,cl_col1+2 set colours 1..7
MOVE.W #$777,cl_col1+6
MOVE.W #$AAA,cl_col1+10
MOVE.W #$CCC,cl_col1+14
MOVE.W #$700,cl_col1+18
MOVE.W #$400,cl_col1+22
MOVE.W #$A00,cl_col1+26
MOVE.W #$04D,cl_col4b colour 4 in lower half
CLR.B key_code
BSR set_chaneq_copper
BRA set_spect_copper
use_other_colours
MOVE.L #chaneq_colours1,chaneq_colours_ptr else colour set 1
MOVE.L #spect_colours1,spect_colours_ptr
MOVE.W #$733,cl_col1+2 set colours 1..7
MOVE.W #$A66,cl_col1+6
MOVE.W #$C99,cl_col1+10
MOVE.W #$AFB,cl_col1+14
MOVE.W #$900,cl_col1+18
MOVE.W #$600,cl_col1+22
MOVE.W #$E00,cl_col1+26
MOVE.W #$990,cl_col4b colour 4 in lower half
CLR.B key_code
BSR set_chaneq_copper
BRA set_spect_copper
* exit d0=-1 cancel
* 0 DF0:
* 1 DF1:
check_which_drive
BSR wait_no_buttons
BSR arrow_is_grey
BSR wipe_spectrum
BSR.S toggle_drive_icon display drive icon (df0/df1)
BSR wait_no_buttons
.wait BTST #6,$BFE001 wait for mouse
BNE.S .wait
MOVEM.W mouse_x,D0/D1 check mouse coords for df0/df1/cancel
CMPI.W #$F0,D0
BLT.S .cancel
CMPI.W #$137,D0
BGT.S .cancel
CMPI.W #2,D1
BLT.S .cancel
CMPI.W #$23,D1
BGT.S .cancel
CMPI.W #$15,D1
BLT.S .wait
CMPI.W #$1F,D1
BGT.S .wait
CMPI.W #$F5,D0
BLT.S .wait
CMPI.W #$113,D0
BLT.S .df0
CMPI.W #$117,D0
BLT.S .wait
CMPI.W #$132,D0
BGT.S .wait
BSR.S toggle_drive_icon
MOVEQ #1,D0
RTS
.df0 BSR.S toggle_drive_icon
MOVEQ #0,D0
RTS
.cancel BSR.S toggle_drive_icon
MOVEQ #-1,D0
RTS
toggle_drive_icon
LEA main_screen+2*40+30,A0
LEA drive_icon,A1
MOVEQ #34-1,D0
.row MOVEQ #9-1,D1
.column MOVE.B 10240(A0),D2
MOVE.B 34*10(A1),10240(A0)
MOVE.B D2,34*10(A1)
MOVE.B (A0),D2
MOVE.B (A1),(A0)+
MOVE.B D2,(A1)+
DBRA D1,.column
ADD.L #40-9,A0
ADDQ.L #1,A1
DBRA D0,.row
MOVE.W #20480,D7
.wait DBRA D7,.wait
RTS
fn_load_sample_abort
MOVE.W #20480,D7
.wait DBRA D7,.wait
BRA restore_arrow_colours
* LOAD SAMPLE
fn_load_sample
BSR save_arrow_colours
BSR wait_no_buttons
CLR.B key_code
CLR.W disk_fn
BSR wipe_spectrum
BSR check_which_drive drive 0/1
TST.L D0
BMI.S fn_load_sample_abort skip if aborted
ifeq ST01_version
ADD.B #'0',D0
MOVE.B D0,DF_msg+2 patch drive no.
MOVE.W #2,ffi_type
LEA DF_msg(PC),A4
elseif
LEA DF_msg(PC),A4 choose
MOVE.W #2,ffi_type drive DF0:
TST.L D0
BEQ.S .df0
LEA DF_msg1(PC),A4 drive ST-01:
MOVE.W #2,ffi_type
.df0
endc
LEA dir_buffer(PC),A5 find disk
BSR find_file_info
BEQ.S .ok
MOVE.W FileInfoBlock+8,D0 error if not an ST-.. disk
MOVE.W #'ST',D1
AND.W #$1F1F,D0
AND.W #$1F1F,D1
CMP.W D0,D1
BNE.S .error
LEA sample_filename,A1 clear name buffer
MOVEQ #16-1,D7
.wipe CLR.B (A1)+
DBRA D7,.wipe
LEA FileInfoBlock+8,A0 get disk name
LEA sample_filename,A1
MOVEQ #16-1,D7
.copy MOVE.B (A0)+,D0
BEQ.S .copied
MOVE.B D0,(A1)+
DBRA D7,.copy
.copied MOVE.B #':',(A1)+ add :
BSR cancel_directory
BSR read_directory
BEQ.S .ok
.error BSR cancel_directory
BRA arrow_flash_red
.ok MOVE.W diskop_cursor,D0
MOVE.W #5,disk_fn
BSR refresh_diskop_filelist
BRA arrow_is_grey
ifeq ST01_version
DF_msg dc.b 'DF1:',0
even
elseif
DF_msg dc.b 'DF0:',0
even
DF_msg1 dc.b 'ST-01:',0
even
endc
load_sample
BSR save_arrow_colours
TST.W current_instr
BEQ.S .skip
CLR.B key_code
MOVE.W current_instr,D0
MULU #in_size,D0
MOVE.L song_file_ptr,A1
LEA sf_instr-in_size(A1,D0.W),A1
MOVE.L A1,A2 wipe instrument in song file
MOVEQ #in_size-1,D0
.wipe CLR.B (A1)+
DBRA D0,.wipe
MOVE.L A2,A1
MOVEQ #22-1,D1 ** BUG ** used d0 for loop counter !!
LEA sample_filename,A0
.disk MOVE.B (A0)+,D0 copy disk name
BEQ.S .disk2
MOVE.B D0,(A1)+ ** loop counter goes splat....
DBRA D1,.disk
.disk2 MOVE.L dir_entry_ptr,A0 copy file name
MOVE.L A0,A3
.file MOVE.B (A0)+,D0
BEQ.S .file2
MOVE.B D0,(A1)+
DBRA D0,.file
.file2 MOVE.W $1A(A3),D0
LSR.W #1,D0
MOVE.W D0,in_length(A2) sample length (in words)
MOVE.W #64,in_volume(A2) volume=64
CLR.W in_repeat(A2) repeat=0
MOVE.W #1,in_replen(A2) replen=1
BSR load_sample_file
.skip BSR refresh_instr_parameters
BRA restore_arrow_colours
check_transpose_keys
MOVEQ #2,D4
CMP.B #$42,key_code if key = TAB then d4=2
BEQ.S .trans
MOVEQ #-2,D4
CMP.B #$63,key_code if key = CTRL then d4=-2 else return
BNE return
.trans TST.W key_lshift skip if neither SHIFT nor ALT
BNE.S .trans0
TST.W key_lalt
BEQ return
MOVEQ #0,D0 if ALT then transpose each voice
MOVE.L D0,A0
BSR.S transpose
MOVEQ #4,D0
MOVE.L D0,A0
BSR.S transpose
MOVEQ #8,D0
MOVE.L D0,A0
BSR.S transpose
MOVEQ #12,D0
MOVE.L D0,A0
BSR.S transpose
BRA refresh_pattern_display
.trans0 CMP.W #18,edit_cursor_x if SHIFT then transpose current voice
BNE.S .trans1
MOVEQ #12,D0
MOVE.L D0,A0
BSR.S transpose
BRA refresh_pattern_display
.trans1 CMP.W #12,edit_cursor_x
BNE.S .trans2
MOVEQ #8,D0
MOVE.L D0,A0
BSR.S transpose
BRA refresh_pattern_display
.trans2 CMP.W #6,edit_cursor_x
BNE.S .trans3
MOVEQ #4,D0
MOVE.L D0,A0
BSR.S transpose
BRA refresh_pattern_display
.trans3 TST.W edit_cursor_x
BNE return
MOVEQ #0,D0
MOVE.L D0,A0
BSR.S transpose
BRA refresh_pattern_display
* entry d4=tranpose offset -2/+2
* a0=voice offset 0/4/8/12
transpose
CLR.B key_code clear key
ADD.L song_file_ptr,A0 a0=song+offset+1024*pattern+voice
ADD.L #sf_patterns,A0
MOVE.L pattern_no,D0
LSL.L #8,D0
LSL.L #2,D0
ADD.L D0,A0
MOVEQ #64-1,D7 d7=length of pattern-1
MOVE.W current_instr,D6 d6=8*(instrument div 16)
MOVE.W D6,D5
AND.W #$10,D6
ASL.W #3,D6
AND.W #15,D5 d5=16*(instrument mod 16)
ASL.W #4,D5
LEA oct1_2_3_periods,A1 a1=periods
.loop MOVE.B 2(A0),D0 for each note
AND.B #$F0,D0 skip if wrong instrument
CMP.B D0,D5
BNE.S .next
MOVE.B (A0),D0
AND.B #$80,D0
CMP.B D6,D0
BNE.S .next
MOVEQ #0,D3 skip if rest
MOVE.W (A0),D2
AND.W #$FFF,D2
BEQ.S .next
MOVEQ #$26,D1 search period table
.search CMP.W 0(A1,D3.W),D2
BEQ.S .found
ADDQ.W #2,D3
DBRA D1,.search
BRA.S .next
.found AND.W #$F000,(A0) skip if period+offset < 0
ADD.L D4,D3
BMI.S .next
MOVE.W 0(A1,D3.W),D3 store new period
OR.W D3,(A0)
.next ADD.L #16,A0 next note
DBRA D7,.loop
RTS
input_module_dir
MOVE.L cptr_arrow_col,A0 if arrow<>cyan then save colours
CMP.W #$0AA,2(A0)
BEQ.S .cyan
BSR save_arrow_colours
.cyan BSR arrow_is_magenta
CLR.L edit_mode cancel edit mode
LEA modules_dir,A6
BSR print_modules_dir edit string
MOVE.W #$C4,input_cursor_x
MOVE.W #$2A,input_cursor_y
BSR set_input_cursor
MOVE.L A6,input_end_addr
ADD.L #15,input_end_addr
BSR input_routine
CLR.L input_end_addr
CLR.W disk_fn
BSR wipe_spectrum
BRA restore_arrow_colours
check_instr_keys
MOVE.B key_code,D0 if no key then return
BEQ return
CMPI.B #$43,D0 if key = ENTER then
BNE.S .tst0
MOVE.W #16,current_instr instrument 16
BSR refresh_instr_parameters
CLR.B key_code
RTS
.tst0 CMPI.B #$F,D0 if key = 0 (pad) then
BNE.S .tstall
CLR.W current_instr instrument 0
BSR refresh_instr_parameters
CLR.B key_code
RTS
.tstall LEA .pad_keys,A0 else scan pad
MOVEQ #0,D1
MOVEQ #16-1,D7
.scan CMP.B 0(A0,D1.W),D0
BEQ.S .found
ADDQ.W #1,D1
DBRA D7,.scan
RTS
.found TST.W key_enter if ENTER pressed then
BEQ.S .noent
ADD.W #$10,D1 plus 16
.noent MOVE.W D1,current_instr set instrument number
BSR refresh_instr_parameters
CLR.B key_code
RTS
.pad_keys
dc.b 0
dc.b $5A,$5B,$5C,$5D
dc.b $3D,$3E,$3F,$4A
dc.b $2D,$2E,$2F,$5E
dc.b $1D,$1E,$1F
check_play_edit_keys
MOVE.B key_code,D0 if key = SPACE then
CMPI.B #$40,D0
BNE.S .amiga
CLR.B key_code clear key
TST.L edit_mode
BNE fn_stop if edit or play mode then
TST.L play_mode stop
BNE fn_stop
CMP.W #3,mode if mode=diskops then
BEQ fn_stop stop
BSR fn_edit else mode=edit
RTS
.amiga CMPI.B #$67,D0 if key = RIGHT AMIGA then
BNE.S .alt
.plypat BSR fn_play_pattern play pattern
CLR.B key_code clear key
RTS
.alt CMPI.B #$65,D0 if key = RIGHT ALT then
BNE.S .shift
BSR fn_play_song play song
CLR.B key_code clear key
RTS
.shift CMPI.B #$61,D0 if key = RIGHT SHIFT then
BNE.S .skip
CMP.W #3,mode if mode=diskops then
BEQ .plypat play pattern
BSR fn_record else record
CLR.B key_code clear key
RTS
.skip RTS
refresh_memory_usage
TST.W memory_flag
BEQ return
CLR.W memory_flag
BSR.S refresh_song_size
MOVE.L 4.w,a6
MOVE.L #MEMF_CHIP!MEMF_CLEAR,D1 get available chip memory
JSR _LVOAvailMem(A6)
CMP.L memory_free,D0 if same size then skip
BEQ.S return
MOVE.L D0,memory_free save size
MOVE.L D0,D6
MOVE.L #131*40+34,char_offset print 5-digit hex
SWAP D0
AND.W #15,D0
ASL.W #1,D0
LEA hex2ascii+1,A0
MOVE.B 0(A0,D0.W),word_to_print
CLR.B word_to_print+1
MOVE.L #word_to_print,string_addr
MOVE.L #1,string_size
BSR print_string
MOVE.W D6,word_to_print
BSR print_hex4
return RTS
refresh_song_size
MOVE.L song_file_ptr,A0
ADD.L #sf_instr+in_length,A0
MOVEQ #31-1,D7 sum sample sizes
MOVEQ #0,D0
.sample MOVEQ #0,D1
MOVE.W (A0),D1
ASL.W #1,D1
ADD.L D1,D0
ADD.L #in_size,A0
DBRA D7,.sample
ADD.L #sf_patterns,D0
MOVE.L song_file_ptr,A0 +pattern size
MOVEQ #128-1,D7
ADD.L #sf_parts,A0
MOVEQ #0,D6
.patts MOVE.B (A0)+,D5 (find largest pattern no)
CMP.B D5,D6
BGT.S .next
MOVE.B D5,D6
.next DBRA D7,.patts
ADDQ.W #1,D6
ASL.L #8,D6 *1024
ASL.L #2,D6
ADD.L D6,D0
CMP.L memory_used,D0 update song size
BEQ.S return
MOVE.L D0,memory_used print if not same
MOVE.L D0,D6
MOVE.L #131*40+28,char_offset
SWAP D0
AND.W #15,D0
ASL.W #1,D0
LEA hex2ascii+1,A0 5-digit hex
MOVE.B 0(A0,D0.W),word_to_print
CLR.B word_to_print+1
MOVE.L #word_to_print,string_addr
MOVE.L #1,string_size
BSR print_string
MOVE.W D6,word_to_print
BSR print_hex4
RTS
save_irq2_3
MOVE.L (tv_Lev3IntVect).w,old_irq3_vect save level 3 vector
MOVE.L 4.w,a6
MOVE.L $78(A6),A0
ifeq A590_version
MOVE.L (A0),A0 old version only valid if no expansion
elseif
MOVE.L 8(A0),A0 jmp's alteration
endc
MOVE.L 14(A0),A0
ADD.L #$68,A0
MOVE.L (A0),old_irq2_patch
MOVE.L #keyboard_irq,(A0)
MOVE.L A0,old_irq2_addr
RTS
backup_edit_icons
MOVE.L #9800,D0
MOVE.L #MEMF_CLEAR,D1
JSR _LVOAllocMem(A6) allocate 9800 bytes
MOVE.L D0,dir_buffer
LEA main_screen+40+15,A0 save top_right of screen
LEA edit_icons_copy,A1 to restore after diskops/plst
MOVEQ #44-1,D0
.row MOVEQ #25-1,D1
.column MOVE.B (A0)+,(A1)+
MOVE.B 10240-1(A0),1100-1(A1)
DBRA D1,.column
ADD.L #40-25,A0
DBRA D0,.row
RTS
restore_and_exit
MOVE.L initialSP,SP restore SP
MOVE.L copper_init,_custom+cop1lch restore copper list
CLR.W _custom+copjmp1
MOVE.L 4.w,a6
MOVE.L GFXbase,A1
JSR _LVOCloseLibrary(A6)
MOVE.L INTbase,A1
MOVE.L request_patch+2,_LVOAutoRequest+2(A1)
JSR _LVOCloseLibrary(A6)
MOVE.L screen_ptr,A1 free screen memory
MOVE.L #27760,D0
JSR _LVOFreeMem(A6)
MOVE.L DOSbase,A1
JSR _LVOCloseLibrary(A6)
MOVE.L song_file_ptr,A1
MOVE.L #sf_size,D0
JSR _LVOFreeMem(A6)
MOVE.L dir_buffer,A1
MOVE.L #9800,D0
JSR _LVOFreeMem(A6)
BSR free_instr_memory
TST.L plst_ptr
BEQ.S .noplst
MOVE.L plst_ptr,A1
MOVE.L plst_size,D0
JSR _LVOFreeMem(A6)
.noplst MOVE.L old_irq3_vect,(tv_Lev3IntVect).w restore vectors
MOVE.W #15,_custom+dmacon cancel audio dma
MOVE.L old_irq2_addr,A0
MOVE.L old_irq2_patch,(A0)
BCLR #1,$BFE001 restore power led
MOVEQ #0,D0 ok
RTS
goto_editor_mode
MOVE.L cptr_arrow_col,A0 if arrow=cyan then
CMP.W #$0AA,2(A0)
BNE.S .nocyan
BSR arrow_is_grey arrow=grey
.nocyan BSR wait_no_buttons wait for release
LEA spectrum_old,A0 clear spectrum
LEA spectrum_new,A1
MOVEQ #23-1,D7
.wipe CLR.W (A0)+
CLR.W (A1)+
DBRA D7,.wipe
BSR clear_screen_topright setup editor icons/spectrum analyser
LEA spectrum_screen,A0
BSR setup_topright
MOVE.W #1,mode mode=editor
upspec_skip
BRA set_spect_colours
update_spectrum_analyser
CMP.W #1,mode if mode<>editor then set spectrum
BNE.S upspec_skip
TST.W plst_flag if plst flag set then set spectrum
BNE.S upspec_skip
MOVEQ #40,D5
MOVEQ #126,D6
LEA spectrum_new,A0
LEA spectrum_old,A1
LEA spectrum_offsets_table,A2
MOVE.L screen_ptr,A3
ADD.W #49*40+16,A3
MOVEQ #23-1,D7 update 23 columns
.column
MOVE.W (A0)+,D0 get new value
CMPI.W #36,D0
BLT.S .clip
MOVE.W #36,D0 max 36
.clip MOVE.W (A1)+,D1 get old value
CMP.W D0,D1
BEQ.S .next if same then don't refresh
BLT.S .up else clear/fill changes
SUB.W D0,D1
SUBQ.W #1,D1
LSL.W #1,D0
MOVE.W 0(A2,D0.W),D0
.wipe CLR.B 0(A3,D0.W)
SUB.W D5,D0
DBRA D1,.wipe
BRA.S .next
.up SUB.W D1,D0
SUBQ.W #1,D0
LSL.W #1,D1
MOVE.W 0(A2,D1.W),D1
.fill MOVE.B D6,0(A3,D1.W)
SUB.W D5,D1
DBRA D0,.fill
.next ADDQ.W #1,A3 next column
DBRA D7,.column
LEA spectrum_new,A0 copy new to old with auto fade
LEA spectrum_old,A1
MOVEQ #23-1,D7
.copy MOVE.W (A0),D0
MOVE.W D0,(A1)+
BEQ.S .zero
SUBQ.W #1,D0
.zero MOVE.W D0,(A0)+
DBRA D7,.copy
RTS
add_keyplay_to_spectrum
MOVEM.L D0-D3/A0,-(SP)
MOVEQ #0,D2
MOVE.W instr_volume-instr_length(A6),D2
BRA.S add_to_spectrum
add_note_to_spectrum
MOVEM.L D0-D3/A0,-(SP)
MOVEQ #0,D2
MOVE.W $12(A6),D2
add_to_spectrum
BSR update_channel_level check if value>previous
BEQ.S .skip if < then ignore
ASL.W #8,D2 d2=0..24 (main band)
DIVU #682,D2
MOVE.W D2,D3
LSR.W #1,D3 d3=0..12 (side bands)
LEA spectrum_new,A0 index spectrum
SUB.W #113,D0
MOVE.W #743,D1
SUB.W D0,D1
MULU D1,D1
DIVU #25093,D1
MOVE.W D1,D0
CMPI.W #46,D0
BLT.S .main
MOVEQ #45,D0
.main LSL.W #1,D0
ADD.W D2,0(A0,D0.W) add to main and side bands
CMP.W #36,0(A0,D0.W)
BLT.S .left
MOVE.W #36,0(A0,D0.W)
.left TST.W D0
BEQ.S .right
ADD.W D3,-2(A0,D0.W)
CMP.W #36,-2(A0,D0.W)
BLT.S .right
MOVE.W #36,-2(A0,D0.W)
.right CMPI.W #44,D0
BEQ.S .skip
ADD.W D3,2(A0,D0.W)
CMP.W #36,2(A0,D0.W)
BLT.S .skip
MOVE.W #36,2(A0,D0.W)
.skip MOVEM.L (SP)+,D0-D3/A0
RTS
spectrum_offsets_table
i set 46*40
rept 41
dc.w i
i set i-40
endr
check_toggle_on_off
MOVE.W mouse_y2,D0
CMP.W #3,mode if mode=diskops then
BNE.S .notm3
CMPI.W #44,D0 if y>44 then
BGE diskop_file_select file select
.notm3 CMPI.W #44,D0 check which icon
BGE.S .skip
CMPI.W #34,D0
BGE.S .chan4
CMPI.W #23,D0
BGE.S .chan3
CMPI.W #12,D0
BGE.S .chan2
TST.W D0
BGE.S .chan1
.skip RTS
.chan1 LEA onoff_1(PC),A0
BRA.S .rel
.chan2 LEA onoff_2(PC),A0
BRA.S .rel
.chan3 LEA onoff_3(PC),A0
BRA.S .rel
.chan4 LEA onoff_4(PC),A0
.rel BTST #6,$BFE001 wait till button released
BEQ.S .rel
LEA main_screen,A1
MOVEQ #0,D0 toggle on/off
MOVE.W 2(A0),D0
ADD.L D0,A1
EOR.W #1,(A0)
TST.W (A0)
BNE.S .on if off then clear level
CLR.W 4(A0)
LEA onoff_icon+24,A0
BSR.S draw_on_off redraw
BRA.S .sum
.on LEA onoff_icon,A0
BSR.S draw_on_off
.sum CLR.W D0 form 4-bit mask of states
MOVE.W onoff_4,D0
LSL.B #1,D0
OR.W onoff_3,D0
LSL.B #1,D0
OR.W onoff_2,D0
LSL.B #1,D0
OR.W onoff_1,D0
MOVE.W D0,onoff_states
MOVE.W #32768,D0 wait 3 frames
.wait DBRA D0,.wait
BSR wait_20ms
RTS
refresh_on_off
LEA onoff_1(PC),A0 refresh all on/off icons
BSR.S .ref
LEA onoff_2(PC),A0
BSR.S .ref
LEA onoff_3(PC),A0
BSR.S .ref
LEA onoff_4(PC),A0
.ref LEA main_screen,A1
MOVEQ #0,D0
MOVE.W 2(A0),D0 offset
ADD.L D0,A1
TST.W (A0) state
BNE.S .on
LEA onoff_icon+24,A0
BRA.S draw_on_off
.on LEA onoff_icon,A0
draw_on_off
MOVEQ #6-1,D4
.row MOVE.B (A0),(A1)
MOVE.B 1(A0),1(A1)
MOVE.B 2(A0),2(A1)
MOVE.B 48(A0),10240(A1)
MOVE.B 49(A0),10241(A1)
MOVE.B 50(A0),10242(A1)
ADDQ.L #4,A0
ADD.L #40,A1
DBRA D4,.row
RTS
update_chaneq_levels
MOVEM.L D0-D7/A0-A6,-(SP)
LEA volume_1(PC),A0
LEA audio_info_1(PC),A1
LEA s_chaneq1,A2
BSR.S .update
LEA volume_2(PC),A0
LEA audio_info_2(PC),A1
LEA s_chaneq2,A2
BSR.S .update
LEA volume_3(PC),A0
LEA audio_info_3(PC),A1
LEA s_chaneq3,A2
BSR.S .update
LEA volume_4(PC),A0
LEA audio_info_4(PC),A1
LEA s_chaneq4,A2
BSR.S .update
MOVEM.L (SP)+,D0-D7/A0-A6
RTS
.update TST.L play_mode if not playing or channel off then fade
BEQ.S .fade
TST.W onoff_1-volume_1(A0)
BEQ.S .fade
TST.W (A0)
BEQ.S .fade if volume=0 then fade
TST.W (A1)
BEQ.S .fade if no note then fade
TST.L frame_count
BNE.S .fade if no new note then fade
MOVEQ #0,D0
MOVE.W (A0),D0 get volume
CMPI.W #64,D0
BLE.S .vol_ok
MOVEQ #64,D0
.vol_ok MOVE.B #233,D7 sprite start = 233-47*(volume/64)
LEA scale_64_47(PC),A3
SUB.B 0(A3,D0.W),D7
MOVE.B D7,(A2)
RTS
.fade CMP.B #233,(A2) if not playing then
BEQ.S .faded sprite start + 1 until = 233
ADDQ.B #1,(A2) i.e. fade out
.faded RTS
onoff_1 dc.w 1 icon state
dc.w 4*40+37 screen offset
dc.w 0 channel level 0..127 (for spectrum analyser)
onoff_2 dc.w 1
dc.w 15*40+37
dc.w 0
onoff_3 dc.w 1
dc.w 26*40+37
dc.w 0
onoff_4 dc.w 1
dc.w 37*40+37
dc.w 0
volume_1 dc.w 0,0,0 current volumes (2nd & 3rd 0's are padding)
volume_2 dc.w 0,0,0
volume_3 dc.w 0,0,0
volume_4 dc.w 0,0,0
onoff_states
dc.w %1111
scale_64_47
dc.b 0,0,1,2,2,3,4,5 rescale 0..64 -> 0..47
dc.b 5,6,7,8,8,9,10,11
dc.b 11,12,13,14,14,15,16,17
dc.b 17,18,19,20,20,21,22,23
dc.b 23,24,25,26,26,27,28,29
dc.b 29,30,31,32,32,33,34,35
dc.b 35,36,37,38,38,39,40,41
dc.b 41,42,43,44,44,45,46,47
dc.b 47
even
update_channel_level
MOVEM.L D0-D3/A0,-(SP) d2=volume,a5=audio channel
LSL.W #8,D2 *256/640
DIVU #640,D2
CMP.L #_custom+aud0,A5 find channel
BNE.S .try2
TST.W onoff_1
BEQ.S .no
CMP.W onoff_1+4,D2 if >previous level then update
BLT.S .try2
MOVE.W D2,onoff_1+4
.try2 CMP.L #_custom+aud1,A5
BNE.S .try3
TST.W onoff_2
BEQ.S .no
CMP.W onoff_2+4,D2
BLT.S .try3
MOVE.W D2,onoff_2+4
.try3 CMP.L #_custom+aud2,A5
BNE.S .try4
TST.W onoff_3
BEQ.S .no
CMP.W onoff_3+4,D2
BLT.S .try4
MOVE.W D2,onoff_3+4
.try4 CMP.L #_custom+aud3,A5
BNE.S .yes
TST.W onoff_4
BEQ.S .no
CMP.W onoff_4+4,D2
BLT.S .yes
MOVE.W D2,onoff_4+4
.yes MOVEM.L (SP)+,D0-D3/A0
MOVEQ #1,D4 new level
RTS
.no MOVEM.L (SP)+,D0-D3/A0
MOVEQ #0,D4 ignore
RTS
* GOTO DISKOPS SCREEN
fn_goto_diskops
BSR wait_no_buttons
CMP.L #'edit',play_mode cancel edit mode
BNE.S .clr1
CLR.L play_mode
BSR arrow_is_grey
.clr1 CMP.L #'edit',edit_mode
BNE.S .clr2
CLR.L edit_mode
BSR arrow_is_grey
.clr2 MOVE.W #3,mode mode=diskops
BSR clear_screen_topright
BSR copy_diskops_screen
CLR.W disk_fn
BSR wait_no_buttons
BSR print_modules_dir
BSR refresh_pack_icon
MOVE.W #$8000,D0
.delay DBRA D0,.delay
BRA clear_spect_colours
print_modules_dir
CMP.W #3,mode if mode<>diskops then return
BNE return
MOVE.L #modules_dir,string_addr else print modules dir
MOVE.L #$5E0,char_offset
MOVE.L #15,string_size
BRA print_string
diskop_file_select
MOVEM.W mouse_x2,D0/D1
SUB.W #120,D0 d0=mouse_x-120
SUB.W #44,D1 d1=mouse_y-44
CMP.W #3,mode skip if mode<>diskops
BEQ.S .diskop
RTS
.diskop CMPI.W #189,D0 if x<189 then
BLT select_file
CMPI.W #12,D1 if y<12 then scroll up list
BLT scroll_up_files
CMPI.W #45,D1 if x>=189 and 12<=y<45 then
BLT goto_editor_mode exit to editor
BRA scroll_down_files else scroll down list
* LOAD SONG
fn_load_song
BSR wait_no_buttons
CLR.W disk_fn
BSR wipe_spectrum
CLR.W ffi_type
LEA st00_name(PC),A4
LEA dir_buffer(PC),A5
BSR find_file_info
BEQ.S .ok
BSR cancel_directory
BSR read_directory
BEQ.S .ok
BRA arrow_flash_red
.ok MOVE.W diskop_cursor,D0
MOVE.W #1,disk_fn
BSR refresh_diskop_filelist
BRA arrow_is_grey
* SAVE SONG
fn_save_song
BSR save_arrow_colours
BSR arrow_is_magenta
BSR check_are_you_sure
BNE arrow_flash_red
BSR wipe_spectrum
BSR fn_stop
CLR.W disk_fn
BSR save_song
BRA arrow_is_grey
* DELETE SONG
fn_delete_song
BSR wait_no_buttons
CLR.W disk_fn
MOVE.L cptr_arrow_col,A4 if arrow<>cyan then save colours
CMP.W #$0AA,2(A4)
BEQ.S .cyan
BSR save_arrow_colours
.cyan BSR wipe_spectrum
CLR.W ffi_type
LEA st00_name(PC),A4
LEA dir_buffer(PC),A5
BSR find_file_info
BEQ.S .ok
BSR cancel_directory
BSR read_directory
BEQ.S .ok
BRA arrow_flash_red
.ok MOVE.W diskop_cursor,D0
MOVE.W #2,disk_fn
BSR refresh_diskop_filelist
BRA arrow_is_cyan
* DELETE MODULE
fn_delete_module
BSR wait_no_buttons
CLR.W disk_fn
MOVE.L cptr_arrow_col,A4 if arrow<>cyan then save colours
CMP.W #$0AA,2(A4)
BEQ.S .cyan
BSR save_arrow_colours
.cyan BSR wipe_spectrum
MOVE.W #1,ffi_type
LEA modules_dir(PC),A4
LEA dir_buffer(PC),A5
BSR find_file_info
BEQ.S .ok
BSR cancel_directory
BSR read_directory
BEQ.S .ok
BRA arrow_flash_red
.ok MOVE.W diskop_cursor,D0
MOVE.W #4,disk_fn
BSR refresh_diskop_filelist
BRA arrow_is_cyan
* LOAD MODULE
fn_load_module
BSR wait_no_buttons
CLR.W disk_fn
BSR wipe_spectrum
MOVE.W #1,ffi_type
LEA modules_dir(PC),A4
LEA dir_buffer(PC),A5
BSR find_file_info
BEQ.S .ok
BSR cancel_directory
BSR read_directory
BEQ.S .ok
BRA arrow_flash_red
.ok MOVE.W diskop_cursor,D0
MOVE.W #3,disk_fn
BSR refresh_diskop_filelist
BRA arrow_is_grey
* SAVE MODULE
fn_save_module
BSR arrow_is_magenta
BSR check_are_you_sure
BNE arrow_flash_red
BSR save_module
BRA arrow_is_grey
scroll_up_files
TST.W disk_fn skip if no function selected
BEQ.S .skip
LEA dir_buffer(PC),A5
MOVE.W diskop_cursor,D0
BEQ.S .skip
SUBQ.W #1,D0
BSR refresh_diskop_filelist
.skip CLR.W fscroll_pending
RTS
scroll_down_files
TST.W disk_fn
BEQ.S .skip
LEA dir_buffer(PC),A5
MOVE.W diskop_cursor,D0
ADDQ.W #1,D0
MOVE.W 16(A5),D1
SUBQ.W #7,D1
CMP.W D1,D0
BGT.S .skip
BSR refresh_diskop_filelist
.skip CLR.W fscroll_pending
RTS
select_file
MOVE.W #1,memory_flag
TST.W disk_fn
BEQ.S .skip
CMPI.W #7,D1
BLT.S .skip
CMPI.W #48,D1
BGT.S .skip
SUBQ.W #7,D1
AND.L #$FFFF,D1
DIVU #6,D1
LEA dir_buffer(PC),A5
MOVE.W diskop_cursor,D0
ADD.W D1,D0
CMP.W 16(A5),D0
BGE.S .skip
MULU #28,D0 index directory
ADD.L (A5),D0
MOVE.L D0,A0
MOVE.L A0,dir_entry_ptr save ptr to dir entry
MOVE.W 26(A5),D0
LEA selected_filename,A1 copy filename
SUBQ.W #1,D0
.name MOVE.B (A0)+,(A1)+
DBRA D0,.name
CMP.W #2,disk_fn
BEQ delete_song
CMP.W #3,disk_fn
BEQ load_module
CMP.W #4,disk_fn
BEQ delete_module
CMP.W #5,disk_fn
BEQ load_sample
BRA load_song
.skip RTS
dir_buffer
.0 dc.l 0 ptr to directory list
.4 dc.l 0 date
.8 dc.l 0 minute
.12 dc.l 0 tick
.16 dc.w 0 no. of entries
.18 dc.l selected_filename
.22 dc.l load_song
.26 dc.w 28 length of each entry
diskop_cursor
dc.w 0
st00_name
dc.b 'st-00:songs/',0
even
modules_dir
dc.b 'st-00:modules/',0,0,0,0,0,0
* PLAY SONG
fn_play_song
BTST #6,$BFE001 wait till button released
BEQ.S fn_play_song
BSR fn_stop stop tune
BSR arrow_is_yellow
MOVE.L #'patp',play_mode mode=play song
CLR.W keyplay_channel clear keyboard note
CLR.W quantize_flag
MOVE.L #$FFFFFFFF,prev_pat_no
CLR.L play_cursor
CLR.W edit_cursor_y reset scroller
BSR set_edit_scroller
MOVEQ #0,D1
MOVE.W song_length,D1 make sure position valid
MOVE.L song_position,D0
CMP.L D1,D0
BPL.S .reset
RTS
.reset CLR.L song_position
RTS
* RECORD SONG
fn_record
BTST #6,$BFE001
BEQ.S fn_record
BSR fn_stop reset scroller
BSR set_edit_scroller
MOVE.L #'patt',play_mode mode=play pattern
BSR arrow_is_blue
MOVE.L #'edit',edit_mode mode=edit
BRA enable_scroller
* entry A4=ptr to directory name
* A5=dir_buffer
* find_file_type=0 file/1=dir/2=disk
find_file_info
MOVE.W #1,memory_flag
MOVE.L DOSbase,A6
MOVE.L A4,D1
MOVEQ #-2,D2 read
JSR _LVOLock(A6) lock file
MOVE.L D0,lock_ptr fail if error
BEQ .error
MOVE.L lock_ptr,D1
MOVE.L #FileInfoBlock,D2 get info block
JSR _LVOExamine(A6)
TST.L D0 fail if error
BEQ.S .error
LEA FileInfoBlock,A0
MOVE.L 132(A0),D0 if date, time and type match then
CMP.L 4(A5),D0
BNE.S .new
MOVE.L 136(A0),D0
CMP.L 8(A5),D0
BNE.S .new
MOVE.L 140(A0),D0
CMP.L 12(A5),D0
BNE.S .new
MOVE.W ffi_type,D0
CMP.W ffi_type_prev,D0
BNE.S .new
MOVE.L lock_ptr,D1 then unlock
JSR _LVOUnLock(A6)
MOVEQ #0,D0 return true
RTS
.new MOVE.L 132(A0),4(A5) else copy date/time/type
MOVE.L 136(A0),8(A5)
MOVE.L 140(A0),12(A5)
MOVE.W ffi_type,ffi_type_prev
MOVE.L lock_ptr,D1 unlock
JSR _LVOUnLock(A6)
MOVEQ #-1,D0 return fail
RTS
.error CLR.L 4(A5) else clear date
MOVEQ #-1,D0 return fail
RTS
read_directory
BSR save_arrow_colours entry a4=name ptr, a5=dir_buffer
BSR arrow_is_green
CLR.W diskop_cursor
MOVE.L DOSbase,A6
MOVE.L A4,D1
MOVEQ #-2,D2
JSR _LVOLock(A6) get info
MOVE.L D0,lock_ptr
BEQ.S .error
MOVE.L lock_ptr,D1
MOVE.L #FileInfoBlock,D2
JSR _LVOExamine(A6)
TST.L D0
BEQ.S .error
.loop MOVE.L lock_ptr,D1 get filenames
MOVE.L #FileInfoBlock,D2
JSR _LVOExNext(A6)
TST.L D0
BEQ.S .done
CMP.B #'.',FileInfoBlock+32 name+24 ??
BSR.S read_filename
BRA.S .loop
.done MOVE.L lock_ptr,D1
JSR _LVOUnLock(A6)
BSR restore_arrow_colours
MOVEQ #0,D0
RTS
.error BSR restore_arrow_colours
MOVEQ #-1,D0
RTS
cancel_directory
CLR.W 16(A5) no. of entries = 0
RTS
read_filename
TST.W ffi_type
BEQ.S .file
CMP.W #2,ffi_type
BNE.S .dir
CMP.L #'.fas',FileInfoBlock+8 ignore .fastdir
BEQ return
LEA FileInfoBlock+8,A0
.getend TST.B (A0)+ ignore .info files
BNE.S .getend
CMP.B #'.',-6(A0)
BNE.S .notinf
CMP.B #'i',-5(A0)
BNE.S .notinf
CMP.B #'n',-4(A0)
BNE.S .notinf
CMP.B #'f',-3(A0)
BNE.S .notinf
CMP.B #'o',-2(A0)
BEQ return
.notinf TST.L FileInfoBlock+124 size
BEQ return
BRA.S .file
.dir CMP.L #'mod.',FileInfoBlock+8 allow mod./MOD.
BEQ.S .file
CMP.L #'MOD.',FileInfoBlock+8
BNE return
.file MOVE.W 16(A5),D6 if 1st file then
BEQ.S .first insert at start of list
SUBQ.W #1,D6
LEA FileInfoBlock+8,A0 a0=filename
MOVE.L (A5),A1 a1=filelist
.loop MOVEQ #0,D2 insert into list in alpha order
MOVEQ #0,D3
.char MOVE.B 0(A0,D2.W),D0 get filename char
BEQ.S .found if end then found position
CMPI.B #$60,D0 upper case
BLT.S .upper
SUB.B #$20,D0
.upper MOVE.B 0(A1,D3.W),D1 get filelist char
BEQ.S .next if end then try next name
CMPI.B #$60,D1
BLT.S .upper2
SUB.B #$20,D1
.upper2 CMP.B D0,D1
BGT.S .found if < then found position
BEQ.S .same if = then try next chars
.next ADD.L #28,A1
DBRA D6,.loop
MOVE.L (A5),A1 if > all then
MOVE.W 16(A5),D0 insert at end of list
MULU #28,D0
ADD.W D0,A1
BRA.S .insert
.same ADDQ.W #1,D2
ADDQ.W #1,D3
BRA.S .char
.found MOVE.L (A5),A2 shift up following names
MOVE.W 16(A5),D0
MULU #28,D0
ADD.L D0,A2
MOVE.L A2,A3
ADD.L #28,A3
.shift MOVE.W -(A2),-(A3)
CMP.L A2,A1
BNE.S .shift
BRA.S .insert
.first MOVE.L (A5),A1
.insert LEA FileInfoBlock+8,A0 copy name (23 chars+0)
MOVE.L A1,A3
MOVEQ #28-1,D0
.wname CLR.B (A3)+
DBRA D0,.wname
MOVEQ #28-1,D0
.cname MOVE.B (A0)+,D1
MOVE.B D1,(A1)+
TST.B D1
BEQ.S .csize
DBRA D0,.cname
.csize CLR.B -5(A3)
MOVE.L FileInfoBlock+124,-4(A3) copy size (4 bytes)
ADDQ.W #1,16(A5) bump no. of entries
RTS
refresh_diskop_filelist
MOVE.W D0,-(SP) entry d0=new diskop cursor
BSR wipe_spectrum
MOVE.W (SP)+,D0
MOVE.W D0,diskop_cursor update cursor position
TST.W 16(A5) skip if no dir
BEQ.S .skip
MOVE.L #51*40+16,A6
MOVE.L A6,char_offset top line
MOVE.L (A5),D6
MULU #28,D0
ADD.L D0,D6 d6=filelist+28*cursor
MOVE.W 16(A5),D0 d0=no. of entries - cursor
SUB.W diskop_cursor,D0
CMPI.W #7,D0
BGE.S .clip if d0>=7 then count=7 else count=d0-1
SUBQ.W #1,D0
MOVE.W D0,D7
BRA.S .ok
.clip MOVEQ #7-1,D7
.ok CMP.W #3,disk_fn
BEQ.S .modules
CMP.W #4,disk_fn
BEQ.S .modules
CMP.W #5,disk_fn
BEQ .samples
.songs MOVE.L D6,string_addr for songs
MOVE.L A6,char_offset print song name only
MOVE.L #22,string_size
BSR print_string_spc
ADD.L #28,D6
ADD.L #6*40,A6
DBRA D7,.songs
.skip RTS
.modules
ADDQ.L #4,D6 for modules
.mod2 MOVE.L D6,string_addr print module name without mod.
MOVE.L A6,char_offset print length
MOVE.L #17,string_size
BSR print_string_spc
MOVE.L D6,A0
CLR.W D0
MOVE.B 21(A0),D0
ASL.W #1,D0
LEA hex2ascii+1,A0
MOVE.B 0(A0,D0.W),word_to_print
CLR.B word_to_print+1
MOVE.L #word_to_print,string_addr
MOVE.L #1,string_size
BSR print_string
MOVE.L D6,A0
MOVE.W 22(A0),word_to_print
BSR print_hex4
ADD.L #28,D6
ADD.L #6*40,A6
DBRA D7,.mod2
RTS
.samples
MOVE.L D6,string_addr for samples
MOVE.L A6,char_offset print name and length
MOVE.L #18,string_size
BSR print_string_spc
MOVE.L D6,A0
MOVE.W 26(A0),word_to_print
BSR print_hex4
ADD.L #28,D6
ADD.L #6*40,A6
DBRA D7,.samples
RTS
setup_topright
MOVE.W #145,D0 entry a0=spectrum screen
BSR wait_for_vpos
LEA main_screen+45*40+15,A1
MOVEQ #2-1,D7 copy spectrum to screen
.plane MOVEQ #55-1,D6
.row MOVEQ #25-1,D5
.column MOVE.B (A0)+,(A1)+
DBRA D5,.column
ADDQ.L #1,A0
ADD.L #40-25,A1
DBRA D6,.row
ADD.L #10240-55*40,A1
DBRA D7,.plane
LEA main_screen+40+15,A0 copy edit icons to screen
LEA edit_icons_copy,A1
MOVEQ #44-1,D0
.row2 MOVEQ #25-1,D1
.colum2 MOVE.B (A1)+,(A0)+
MOVE.B 1100-1(A1),10240-1(A0)
DBRA D1,.colum2
ADD.L #40-25,A0
DBRA D0,.row2
BSR refresh_on_off update on/off icons
RTS
copy_diskops_screen
LEA diskops_screen,A0 copy to main screen
MOVE.W #145,D0
BSR wait_for_vpos
LEA main_screen+40+15,A1
MOVEQ #1,D7
.plane MOVEQ #99-1,D6
.row MOVEQ #25-1,D5
.column MOVE.B (A0)+,(A1)+
DBRA D5,.column
ADDQ.L #1,A0
ADD.L #15,A1
DBRA D6,.row
ADD.L #(256-99)*40,A1
DBRA D7,.plane
RTS
clear_screen_topright
MOVE.W #145,D0
BSR wait_for_vpos
MOVE.L screen_ptr,A1
ADD.L #15,A1
MOVEQ #100-1,D6
.row MOVEQ #25-1,D5
.column CLR.B (A1)+
DBRA D5,.column
ADD.L #15,A1
DBRA D6,.row
RTS
wipe_spectrum
MOVE.W #145,D0
BSR wait_for_vpos
MOVE.L screen_ptr,A1
ADD.L #45*40+15,A1
MOVEQ #56-1,D6
.row MOVEQ #25-1,D5
.column CLR.B (A1)+
DBRA D5,.column
ADD.L #40-25,A1
DBRA D6,.row
RTS
CLR.W D0
MOVE.B _custom+joy0dat,D0
MOVE.W D0,mouse_oldy
MOVE.B _custom+joy0dat+1,D0
MOVE.W D0,mouse_oldx
RTS
wait_no_buttons
BTST #6,$BFE001
BEQ.S wait_no_buttons
BTST #2,_custom+potinp
BEQ.S wait_no_buttons
MOVE.W #145,D0
BRA wait_for_vpos
check_are_you_sure
BSR.S wait_no_buttons
MOVE.W #$4000,D7
.delay DBRA D7,.delay
BSR wipe_spectrum
BSR.S toggle_rusure_icon show 'are you sure?' icon
BSR.S wait_no_buttons
.wait BTST #6,$BFE001 wait for left button
BNE.S .wait
MOVEM.W mouse_x,D0/D1 get mouse coords
CMPI.W #$AB,D0
BLT.S .wait
CMPI.W #$FC,D0
BGT.S .wait
CMPI.W #$48,D1
BLT.S .wait
CMPI.W #$52,D1
BGT.S .wait
CMPI.W #$C5,D0 loop if not on yes or no buttons
BLT.S .yes
CMPI.W #$EA,D0
BLT.S .wait
BSR.S toggle_rusure_icon restore screen
MOVEQ #-1,D0
RTS
.yes BSR.S toggle_rusure_icon
MOVEQ #0,D0
RTS
toggle_rusure_icon
LEA main_screen+$834,A0 toggle 'are you sure?' message
LEA rusure_icon,A1 on to screen
MOVEQ #39-1,D0
.row MOVEQ #13-1,D1
.column MOVE.B 10240(A0),D2
MOVE.B 39*14(A1),10240(A0)
MOVE.B D2,39*14(A1)
MOVE.B (A0),D2
MOVE.B (A1),(A0)+
MOVE.B D2,(A1)+
DBRA D1,.column
ADD.L #40-13,A0
ADDQ.L #1,A1
DBRA D0,.row
RTS
wait_for_vpos
MOVE.L _custom+vposr,D1 wait till vpos = d0
LSR.L #8,D1
AND.W #511,D1
CMP.W D1,D0
BNE.S wait_for_vpos
RTS
arrow_is_cyan
MOVE.L cptr_arrow_col,A0
MOVE.W #$0AA,2(A0)
MOVE.W #$077,6(A0)
MOVE.W #$044,10(A0)
RTS
arrow_is_grey
MOVE.L cptr_arrow_col,A0
MOVE.W #$AAA,2(A0)
MOVE.W #$777,6(A0)
MOVE.W #$444,10(A0)
RTS
arrow_is_green
MOVE.L cptr_arrow_col,A0
MOVE.W #$0A0,2(A0)
MOVE.W #$070,6(A0)
MOVE.W #$040,10(A0)
RTS
arrow_is_yellow
MOVE.L cptr_arrow_col,A0
MOVE.W #$BA0,2(A0)
MOVE.W #$970,6(A0)
MOVE.W #$740,10(A0)
RTS
arrow_is_blue
MOVE.L cptr_arrow_col,A0
MOVE.W #$05B,2(A0)
MOVE.W #$049,6(A0)
MOVE.W #$006,10(A0)
RTS
arrow_is_magenta
MOVE.L cptr_arrow_col,A0
MOVE.W #$A5A,2(A0)
MOVE.W #$727,6(A0)
MOVE.W #$404,10(A0)
RTS
arrow_flash_red
MOVE.W #1,memory_flag
MOVE.L cptr_arrow_col,A0
MOVE.W #$C00,2(A0)
MOVE.W #$900,6(A0)
MOVE.W #$700,10(A0)
MOVEQ #15,D1
.wait BSR wait_20ms wait 1/3 second
DBRA D1,.wait
BRA arrow_is_grey back to grey mouse
check_help
BSR check_hallonsoft_mode check for hallonsoft typed
CMP.B #$5F,key_code if key = HELP then
BNE.S return2
* GOTO PLST SCREEN
fn_goto_plst
CMP.W #3,mode skip if mode=diskops
BEQ.S return2
CLR.B key_code clear key
TST.W plst_flag if plst flag set then
BEQ.S set_plst_mode
cancel_plst_mode
MOVE.W #1,mode editor mode
BSR clear_screen_topright
BSR toggle_plst_screen remove plst screen
BSR goto_editor_mode
NOT.W plst_flag clear plst flag
MOVE.W #13107,D0 wait 15ms
.wait DBRA D0,.wait
RTS
set_plst_mode
MOVE.W #4,mode else mode=plst
NOT.W plst_flag set plst flag
BSR clear_screen_topright
BSR toggle_plst_screen show plst screen
BSR refresh_plst_screen
MOVE.W #$F21A,D0 wait 70ms
.wait DBRA D0,.wait
return2 RTS
* GET INSTR FROM PLST
* entry d1=file 0..11 from menu
plst_file_select
LEA plst_indices,A0 get index
ASL.W #2,D1
MOVE.L 0(A0,D1.W),D1
BMI.S .skip
DIVU #in_size,D1 /size+1=entry no.
ADDQ.W #1,D1
MOVE.W D1,plst_entry_no
BSR get_plst_file
.skip RTS
mountlist_getdrive
CLR.L FileInfoBlock+8 clear name
CLR.L FileInfoBlock+12
CLR.L FileInfoBlock+16
MOVE.L DOSbase,A6
MOVE.L A4,D1
MOVEQ #-2,D2
JSR _LVOLock(A6) lock file
MOVE.L D0,lock_ptr
BEQ.S .error
MOVE.L lock_ptr,D1
MOVE.L #FileInfoBlock,D2 get info
JSR _LVOExamine(A6)
TST.L D0
BEQ.S .error
MOVE.L lock_ptr,D1
JSR _LVOUnLock(A6)
MOVEQ #-1,D0
RTS
.error MOVEQ #-1,D0
RTS
DF0_msg dc.b 'DF0:',0
even
DF1_msg dc.b 'DF1:',0
even
DF2_msg dc.b 'DF2:',0
even
mountlist_nodisk
MOVEQ #-1,D0
RTS
mountlist_getname
MOVE.W FileInfoBlock+8,D0 name
BEQ.S mountlist_nodisk skip if no disk in drive
MOVE.W #'ST',D1 check for ST disk
AND.W #$1F1F,D0
AND.W #$1F1F,D1
CMP.W D0,D1
BNE.S .notst if so then copy number
MOVE.B FileInfoBlock+11,3(A0) to search disk
MOVE.B FileInfoBlock+12,4(A0)
MOVEQ #0,D0
RTS
.notst CLR.B 3(A0) else cancel search disk
CLR.B 4(A0)
RTS
* MOUNTLIST
fn_mountlist
MOVEQ #0,D0 cancel search disks
MOVE.B D0,search1+3
MOVE.B D0,search1+4
MOVE.B D0,search2+3
MOVE.B D0,search2+4
MOVE.B D0,search3+3
MOVE.B D0,search3+4
MOVE.W #1,stop_request disable auto_request for empty drives
LEA DF0_msg(PC),A4 check each drive and
LEA dir_buffer(PC),A5 mount any ST disks
BSR mountlist_getdrive
LEA search1(PC),A0
BSR mountlist_getname
LEA DF1_msg(PC),A4
LEA dir_buffer(PC),A5
BSR mountlist_getdrive
LEA search2(PC),A0
BSR mountlist_getname
LEA DF2_msg(PC),A4
LEA dir_buffer(PC),A5
BSR mountlist_getdrive
LEA search3(PC),A0
BSR mountlist_getname
CLR.W stop_request enable auto_request
BSR plst_scan_search
BSR refresh_plst_screen
RTS
alter_search1
LEA search1+3,A6
MOVE.W #$9C,input_cursor_x
BRA.S alter_search_disk
alter_search2
LEA search2+3,A6
MOVE.W #$CC,input_cursor_x
BRA.S alter_search_disk
alter_search3
LEA search3+3,A6
MOVE.W #$FC,input_cursor_x
alter_search_disk
CLR.B (A6) cancel name, ST-__
CLR.B 1(A6)
BSR save_arrow_colours
BSR arrow_is_magenta
BSR print_plst_search_disks
MOVE.W #$14,input_cursor_y
BSR set_input_cursor
BSR wait_number_or_enter if enter then clear & exit
CMPI.B #$44,D1
BEQ.S .abort
ADD.B #'0',D1
MOVE.B D1,(A6)
ADDQ.W #8,input_cursor_x
BSR print_plst_search_disks
BSR set_input_cursor
BSR wait_number_or_enter
CMPI.B #$44,D1
BEQ.S .abort
ADD.B #'0',D1
MOVE.B D1,1(A6)
BSR plst_scan_search
BSR refresh_plst_screen
CLR.W input_cursor_x
MOVE.W #$10E,input_cursor_y
BSR set_input_cursor
BRA restore_arrow_colours
.abort CLR.B (A6)
CLR.B 1(A6)
BSR restore_arrow_colours
CLR.W input_cursor_x
MOVE.W #$10E,input_cursor_y
BSR set_input_cursor
BSR plst_scan_search
BRA refresh_plst_screen
* exit d1=0..9 : number key
* $44 : ENTER/RIGHT BUTTON
wait_number_or_enter
CLR.B key_code clear key
.wait BTST #2,_custom+potinp if right button then return ENTER
BEQ.S .enter
TST.B key_code loop if key = '
BEQ.S .wait
MOVE.B key_code,D1 if key = ENTER then return
CMPI.B #$44,D1
BEQ .key
CMPI.B #10,D1 if key = '0'..'9' then
BHI.S .wait return 0..9
BNE.S .key
CLR.B D1
.key CLR.B key_code
RTS
.enter MOVE.B #$44,D1
RTS
scroll_plst_up
MOVE.W plst_cursor,D0
MOVE.W D0,D2
ADD.W alter_dir,D0
TST.W key_lshift
BNE.S .fast
BTST #2,_custom+potinp
BNE.S .slow
.fast SUB.W #9,D0
.slow TST.W D0
BPL.S scroll_plst_update
CLR.W D0
BRA.S scroll_plst_update
scroll_plst
TST.W alter_dir
BMI.S scroll_plst_up
MOVE.W plst_cursor,D0
MOVE.W D0,D2
ADD.W alter_dir,D0
TST.W key_lshift
BNE.S .fast
BTST #2,_custom+potinp
BNE.S .slow
.fast ADD.W #9,D0
.slow MOVE.W plst_active_entries,D1
SUB.W #12,D1
CMP.W D0,D1
BGE.S scroll_plst_update
MOVE.W D1,D0
NOP
scroll_plst_update
BSR.S .getfirst
BRA refresh_plst_screen
.getfirst
MOVE.W plst_cursor,D1
MOVE.W D0,plst_cursor
CMP.W D0,D1
BEQ return
TST.W D0
BEQ.S .clear
SUBQ.W #1,D0
MOVE.L plst_ptr,A0
MOVEQ #0,D6
.loop CMP.W #'ST',0(A0,D6.L)
BEQ.S .active
ADD.L #in_size,D6
BRA.S .loop
.active ADD.L #in_size,D6
DBRA D0,.loop
MOVE.L D6,plst_indices
RTS
.clear CLR.L plst_indices
RTS
search1 dc.b 'ST-',0,0,':' plst search disks
search2 dc.b 'ST-',0,0,':'
search3 dc.b 'ST-',0,0,':'
plst_scan_all_on
MOVE.W #'ST',(A0) if no active search disks then
ADD.L #in_size,A0 flag all entries active
DBRA D7,plst_scan_all_on
MOVE.W plst_entries,plst_active_entries full plst
MOVE.L plst_size,plst_active_size
CLR.W plst_cursor
CLR.L plst_indices
RTS
plst_scan_all_off
CLR.W plst_active_entries clear plst
CLR.L plst_active_size
CLR.W plst_cursor
CLR.L plst_indices
RTS
plst_scan_search
TST.L plst_ptr skip if on plst
BEQ.S plst_scan_all_off
MOVE.L plst_ptr,A0 else scan plst
MOVE.W plst_entries,D7
SUBQ.W #1,D7
TST.B search1+3 if any active search disks then
BNE.S .look
TST.B search2+3
BNE.S .look
TST.B search3+3
BEQ.S plst_scan_all_on
.look MOVE.L search1+2,A3
MOVE.L search2+2,A4
MOVE.L search3+2,A5
MOVEQ #0,D6 d6=count of active entries
.loop MOVE.W #'st',(A0) inactive = st....
MOVE.L 2(A0),D0
CMP.L A3,D0 if disk name match then
BNE.S .try2
MOVE.W #'ST',(A0) set active = ST....
ADDQ.W #1,D6
BRA.S .next
.try2 CMP.L A4,D0
BNE.S .try3
MOVE.W #'ST',(A0)
ADDQ.W #1,D6
BRA.S .next
.try3 CMP.L A5,D0
BNE.S .next
MOVE.W #'ST',(A0)
ADDQ.W #1,D6
.next ADD.L #in_size,A0
DBRA D7,.loop
MOVE.W D6,plst_active_entries
MULU #in_size,D6
MOVE.L D6,plst_active_size
CLR.W plst_cursor
CLR.L plst_indices
RTS
print_plst_search_disks
TST.W plst_flag if plst flag set then
BEQ return2
MOVE.L #15*40+16,char_offset print search disks
MOVE.L #5,string_size
MOVE.L #search1,string_addr
BSR print_string
ADDQ.L #1,char_offset
MOVE.L #search2,string_addr
BSR print_string
ADDQ.L #1,char_offset
MOVE.L #search3,string_addr
BRA print_string
refresh_plst_screen
TST.W plst_flag if plst flag set then
BEQ return2
MOVE.W plst_active_entries,word_to_print
MOVE.L #4*40+25,char_offset no. of active samples in plst
BSR print_dec4
BSR print_plst_search_disks print search disks
TST.L plst_ptr skip if no plst loaded
BEQ return2 print sample names in list
MOVE.L plst_indices,D6 d6=1st sample index
MOVE.L plst_ptr,A6 a6=plst
MOVE.L #24*40+16,A5 a5=char_offset
LEA plst_indices,A4 a4=indices of shown samples
MOVEQ #12-1,D7 show up to 12 names
.names CMP.W #'ST',0(A6,D6.L) if name=ST... then
BNE.S .notst
MOVE.L D6,(A4)+ store sample index
MOVE.L A5,char_offset print sample name
MOVE.L #19,string_size
LEA 0(A6,D6.L),A3
ADDQ.L #3,A3
MOVE.L A3,string_addr
BSR print_string_spc
MOVE.W 22(A6,D6.L),word_to_print print size in bytes
ASL word_to_print
BSR print_hex4
ADD.L #in_size,D6 next index
CMP.L plst_size,D6
BGT.S .nomore
ADD.L #6*40,A5
DBRA D7,.names
RTS
.notst ADD.L #in_size,D6 if name<>ST.. then
CMP.L plst_size,D6 skip over
BGT.S .nomore
BRA.S .names
.nomore MOVE.L #-1,(A4)+ remaining indices empty
MOVE.L A5,char_offset
MOVE.L #23,string_size
MOVE.L #null_string,string_addr print spaces
BSR print_string_spc
ADD.L #6*40,A5
DBRA D7,.nomore
RTS
toggle_plst_screen
LEA main_screen+40+15,A0
LEA plst_screen,A1
MOVEQ #99-1,D0
.row MOVEQ #25-1,D1
.column MOVE.B 10240(A0),D2
MOVE.B 99*26(A1),10240(A0)
MOVE.B D2,99*26(A1)
MOVE.B (A0),D2
MOVE.B (A1),(A0)+
MOVE.B D2,(A1)+
DBRA D1,.column
ADD.L #40-25,A0
ADDQ.L #1,A1
DBRA D0,.row
RTS
plst_flash_error
BSR refresh_plst_screen
BRA arrow_flash_red
* LOAD PLST
fn_load_plst
MOVE.W #145,D0
BSR wait_for_vpos
MOVE.L screen_ptr,A1 clear filenames window
ADD.L #23*40+15,A1
MOVEQ #75-1,D6
.row MOVEQ #25-1,D5
.column CLR.B (A1)+
DBRA D5,.column
ADD.L #40-25,A1
DBRA D6,.row
BSR check_are_you_sure make sure
TST.L D0
BNE.S plst_flash_error
CLR.B search1+3 cancel search disks
CLR.B search1+4
CLR.B search2+3
CLR.B search2+4
CLR.B search3+3
CLR.B search3+4
BSR save_arrow_colours
BSR arrow_is_green
MOVE.L plst_ptr,A1 free old list memory
BEQ.S .free
MOVE.L plst_size,D0
MOVE.L 4.w,a6
JSR _LVOFreeMem(A6)
CLR.L plst_ptr
CLR.L plst_size
CLR.W plst_entries
BSR clear_screen_topright
.free MOVE.L DOSbase,A6 check for plst
MOVE.L #plst_name,D1
MOVEQ #-2,D2
JSR _LVOLock(A6)
MOVE.L D0,D7
BEQ .error
MOVE.L D7,D1
MOVE.L #FileInfoBlock,D2
JSR _LVOExamine(A6)
TST.L D0
BEQ .error
MOVE.L D7,D1
JSR _LVOUnLock(A6)
LEA FileInfoBlock,A0
MOVE.L 124(A0),D0 size
MOVE.L D0,plst_size
DIVU #in_size,D0
MOVE.W D0,plst_entries no. of filenames
MOVE.L plst_size,D0
CLR.L plst_ptr
MOVEQ #0,D1
MOVE.L 4.w,a6
JSR _LVOAllocMem(A6) allocate
BEQ.S .error
MOVE.L D0,plst_ptr
MOVE.L #plst_name,D1
MOVE.L #1005,D2 read
MOVE.L DOSbase,A6
JSR _LVOOpen(A6)
MOVE.L D0,D7
BEQ.S .error
MOVE.L D7,D1
MOVE.L plst_ptr,D2
MOVE.L plst_size,D3
JSR _LVORead(A6)
CMP.L plst_size,D0
BNE .error
MOVE.L D7,D1
JSR _LVOClose(A6)
MOVE.W #1,plst_entry_no
BSR refresh_song_parameters
BSR plst_scan_search
BSR refresh_plst_screen
BRA restore_arrow_colours
.error BSR arrow_flash_red
BSR plst_scan_search
BSR refresh_plst_screen
BRA restore_arrow_colours
check_f6_to_f10
TST.L play_mode
BEQ.S .f6
RTS
.f6 CMP.B #$55,key_code if key = F6 then
BNE.S .f7
CLR.W edit_cursor_y goto top
BSR set_edit_scroller
CLR.B key_code
RTS
.f7 CMP.B #$56,key_code if key = F7 then
BNE.S .f8
MOVE.W #16,edit_cursor_y goto pos 16
BSR set_edit_scroller
CLR.B key_code
RTS
.f8 CMP.B #$57,key_code if key = F8 then
BNE.S .f9
MOVE.W #32,edit_cursor_y goto pos 32
BSR set_edit_scroller
CLR.B key_code
RTS
.f9 CMP.B #$58,key_code if key = F9 then
BNE.S .f10
MOVE.W #48,edit_cursor_y goto pos 48
BSR set_edit_scroller
CLR.B key_code
RTS
.f10 CMP.B #$59,key_code if key = F10 then
BNE.S .skip
MOVE.W #63,edit_cursor_y goto pos 63
BSR set_edit_scroller
CLR.B key_code
.skip RTS
check_cut_paste
TST.W key_lshift
BNE.S .voice4
MOVEQ #0,D0
MOVE.L D0,A0
TST.W key_lalt
BNE.S .got
RTS
.voice4 CMP.W #18,edit_cursor_x
BNE.S .voice3
MOVEQ #12,D0
MOVE.L D0,A0
BRA.S .got
.voice3 CMP.W #12,edit_cursor_x
BNE.S .voice2
MOVEQ #8,D0
MOVE.L D0,A0
BRA.S .got
.voice2 CMP.W #6,edit_cursor_x
BNE.S .voice1
MOVEQ #4,D0
MOVE.L D0,A0
BRA.S .got
.voice1 TST.W edit_cursor_x
BNE.S .skip
MOVEQ #0,D0
MOVE.L D0,A0
BRA.S .got
.skip RTS
.got ADD.L song_file_ptr,A0 a0=address of voice in pattern
ADD.L #sf_patterns,A0
MOVE.L pattern_no,D0
LSL.L #8,D0
LSL.L #2,D0
ADD.L D0,A0
TST.W key_lalt
BNE.S .whole
CMP.B #$52,key_code F3
BEQ cut_voice
CMP.B #$53,key_code F4
BEQ copy_voice
CMP.B #$54,key_code F5
BEQ paste_voice
RTS
.whole CMP.B #$52,key_code F3
BEQ.S cut_whole
CMP.B #$53,key_code F4
BEQ.S copy_whole
CMP.B #$54,key_code F5
BEQ.S paste_whole
RTS
cut_whole
LEA cutwhole_buffer,A1
CLR.W D0
.loop MOVE.L 0(A0,D0.W),(A1)+
CLR.L 0(A0,D0.W)
ADDQ.W #4,D0
CMPI.W #1024,D0
BNE.S .loop
CLR.B key_code
BRA refresh_pattern_display
copy_whole
LEA cutwhole_buffer,A1
CLR.W D0
.loop MOVE.L 0(A0,D0.W),(A1)+
ADDQ.W #4,D0
CMPI.W #1024,D0
BNE.S .loop
CLR.B key_code
RTS
paste_whole
LEA cutwhole_buffer,A1
CLR.W D0
.loop MOVE.L (A1)+,0(A0,D0.W)
ADDQ.W #4,D0
CMPI.W #1024,D0
BNE.S .loop
CLR.B key_code
BRA refresh_pattern_display
cut_voice
LEA cutvoice_buffer,A1
CLR.W D0
.loop MOVE.L 0(A0,D0.W),(A1)+
CLR.L 0(A0,D0.W)
ADD.W #16,D0
CMPI.W #1024,D0
BNE.S .loop
CLR.B key_code
BRA refresh_pattern_display
copy_voice
LEA cutvoice_buffer,A1
CLR.W D0
.loop MOVE.L 0(A0,D0.W),(A1)+
ADD.W #16,D0
CMPI.W #1024,D0
BNE.S .loop
CLR.B key_code
RTS
paste_voice
LEA cutvoice_buffer,A1
CLR.W D0
.loop MOVE.L (A1)+,0(A0,D0.W)
ADD.W #16,D0
CMPI.W #1024,D0
BNE.S .loop
CLR.B key_code
BRA refresh_pattern_display
check_octave_keys
CMP.B #$50,key_code if key = F1 then octave 1-2
BEQ.S .oct12
CMP.B #$51,key_code if key = F2 then octave 2-3
BEQ.S .oct23
RTS
.oct12 MOVE.L #oct1_2_periods,octave_periods
MOVE.L #oct1_2_names,octave_names
CLR.B key_code
RTS
.oct23 MOVE.L #oct2_3_periods,octave_periods
MOVE.L #oct2_3_names,octave_names
CLR.B key_code
RTS
set_arrow_position
MOVE.W mouse_x,D0
ADDQ.W #3,D0
MOVE.W mouse_y,D1
MOVEQ #17,D2
MOVE.L arrow_spr_ptr,A0
BRA position_sprite
edit_hex_parameters
CMP.L #'edit',edit_mode
BEQ.S .edit
RTS
.edit LEA hex_keys,A0 allow 0..9A..F only
MOVEQ #0,D0
MOVEQ #0,D1
MOVE.B key_code,D0
.find CMP.B (A0)+,D0
BEQ.S .pos1
ADDQ.B #1,D1
CMPI.B #$10,D1
BEQ.S .skip
BRA.S .find
.skip RTS
.pos1 CMP.W #1,edit_cursor_x
BNE.S .pos2
CMPI.W #1,D1
BGT.S .skip
MOVE.L #$FFF,D2
CLR.W edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA .done
.pos2 CMP.W #2,edit_cursor_x
BNE.S .pos3
MOVE.L #$FFF,D2
MOVE.W #2,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA .done
.pos3 CMP.W #3,edit_cursor_x
BNE.S .pos4
MOVE.L #$F0FF,D2
MOVE.W #2,edh_index
LSL.W #8,D1
BRA .done
.pos4 CMP.W #4,edit_cursor_x
BNE.S .pos5
MOVE.L #$FF0F,D2
MOVE.W #2,edh_index
LSL.W #4,D1
BRA .done
.pos5 CMP.W #5,edit_cursor_x
BNE.S .pos7
MOVE.L #$FFF0,D2
MOVE.W #2,edh_index
BRA .done
.pos7 CMP.W #7,edit_cursor_x
BNE.S .pos8
CMPI.W #1,D1
BGT .skip
MOVE.L #$FFF,D2
MOVE.W #4,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA .done
.pos8 CMP.W #8,edit_cursor_x
BNE.S .pos9
MOVE.L #$FFF,D2
MOVE.W #6,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA .done
.pos9 CMP.W #9,edit_cursor_x
BNE.S .pos10
MOVE.L #$F0FF,D2
MOVE.W #6,edh_index
LSL.W #8,D1
BRA .done
.pos10 CMP.W #10,edit_cursor_x
BNE.S .pos11
MOVE.L #$FF0F,D2
MOVE.W #6,edh_index
LSL.W #4,D1
BRA .done
.pos11 CMP.W #11,edit_cursor_x
BNE.S .pos13
MOVE.L #$FFF0,D2
MOVE.W #6,edh_index
BRA .done
.pos13 CMP.W #13,edit_cursor_x
BNE.S .pos14
CMPI.W #1,D1
BGT .skip
MOVE.L #$FFF,D2
MOVE.W #8,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA .done
.pos14 CMP.W #14,edit_cursor_x
BNE.S .pos15
MOVE.L #$FFF,D2
MOVE.W #10,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA .done
.pos15 CMP.W #15,edit_cursor_x
BNE.S .pos16
MOVE.L #$F0FF,D2
MOVE.W #10,edh_index
LSL.W #8,D1
BRA .done
.pos16 CMP.W #16,edit_cursor_x
BNE.S .pos17
MOVE.L #$FF0F,D2
MOVE.W #10,edh_index
LSL.W #4,D1
BRA .done
.pos17 CMP.W #17,edit_cursor_x
BNE.S .pos19
MOVE.L #$FFF0,D2
MOVE.W #10,edh_index
BRA .done
.pos19 CMP.W #19,edit_cursor_x
BNE.S .pos20
CMPI.W #1,D1
BGT .skip
MOVE.L #$FFF,D2
MOVE.W #12,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA.S .done
.pos20 CMP.W #20,edit_cursor_x
BNE.S .pos21
MOVE.L #$FFF,D2
MOVE.W #14,edh_index
LSL.W #4,D1
LSL.W #8,D1
BRA.S .done
.pos21 CMP.W #21,edit_cursor_x
BNE.S .pos22
MOVE.L #$F0FF,D2
MOVE.W #14,edh_index
LSL.W #8,D1
BRA.S .done
.pos22 CMP.W #22,edit_cursor_x
BNE.S .pos23
MOVE.L #$FF0F,D2
MOVE.W #14,edh_index
LSL.W #4,D1
BRA.S .done
.pos23 MOVE.L #$FFF0,D2
MOVE.W #14,edh_index
.done MOVE.L song_file_ptr,A0 index pattern
ADD.L #sf_patterns,A0
MOVE.L pattern_no,D0
LSL.L #8,D0
LSL.L #2,D0
ADD.L D0,A0
MOVEQ #0,D0
MOVE.W edit_cursor_y,D0
LSL.W #4,D0
EXT.L D0
ADD.L D0,A0
ADD.W edh_index,A0 + parameter index
AND.W D2,(A0) mask old value
ADD.W D1,(A0) add new value
MOVE.W (A0),word_to_print
MOVEQ #0,D0
MOVE.W edit_cursor_y,D0
MULU #$118,D0
MOVE.W edit_cursor_x,D1
DIVU #6,D1
MULU #9,D1
ADD.L D1,D0
ADD.L #$1D68,D0
MOVE.L D0,char_offset
TST.W edh_index print value
BEQ.S .print1
CMP.W #4,edh_index
BEQ.S .print1
CMP.W #8,edh_index
BEQ.S .print1
CMP.W #12,edh_index
BEQ.S .print1
BSR print_hex4
.exit BSR edit_cursor_down
CLR.B key_code
RTS
.print1 SUBQ.L #1,char_offset
MOVE.L #1,string_size
MOVEQ #0,D0
MOVE.W (A0),D0
AND.W #$F000,D0
LSR.W #4,D0
LSR.W #7,D0
ADD.L #hex2ascii+1,D0
MOVE.L D0,string_addr
BSR print_string
BRA.S .exit
check_edit_pattern
TST.B key_code
BNE.S .key
RTS
.key MOVE.W edit_cursor_x,D0 if position 0,6,12,18 then
BEQ.S .piano piano key else hex key
CMPI.W #6,D0
BEQ.S .piano
CMPI.W #12,D0
BEQ.S .piano
CMPI.W #18,D0
BEQ.S .piano
CMP.L #'edit',edit_mode
BEQ edit_hex_parameters
RTS
.piano MOVEQ #0,D1
LEA piano_keys,A0
MOVE.B key_code,D1
MOVEQ #0,D0
.find MOVE.L D0,D4 check if piano key
CMP.B 0(A0,D0.W),D1
BEQ.S .found
ADDQ.B #1,D0
CMPI.B #39,D0
BNE.S .find
RTS
.found CLR.B key_code cancel key
ASL.W #1,D0
ASL.W #1,D4
MOVEQ #0,D3
MOVE.L octave_periods,A1 convert to period
MOVE.W 0(A1,D0.L),D3
MOVE.W D3,keyplay_period
TST.L edit_mode
BEQ .play
MOVE.L song_file_ptr,A0 if edit mode then
ADD.L #sf_patterns,A0 insert into pattern
MOVE.L pattern_no,D0
LSL.L #8,D0
LSL.L #2,D0
ADD.L D0,A0
MOVEQ #0,D0
MOVE.W edit_cursor_y,D0
BSR quantize
LSL.W #4,D0
EXT.L D0
ADD.L D0,A0
MOVE.W edit_cursor_x,D0
DIVU #6,D0
LSL.W #2,D0
EXT.L D0
ADD.L D0,A0
MOVE.W D3,(A0)
TST.W keyplay_period if no note then clear instr no.
BEQ.S .nonote else set
MOVEQ #0,D0
MOVE.W current_instr,D0
LSL.W #4,D0
AND.B #15,2(A0)
ADD.B D0,2(A0)
LSL.W #4,D0
AND.W #$F000,D0
OR.W D0,(A0)
BRA.S .print
.nonote AND.W #$FFF,2(A0)
.print MOVE.W 2(A0),temp print note
MOVE.L octave_names,A0
LSL.W #1,D4
EXT.L D4
ADD.L D4,A0
MOVE.L A0,string_addr
MOVE.L #3,string_size
MOVEQ #0,D0
MOVE.W edit_cursor_y,D0
BSR quantize
MULU #$118,D0
MOVEQ #0,D1
MOVE.W edit_cursor_x,D1
DIVU #6,D1
MULU #9,D1
ADD.L D1,D0
ADD.L #$1D64,D0
MOVE.L D0,char_offset
BSR print_string
BSR print_hex_instr
MOVE.W temp,word_to_print
BSR print_hex4
BSR edit_cursor_down
.play TST.W quantize_flag if note this time slot then play
BNE.S .exit
TST.W keyplay_period
BNE.S .voice4
.exit RTS
.voice4 MOVE.L #0,A5
CMP.W #18,edit_cursor_x
BNE.S .voice3
LEA _custom+aud3,A5
LEA audio_info_4,A4
MOVE.W #8,keyplay_channel
BRA play_editkey
.voice3 CMP.W #12,edit_cursor_x
BNE.S .voice2
LEA _custom+aud2,A5
LEA audio_info_3,A4
MOVE.W #4,keyplay_channel
BRA.S play_editkey
.voice2 CMP.W #6,edit_cursor_x
BNE.S .voice1
LEA _custom+aud1,A5
LEA audio_info_2,A4
MOVE.W #2,keyplay_channel
BRA.S play_editkey
.voice1 TST.W edit_cursor_x
BNE.S .skip
LEA _custom+aud0,A5
LEA audio_info_1,A4
MOVE.W #1,keyplay_channel
BRA.S play_editkey
.skip RTS
quantize
TST.L play_mode if play mode then
BEQ.S .ok
MOVE.L tempo,D1 if note played over half-way
ASR.L #1,D1 thru a note duration then
CMP.L frame_count,D1 note in next slot, no sound
BLE.S .over
.ok CLR.W quantize_flag
RTS
.over ADDQ.W #1,D0
AND.W #$3F,D0
MOVE.W #1,quantize_flag
RTS
play_editkey
LEA instr_length,A6
MOVE.W instr_repeat-instr_length(A6),D0
BNE.S .rep
MOVE.W (A6),D0
BRA.S .norep
.rep ADD.W instr_replen-instr_length(A6),D0
.norep MOVE.W instr_volume-instr_length(A6),ac_vol(A5)
MOVE.W keyplay_period,$10(A4)
CLR.B $1B(A4)
CLR.W $18(A4)
MOVE.W keyplay_period,ac_per(A5)
MOVE.W keyplay_channel,D2
MOVE.W D2,_custom+dmacon
MOVE.L instr_addr-instr_length(A6),(A5)
MOVE.W D0,ac_len(A5)
MOVEQ #0,D1
MOVE.W instr_repeat-instr_length(A6),D1
ASL.W #1,D1
ADD.L instr_addr-instr_length(A6),D1
MOVE.L D1,10(A4)
MOVE.W instr_replen-instr_length(A6),14(A4)
MOVE.W keyplay_period,D0
BSR add_keyplay_to_spectrum
MOVE.W #$12C,D0
.wait DBRA D0,.wait
MOVE.W keyplay_channel,D0
AND.W onoff_states,D0
OR.W #$8000,D0
MOVE.W D0,_custom+dmacon
MOVE.W #$12C,D0
.wait2 DBRA D0,.wait2
LEA instr_length,A6
MOVE.L D1,(A5)
MOVE.W instr_replen-instr_length(A6),ac_len(A5)
CLR.W keyplay_channel
RTS
check_cursor_keys
MOVE.B key_code,D0
CMPI.B #$4E,D0
BEQ cursor_right
CMPI.B #$4F,D0
BEQ cursor_left
CMPI.B #$4C,D0
BEQ.S cursor_up
CMPI.B #$4D,D0
BEQ cursor_down
CLR.W cursor_rep_flag
RTS
fscroll_up
MOVE.W #1,fscroll_pending diskop scroll up/down
RTS
fscroll_down
MOVE.W #2,fscroll_pending
RTS
pscroll_up
MOVE.W #1,pscroll_pending plst scroll up/down
RTS
pscroll_down
MOVE.W #2,pscroll_pending
RTS
cursor_up
CMP.W #3,mode if diskops then scroll files
BEQ.S fscroll_up
TST.W plst_flag if plst then scroll files
BNE.S pscroll_up
TST.W cursor_rep_flag if already pressed then
BEQ.S .move auto repeat
ADDQ.W #1,cursor_rep_count
TST.W key_lshift faster if shift/alt
BNE.S .shift
TST.W key_lalt
BNE.S .alt
CMP.W #6,cursor_rep_count
BPL.S .move
RTS
.shift CMP.W #3,cursor_rep_count
BPL.S .move
RTS
.alt CMP.W #1,cursor_rep_count
BPL.S .move
RTS
.move CLR.W cursor_rep_count
MOVE.W #$FFFF,cursor_rep_flag
CMP.L #'patt',play_mode if not playing then
BEQ.S .skip
CMP.L #'patp',play_mode
BEQ.S .skip
SUBQ.W #1,edit_cursor_y edit cursor up
AND.W #$3F,edit_cursor_y
BRA set_edit_scroller
.skip RTS
cursor_down
CMP.W #3,mode
BEQ fscroll_down
TST.W plst_flag
BNE pscroll_down
TST.W cursor_rep_flag
BEQ.S edit_cursor_down
ADDQ.W #1,cursor_rep_count
TST.W key_lshift
BNE.S .shift
TST.W key_lalt
BNE.S .alt
CMP.W #6,cursor_rep_count
BPL.S edit_cursor_down
RTS
.shift CMP.W #3,cursor_rep_count
BPL.S edit_cursor_down
RTS
.alt CMP.W #1,cursor_rep_count
BPL.S edit_cursor_down
RTS
edit_cursor_down
CLR.W cursor_rep_count
MOVE.W #$FFFF,cursor_rep_flag
CMP.L #'patt',play_mode
BEQ.S ecd_skip
CMP.L #'patp',play_mode
BEQ.S ecd_skip
ADDQ.W #1,edit_cursor_y edit cursor down
AND.W #$3F,edit_cursor_y
BRA set_edit_scroller
ecd_skip
RTS
cursor_right
TST.W input_in_progress
BNE.S ecd_skip
TST.W key_lshift
BNE.S cursor_position_right
TST.W key_lalt
BNE.S cursor_pattern_right
TST.W cursor_rep_flag
BEQ cursor_right_move
ADDQ.W #1,cursor_rep_count
CMP.W #6,cursor_rep_count
BPL cursor_right_move
.skip RTS
cursor_position_left
MOVEQ #-1,D0
BRA.S cursor_position_lr
cursor_position_right
MOVEQ #1,D0
cursor_position_lr
TST.W cursor_rep_flag
BEQ.S .move
ADDQ.W #1,cursor_rep_count
CMP.W #5,cursor_rep_count
BPL.S .move
RTS
.move CLR.W cursor_rep_count
MOVE.W #$FFFF,cursor_rep_flag
CMP.L #'patp',play_mode
BEQ return
MOVE.L D0,pat_pos_dir
MOVE.W #1,pat_pos_flag
RTS
cursor_pattern_left
MOVEQ #-1,D0
BRA.S cursor_pattern_lr
cursor_pattern_right
MOVEQ #1,D0
cursor_pattern_lr
CMP.L #'patp',play_mode
BEQ return
MOVE.L D0,pat_pos_dir
MOVE.W #2,pat_pos_flag
CLR.B key_code
RTS
change_pattern
MOVE.L pat_pos_dir,D0
ADD.L D0,pattern_no
AND.L #$3F,pattern_no
BSR refresh_pattern_display
CLR.W pat_pos_flag
RTS
check_pat_or_pos
MOVE.W pat_pos_flag,D0
BEQ return
CMPI.W #2,D0
BEQ.S change_pattern
CLR.W pat_pos_flag
MOVE.L pat_pos_dir,D0
BMI.S .left
CMP.L #$7F,song_position
BEQ return
ADD.L D0,song_position
AND.L #$7F,song_position
BSR refresh_song_position
RTS
.left TST.L song_position
BEQ return
ADD.L D0,song_position
AND.L #$7F,song_position
BSR refresh_song_position
RTS
cursor_right_move
CLR.W cursor_rep_count
MOVE.W #$FFFF,cursor_rep_flag
ADDQ.W #1,edit_cursor_x edit cursor right
CMP.W #24,edit_cursor_x
BMI.S .ok
CLR.W edit_cursor_x
.ok BRA.S set_edit_cursor
cursor_left
TST.W input_in_progress
BNE return
TST.W key_lshift
BNE cursor_position_left
TST.W key_lalt
BNE cursor_pattern_left
TST.W cursor_rep_flag
BEQ.S .move
ADDQ.W #1,cursor_rep_count
CMP.W #6,cursor_rep_count
BPL.S .move
RTS
.move CLR.W cursor_rep_count
MOVE.W #$FFFF,cursor_rep_flag
SUBQ.W #1,edit_cursor_x edit cursor left
TST.W edit_cursor_x
BPL.S set_edit_cursor
MOVE.W #23,edit_cursor_x
set_edit_cursor
MOVE.W edit_cursor_x,D0 convert xpos to sprite x
LEA xpos2column,A0
MOVE.B 0(A0,D0.W),D0
LSL.W #3,D0
ADD.W #9,D0
MOVE.W #189,D1
MOVEQ #14,D2
LEA s_editcursor,A0
BRA position_sprite
set_input_cursor
MOVE.W input_cursor_x,D0
MOVE.W input_cursor_y,D1
SUBQ.W #1,D0
MOVEQ #2,D2
LEA s_inputcursor,A0
BRA position_sprite
check_arrow_and_cursor
BSR set_arrow_position
BSR check_cursor_keys
BSR.S check_arrow_functions
CMP.W #-1,rep_delay if =0 then
BEQ.S .nodel
MOVEQ #0,D0
.del ADDQ.L #1,D0
CMPI.L #40000,D0
BEQ.S .nodel
BTST #6,$BFE001 if button not released then
BEQ.S .del auto-repeat after 1/4 second
CLR.W alter_dir
BRA main_loop
.nodel MOVE.W #-1,rep_delay if =-1 then
BTST #6,$BFE001 if button not released then
BEQ.S check_arrow_and_cursor auto-repeat without delay
CLR.W rep_delay clear flag
CLR.W alter_dir
BRA main_loop
check_arrow_functions
MOVE.W mouse_x,mouse_x2 if mouse x=0,y=0 then
BNE.S .noquit
TST.W mouse_y
BNE.S .noquit
BSR fn_stop
BSR arrow_is_magenta
BSR check_are_you_sure quit if sure
BEQ restore_and_exit
BSR arrow_flash_red
.noquit MOVE.W mouse_y,mouse_y2
MOVE.W mouse_y2,D0
CMPI.W #122,D0 if y>=122 then edit pattern no
BGE input_pattern_no
CMPI.W #111,D0 if y>=111 then edit samplename
BGE input_instr_name
CMPI.W #100,D0 if y>=100 then edit songname
BGE input_song_name
MOVE.W mouse_x2,D0
TST.W plst_flag plst ?
BNE.S .plst
CMP.W #3,mode if mode=diskops then
BNE.S .nod
CMPI.W #120,D0 if x>=120 then diskops
BGE .diskop
.nod CMPI.W #244,D0 if x>=244 then toggle on/off icons
BGE check_toggle_on_off
CMPI.W #181,D0 if x>=181 then 2nd column
BGE .col2nd
CMPI.W #120,D0 if x>=120 then 1st column
BGE .col1st
.param
CMPI.W #120,D0 alter parameters
BGE.S .skip
CMPI.W #109,D0 if 109<=x<120 then parameter down
BGE alter_parameter_down
CMPI.W #98,D0 if 98<=x<109 then parameter up
BGE alter_parameter_up
.skip RTS else skip
.plst MOVEQ #0,D1 plst functions
MOVEM.W mouse_x2,D0/D1
CMPI.W #120,D0 if x<120 then alter parameters
BLT.S .param2
CMPI.W #11,D1 if y<=11 then
BGT.S .plst2
CMPI.W #$C1,D0 if x<=193 then load plst
BLE fn_load_plst
CMPI.W #$11C,D0 if x>=284 then exit plst
BGE cancel_plst_mode
RTS else skip
.plst2 CMPI.W #22,D1 if 11<y<=22 then
BGT.S .plst3
CMPI.W #268,D0 if x>=268 then mountlist
BGE fn_mountlist
CMPI.W #220,D0 if x>=220 then edit search3
BGE alter_search3
CMPI.W #172,D0 if x>=172 then edit search2
BGE alter_search2
CMPI.W #120,D0 if x>=120 then edit search1
BGE alter_search1
RTS else skip
.plst3 CMPI.W #312,D0 if 128<=x<=312
BGT.S .param2 and 24<=y<=95 then
CMPI.W #128,D0
BLT.S .param2
CMPI.W #24,D1
BLT.S .param2
CMPI.W #95,D1
BGT.S .param2
SUB.W #24,D1 d1=(y-24)/6=0..11
AND.L #$FF,D1
DIVU #6,D1
BRA plst_file_select file select
.param2 MOVE.W mouse_x2,D0 else alter parameters
BRA .param
.col2nd MOVE.W mouse_y2,D0 2nd column functions
CMP.W #3,mode if mode=diskops then
BNE.S .nod2
CMPI.W #44,D0 if y>=44 then file select
BGE diskop_file_select
.nod2 CMPI.W #44,D0
BGE.S .skip2
CMPI.W #34,D0 if 34<=y<44 then goto diskops
BGE fn_goto_diskops
CMPI.W #23,D0 if y>=23 then goto plst
BGE fn_goto_plst
CMPI.W #12,D0 if y>=12 then clear song
BGE fn_clear
TST.W D0 if y>=0 then stop
BGE fn_stop
.skip2 RTS
.col1st MOVE.W mouse_y2,D0 1st column functions
CMP.W #3,mode if mode=diskops then
BNE.S .nod3
CMPI.W #44,D0 if y>=44 then file select
BGE diskop_file_select
.nod3 CMPI.W #44,D0
BGE.S .skip2
CMPI.W #34,D0 if 34<=y<44 then record
BGE fn_record
CMPI.W #23,D0 if y>=23 then edit
BGE fn_edit
CMPI.W #12,D0 if y>=12 then play pattern
BGE fn_play_pattern
TST.W D0 if y>=0 then play song
BGE fn_play_song
RTS
.diskop MOVEM.W mouse_x2,D0/D1 diskop functions
CMP.W #3,mode
BNE.S .nodisk
CMPI.W #44,D1
BGE diskop_file_select
.nodisk CMPI.W #44,D1 if y>=44 then file select
BGE diskop_file_select
CMPI.W #34,D1 if y>=34 then edit module dir
BGE input_module_dir
CMPI.W #252,D0 if x<252 then song/module functions
BLT.S songmod_functions
CMPI.W #22,D1 if 22<=y<44 then toggle pack
BGE toggle_pack_icon
CMPI.W #11,D1 if y>=11 then save sample
BGE fn_save_sample
BRA fn_load_sample else load sample
toggle_pack_icon
EOR.W #1,pack_flag
BSR.S refresh_pack_icon
MOVE.W #$C800,D0
.wait DBRA D0,.wait
RTS
refresh_pack_icon
CMP.W #3,mode skip if mode<>diskops
BNE return
LEA main_screen+26*40+37,A1
LEA onoff_icon,A0 pack on/off
TST.W pack_flag
BNE.S .on
LEA onoff_icon+24,A0
.on BSR draw_on_off
RTS
pack_flag
dc.w 1 0=off/1=on
songmod_functions
CMPI.W #186,D0 songs/module functions
BLT.S .song if x>=186 then
CMPI.W #22,D1
BGE fn_delete_module if y>=22 then delete module
CMPI.W #11,D1
BGE fn_save_module if y>=11 then save module
BRA fn_load_module else load module
.song CMPI.W #22,D1 else
BGE fn_delete_song if y>=22 then delete song
CMPI.W #11,D1
BGE fn_save_song if y>=11 then save song
BRA fn_load_song else load song
* SAVE SAMPLE
fn_save_sample
BSR save_arrow_colours
CLR.B key_code
MOVEQ #0,D0
MOVE.W current_instr,D0 index instrument in song file
SUBQ.W #1,D0
MULU #in_size,D0
MOVE.L song_file_ptr,A0
ADD.L #sf_instr,A0
ADD.L D0,A0
MOVEQ #0,D0
MOVE.W in_length(A0),D0 byte length
ADD.L D0,D0
MOVE.L D0,file_length
LEA st01_msg+6(PC),A1
MOVEQ #22-1,D0
.name MOVE.B (A0)+,(A1)+
DBRA D0,.name
MOVE.L #st01_msg+6,file_nameptr
CMP.B #':',st01_msg+11 if no drive specifier then st-01
BEQ.S .drive
MOVE.L #st01_msg,file_nameptr
.drive LEA instr_addr_list,A0 get address
MOVEQ #0,D1
MOVE.W current_instr,D1
LSL.L #2,D1
MOVE.L 0(A0,D1.W),file_addr
BSR arrow_is_green
MOVE.L DOSbase,A6
MOVE.L file_nameptr,D1
MOVE.L #1006,D2 write
JSR _LVOOpen(A6)
MOVE.L D0,file_handle
BNE.S .ok error if can't open
BRA arrow_flash_red
.ok MOVE.L file_handle,D1
MOVE.L file_addr,D2
MOVE.L file_length,D3
JSR _LVOWrite(A6)
MOVE.L file_handle,D1
JSR _LVOClose(A6)
CLR.L file_handle
BSR restore_arrow_colours
RTS
* CLEAR SONG
fn_clear
MOVE.W #1,memory_flag
BSR fn_stop stop tune
BSR arrow_is_magenta
BSR check_are_you_sure make sure
BNE clear_aborted
fn_clear_nocheck
BSR free_instr_memory wipe instruments
MOVE.L song_file_ptr,A0
MOVE.L A0,A1
MOVE.L A1,A2
ADD.L #sf_size,A2 wipe song
.wpsong CLR.L (A1)+
CMP.L A1,A2
BNE.S .wpsong
LEA songs_dir_name(PC),A1 wipe name
MOVEQ #28-1,D0
.wpname CLR.B (A1)+
DBRA D0,.wpname
MOVE.L A0,A1 valid replen values
ADD.L #sf_instr,A1
MOVEQ #31-1,D0
.wpinst MOVE.W #1,in_replen(A1)
ADD.L #in_size,A1
DBRA D0,.wpinst
LEA st01_msg+6(PC),A1 wipe instrument filename
MOVEQ #28-1,D0
.wpfnam CLR.B (A1)+
DBRA D0,.wpfnam
MOVE.L song_file_ptr,A0 init song file
MOVE.W #1*256+0,sf_length(A0) length=1,restart=0
MOVE.L #'M.K.',sf_ident(A0)
CLR.L song_position reset and refresh display
CLR.L play_cursor
CLR.L play_row_index
MOVE.W #1,current_instr
MOVE.L #6,tempo
BSR refresh_song_position
CLR.L pattern_no
CLR.W edit_cursor_y
BSR refresh_pattern_display
BSR set_edit_scroller
BSR refresh_song_parameters
BSR refresh_instr_parameters
BSR refresh_song_name
clear_aborted
BSR arrow_is_grey
RTS
free_instr_memory
MOVE.W #1,memory_flag
MOVEQ #1,D7 for 31 instruments
MOVE.L 4.w,a6
.loop MOVE.W D7,D2
LSL.W #2,D2
LEA instr_alloc_list-4,A0
LEA instr_header,A1
CLR.L 0(A1,D2.W)
LEA instr_addr_list,A2 clear ptrs
CLR.L 0(A2,D2.W)
MOVE.L 0(A0,D2.W),D1 if memory allocated then
BEQ.S .free
MOVE.L 31*4(A0,D2.W),D0 clear addr,size
CLR.L 0(A0,D2.W)
CLR.L 31*4(A0,D2.W)
MOVE.L D1,A1
JSR _LVOFreeMem(A6) free memory
.free ADDQ.W #1,D7 next
CMPI.W #32,D7
BNE.S .loop
RTS
alter_parameter_down
MOVE.W #-1,alter_dir set direction down/up
BRA.S alter_parameter
alter_parameter_up
CLR.W alter_dir
alter_parameter
MOVE.W #1,memory_flag
MOVE.W mouse_y2,D0
CMPI.W #100,D0 skip if y<0 or y>=100
BGE.S .skip
CMPI.W #89,D0 alter selected parameter
BGE alter_replen
CMPI.W #78,D0
BGE alter_repeat
CMPI.W #67,D0
BGE alter_instr_length
CMPI.W #56,D0
BGE alter_volume
CMPI.W #45,D0
BGE alter_instr_number
CMPI.W #34,D0
BGE alter_restart
CMPI.W #23,D0
BGE alter_song_length
CMPI.W #12,D0
BGE alter_song_pattern
TST.W mouse_y2
BGE alter_song_position
.skip RTS
save_arrow_colours
MOVE.L cptr_arrow_col,A0
MOVE.W 2(A0),old_arrow_colours
MOVE.W 6(A0),old_arrow_colours+2
MOVE.W 10(A0),old_arrow_colours+4
RTS
restore_arrow_colours
MOVE.W #1,memory_flag
MOVE.L cptr_arrow_col,A0
MOVE.W old_arrow_colours,2(A0)
MOVE.W old_arrow_colours+2,6(A0)
MOVE.W old_arrow_colours+4,10(A0)
RTS
input_pattern_no
CMP.L #'patp',play_mode skip if playing song
BNE.S .ok
RTS
.ok BSR.S save_arrow_colours
BSR arrow_is_magenta
CLR.B key_code
MOVE.W #12,input_cursor_x input 1st digit
MOVE.W #134,input_cursor_y
BSR set_input_cursor
MOVE.L #128*40+1,char_offset
BSR.S wait_number_key
MOVE.B D1,D0
MULU #10,D0
MOVE.B D0,ipn_temp+1
BSR.S print_dec1
MOVE.W #20,input_cursor_x input 2nd digit
MOVE.W #134,input_cursor_y
BSR set_input_cursor
BSR.S wait_number_key
MOVE.B ipn_temp+1,pattern_no+3
ADD.B D1,pattern_no+3
AND.L #$3F,pattern_no pattern no = 0..63
CLR.W input_cursor_x cursor off screen
MOVE.W #270,input_cursor_y
BSR set_input_cursor
BSR refresh_pattern_display
BSR set_edit_cursor
BRA restore_arrow_colours
* exit d1=0..9
wait_number_key
MOVEQ #0,D0 wait for key 0..9
MOVE.B key_code,D0
BEQ.S wait_number_key
CLR.B key_code
CMPI.B #10,D0
BEQ.S .zero
BGT.S wait_number_key
CMPI.B #1,D0
BLT.S wait_number_key
MOVE.L D0,D1
RTS
.zero MOVEQ #0,D1
RTS
print_dec1
ADD.B #'0',D1 entry d1.w=0..9,exit d1 swapped
MOVE.B D1,temp_str
CLR.W D1
SWAP D1
MOVE.L #1,string_size
MOVE.L #temp_str,string_addr
BSR print_string
CLR.L temp_str
CLR.W word_to_print
RTS
input_clear
CMP.W input_cursor_x,D5 step cursor back to start
BEQ.S .start
SUBQ.L #1,A6
SUBQ.W #8,input_cursor_x
BRA.S input_clear
.start MOVE.L A6,A4 clear line to end
.wipe CLR.B (A4)+
CMP.L input_end_addr,A4
BNE.S .wipe
BSR refresh_all_parameters
BRA input_exit
refresh_all_parameters
BSR refresh_instr_parameters
BSR refresh_song_parameters
BRA print_modules_dir
input_routine
MOVE.W #1,input_in_progress
MOVE.W input_cursor_x,D5
MOVE.W mouse_x,D0
ADDQ.L #3,D0
MOVE.W #270,D1
MOVEQ #17,D2
MOVE.L arrow_spr_ptr,A0
BSR position_sprite
LEA valid_name_keycodes,A5
CLR.B key_code
BSR.S refresh_all_parameters
.loop BTST #2,_custom+potinp if right button then clear line
BEQ input_clear
CLR.W D1
MOVE.B key_code,D1
BEQ.S .loop
CMPI.B #$4E,D1 CRIGHT
BEQ .right
CMPI.B #$4F,D1 CLEFT
BEQ .left
CMPI.B #$46,D1 DEL
BEQ .delete
CMPI.B #$41,D1 BACKSPACE
BEQ .backsp
CMPI.B #$44,D1 RETURN
BEQ input_exit
BTST #7,D1 loop if key release
BNE.S .loop
TST.W key_lshift if shift then add 128
BEQ.S .noshft
BSET #7,D1
.noshft MOVEQ #0,D0
.search CMP.B 0(A5,D0.W),D1 search valid keycodes
BEQ.S .found
ADDQ.B #1,D0
CMPI.B #46,D0
BGT.S .loop
BRA.S .search
.found CMP.L input_end_addr,A6 skip if end of line
BEQ.S .loop
MOVE.L input_end_addr,A4
.shiftr MOVE.B -(A4),1(A4) shift chars right
CMP.L A4,a6
BNE.S .shiftr
MOVE.L input_end_addr,A4 make sure line terminated
CLR.B (A4)
LEA valid_name_chars,A0 insert ascii
MOVE.B 0(A0,D0.W),D1
MOVE.B D1,(A6)+
ADDQ.W #8,input_cursor_x cursor right
BSR set_input_cursor
BSR refresh_all_parameters
CLR.B key_code
BRA .loop
.backsp CMP.W input_cursor_x,D5 backspace
BNE.S .back2
BRA .loop
.back2 SUBQ.L #1,A6
MOVE.L A6,A4
.back3 MOVE.B 1(A4),(A4)+ shift left
CMP.L input_end_addr,A4
BNE.S .back3
SUBQ.W #8,input_cursor_x cursor left
BSR set_input_cursor
BSR refresh_all_parameters
BSR wait_20ms
BSR wait_20ms
BSR wait_20ms
BRA .loop
.delete MOVE.L A6,A4 delete char
.del2 MOVE.B 1(A4),(A4)+ shift left
CMP.L input_end_addr,A4
BNE.S .del2
BSR refresh_all_parameters
BSR wait_20ms
BSR wait_20ms
BSR wait_20ms
BRA .loop
.right CMP.L input_end_addr,A6 cursor right
BEQ .loop
ADDQ.L #1,A6
ADDQ.W #8,input_cursor_x
BSR set_input_cursor
BSR wait_20ms
BSR wait_20ms
BSR wait_20ms
BRA .loop
.left CMP.W input_cursor_x,D5 cursor left
BEQ .loop
SUBQ.L #1,A6
SUBQ.W #8,input_cursor_x
BSR set_input_cursor
BSR wait_20ms
BSR wait_20ms
BSR wait_20ms
BRA .loop
input_exit
CMP.W input_cursor_x,D5 goto start of line
BEQ.S .start
SUBQ.L #1,A6
SUBQ.W #8,input_cursor_x
BRA.S input_exit
.start MOVE.L A6,A4
.find0 TST.B (A4)+ find terminator
BNE.S .find0
SUBQ.L #1,A4
.pad0 CMP.L input_end_addr,A4 pad with 0's to end
BEQ.S .done
CLR.B (A4)+
BRA.S .pad0
.done CLR.W input_cursor_x cursor off screen
MOVE.W #270,input_cursor_y
BSR set_input_cursor
CLR.W input_in_progress
CLR.B key_code
BRA refresh_all_parameters
input_song_name
BSR save_arrow_colours
BSR arrow_is_magenta
CLR.L edit_mode
MOVE.L song_file_ptr,A6
MOVE.W #108,input_cursor_x
MOVE.W #108,input_cursor_y
BSR set_input_cursor
MOVE.L A6,input_end_addr
ADD.L #19,input_end_addr
BSR input_routine
CLR.L input_end_addr
BRA restore_arrow_colours
input_instr_name
BSR save_arrow_colours
BSR arrow_is_magenta
CLR.L edit_mode
MOVE.L song_file_ptr,A6
LEA sf_instr-in_size(A6),A6
MOVE.W current_instr,D7
MULU #in_size,D7
ADD.L D7,A6
MOVE.W #108,input_cursor_x
MOVE.W #119,input_cursor_y
BSR set_input_cursor
MOVE.L A6,input_end_addr
ADD.L #21,input_end_addr
BSR input_routine
BSR refresh_instr_parameters
CLR.L input_end_addr
BRA restore_arrow_colours
load_sample_file
MOVE.W #15,_custom+dmacon cancel audio dma
CLR.B key_code
LEA st01_msg+6(PC),A0 wipe instrument filename
MOVEQ #28-1,D0
.wname CLR.B (A0)+
DBRA D0,.wname
LEA instr_alloc_list-4,A0 free previous memory
MOVEQ #0,D0
MOVE.W current_instr,D0
ASL.W #2,D0
MOVE.L 0(A0,D0.W),D1
BEQ.S .free
MOVE.L $7C(A0,D0.W),D0
MOVE.L D1,A1
MOVE.L 4.w,a6
JSR _LVOFreeMem(A6)
.free LEA instr_alloc_list-4,A0
MOVE.W current_instr,D0
ASL.W #2,D0
CLR.L 0(A0,D0.W) clear addr,size
CLR.L $7C(A0,D0.W)
LEA instr_addr_list,A0
CLR.L 0(A0,D0.W)
MOVEQ #0,D0
MOVE.W current_instr,D0
MULU #in_size,D0
MOVE.L song_file_ptr,A0 get length from song
ADD.L #sf_instr-in_size+in_length,A0
ADD.L D0,A0
MOVEQ #0,D0
MOVE.W (A0),D0
ADD.L D0,D0
MOVE.L D0,file_length
SUB.L #in_length,A0
MOVE.W in_volume(A0),old_volume preserve volume
CLR.W in_volume(A0)
LEA st01_msg+6(PC),A1 copy name
MOVEQ #22-1,D0
.cname MOVE.B (A0)+,(A1)+
DBRA D0,.cname
MOVE.L #st01_msg+6,file_nameptr if no drive spec then st-01
CMP.B #':',st01_msg+11
BEQ.S .diskok
MOVE.L #st01_msg,file_nameptr
.diskok MOVE.L file_length,D0
BEQ.S .noaloc
MOVE.L #MEMF_CHIP!MEMF_CLEAR,D1 allocate memory
MOVE.L 4.w,a6
JSR _LVOAllocMem(A6)
TST.L D0
BEQ .error
.noaloc MOVE.L D0,file_addr
BSR refresh_instr_parameters update display
LEA instr_alloc_list-4,A0
MOVEQ #0,D1
MOVE.W current_instr,D1
ASL.W #2,D1
MOVE.L file_addr,0(A0,D1.W) save addr,length
MOVE.L file_length,$7C(A0,D1.W)
BSR load_a_file load it
MOVE.L file_addr,A0
MOVE.W #257-1,D0
.find_body
CMP.L #'BODY',(A0) IFF ?
BEQ.S .is_iff
ADDQ.L #2,A0
DBRA D0,.find_body
BRA .not_iff
.error MOVE.W #1,memory_flag
BRA arrow_flash_red
.is_iff MOVE.L file_addr,A1 IFF file
MOVE.L A0,A2 extract header
SUB.L A1,A2
ADDQ.L #8,A2
MOVE.L file_length,A1
SUB.L A2,A1
MOVE.L A1,iff_length
ADDQ.L #8,A0
MOVE.L A0,instr_addr_list
MOVE.W current_instr,D0
ASL.W #2,D0
LEA instr_header,A0 save header length
MOVE.L A2,0(A0,D0.W)
LEA instr_addr_list,A0
MOVE.L instr_addr_list,0(A0,D0.W) adjust sample length
MOVEQ #0,D0 in song
MOVE.W current_instr,D0
MULU #in_size,D0
MOVE.L song_file_ptr,A0
SUB.L #in_size-sf_instr,A0
ADD.L D0,A0
MOVE.L iff_length,D7
LSR.W #1,D7
MOVE.W D7,in_length(A0)
BRA.S .ptrs_set
.not_iff
MOVE.W current_instr,D0 non-IFF file
ASL.W #2,D0
LEA instr_header,A0 no header
CLR.L 0(A0,D0.W)
LEA instr_alloc_list-4,A1 address=start of file
LEA instr_addr_list,A0
MOVE.L 0(A1,D0.W),D1
MOVE.L D1,0(A0,D0.W)
.ptrs_set
MOVEQ #0,D0
MOVE.W current_instr,D0
MULU #in_size,D0
MOVE.L song_file_ptr,A0
SUB.L #in_size-sf_instr,A0
ADD.L D0,A0
MOVE.W old_volume,D0 restore volume
MOVE.W D0,in_volume(A0)
LEA instr_addr_list+4,A0
MOVEQ #0,D0 clear 1st 4-bytes of each sample
.clr_1st
MOVE.L 0(A0,D0.W),A1
CLR.L (A1)
ADDQ.W #4,D0
CMPI.W #31*4,D0
BNE.S .clr_1st
CLR.W ain_disable
MOVE.W #1,memory_flag
BSR refresh_memory_usage
RTS
delete_song
BSR arrow_is_magenta
BSR check_are_you_sure
BNE.S .abort
CLR.B key_code
LEA selected_filename,A0
LEA songs_dir_name(PC),A1 name=songs_dir+filename
MOVEQ #20-1,D0
.name MOVE.B (A0)+,(A1)+
DBRA D0,.name
MOVE.L #songs_dir,file_nameptr
MOVE.L DOSbase,A6
MOVE.L file_nameptr,D1
MOVE.L D1,A0
JSR _LVODeleteFile(A6)
TST.L D0
BEQ.S .error
BSR wipe_spectrum
CLR.W disk_fn
BRA restore_arrow_colours
.error BSR wipe_spectrum
.abort CLR.W disk_fn
BSR arrow_flash_red
BRA restore_arrow_colours
delete_module
BSR arrow_is_magenta
BSR check_are_you_sure
BNE.S .abort
CLR.B key_code
LEA modules_dir,A0 name=modules_dir+filename
LEA modname_buffer,A1
MOVEQ #16-1,D1
.dir MOVE.B (A0)+,D0
BEQ.S .plus
MOVE.B D0,(A1)+
DBRA D1,.dir
.plus LEA selected_filename,A0
MOVEQ #28-1,D0
.fname MOVE.B (A0)+,(A1)+
DBRA D0,.fname
MOVE.L #modname_buffer,file_nameptr
MOVE.L DOSbase,A6
MOVE.L file_nameptr,D1
MOVE.L D1,A0
JSR _LVODeleteFile(A6)
TST.L D0
BEQ.S .error
BSR wipe_spectrum
CLR.W disk_fn
BRA restore_arrow_colours
.error BSR wipe_spectrum
.abort CLR.W disk_fn
BSR arrow_flash_red
BRA restore_arrow_colours
load_song
BSR fn_stop
CLR.B key_code
MOVE.L song_file_ptr,A0 wipe 64K, patterns
ADD.L #sf_patterns,A0
MOVE.W #(64*1024)/4-1,D0
.wpat CLR.L (A0)+
DBRA D0,.wpat
LEA songs_dir_name(PC),A0 wipe song name
MOVEQ #28-1,D0
.wname CLR.B (A0)+
DBRA D0,.wname
LEA selected_filename,A0
LEA songs_dir_name(PC),A1 copy name
MOVEQ #$13,D0
.cname MOVE.B (A0)+,(A1)+
DBRA D0,.cname
MOVE.L song_file_ptr,file_addr load file
MOVE.L #songs_dir,file_nameptr
MOVE.L #sf_size,file_length (max length)
BSR load_a_file
TST.L D0
BEQ load_error
MOVE.L song_file_ptr,A0 unpack if packed
CMP.L #'PACK',(A0)
BNE.S .nopack
MOVE.L 4(A0),packed_size
MOVE.L 8(A0),unpacked_size
MOVE.L song_file_ptr,D0 unpack at top of song area
ADD.L #sf_size,D0
SUB.L unpacked_size,D0
MOVE.L D0,pack_buffer_ptr
BSR unpack_song
.nopack MOVE.L song_file_ptr,A0
CMP.L #'M.K.',sf_ident(A0) if old soundtracker file
BEQ.S .is_mk then adjust
BSR convert_old_format
.is_mk MOVE.L song_file_ptr,A0
CMP.B #120,sf_restart(A0) if restart=120 then clear
BNE.S .not120
CLR.B sf_restart(A0)
.not120 CLR.L pattern_no setup display
CLR.L song_position
BSR refresh_song_position
BSR refresh_pattern_display
CLR.W edit_cursor_y
BSR set_edit_scroller
BSR refresh_instr_parameters
BSR refresh_song_parameters
BSR.S sort_for_min_swaps
LEA load_sort_list,A0
MOVEQ #31-1,D0
.load MOVE.L (A0)+,D1 load instruments
MOVE.W D1,current_instr
MOVEM.L D0/D1/A0,-(SP)
BSR load_sample_file
MOVEM.L (SP)+,D0/D1/A0
DBRA D0,.load
MOVE.W #1,current_instr
MOVE.L #6,tempo
BRA refresh_instr_parameters
sort_for_min_swaps
MOVEM.L D0/D1/D3/D4/A0/A1,-(SP) sort samples for loading
MOVE.L song_file_ptr,A0 with minimum disk swaps
ADD.L #sf_instr+3,A0
LEA load_sort_list,A1 get ST no. and sample no.
MOVEQ #1,D0
.list MOVE.B (A0)+,(A1)+
MOVE.B (A0),(A1)+
MOVE.W D0,(A1)+
ADD.L #in_size-1,A0
ADDQ.L #1,D0
CMPI.L #32,D0
BNE.S .list
.outer CLR.W load_sort_flag bubble sort according to ST no.
LEA load_sort_list,A0
MOVEQ #30-1,D2
.inner MOVE.W (A0),D0
MOVE.W 4(A0),D1
CMP.W D1,D0
BGT.S .swapem
.next ADDQ.L #4,A0
DBRA D2,.inner
TST.W load_sort_flag
BNE.S .outer
LEA load_sort_list,A0 clear ST nos. leaving sample nos.
MOVEQ #31-1,D0
.tidy CLR.W (A0)
ADDQ.L #4,A0
DBRA D0,.tidy
MOVEM.L (SP)+,D0/D1/D3/D4/A0/A1
RTS
.swapem MOVE.W #1,load_sort_flag
MOVE.L (A0),D3
MOVE.L 4(A0),D4
MOVE.L D4,(A0)
MOVE.L D3,4(A0)
BRA.S .next
convert_old_format
MOVE.L song_file_ptr,A0 convert old files
MOVE.L A0,A1 shift up patterns for 16 extra
ADD.L #sf_instr+15*in_size+64*1024,A0 instruments
ADD.L #sf_instr+15*in_size-4,A1
.copyup MOVE.L (A0),16*in_size+4(A0)
CLR.L (A0)
SUBQ.L #4,A0
CMP.L A0,A1
BNE.S .copyup
MOVE.L song_file_ptr,A0
MOVE.L A0,A1
ADD.L #sf_length,A0 insert M.K. identifier
ADD.L #sf_ident,A1
.copydn MOVE.W 4(A0),(A0)+
CMP.L A0,A1
BNE.S .copydn
MOVE.L #'M.K.',(A0)
RTS
* STOP PLAYING/EDITING
fn_stop
BSR arrow_is_grey arrow grey
CLR.B key_code cancel keyboard
CLR.L edit_mode leave edit mode
CLR.L play_mode stop playing
CLR.W keyplay_channel cancel keyboard note playing
MOVE.W #15,_custom+dmacon cancel audio dma
RTS
get_plst_file
BSR save_arrow_colours
TST.L plst_ptr skip if no plst or instr 0
BEQ.S .skip
TST.W current_instr
BEQ.S .skip
CLR.B key_code
MOVE.W plst_entry_no,D0
SUBQ.W #1,D0
MULU #in_size,D0
MOVE.L plst_ptr,A0 a0=entry in plst
ADD.L D0,A0
MOVE.W current_instr,D0
MULU #in_size,D0
MOVE.L song_file_ptr,A1 a1=instr entry in song
LEA sf_instr-in_size(A1,D0.W),A1
MOVE.L A1,A2
MOVEQ #in_size-1,D0 copy params
.copy MOVE.B (A0)+,(A1)+
DBRA D0,.copy
TST.W in_replen(A2) if replen=0 then =1
BNE.S .not0
MOVE.W #1,in_replen(A2)
.not0 BSR load_sample_file
.skip BSR refresh_instr_parameters
BRA restore_arrow_colours
* EDIT SONG
fn_edit BSR fn_stop stop tune
BSR arrow_is_blue reset scroller
BSR set_edit_scroller
MOVE.L #'edit',edit_mode mode=edit
RTS
save_song
BSR fn_stop
CLR.B key_code
MOVE.L song_file_ptr,A0
ADD.L #sf_parts,A0 find maximum pattern no. used
MOVEQ #0,D0
MOVEQ #0,D1
MOVEQ #0,D2
CLR.W max_pat_no
.getmax MOVE.B 0(A0,D0.W),D1
ADDQ.W #1,D0
CMPI.W #128,D0
BGT.S .gotmax
MOVE.W max_pat_no,D2
CMP.W D2,D1
BLE.S .getmax
MOVE.W D1,max_pat_no
BRA.S .getmax
.gotmax MOVE.L song_file_ptr,A0
LEA songs_dir_name(PC),A1 copy song name to filename
MOVEQ #20-1,D0
.cname MOVE.B (A0)+,(A1)+
DBRA D0,.cname
MOVE.L #songs_dir,file_nameptr
MOVE.L song_file_ptr,file_addr
MOVE.L #sf_patterns,file_length length=header+1024*(max+1)
MOVEQ #0,D0
MOVE.W max_pat_no,D0
ADDQ.L #1,D0
LSL.L #8,D0
LSL.L #2,D0
ADD.L D0,file_length
BSR.S external_lengths
TST.W pack_flag pack if required
BEQ.S .nopack
BSR.S pack_song
BSR save_a_file
BSR unpack_song (unpack after save)
BSR.S internal_lengths
BRA arrow_is_grey
.nopack BSR save_a_file
BSR.S internal_lengths
BRA arrow_is_grey
external_lengths
LEA instr_header+4,A1
MOVE.L song_file_ptr,A0 add header lengths for save
ADD.L #sf_instr+in_length,A0
MOVEQ #31-1,D7
.loop MOVE.L (A1)+,D0 /2 for word length
LSR.L #1,D0
ADD.W D0,(A0)
ADD.L #in_size,A0
DBRA D7,.loop
RTS
internal_lengths
LEA instr_header+4,A1
MOVE.L song_file_ptr,A0 sub header lengths for internal use
ADD.L #sf_instr+in_length,A0
MOVEQ #31-1,D7
.loop MOVE.L (A1)+,D0
LSR.L #1,D0
SUB.W D0,(A0)
ADD.L #in_size,A0
DBRA D7,.loop
RTS
pack_song
BSR arrow_is_grey
MOVE.L song_file_ptr,A0
MOVE.L A0,A1
ADD.L #12,A1
MOVE.L A1,pack_dest_start dest for packed file
MOVE.L A0,A1
ADD.L #sf_size,A1
MOVE.L A1,pack_source_end end of workspace
MOVE.L A0,A1
ADD.L #sf_size,A1
SUB.L file_length,A1
MOVE.L A1,pack_buffer_ptr start of unpacked file
MOVE.L file_length,unpacked_size
MOVE.L song_file_ptr,A0
ADD.L file_length,A0 copy up unpacked file
MOVE.L song_file_ptr,A1
ADD.L #sf_size,A1
MOVE.L file_length,D0
.copyup MOVE.B -(A0),-(A1)
SUBQ.L #1,D0
BNE.S .copyup
BSR.S cruncher
SUB.L pack_dest_start,A2 packed size
MOVE.L A2,D0
MOVE.L D0,packed_size
MOVE.L D0,D1
ADD.L pack_dest_start,D1
MOVE.L D1,pack_dest_end end of packed file (UNUSED)
MOVE.L song_file_ptr,A0
MOVE.L #'PACK',(A0) set id,sizes
MOVE.L packed_size,4(A0)
MOVE.L unpacked_size,8(A0)
MOVE.L song_file_ptr,file_addr file address,length
MOVE.L packed_size,D0
ADD.L #12,D0
MOVE.L D0,file_length
RTS
*------------------------------
* FILE CRUNCHER
* entry pack_buffer_ptr = source start
* pack_source_end = source end +1
* pack_dest_start = dest
cruncher
MOVE.L pack_buffer_ptr,A0 a0=source
MOVE.L pack_source_end,A1 a1=source end+1
MOVE.L pack_dest_start,A2 a2=dest
MOVEQ #1,D2 d2=dest long bit buffer
CLR.W D1 d1=count of unpackable bytes
.loop BSR.S .scan try to pack
TST.B D0
BEQ.S .next
ADDQ.W #1,D1 if byte not packed then
CMPI.W #264,D1 count+1
BNE.S .next if count=264 then
BSR .put_fill save fill
.next CMP.L A0,A1 if source<end then loop
BGT.S .loop
BSR .put_fill save fill
BRA .put_last_long empty bit buffer
.scan MOVE.L A0,A3 a3=source+127
ADD.L #127,A3
CMP.L A1,A3 if a3>end then a3=end
BLE.S .scan2
MOVE.L A1,A3
.scan2 MOVEQ #1,D5 d5=longest match, init 1
MOVE.L A0,A5 a5=source+1
ADDQ.L #1,A5
.get_pair
MOVE.B (A0),D3 d3,d4=next 2 source bytes
MOVE.B 1(A0),D4
.compare
CMP.B (A5)+,D3 search for match
BNE.S .compare2
CMP.B (A5),D4
BEQ.S .matched_pair
.compare2
CMP.L A5,A3 if none then loop
BGT.S .compare if all tried then no match
BRA.S .no_match
.matched_pair
SUBQ.L #1,A5 if match then
MOVE.L A0,A4 a4=source,a5=matched string
.find_length
MOVE.B (A4)+,D3 find length of matched string
CMP.B (A5)+,D3
BNE.S .found_length
CMP.L A5,A3
BGT.S .find_length
.found_length
MOVE.L A4,D3 d3=length
SUB.L A0,D3
SUBQ.L #1,D3
CMP.L D3,D5 if <= previous best then skip
BGE.S .no_good
MOVE.L A5,D4 d4=distance
SUB.L A0,D4
SUB.L D3,D4
SUBQ.L #1,D4
CMPI.L #4,D3 if distance>4 then
BLE.S .small
MOVEQ #6,D6 mode 3
CMPI.L #257,D3 limit length to 256
BLT.S .big
MOVE.W #256,D3
.big BRA.S .usable
.small MOVE.W D3,D6 if distance=1,2 or 3 then
SUBQ.W #2,D6 mode 0,1 or 2
LSL.W #1,D6
.usable LEA .copy_table,A6 if distance usable then
CMP.W 0(A6,D6.W),D4
BGE.S .no_good
MOVE.L D3,D5 d5=best length
MOVE.L D4,pack_best_distance save distance
MOVE.B D6,pack_best_mode save mode
.no_good
CMP.L A5,A3 repeat
BGT.S .get_pair
.no_match
CMPI.L #1,D5 if best length=1 then
BEQ.S .put_byte save byte for fill
BSR.S .put_fill else save previous fill
MOVE.B pack_best_mode,D6
MOVE.L pack_best_distance,D3
MOVE.W 8(A6,D6.W),D0
BSR .put_bits put mode bits
MOVE.W 16(A6,D6.W),D0
BEQ.S .no_count
MOVE.L D5,D3 put count bits (if any)
SUBQ.W #1,D3
BSR .put_bits
.no_count
MOVE.W 24(A6,D6.W),D0
MOVE.W 32(A6,D6.W),D3
BSR.S .put_bits put distance bits
ADD.W #1,40(A6,D6.W)
ADD.L D5,A0
CLR.B D0
RTS
.put_byte
MOVE.B (A0)+,D3
MOVEQ #8,D0
BSR.S .put_bits
MOVEQ #1,D0
RTS
.copy_table
dc.w 256,512,1024,4096 max distance
dc.w 8,9,10,8 address bits
dc.w 0,0,0,8 count bits
dc.w 2,3,3,3 no. of header bits
dc.w %01,%100,%101,%110 header code
dc.w 0,0,0,0 no. of times command used
.put_fill
TST.W D1 d1=count
BEQ.S .pf2
MOVE.W D1,D3
CLR.W D1
CMPI.W #9,D3 if count<9 then
BGE.S .pf3
ADDQ.W #1,pack_used_00 bump usage count (UNUSED)
SUBQ.W #1,D3 1..8 => 0..7
MOVEQ #5,D0 put bits : 00nnn
BRA.S .put_bits
.pf2 RTS if count>=9 then
.pf3 ADDQ.W #1,pack_used_111 bump usage count (UNUSED)
SUB.W #9,D3 9..264 => 0..255
OR.W #$700,D3 put bits : 111nnnnnnnn
MOVEQ #11,D0
.put_bits
SUBQ.W #1,D0 d0=no. of bits, d3=bits
.pb2 LSR.L #1,D3
ROXL.L #1,D2
BCS.S .put_long
DBRA D0,.pb2
RTS
.put_last_long
CLR.W D0
.put_long
MOVE.L D2,(A2)+
MOVEQ #1,D2
DBRA D0,.pb2
RTS
*------------------------------
unpack_song
MOVE.L song_file_ptr,A0
ADD.L #12,A0 skip header
MOVE.L pack_buffer_ptr,A1 decrunch
MOVE.L packed_size,D0
MOVE.L unpacked_size,D1
BSR.S decruncher
MOVE.L pack_buffer_ptr,A0 copy down
MOVE.L song_file_ptr,A1
MOVE.L unpacked_size,D0
.down MOVE.B (A0)+,(A1)+
SUBQ.L #1,D0
BNE.S .down
MOVE.L song_file_ptr,A0 clear rest of song file
ADD.L #sf_size,A0
MOVE.L song_file_ptr,A1
ADD.L unpacked_size,A1
SUB.L A1,A0
MOVE.L A0,D0
.tidy CLR.B (A1)+
SUBQ.L #1,D0
BNE.S .tidy
RTS
*------------------------------
* FILE DECRUNCHER
* entry a0=source
* a1=dest
* d0=packed size
* d1=unpacked size
* format
* 00nnn : fill next 1..8 bytes
* 01aaaaaaaa : copy 2 bytes from dest+0..255
* 100aaaaaaaaa : copy 3 bytes from dest+0..511
* 101aaaaaaaaaa : copy 4 bytes from dest+0..1023
* 110nnnnnnnnaaaaaaaa : copy 1..256 bytes from dest+0..255
* 111nnnnnnnn : fill next 9..264 bytes
decruncher
ADD.L D0,A0 a0=source ptr
MOVE.L D1,A2 a2=dest ptr
ADD.L A1,A2
MOVE.L -(A0),D0
.loop LSR.L #1,D0
BNE.S .ok
BSR.S .get_long
.ok BCS.S .com1xx
MOVEQ #8,D1
MOVEQ #2-1,D3
LSR.L #1,D0
BNE.S .ok2
BSR.S .get_long
.ok2 BCS.S .copy
MOVEQ #3,D1
CLR.W D4
.fill BSR.S .get_bits
MOVE.W D2,D3
ADD.W D4,D3
.fill2 MOVEQ #8-1,D1
.fill3 LSR.L #1,D0
BNE.S .ok3
BSR.S .get_long
.ok3 ROXL.L #1,D2
DBRA D1,.fill3
MOVE.B D2,-(A2)
DBRA D3,.fill2
BRA.S .next
.com111 MOVEQ #8,D1
MOVEQ #8,D4
BRA.S .fill
.com1xx MOVEQ #2,D1
BSR.S .get_bits
CMPI.B #2,D2
BLT.S .com10x
CMPI.B #3,D2
BEQ.S .com111
MOVEQ #8,D1
BSR.S .get_bits
MOVE.W D2,D3
MOVE.W #8,D1
BRA.S .copy
.com10x MOVE.W #9,D1
ADD.W D2,D1
ADDQ.W #2,D2
MOVE.W D2,D3
.copy BSR.S .get_bits
.copy2 SUBQ.W #1,A2
MOVE.B 0(A2,D2.W),(A2)
DBRA D3,.copy2
.next CMP.L A2,A1
BLT.S .loop
RTS
.get_long
MOVE.L -(A0),D0
MOVE #$10,CCR
ROXR.L #1,D0
RTS
.get_bits
SUBQ.W #1,D1
CLR.W D2
.get_bits2
LSR.L #1,D0
BNE.S .get_bits3
MOVE.L -(A0),D0
MOVE #$10,CCR
ROXR.L #1,D0
.get_bits3
ROXL.L #1,D2
DBRA D1,.get_bits2
RTS
*------------------------------
load_module
BSR fn_stop
BSR arrow_is_green
CLR.B key_code
BSR free_instr_memory clear instruments
MOVE.L song_file_ptr,A0
ADD.L #sf_patterns,A0
MOVE.W #(64*1024)/4-1,D0
.wipe CLR.L (A0)+
DBRA D0,.wipe
LEA modules_dir,A0 name=dir+name
LEA modname_buffer,A1
MOVEQ #16-1,D1
.dir MOVE.B (A0)+,D0
BEQ.S .plus
MOVE.B D0,(A1)+
DBRA D1,.dir
.plus LEA selected_filename,A0
MOVEQ #28-1,D0
.name MOVE.B (A0)+,(A1)+
DBRA D0,.name
MOVE.L DOSbase,A6
MOVE.L #modname_buffer,D1
MOVE.L #1005,D2 read
JSR _LVOOpen(A6)
TST.L D0 error if fail
BEQ load_error
MOVE.L D0,file_handle
MOVE.L D0,D1
MOVE.L song_file_ptr,D2 read header
MOVE.L #sf_patterns,D3
JSR _LVORead(A6)
MOVE.L song_file_ptr,A0
CMP.L #'M.K.',sf_ident(A0) if not M.K. file then
BEQ.S .is_mk
MOVE.L file_handle,D1 back to start
MOVEQ #0,D2
MOVEQ #-1,D3
JSR _LVOSeek(A6)
MOVE.L file_handle,D1
MOVE.L song_file_ptr,D2 read smaller header
MOVE.L #$258,D3
JSR _LVORead(A6)
BSR convert_old_format convert to MK format
.is_mk MOVE.L song_file_ptr,A0
CMP.B #120,sf_restart(A0) if restart<>120 then =0
BNE.S .not120
CLR.B sf_restart(A0)
.not120 ADD.L #sf_parts,A0
MOVEQ #128-1,D0 find maximum pattern no.
MOVEQ #0,D3
.getmax CMP.B (A0)+,D3
BGT.S .gotmax
MOVE.B -1(A0),D3
.gotmax DBRA D0,.getmax
ADDQ.W #1,D3
MULU #1024,D3 read patterns
MOVE.L file_handle,D1
MOVE.L song_file_ptr,D2
ADD.L #sf_patterns,D2
JSR _LVORead(A6)
CLR.L pattern_no setup display
CLR.L song_position
BSR refresh_song_position
BSR refresh_pattern_display
CLR.W edit_cursor_y
BSR set_edit_scroller
BSR refresh_instr_parameters
BSR refresh_song_parameters
MOVE.W #1,current_instr load instruments
.iloop BSR refresh_instr_parameters
MOVE.L song_file_ptr,A0
MOVE.W current_instr,D7
MULU #in_size,D7
MOVEQ #0,D0
MOVE.W sf_instr+in_length-in_size(A0,D7.W),D0 skip if empty
BEQ.S .inext
ADD.L D0,D0
MOVE.L 4.w,a6
MOVE.L #MEMF_CLEAR+MEMF_CHIP,D1 allocate memory
MOVE.L D0,-(SP)
JSR _LVOAllocMem(A6)
MOVE.L (SP)+,D6
MOVE.W current_instr,D7
LSL.W #2,D7
LEA instr_addr_list,A0
MOVE.L D0,0(A0,D7.W)
TST.L D0 skip if no room
BEQ.S .inext
LEA instr_alloc_list-4,A0
MOVE.L D0,0(A0,D7.W) save addr,size
MOVE.L D6,$7C(A0,D7.W)
LEA instr_alloc_list-4,A0
MOVE.L DOSbase,A6
MOVE.L file_handle,D1
MOVE.L D0,D2
MOVE.L D6,D3
JSR _LVORead(A6)
.inext MOVE.W #1,memory_flag memory usage changed
ADDQ.W #1,current_instr next instrument
CMP.W #32,current_instr
BNE .iloop
MOVE.L file_handle,D1
JSR _LVOClose(A6)
MOVE.W #1,current_instr setup
MOVE.L #6,tempo
BSR arrow_is_grey
BRA refresh_instr_parameters
load_error
MOVE.L cptr_arrow_col,A0
MOVE.W #$C00,2(A0) arrow red
MOVE.W #$900,6(A0)
MOVE.W #$700,10(A0)
BSR fn_clear_nocheck clear song
BRA arrow_is_grey
save_module
BSR arrow_is_green
MOVE.L song_file_ptr,A0 find maximum pattern no.
ADD.L #sf_parts,A0
MOVEQ #0,D0
MOVEQ #0,D1
MOVEQ #0,D2
CLR.W max_pat_no
.getmax MOVE.B 0(A0,D0.W),D1
ADDQ.W #1,D0
CMPI.W #128,D0
BGT.S .gotmax
MOVE.W max_pat_no,D2
CMP.W D2,D1
BLE.S .getmax
MOVE.W D1,max_pat_no
BRA.S .getmax
.gotmax LEA save_mod_name(PC),A0 name=dir+'mod.'+songname
MOVEQ #56-1,D0
.wname CLR.B (A0)+
DBRA D0,.wname
LEA modules_dir,A0
LEA save_mod_name,A1
MOVEQ #16-1,D1
.dir MOVE.B (A0)+,D0
BEQ.S .mod
MOVE.B D0,(A1)+
DBRA D1,.dir
.mod MOVE.B #'m',(A1)+
MOVE.B #'o',(A1)+
MOVE.B #'d',(A1)+
MOVE.B #'.',(A1)+
MOVE.L song_file_ptr,A0
MOVEQ #28-1,D0
.name MOVE.B (A0)+,(A1)+
DBRA D0,.name
MOVE.L song_file_ptr,file_addr
MOVE.L #sf_patterns,file_length
MOVEQ #0,D0
MOVE.W max_pat_no,D0
ADDQ.L #1,D0
LSL.L #8,D0
LSL.L #2,D0
ADD.L D0,file_length
BSR.S .open save header, patterns
BNE.S .error
BSR .write
BNE.S .error
MOVEQ #1,D6
.instr BSR.S .save_instr save instruments
ADDQ.B #1,D6
CMPI.B #32,D6
BNE.S .instr
BSR .close
BRA arrow_is_grey
.error BRA arrow_flash_red
.save_instr
MOVE.W D6,D0 index instrument info
LSL.W #2,D0
LEA instr_alloc_list-4,A0
MOVE.L 0(A0,D0.W),D1
BEQ.S .no_instr
TST.L $7C(A0,D0.W) skip if empty
BEQ.S .no_instr
LEA instr_addr_list,A0
MOVE.L 0(A0,D0.W),D1
MOVE.L D1,file_addr
MOVE.L song_file_ptr,A0 save it
ADD.L #sf_instr+in_length-in_size,A0
MOVE.W D6,D0
MULU #in_size,D0
ADD.L D0,A0
MOVEQ #0,D0
MOVE.W (A0),D0
ASL.L #1,D0
MOVE.L D0,file_length
BNE.S .write
.no_instr
RTS
.open MOVE.L DOSbase,A6
MOVE.L #save_mod_name,D1
MOVE.L #1006,D2
JSR _LVOOpen(A6)
MOVE.L D0,D7
BEQ.S .ferror
MOVEQ #0,D0
RTS
.ferror MOVEQ #-1,D0
RTS
.write MOVE.L DOSbase,A6
MOVE.L D7,D1
MOVE.L file_addr,D2
MOVE.L file_length,D3
JSR _LVOWrite(A6)
TST.L D0
BEQ.S .ferror
MOVEQ #0,D0
RTS
.close MOVE.L DOSbase,A6
MOVE.L D7,D1
JMP _LVOClose(A6)
save_mod_name
ds.b 56
* PLAY PATTERN
fn_play_pattern
BTST #6,$BFE001 wait till button released
BEQ.S fn_play_pattern
CLR.L edit_mode cancel edit mode
BSR fn_stop
BSR arrow_is_yellow
MOVE.L #'patt',play_mode mode=play pattern
enable_scroller
CLR.W keyplay_channel
MOVE.L cptr_con0c,A0 enable plane 3
MOVE.W #$3200,(A0)
CLR.L play_cursor
RTS
alter_repeat
MOVE.L song_file_ptr,A0
ADD.L #sf_instr+in_length-in_size,A0
MOVEQ #0,D0
MOVE.W current_instr,D0
TST.W D0
BEQ.S .skip
MULU #in_size,D0
ADD.L D0,A0
CMP.W #-1,alter_dir
BEQ.S .down
ADDQ.W #1,in_repeat-in_length(A0)
BTST #2,_custom+potinp
BNE.S .slow
ADDQ.W #7,in_repeat-in_length(A0)
.slow MOVE.W (A0),D0
SUB.W in_replen-in_length(A0),D0
CMP.W in_repeat-in_length(A0),D0
BGT.S .skip
TST.W D0
BPL.S .ok
CLR.W in_repeat-in_length(A0)
BRA refresh_instr_parameters
.ok MOVE.W D0,in_repeat-in_length(A0)
.skip BRA refresh_instr_parameters
.down SUBQ.W #1,in_repeat-in_length(A0)
BTST #2,_custom+potinp
BNE.S .slow2
SUBQ.W #7,in_repeat-in_length(A0)
.slow2 TST.W in_repeat-in_length(A0)
BPL.S .skip
CLR.W in_repeat-in_length(A0)
BRA.S .skip
alter_replen
MOVE.L song_file_ptr,A0
ADD.L #sf_instr+in_length-in_size,A0
MOVEQ #0,D0
MOVE.W current_instr,D0
TST.W D0
BEQ.S .skip
MULU #in_size,D0
ADD.L D0,A0
CMP.W #-1,alter_dir
BEQ.S .down
ADDQ.W #1,in_replen-in_length(A0)
BTST #2,_custom+potinp
BNE.S .slow
ADDQ.W #7,in_replen-in_length(A0)
.slow MOVE.W (A0),D0
SUB.W in_repeat-in_length(A0),D0
CMP.W in_replen-in_length(A0),D0
BGT.S .skip
TST.W D0
BNE.S .ok
MOVE.W #1,in_replen-in_length(A0)
BRA refresh_instr_parameters
.ok MOVE.W D0,in_replen-in_length(A0)
.skip BRA refresh_instr_parameters
.down SUBQ.W #1,in_replen-in_length(A0)
BTST #2,_custom+potinp
BNE.S .slow2
SUBQ.W #7,in_replen-in_length(A0)
.slow2 CMP.W #1,in_replen-in_length(A0)
BGE.S .skip
MOVE.W #1,in_replen-in_length(A0)
BRA.S .skip
alter_instr_length
MOVE.L song_file_ptr,A0
ADD.L #sf_instr+in_length-in_size,A0
MOVEQ #0,D0
MOVE.W current_instr,D0
TST.W D0
BEQ.S .skip
MULU #in_size,D0
ADD.L D0,A0
CMP.W #-1,alter_dir
BEQ.S .down
ADDQ.W #1,(A0)
BTST #2,_custom+potinp
BNE.S .slow
ADDQ.W #7,(A0)
.slow CMP.W #$3FFF,(A0)
BLE.S .skip
MOVE.W #$3FFF,(A0)
.skip BRA refresh_instr_parameters
.down SUBQ.W #1,(A0)
BTST #2,_custom+potinp
BNE.S .slow2
SUBQ.W #7,(A0)
.slow2 MOVE.W in_repeat-in_length(A0),D0
ADD.W in_replen-in_length(A0),D0
CMP.W (A0),D0
BLE.S .skip
TST.W in_repeat-in_length(A0)
BEQ.S .clip
.ok MOVE.W D0,(A0)
BRA.S .skip
.clip CMP.W #1,in_replen-in_length(A0)
BNE.S .ok
CLR.W (A0)
BRA.S .skip
alter_volume
CMP.W #-1,alter_dir
BEQ.S .down
MOVE.L song_file_ptr,A0
ADD.L #sf_instr+in_length-in_size,A0
MOVEQ #0,D0
MOVE.W current_instr,D0
TST.W D0
BEQ.S .skip
MULU #in_size,D0
ADD.L D0,A0
ADDQ.W #1,in_volume-in_length(A0)
CMP.W #64,in_volume-in_length(A0)
BMI.S .notmax
MOVE.W #64,in_volume-in_length(A0)
.notmax BSR refresh_instr_parameters
BTST #2,_custom+potinp
BNE.S .wait
.skip RTS
.wait MOVE.W #$2000,D0
.wait2 DBRA D0,.wait2
RTS
.down MOVE.L song_file_ptr,A0
ADD.L #sf_instr+in_length-in_size,A0
MOVEQ #0,D0
MOVE.W current_instr,D0
MULU #in_size,D0
ADD.L D0,A0
SUBQ.W #1,in_volume-in_length(A0)
TST.W in_volume-in_length(A0)
BPL.S .notmin
CLR.W in_volume-in_length(A0)
.notmin BSR refresh_instr_parameters
BTST #2,_custom+potinp
BEQ.S .skip
BRA.S .wait
alter_instr_number
TST.W ain_disable ?? (UNUSED)
BEQ.S .do_it
BSR refresh_instr_parameters
CLR.W ain_disable
RTS
.do_it BTST #2,_custom+potinp if right button then instr 0
BNE.S .no_rgt
CLR.W current_instr
BRA refresh_instr_parameters
.no_rgt CMP.W #-1,alter_dir
BEQ.S .down
ADDQ.W #1,current_instr
CMP.W #31,current_instr
BMI.S .notmax
MOVE.W #31,current_instr
.notmax BSR wait_20ms
BSR wait_20ms
BRA refresh_instr_parameters
.down TST.W current_instr
BEQ.S .notmin
SUBQ.W #1,current_instr
CMP.W #1,current_instr
BPL.S .notmin
MOVE.W #1,current_instr
.notmin BSR wait_20ms
BSR wait_20ms
BRA refresh_instr_parameters
alter_restart
CMP.W #-1,alter_dir
BEQ.S .down
MOVE.L song_file_ptr,A0
ADD.L #sf_length,A0
ADDQ.B #1,sf_restart-sf_length(A0)
MOVE.B sf_restart-sf_length(A0),D0
CMP.B (A0),D0
BMI.S .notmax
MOVE.B (A0),sf_restart-sf_length(A0)
SUBQ.B #1,sf_restart-sf_length(A0)
.notmax BSR refresh_song_parameters
BTST #2,_custom+potinp
BEQ wait_20ms
BSR wait_20ms
BRA wait_20ms
.down MOVE.L song_file_ptr,A0
ADD.L #sf_restart,A0
SUBQ.B #1,(A0)
TST.B (A0)
BPL.S .notmin
CLR.B (A0)
.notmin BSR refresh_song_parameters
BTST #2,_custom+potinp
BEQ wait_20ms
BSR wait_20ms
BRA wait_20ms
alter_song_length
BSR fn_stop
CMP.W #-1,alter_dir
BEQ.S .down
MOVE.L song_file_ptr,A0
ADD.L #sf_length,A0
ADDQ.B #1,(A0)
CMP.B #127,(A0)
BMI.S .notmax
MOVE.B #127,(A0)
.notmax BSR refresh_song_parameters
BTST #2,_custom+potinp
BEQ wait_20ms
BSR wait_20ms
BRA wait_20ms
.down MOVE.L song_file_ptr,A0
ADD.L #sf_length,A0
SUBQ.B #1,(A0)
CMP.B #1,(A0)
BPL.S .notmin
MOVE.B #1,(A0)
.notmin MOVE.B sf_restart-sf_length(A0),D0
CMP.B (A0),D0
BNE.S .notres
ADDQ.B #1,(A0)
.notres BSR refresh_song_parameters
BTST #2,_custom+potinp
BEQ wait_20ms
BSR wait_20ms
BRA wait_20ms
alter_song_pattern
BSR fn_stop
CMP.W #-1,alter_dir
BEQ.S .down
MOVE.L song_file_ptr,A0
ADD.L #sf_parts,A0
ADD.L song_position,A0
ADDQ.B #1,(A0)
CMP.B #63,(A0)
BMI.S .notmax
MOVE.B #63,(A0)
.notmax BSR refresh_song_position
BTST #2,_custom+potinp
BEQ wait_20ms
BSR wait_20ms
BSR wait_20ms
BRA wait_20ms
.down MOVE.L song_file_ptr,A0
ADD.L #sf_parts,A0
ADD.L song_position,A0
SUBQ.B #1,(A0)
TST.B (A0)
BPL.S .notmin
CLR.B (A0)
.notmin BSR refresh_song_position
BTST #2,_custom+potinp
BEQ wait_20ms
BSR.S wait_20ms
BSR.S wait_20ms
BRA.S wait_20ms
alter_song_position
CMP.W #-1,alter_dir
BEQ.S .down
ADDQ.L #1,song_position
CMP.L #127,song_position
BMI.S .notmax
MOVE.L #127,song_position
.notmax BSR refresh_song_position
BTST #2,_custom+potinp
BEQ.S wait_20ms
BSR.S wait_20ms
BSR.S wait_20ms
BRA.S wait_20ms
.down SUBQ.L #1,song_position
TST.L song_position
BPL.S .notmin
CLR.L song_position
.notmin BSR refresh_song_position
BTST #2,_custom+potinp
BEQ.S wait_20ms
BSR.S wait_20ms
BSR wait_20ms
wait_20ms
MOVE.W #17920,D0
.wait DBRA D0,.wait
RTS
*------------------------------
* SONG PLAYER
player MOVEM.L D0-D7/A0-A6,-(SP)
MOVE.L song_file_ptr,A0
MOVE.B sf_length(A0),song_length+1 save length
TST.L play_mode skip if not playing
BEQ player_done
ADDQ.L #1,frame_count frame+1
MOVE.L frame_count,D0 if frame>=tempo then
CMP.L tempo,D0 frame=0, update song
BLT.S .midcyc
CLR.L frame_count
BRA player_nextnote
.midcyc LEA audio_info_1,A6 else update continuous effects
LEA _custom+aud0,A5
BSR songcomm_1234A
LEA audio_info_2,A6
LEA _custom+aud1,A5
BSR songcomm_1234A
LEA audio_info_3,A6
LEA _custom+aud2,A5
BSR songcomm_1234A
LEA audio_info_4,A6
LEA _custom+aud3,A5
BSR songcomm_1234A
BRA player_done
songcomm_arpeggio
MOVE.L frame_count,D0
DIVS #3,D0 d0=frame mod 3
SWAP D0
TST.W D0
BEQ.S .cycle0
CMPI.W #2,D0
BEQ.S .cycle2
.cycle1 MOVEQ #0,D0
MOVE.B 3(A6),D0
LSR.B #4,D0
BRA.S .index
.cycle2 MOVEQ #0,D0
MOVE.B 3(A6),D0
AND.B #15,D0
BRA.S .index
.cycle0 MOVE.W 16(A6),D2
BRA.S .set
.index ASL.W #1,D0
MOVEQ #0,D1
MOVE.W 16(A6),D1
AND.W #$FFF,D1
LEA oct1_2_3_periods,A0
MOVEQ #55-1,D7
.search MOVE.W 0(A0,D0.W),D2
CMP.W (A0),D1
BGE.S .set
ADDQ.L #2,A0
DBRA D7,.search
RTS
.set MOVE.W D2,6(A5)
RTS
player_nextnote
MOVE.L song_file_ptr,A0
MOVE.L A0,A3
ADD.L #sf_instr+in_length-in_size,A3 a3=instruments info
MOVE.L A0,A2
ADD.L #sf_parts,A2 a2=song positions
ADD.L #sf_patterns,A0 a0=patterns
CMP.L #'patp',play_mode if play pattern then
BEQ.S .song
MOVE.L pattern_no,D1 index current pattern
BRA.S .patt
.song MOVEQ #0,D1 if playing song then
MOVE.L song_position,D0 index pattern at position
MOVE.B 0(A2,D0.L),D1
.patt LSL.L #8,D1
LSL.L #2,D1
ADD.L play_cursor,D1
MOVE.L D1,play_row_index index to current play row
CLR.W player_channels clear channel flags
LEA _custom+aud0,A5 update each voice
LEA audio_info_1,A6
LEA volume_1(PC),A2
BSR.S player_update
LEA _custom+aud1,A5
LEA audio_info_2,A6
LEA volume_2(PC),A2
BSR.S player_update
LEA _custom+aud2,A5
LEA audio_info_3,A6
LEA volume_3(PC),A2
BSR.S player_update
LEA _custom+aud3,A5
LEA audio_info_4,A6
LEA volume_4(PC),A2
BSR.S player_update
BRA player_set
player_update
MOVE.L 0(A0,D1.L),(A6) get note info for this voice
ADDQ.L #4,D1 bump index
MOVEQ #0,D2
MOVE.B 2(A6),D2 get instrument no.
AND.B #$F0,D2
LSR.B #4,D2
MOVE.B (A6),D0
AND.B #$F0,D0
OR.B D0,D2
TST.B D2
BEQ.S .tstper if instrument<>0 then
MOVEQ #0,D3
LEA instr_addr_list,A1
MOVE.L D2,D4
LSL.L #2,D2
MULU #in_size,D4
MOVE.L 0(A1,D2.L),4(A6) get address,length,volume
MOVE.W (A3,D4.L),8(A6)
MOVE.W in_volume-in_length(A3,D4.L),18(A6)
MOVE.W in_repeat-in_length(A3,D4.L),D3
TST.W D3
BEQ.S .no_rep if repeat then
MOVE.L 4(A6),D2
ASL.W #1,D3
ADD.L D3,D2
MOVE.L D2,10(A6) repeat addr
MOVE.W in_repeat-in_length(A3,D4.L),D0
ADD.W in_replen-in_length(A3,D4.L),D0
MOVE.W D0,8(A6) initial length
MOVE.W in_replen-in_length(A3,D4.L),14(A6) repeat length
MOVE.W 18(A6),ac_vol(A5) set volume
MOVE.W 18(A6),(A2) set volume for eq
BRA.S .tstper
.no_rep MOVE.L 4(A6),D2 if no repeat then
ADD.L D3,D2
MOVE.L D2,10(A6) repeat addr=addr
MOVE.W in_replen-in_length(A3,D4.L),14(A6) repeat length=1
MOVE.W 18(A6),ac_vol(A5) set volume
MOVE.W 18(A6),(A2) set volume for eq
.tstper MOVE.W (A6),D0 if period<>0 then
AND.W #$FFF,D0
BEQ.S .no_period
MOVE.B 2(A6),D0 if tone portamento then
AND.B #15,D0
CMPI.B #3,D0
BNE.S .noport
BSR init_toneporta initialize
BRA songcomm_B_to_F do commands
.noport MOVE.W (A6),16(A6) else
AND.W #$FFF,16(A6) get period
MOVE.W 20(A6),D0
MOVE.W D0,_custom+dmacon disable channel
CLR.B 27(A6)
MOVE.L 4(A6),(A5) set address
MOVE.W 8(A6),ac_len(A5) set length
MOVE.W 16(A6),D0 set period
AND.W #$FFF,D0
MOVE.W D0,ac_per(A5)
BSR add_note_to_spectrum send to spectrum analyser
MOVE.W 20(A6),D0 flag channel
OR.W D0,player_channels
.no_period
BRA songcomm_B_to_F do commands
player_set
MOVE.W #$12C,D0 wait 350us
.wait DBRA D0,.wait
MOVE.W player_channels,D0 enable active channels
AND.W onoff_states,D0
OR.W #$8000,D0
MOVE.W D0,_custom+dmacon
MOVE.W #$12C,D0 wait 350us
.wait2 DBRA D0,.wait2
LEA audio_info_4,A6
MOVE.L 10(A6),_custom+aud3+ac_ptr set addr,length for repeats
MOVE.W 14(A6),_custom+aud3+ac_len
LEA audio_info_3,A6
MOVE.L 10(A6),_custom+aud2+ac_ptr
MOVE.W 14(A6),_custom+aud2+ac_len
LEA audio_info_2,A6
MOVE.L 10(A6),_custom+aud1+ac_ptr
MOVE.W 14(A6),_custom+aud1+ac_len
LEA audio_info_1,A6
MOVE.L 10(A6),_custom+aud0+ac_ptr
MOVE.W 14(A6),_custom+aud0+ac_len
CMP.L #'patp',play_mode if playing song then
BNE.S .notply
BSR set_play_scroller scroll pattern
.notply CMP.L #'patt',play_mode if playing pattern then
BNE.S .notpat
BSR set_play_scroller scroll pattern
CMP.L #'edit',edit_mode if recording then
BNE.S .notpat
MOVE.L play_cursor,D0 update cursor
LSR.L #4,D0
MOVE.W D0,edit_cursor_y
.notpat ADD.L #16,play_cursor step down 1 row
CMP.L #64*16,play_cursor
BNE.S player_done if end then new pattern
player_newpat
CLR.L play_cursor reset cursor
CLR.W pattern_break_flag cancel break
CMP.L #'patp',play_mode if playing pattern then
BNE.S player_done repeat
ADDQ.L #1,song_position else
AND.L #$7F,song_position next
MOVEQ #0,D0
MOVE.W song_length,D0 if end of song then
MOVE.L song_position,D1 restart
CMP.L D0,D1
BNE.S player_done
MOVEQ #0,D0
MOVE.L song_file_ptr,A0
MOVE.B sf_restart(A0),D0
MOVE.L D0,song_position
player_done
TST.W pattern_break_flag if break/jump then new pattern
BNE.S player_newpat
MOVEM.L (SP)+,D0-D7/A0-A6
RTS
check_hallonsoft_mode
TST.W hsoft_flag if 'hallonsoft' typed in then
BEQ return
CLR.W hsoft_flag
LEA _custom+$10,A0 setup new screen
MOVE.L #hallon_logo,D0 set copper list
MOVE.W D0,cl_hallon+30
SWAP D0
MOVE.W D0,cl_hallon+26
MOVE.L #hallon_logo+1024,D0
MOVE.W D0,cl_hallon+38
SWAP D0
MOVE.W D0,cl_hallon+34
MOVE.L #cl_hallon,cop1lch-$10(A0)
.wait BTST #6,$BFE001 wait for left button
BNE.S .wait
BSR wait_no_buttons wait till release
BSR wait_20ms wait 1/5 second
BSR wait_20ms
BSR wait_20ms
BSR wait_20ms
BSR wait_20ms
MOVE.L clist_ptr,cop1lch-$10(A0) restore copper list
MOVE.W #$8020,dmacon-$10(A0) enable sprite dma
CLR.B key_code cancel any keys
RTS
set_play_scroller
MOVE.L play_cursor,D0 play ptr = 0..1023
LSR.L #4,D0 /16 for row 0..63
BRA.S set_scroller
set_edit_scroller
MOVE.W edit_cursor_y,D0 edit cursor = 0..63
set_scroller
MULU #7*40,D0 set pattern screen scroll addr
MOVE.L screen_ptr,A0
ADD.L #139*40,A0
ADD.L A0,D0
MOVE.L cptr_plane3b,A1
MOVE.W D0,6(A1)
SWAP D0
MOVE.W D0,2(A1)
RTS
* exit mouse_x=0..319/mouse_y=0..255
scan_mouse_coords
MOVE.W _custom+joy0dat,D0 d0=mouse data yyyyyyyyxxxxxxxx
MOVE.W D0,D2 save in d2
AND.W #$FF,D0 d0=new_x
MOVE.W D0,D1
SUB.W mouse_oldx,D0 d0=new_x - old_x
MOVE.W D1,mouse_oldx old_x=new_x
EXT.W D0
CMPI.W #127,D0 if overflow then
BMI.S .underx
MOVE.W #255,D1 d0=255-d0
SUB.W D0,D1
MOVE.W D1,D0
BRA.S .sumx
.underx CMPI.W #-127,D0 if underflow then
BPL.S .sumx
ADD.W #255,D0 d0=255+d0
.sumx ADD.W D0,mouse_sumx sum_x+d0
MOVE.W D2,D0 d0=new_y
LSR.W #8,D0
MOVE.W D0,D1
SUB.W mouse_oldy,D0 d0=new_y-old_y
MOVE.W D1,mouse_oldy old_y=new_y
EXT.W D0
CMPI.W #127,D0 if overflow then
BMI.S .undery
MOVE.W #255,D1 d0=255-d0
SUB.W D0,D1
MOVE.W D1,D0
BRA.S .sumy
.undery CMPI.W #-127,D0 if underflow then
BPL.S .sumy
ADD.W #255,D0 d0=255+d0
.sumy ADD.W D0,mouse_sumy sum_y+d0
TST.W mouse_sumx if sum_x<0 then =0
BPL.S .xok
CLR.W mouse_sumx
.xok CMP.W #1,mouse_sumy if sum_y<1 then =1
BPL.S .yok
MOVE.W #1,mouse_sumy
.yok CMP.W #639,mouse_sumx if sum_x>639 then =639
BMI.S .xok2
MOVE.W #639,mouse_sumx
.xok2 CMP.W #511,mouse_sumy if sum_y>511 then =511
BMI.S .yok2
MOVE.W #511,mouse_sumy
.yok2 MOVEQ #0,D0
MOVE.W mouse_sumx,D0
LSR.W #1,D0
MOVE.W D0,mouse_x mouse_x=sum_x/2=0..319
MOVEQ #0,D0
MOVE.W mouse_sumy,D0
LSR.W #1,D0
MOVE.W D0,mouse_y mouse_y=sum_y/2=0..255
RTS
vbl_irq
MOVEM.L D0/D1/A0/A1/A5/A6,-(SP)
LEA _custom,A0
MOVE.L 4.w,a6
MOVE.W intenar(A0),D1 skip if no irq's enabled
BTST #14,D1
BEQ.S .exit
AND.W intreqr(A0),D1 if blitter irq then
BTST #6,D1
BEQ.S .vbl
MOVEM.L $9C(A6),A1/A5 goto exec's handler
PEA _LVOExitIntr(A6)
JMP (A5)
.vbl BTST #5,D1 if vbl irq then
BEQ.S .copper
MOVEM.L D0-D7/A0-A6,-(SP) save all regs
BSR scan_mouse_coords update mouse
BSR set_arrow_position update arrow
BSR update_chaneq_levels channel levels
BSR player play song
BSR check_cursor_keys cursor functions
BSR update_spectrum_analyser spectrum
MOVEM.L (SP)+,D0-D7/A0-A6 restore regs
MOVEM.L $90(A6),A1/A5 goto exec's handler
PEA _LVOExitIntr(A6)
JMP (A5)
.copper BTST #4,D1 if copper irq then
BEQ.S .exit
MOVEM.L $84(A6),A1/A5 goto exec's handler
PEA _LVOExitIntr(A6)
JMP (A5)
.exit MOVEM.L (SP)+,D0-D1/A0-A1/A5-A6
RTE
keyboard_irq
MOVEM.L D0-D7/A0-A6,-(SP)
LEA $BFE001,A0 get key
MOVE.B $C00(A0),D0
MOVEQ #0,D1
MOVE.B D1,$E00(A0)
MOVE.B D1,$E00(A0)
OR.B #$40,$E00(A0)
NOT.B D0 normalize
ROR.B #1,D0
MOVEQ #100,D7
.wait DBRA D7,.wait delay
AND.B #$BF,$E00(A0)
CMPI.B #$60,D0 check for left shift/alt
BEQ.S .pre_ls
CMPI.B #$64,D0
BEQ.S .pre_la
CMPI.B #$64+$80,D0
BEQ.S .rel_la
CMPI.B #$60+$80,D0
BEQ.S .rel_ls
CMPI.B #$43,D0 check for ENTER
BNE.S .noent
MOVE.W #1,key_enter
.noent CMPI.B #$43+$80,D0
BNE.S .noent2
CLR.W key_enter
.noent2 MOVE.B D0,key_code save keycode
BSR.S check_for_hsoft
.exit MOVEM.L (SP)+,D0-D7/A0-A6
RTS
.pre_ls MOVE.W #1,key_lshift
BRA.S .exit
.rel_ls CLR.W key_lshift
BRA.S .exit
.pre_la MOVE.W #1,key_lalt
BRA.S .exit
.rel_la CLR.W key_lalt
BRA.S .exit
check_for_hsoft
TST.B D0 sets a flag if 'HALLONSOFT'
BMI return typed in at any time
MOVE.L hsoft_ptr,A0
CMP.B (A0)+,D0
BEQ.S .gotchr
MOVE.L #hallonsoft,hsoft_ptr
RTS
.gotchr MOVE.L A0,hsoft_ptr
TST.B (A0)
BMI.S .gotall
RTS
.gotall MOVE.L #hallonsoft,hsoft_ptr
LEA hsoft_flag+138,A0 set flag
MOVE.W #1,-138(A0)
RTS
hex_chars
dc.b '0123456789abcdef'
setup LEA hex2ascii,A0 make string table '00'..'FF'
LEA hex_chars,A1
MOVEQ #0,D0
MOVE.W #256-1,D7
.makeha MOVE.W D0,D1
LSR.W #4,D1
MOVE.B 0(A1,D1.W),(A0)+
MOVE.W D0,D1
AND.W #15,D1
MOVE.B 0(A1,D1.W),(A0)+
ADDQ.B #1,D0
DBRA D7,.makeha
LEA DOSname,A1 open dos
JSR _LVOOldOpenLibrary(A6)
MOVE.L D0,DOSbase
MOVE.L 4.w,a6 top half scroller
MOVE.L #27760,D0 = 2*123*40 + 64*7*40
MOVE.L #MEMF_CHIP!MEMF_CLEAR,D1 allocate memory for screen
JSR _LVOAllocMem(A6) used for printing and for
MOVE.L D0,screen_ptr pattern scroller
MOVE.W D0,cl_plane3+4 patch plane 3 addr in copper
SWAP D0
MOVE.W D0,cl_plane3
MOVE.L DOSbase,A6
MOVE.L #plst_name,D1 check for PLST file
MOVEQ #-2,D2
JSR _LVOLock(A6)
MOVE.L D0,D7
BEQ .noplst
MOVE.L D7,D1
MOVE.L #FileInfoBlock,D2 get info block
JSR _LVOExamine(A6)
TST.L D0
BEQ.S .noplst
MOVE.L D7,D1
JSR _LVOUnLock(A6)
LEA FileInfoBlock,A0
MOVE.L 124(A0),D0 save size
MOVE.L D0,plst_size
DIVU #in_size,D0 no. of entries=size/30
MOVE.W D0,plst_entries
MOVE.L plst_size,D0
CLR.L plst_ptr
MOVEQ #0,D1
MOVE.L 4.w,a6
JSR _LVOAllocMem(A6) allocate memory
MOVE.L D0,plst_ptr
BEQ.S .noplst
MOVE.L #plst_name,D1
MOVE.L #1005,D2 read file
MOVE.L DOSbase,A6
JSR _LVOOpen(A6)
MOVE.L D0,D7
BEQ.S .noplst
MOVE.L D7,D1
MOVE.L plst_ptr,D2
MOVE.L plst_size,D3
JSR _LVORead(A6)
CMP.L plst_size,D0
BNE.S .noplst
MOVE.L D7,D1
JSR _LVOClose(A6)
BRA.S .plstok
.noplst TST.L plst_ptr if error then
BEQ.S .plstok free any memory alloc'd
MOVE.L 4.w,a6
MOVE.L plst_ptr,A1
MOVE.L plst_size,D0
JSR _LVOFreeMem(A6)
.plstok MOVE.W _custom+joy0dat,D0 init mouse x,y
MOVE.W D0,D1
AND.W #$FF,D0
MOVE.W D0,mouse_oldx
LSR.W #8,D1
MOVE.W D1,mouse_oldy
MOVE.L #sf_size,D0
MOVE.L #MEMF_CLEAR,D1
MOVE.L 4.w,a6
JSR _LVOAllocMem(A6) allocate song file memory
MOVE.L D0,song_file_ptr
MOVE.L D0,A0
ADD.L #sf_instr,A0 valid replen values
MOVEQ #31-1,D0
.wipe MOVE.W #1,in_replen(A0)
ADD.L #in_size,A0
DBRA D0,.wipe
MOVE.L song_file_ptr,A0
MOVE.W #1*256+0,sf_length(A0) length=1,restart=0
MOVE.L #'M.K.',sf_ident(A0) store id
CLR.W _custom+aud0+ac_vol audio off
CLR.W _custom+aud1+ac_vol
CLR.W _custom+aud2+ac_vol
CLR.W _custom+aud3+ac_vol
MOVE.W #1,plst_entry_no
CLR.L song_position reset cursor & mode
CLR.L play_cursor
CLR.L play_row_index
CLR.L play_mode
CLR.L edit_mode
MOVEQ #6,D0 default tempo
MOVE.L D0,tempo
MOVE.L #copper_list,D0 set copper list ptr
MOVE.L D0,clist_ptr
MOVE.L D0,clist_ptr2
MOVE.L #cl_plane1_2,cptr_plane1_2 various copper patch addrs
MOVE.L #cl_arrow_col,cptr_arrow_col
MOVE.L #cl_plane3b,cptr_plane3b
MOVE.L #cl_con0c,cptr_con0c
MOVE.L #oct1_2_periods,octave_periods set keyboard octave
MOVE.L #oct1_2_names,octave_names
MOVE.L #s_arrow,arrow_spr_ptr arrow sprite
MOVE.L arrow_spr_ptr,sprite_addrs note: sprite 2 not used
MOVE.L #s_inputcursor,sprite_addrs+4
MOVE.L #s_editcursor,sprite_addrs+12
MOVE.L #s_chaneq1,sprite_addrs+16
MOVE.L #s_chaneq2,sprite_addrs+20
MOVE.L #s_chaneq3,sprite_addrs+24
MOVE.L #s_chaneq4,sprite_addrs+28
LEA sprite_addrs,A0
LEA copper_list,A1 patch sprite addresses
MOVEQ #16-1,D2 into copper list
.setspr MOVE.W (A0)+,2(A1)
ADDQ.L #4,A1
DBRA D2,.setspr
BSR set_edit_cursor
CLR.L pattern_no
BSR refresh_pattern_display
BSR refresh_song_position
BSR refresh_song_parameters
MOVE.W #1,current_instr
BSR refresh_instr_parameters
MOVE.L #vbl_irq,(tv_Lev3IntVect).w
MOVE.L #main_screen,D0 patch plane 1,2 addrs
LEA cl_plane1_2,A1 in copper list
MOVE.W D0,6(A1)
SWAP D0
MOVE.W D0,2(A1)
SWAP D0
ADD.L #10240,D0
MOVE.W D0,14(A1)
SWAP D0
MOVE.W D0,10(A1)
MOVE.L 4.w,a6
LEA GFXname,A1 get old copper list
JSR _LVOOldOpenLibrary(A6)
MOVE.L D0,GFXbase
MOVE.L D0,A0
MOVE.L gb_copinit(A0),copper_init
LEA INTname,A1 open intuition
JSR _LVOOldOpenLibrary(A6)
MOVE.L D0,INTbase patch auto_request
MOVE.L D0,A0
MOVE.L _LVOAutoRequest+2(A0),request_patch+2
MOVE.L #new_auto_request,_LVOAutoRequest+2(A0)
BSR.S set_chaneq_copper
BRA set_spect_copper
chaneq_colours_ptr
dc.l chaneq_colours2
spect_colours_ptr
dc.l spect_colours2
set_chaneq_copper
LEA cl_chaneq,A0
MOVE.L chaneq_colours_ptr,A5
MOVE.L #$B807FFFE,D0
MOVEQ #48-1,D7
.loop MOVE.L D0,(A0)+ CWAIT v184,h3
LEA .colnos(PC),A1
MOVEQ #2-1,D5
.loop2 MOVEQ #3-1,D6
.loop3 MOVE.W (A1)+,(A0)+ set colours 25..27,29..31
MOVE.W (A5)+,(A0)+
DBRA D6,.loop3
LEA -6(A5),A5
DBRA D5,.loop2
LEA 6(A5),A5
ADD.L #$1000000,D0 vert+1
DBRA D7,.loop
RTS
.colnos dc.w color0+2*25
dc.w color0+2*26
dc.w color0+2*27
dc.w color0+2*29
dc.w color0+2*30
dc.w color0+2*31
chaneq_colours2
dc.l $F000B00,$7000F00,$B000700 red->yellow->green
dc.l $F100B10,$7100F10,$B100710
dc.l $F200B20,$7200F20,$B200720
dc.l $F300B30,$7300F30,$B300730
dc.l $F400B40,$7400F50,$B500750
dc.l $F600B60,$7600F70,$B700770
dc.l $F800B80,$7800F90,$B900790
dc.l $FA00BA0,$7A00FB0,$BB007B0
dc.l $FC00BC0,$7C00FD0,$BD007D0
dc.l $FE00BE0,$7E00FF0,$BF007F0
dc.l $FF00BF0,$7F00EF0,$AF006F0
dc.l $EF00AF0,$6F00DF0,$9F005F0
dc.l $DF009F0,$5F00CF0,$8F004F0
dc.l $CF008F0,$4F00BF0,$7F003F0
dc.l $BF007F0,$3F00AF0,$6F002F0
dc.l $9F005F0,$1F009F0,$5F001F0
dc.l $8F004F0,$0F008F0,$4F000F0
dc.l $7F003F0,$0E007F0,$3F000E0
dc.l $6F002F0,$0D006F0,$2F000D0
dc.l $5F001F0,$0C005F0,$1F000C0
dc.l $4F000F0,$0B004F0,$0F000B0
dc.l $3F000E0,$0A003F0,$0E000A0
dc.l $2F000D0,$09001F0,$0C00080
dc.l $0F000B0,$07000E0,$0A00060
chaneq_colours1
dc.l $00E000C,$008000E,$00C0009 blue->cyan
dc.l $00E000C,$009000F,$00D0009
dc.l $00F000D,$00A001F,$00D000A
dc.l $01F001D,$00A001F,$01D000B
dc.l $02F001D,$00B002F,$02D000B
dc.l $03F002D,$01B003F,$02D001B
dc.l $03F003D,$01B004F,$03D002B
dc.l $04F003D,$02B005F,$04D002B
dc.l $05F004D,$03B005F,$04D003B
dc.l $06F005D,$03B006F,$05D004B
dc.l $07F005D,$04B007F,$06D004B
dc.l $07F006D,$05B008F,$06D005B
dc.l $08F007D,$05B009F,$07D006B
dc.l $09F007D,$06B009F,$08D006B
dc.l $0AF008D,$07B00AF,$08D007B
dc.l $0BF009D,$07B00BF,$09D008B
dc.l $0BF009D,$08B00CF,$0AD008B
dc.l $0CF00AD,$09B00DF,$0AD009B
dc.l $0DF00BD,$09B00DF,$0BD00AB
dc.l $0EF00BD,$0AB00EF,$0CD00AB
dc.l $0FF00CD,$0BB00FF,$0CD00BB
dc.l $1FF00DD,$0BB01FF,$0DD00BB
dc.l $2FF01DD,$1BB02FF,$1DD01BB
dc.l $3FF02DD,$1BB03FF,$2DD01BB
set_spect_copper
LEA cl_spectrum,A5
MOVE.L spect_colours_ptr,A4
MOVEQ #40-1,D0 40 rows
MOVE.L #$687DFFFE,D1
.loop MOVE.L D1,(A5)+ CWAIT v104,h62
MOVE.W #color0+2*6,(A5)+ color6=spectrum colour
MOVE.W (A4)+,(A5)+
ADD.L #$00600000,D1 CWAIT v104,h110
MOVE.L D1,(A5)+
MOVE.L #$018C0000,(A5)+ color6=0
ADD.L #$01000000,D1 vert wait+1
SUB.L #$00600000,D1
DBRA D0,.loop
RTS
set_spect_colours
LEA cl_spectrum+6,A1
MOVE.L spect_colours_ptr,A0
MOVEQ #40-1,D0
.loop MOVE.W (A0)+,(A1)
ADD.L #16,A1
DBRA D0,.loop
RTS
clear_spect_colours
LEA cl_spectrum+6,A0
MOVEQ #40-1,D0
.loop CLR.W (A0)
ADD.L #16,A0
DBRA D0,.loop
RTS
spect_colours1
dc.l $01F002F,$02F002F,$03F003F blue->cyan
dc.l $03F004F,$04F004F,$05F005F
dc.l $05F006F,$06F006F,$07F007F
dc.l $07F008F,$08F008F,$09F009F
dc.l $09F00AF,$0AF00AF,$0BF00BF
dc.l $0BF00CF,$0CF00CF,$0DF00DF
dc.w $0DF
spect_colours2
dc.l $F000F10,$F200F30,$F400F50 red->yellow->green
dc.l $F600F70,$F800F90,$FA00FB0
dc.l $FC00FD0,$FE00FF0,$EF00DF0
dc.l $CF00BF0,$AF009F0,$8F007F0
dc.l $6F005F0,$4F003F0,$2F001F0
dc.l $0F000E0,$0D000C0,$0B000A0
dc.w $090
plst_name
dc.b 'ST-00:PLST',0
dc.b 0
INTname dc.b 'intuition.library',0
new_auto_request
TST.W stop_request if request enabled then
BNE.S no_request
MOVE.L copper_init,_custom+cop1lch set old copper list
request_patch
JSR 0 do request
MOVE.L clist_ptr,_custom+cop1lch set my copper list
RTS
no_request
MOVEQ #0,D0
RTS
print_allright
MOVEM.L D0-D7/A0-A6,-(SP)
MOVE.L #12,string_size
MOVE.L #127*40+15,char_offset
MOVE.L #allright_msg,string_addr
BSR print_string
CLR.L string_size
MOVEM.L (SP)+,D0-D7/A0-A6
RTS
allright_msg
dc.b 'all right ',0
even
refresh_pattern_display
CLR.W new_pat_flag
MOVE.L cptr_con0c,A0 disable plane 3
MOVE.W #$2200,(A0)
MOVE.L #128*40+1,char_offset
MOVE.L pattern_no,D1 print pattern no.
LEA temp_str,A0
DIVU #10,D1
ADD.W #'0',D1
MOVE.B D1,(A0)+
CLR.W D1
SWAP D1
ADD.W #'0',D1
MOVE.B D1,(A0)+
CLR.W D1
SWAP D1
MOVE.L #2,string_size
MOVE.L #temp_str,string_addr
BSR print_string
CLR.L temp_str
MOVE.L #188*40+1,char_offset
MOVE.L song_file_ptr,A6 a6=song+offset+1024*pattern
ADD.L #sf_patterns,A6
MOVE.L pattern_no,D6
LSL.L #8,D6
LSL.L #2,D6
ADD.L D6,A6
CLR.L rpd_row row no.
MOVEQ #0,D6
.row MOVEQ #0,D7 print row no.
MOVE.L #2,string_size
MOVE.L rpd_row,D1
LEA temp_str,A0
DIVU #10,D1
ADD.W #'0',D1
MOVE.B D1,(A0)+
CLR.W D1
SWAP D1
ADD.W #'0',D1
MOVE.B D1,(A0)+
CLR.W D1
SWAP D1
MOVE.L #2,string_size
MOVE.L #temp_str,string_addr
BSR print_string
CLR.L temp_str
ADDQ.L #1,char_offset skip 1 char
ADDQ.L #1,rpd_row row no. + 1
.voice MOVEQ #0,D0 for each voice
MOVEQ #0,D1 print note name
MOVE.L #3,string_size
MOVE.W (A6),D1
AND.W #$FFF,D1
MOVE.L #oct1_2_3_periods,A0
.search CMP.W 0(A0,D0.L),D1
BEQ.S .found
ADDQ.L #2,D0
BRA.S .search
.found LSL.L #1,D0
ADD.L #oct1_2_3_names,D0
MOVE.L D0,string_addr
BSR print_string
MOVEQ #0,D0 print parameters
MOVE.W (A6),D0
AND.W #$F000,D0
LSR.W #8,D0
BSR print_hex1
MOVE.L #2,string_size
MOVEQ #0,D0
MOVE.B 2(A6),D0
LSL.L #1,D0
LEA hex2ascii,A0
ADD.L D0,A0
MOVE.L A0,string_addr
BSR print_string
MOVEQ #0,D0
MOVE.B 3(A6),D0
LSL.L #1,D0
MOVE.L #hex2ascii,A0
ADD.L D0,A0
MOVE.L A0,string_addr
BSR print_string
ADDQ.L #1,char_offset skip char
ADDQ.L #4,a6 next voice
ADDQ.L #1,D7
CMPI.L #4,D7
BNE .voice
ADD.L #6*40+1,char_offset next row
ADDQ.L #1,D6
CMPI.L #64,D6
BNE .row
MOVE.L cptr_con0c,A0 enable plane 3
MOVE.W #$3200,(A0)
RTS
refresh_song_position
MOVE.W song_position+2,word_to_print print song position
MOVE.L #4*40+8,char_offset
BSR print_dec4
MOVE.L song_file_ptr,A0 print pattern no. at position
ADD.L #sf_parts,A0
ADD.L song_position,A0
MOVE.B (A0),word_to_print+1
MOVE.B (A0),new_pat_no+3
MOVEQ #0,D1
MOVE.B (A0),D1
CMP.B prev_pat_no+3,D1 flag if new pattern
BEQ.S .same
MOVE.W #1,new_pat_flag
.same MOVE.L #$260,char_offset
MOVE.B (A0),prev_pat_no+3
BRA print_dec4
refresh_song_parameters
MOVE.L song_file_ptr,A0 print song length
ADD.L #sf_length,A0
MOVE.L A0,temp
MOVE.B (A0),word_to_print+1
MOVE.L #26*40+8,char_offset
BSR print_dec4
MOVE.L temp,A0 print song restart
MOVE.B sf_restart-sf_length(A0),word_to_print+1
MOVE.L #37*40+8,char_offset
BSR print_dec4
refresh_song_name
MOVE.L song_file_ptr,string_addr print song name
MOVE.L #103*40+13,char_offset
MOVE.L #$14,string_size
BRA print_string
refresh_instr_parameters
MOVE.W current_instr,word_to_print print instrument no.
MOVE.L #$788,char_offset
BSR print_hex4
MOVEQ #0,D0
MOVE.W current_instr,D0
TST.W D0
BEQ .skip
ASL.L #2,D0
LEA instr_addr_list,A0
MOVE.L 0(A0,D0.L),instr_addr
MOVE.L song_file_ptr,A0
SUB.L #in_size-sf_instr,A0
MOVE.W current_instr,D0
MULU #in_size,D0
ADD.L D0,A0
MOVE.L A0,temp
MOVE.W in_length(A0),instr_length
MOVE.W in_volume(A0),instr_volume
MOVE.W in_repeat(A0),instr_repeat
MOVE.W in_replen(A0),instr_replen
MOVE.W in_volume(A0),word_to_print
MOVE.L #$940,char_offset print volume
BSR print_hex4
MOVE.W instr_length,D0
ADD.W D0,D0
MOVE.W D0,word_to_print
MOVE.L #$AF8,char_offset print length
BSR print_hex4
MOVE.W instr_repeat,D0
ADD.W D0,D0
MOVE.W D0,word_to_print
MOVE.L #$CB0,char_offset print repeat
BSR print_hex4
MOVE.W instr_replen,D0
ADD.W D0,D0
MOVE.W D0,word_to_print
MOVE.L #$E68,char_offset print replen
BSR print_hex4
MOVE.L temp,string_addr
MOVE.L #$11DD,char_offset print name string
MOVE.L #22,string_size
BSR print_string
.skip RTS
* entry word_to_print = word
print_dec4
MOVEQ #0,D1
MOVE.W word_to_print,D1
LEA temp_str,A0
DIVU #1000,D1
BSR.S .digit
DIVU #100,D1
BSR.S .digit
DIVU #10,D1
BSR.S .digit
BSR.S .digit
MOVE.L #4,string_size
MOVE.L #temp_str,string_addr
BSR print_string
CLR.L temp_str
CLR.W word_to_print
RTS
.digit ADD.W #'0',D1
MOVE.B D1,(A0)+
CLR.W D1
SWAP D1
RTS
print_hex_instr
MOVEQ #0,D0
TST.W keyplay_period
BEQ.S print_hex1
MOVE.W current_instr,D0
print_hex1
LSL.L #1,D0
LEA hex2ascii,A0
ADD.L D0,A0
MOVE.L A0,string_addr
MOVE.L #1,string_size
BSR.S print_string
CLR.W word_to_print
RTS
* entry word_to_print = word
print_hex4
LEA word_to_print,A0
MOVEQ #0,D0
MOVE.B (A0),D0
LSL.L #1,D0
LEA hex2ascii,A0
ADD.L D0,A0
MOVE.L A0,string_addr
MOVE.L #2,string_size
BSR.S print_string
LEA word_to_print,A0
MOVEQ #0,D0
MOVE.B 1(A0),D0
LSL.L #1,D0
MOVE.L #hex2ascii,A0
ADD.L D0,A0
MOVE.L A0,string_addr
MOVE.L #2,string_size
BSR.S print_string
CLR.W word_to_print
RTS
print_string
CLR.L string_index index=0
MOVE.L string_size,D3 d3=length
.loop MOVE.L string_addr,A0 index char
ADD.L string_index,A0
MOVEQ #0,D1
MOVE.B (A0),D1 if =0 then print null char (e.g. '_')
BNE.S .notnul
MOVE.B null_char,D1
.notnul CMPI.B #96,D1 lower->upper
BLT.S .upp
SUB.B #32,D1
.upp SUB.B #32,D1
LSL.W #4,D1
LEA charset,A0 index char
ADD.L D1,A0
MOVE.L screen_ptr,A1 row ptr
ADD.L char_offset,A1 +column index
MOVE.B (A0),(A1) print char
MOVE.B 2(A0),40(A1)
MOVE.B 4(A0),80(A1)
MOVE.B 6(A0),120(A1)
MOVE.B 8(A0),160(A1)
ADDQ.L #1,string_index index+1
ADDQ.L #1,char_offset column+1
CMP.L string_index,D3 until index=length
BNE.S .loop
RTS
print_string_spc
MOVE.W null_char,-(SP)
MOVE.B #' ',null_char
BSR print_string
MOVE.W (SP)+,null_char
RTS
null_char dc.b $7F,0
* entry d0=x coord
* d1=y coord
* d2=height
* a0=sprite ptr
position_sprite
ADD.W #44,D1 x+125,y+44
ADD.W D1,D2 put msb's in right place
ROL.W #7,D2
ASL.W #1,D2
BCC.S .lmsb0
OR.W #2,D2
.lmsb0 ROL.W #7,D1
ASL.W #1,D1
BCC.S .fmsb0
OR.W #4,D2
.fmsb0 ADD.W #125,D0
ASR.W #1,D0
BCC.S .hmsb0
OR.W #1,D2
.hmsb0 OR.W D0,D1
MOVE.W D1,(A0) store control words
MOVE.W D2,2(A0)
RTS
* load/save file
* entry file_nameptr = filename ptr
* file_addr = addr
* file_length = length
load_a_file
TST.L file_length
BEQ.S .skip
BSR arrow_is_green
MOVE.L DOSbase,A6
MOVE.L file_nameptr,D1
MOVE.L #1005,D2 read
JSR _LVOOpen(A6)
MOVE.L D0,file_handle
BNE.S .ok
BSR arrow_flash_red
MOVEQ #0,D0
RTS
.ok MOVE.L file_handle,D1
MOVE.L file_addr,D2
MOVE.L file_length,D3
JSR _LVORead(A6)
MOVE.L file_handle,D1
JSR _LVOClose(A6)
.skip CLR.L file_handle
BRA arrow_is_grey
save_a_file
BSR arrow_is_green
MOVE.L DOSbase,A6
MOVE.L file_nameptr,D1
MOVE.L #1006,D2 write
JSR _LVOOpen(A6)
MOVE.L D0,file_handle
BNE.S .ok
BRA arrow_flash_red
.ok MOVE.L file_handle,D1
MOVE.L file_addr,D2
MOVE.L file_length,D3
JSR _LVOWrite(A6)
MOVE.L file_handle,D1
JSR _LVOClose(A6)
CLR.L file_handle
BRA arrow_is_grey
init_toneporta
MOVE.W (A6),D2 set start period
AND.W #$FFF,D2
MOVE.W D2,24(A6)
MOVE.W 16(A6),D0 if = current then no portamento
CLR.B 22(A6) else set flag up/down
CMP.W D0,D2
BEQ.S .cancel
BGE.S .up
MOVE.B #1,22(A6)
.up RTS
.cancel CLR.W 24(A6)
RTS
songcomm_toneporta
MOVE.B 3(A6),D0
BEQ.S .continue
MOVE.B D0,23(A6)
CLR.B 3(A6)
.continue
TST.W 24(A6)
BEQ.S .skip
MOVEQ #0,D0
MOVE.B 23(A6),D0
TST.B 22(A6)
BNE.S .down
ADD.W D0,16(A6)
MOVE.W 24(A6),D0
CMP.W 16(A6),D0
BGT.S .ok
MOVE.W 24(A6),16(A6)
CLR.W 24(A6)
.ok MOVE.W 16(A6),ac_per(A5)
RTS
.down SUB.W D0,16(A6)
MOVE.W 24(A6),D0
CMP.W 16(A6),D0
BLT.S .ok
MOVE.W 24(A6),16(A6)
CLR.W 24(A6)
MOVE.W 16(A6),ac_per(A5)
.skip RTS
songcomm_vibrato
MOVE.B 3(A6),D0
BEQ.S .continue
MOVE.B D0,26(A6)
.continue
MOVE.B 27(A6),D0
LEA small_sine(PC),A4
LSR.W #2,D0
AND.W #$1F,D0
MOVEQ #0,D2
MOVE.B 0(A4,D0.W),D2
MOVE.B 26(A6),D0
AND.W #15,D0
MULU D0,D2
LSR.W #6,D2
MOVE.W 16(A6),D0
TST.B 27(A6)
BMI.S .minus
ADD.W D2,D0
BRA.S .plus
.minus SUB.W D2,D0
.plus MOVE.W D0,ac_per(A5)
MOVE.B 26(A6),D0
LSR.W #2,D0
AND.W #$3C,D0
ADD.B D0,27(A6)
RTS
small_sine
dc.l $0018314A =255*sin(n*180/32),n=0..31
dc.l $61788DA1
dc.l $B4C5D4E0
dc.l $EBF4FAFD
dc.l $FFFDFAF4
dc.l $EBE0D4C5
dc.l $B4A18D78
dc.l $614A3118
no_songcomm
MOVE.W 16(A6),ac_per(A5)
RTS
songcomm_1234A
MOVE.W 2(A6),D0
AND.W #$FFF,D0
BEQ no_songcomm
MOVE.B 2(A6),D0
AND.B #15,D0
TST.B D0
BEQ songcomm_arpeggio
CMPI.B #1,D0
BEQ.S songcomm_portaup
CMPI.B #2,D0
BEQ songcomm_portadown
CMPI.B #3,D0
BEQ songcomm_toneporta
CMPI.B #4,D0
BEQ songcomm_vibrato
MOVE.W 16(A6),ac_per(A5)
CMPI.B #$A,D0
BEQ.S songcomm_volslide
RTS
songcomm_volslide
MOVEQ #0,D0
MOVE.B 3(A6),D0
LSR.B #4,D0
TST.B D0
BEQ.S .down
.up ADD.W D0,18(A6)
CMP.W #64,18(A6)
BMI.S .up2
MOVE.W #64,18(A6)
.up2 MOVE.W 18(A6),ac_vol(A5)
RTS
.down MOVEQ #0,D0
MOVE.B 3(A6),D0
AND.B #15,D0
SUB.W D0,18(A6)
BPL.S .down2
CLR.W 18(A6)
.down2 MOVE.W 18(A6),ac_vol(A5)
RTS
songcomm_portaup
MOVEQ #0,D0
MOVE.B 3(A6),D0
SUB.W D0,16(A6)
MOVE.W 16(A6),D0
CMPI.W #$71,D0
BPL.S .ok
MOVE.W #$71,16(A6)
.ok MOVE.W 16(A6),ac_per(A5)
RTS
songcomm_portadown
CLR.W D0
MOVE.B 3(A6),D0
ADD.W D0,16(A6)
MOVE.W 16(A6),D0
CMPI.W #$358,D0
BMI.S .ok
MOVE.W #$358,16(A6)
.ok MOVE.W 16(A6),ac_per(A5)
RTS
songcomm_B_to_F
MOVE.B 2(A6),D0
AND.B #15,D0
CMPI.B #$E,D0
BEQ.S .set_filter
CMPI.B #$D,D0
BEQ.S .pattern_break
CMPI.B #$B,D0
BEQ.S .position_jump
CMPI.B #$C,D0
BEQ.S .set_volume
CMPI.B #$F,D0
BEQ.S .set_speed
RTS
.set_filter
MOVE.B 3(A6),D0
AND.B #1,D0
ASL.B #1,D0
AND.B #$FD,$BFE001
OR.B D0,$BFE001
RTS
.pattern_break
MOVE.W #1,pattern_break_flag
RTS
.position_jump
MOVE.W #1,pattern_break_flag
CMP.L #'patt',play_mode only if playing song
BEQ.S .pj2
MOVE.B 3(A6),D0
SUBQ.B #1,D0
MOVE.B D0,song_position+3
.pj2 RTS
.set_volume
CMP.B #64,3(A6) max 64
BLE.S .sv2
MOVE.B #64,3(A6)
.sv2 MOVE.B 3(A6),ac_vol(A5)
MOVE.B 3(A6),1(A2)
MOVE.B 3(A6),19(A6)
RTS
.set_speed
CMP.B #31,3(A6) max 31
BLE.S .ss2
MOVE.B #31,3(A6)
.ss2 MOVEQ #0,D0
MOVE.B 3(A6),D0
MOVE.L D0,tempo
CLR.L frame_count
RTS
songs_dir
dc.b 'st-00:songs/'
songs_dir_name
ds.b 28
st01_msg
dc.b 'st-01:'
ds.b 28
modname_buffer
ds.b 50
song_length
dc.w 1
DOSname dc.b 'dos.library',0
GFXname dc.b 'graphics.library',0
dc.b 0
audio_info_1
dc.l 0,0,0,0,0,$10000,0
audio_info_2
dc.l 0,0,0,0,0,$20000,0
audio_info_3
dc.l 0,0,0,0,0,$40000,0
audio_info_4
dc.l 0,0,0,0,0,$80000,0
hex_keys
dc.b $0A,$01,$02,$03 keys 0..9,A..F
dc.b $04,$05,$06,$07
dc.b $08,$09,$20,$35
dc.b $33,$22,$12,$23
piano_keys
dc.b $31,$21,$32,$22 keys ZSXDCVGB
dc.b $33,$34,$24,$35
dc.b $25,$36,$26,$37 HNJM,L.;
dc.b $38,$28,$39,$29
dc.b $3A,$10,$02,$11 /Q2W3ER5
dc.b $03,$12,$13,$05
dc.b $14,$06,$15,$07 T6Y7UI9O
dc.b $16,$17,$09,$18
dc.b $0A,$19,$1A,$0C 0P[=]\{BS}
dc.b $1B,$0D,$46
dc.b $00
oct1_2_periods
dc.l $3580328,$2FA02D0,$2A60280,$25C023A
dc.l $21A01FC,$1E001C5,$1AC0194,$17D0168
dc.l $15301AC,$194017D,$1680153,$140012E
dc.l $11D010D,$0FE00F0,$0E200D6,$0CA00BE
dc.l $0B400AA,$0A00097,$08F0087
dc.w 0
oct1_2_names
dc.b 'c-1 c#1 d-1 d#1 e-1 f-1 f#1 g-1 g#1 a-1 a#1 b-1 '
dc.b 'c-2 c#2 d-2 d#2 e-2 '
dc.b 'c-2 c#2 d-2 d#2 e-2 f-2 f#2 g-2 g#2 a-2 a#2 b-2 '
dc.b 'c-3 c#3 d-3 d#3 e-3 f-3 f#3 g-3 g#3 '
dc.b '--- '
oct2_3_periods
dc.l $1AC0194,$17D0168,$1530140,$12E011D
dc.l $10D00FE,$0F000E2,$0D600CA,$0BE00B4
dc.l $0AA00D6,$0CA00BE,$0B400AA,$0A00097
dc.l $08F0087,$07F0078,$0710000,0
dc.l 0,0,0
dc.w 0
oct2_3_names
dc.b 'c-2 c#2 d-2 d#2 e-2 f-2 f#2 g-2 g#2 a-2 a#2 b-2 '
dc.b 'c-3 c#3 d-3 d#3 e-3 '
dc.b 'c-3 c#3 d-3 d#3 e-3 f-3 f#3 g-3 g#3 a-3 a#3 b-3 '
dc.b '--- --- --- --- --- --- --- --- --- --- '
oct1_2_3_periods
dc.l $3580328,$2FA02D0,$2A60280,$25C023A
dc.l $21A01FC,$1E001C5,$1AC0194,$17D0168
dc.l $1530140,$12E011D,$10D00FE,$0F000E2
dc.l $0D600CA,$0BE00B4,$0AA00A0,$097008F
dc.l $087007F,$0780071,0,0
dc.l 0,0,0,0
dc.l 0,0,0
oct1_2_3_names
dc.b 'c-1 c#1 d-1 d#1 e-1 f-1 f#1 g-1 g#1 a-1 a#1 b-1 '
dc.b 'c-2 c#2 d-2 d#2 e-2 f-2 f#2 g-2 g#2 a-2 a#2 b-2 '
dc.b 'c-3 c#3 d-3 d#3 e-3 f-3 f#3 g-3 g#3 a-3 a#3 b-3 '
dc.b '--- '
valid_name_keycodes
dc.b $40 SPACE
dc.b $20,$35,$33,$22,$12,$23,$24,$25 A..Z
dc.b $17,$26,$27,$28,$37,$36,$18,$19
dc.b $10,$13,$21,$14,$16,$34,$11,$32
dc.b $15,$31
dc.b $0A,$01,$02,$03,$04,$05,$06,$07 0..9
dc.b $08,$09
dc.b $88,$89,$39,$0B,$2A,$AA,$A9,$87,$8B *(.-#@:&_
dc.w $54,$59,$5E,$63,$6A,$70,$76,$7E
dc.w $85,$8C,$95,$9E,$A7,$B1,$BC,$C6
dc.w $D3,$DF,$ED,$FB,$10A,$11A,$12A,$13D
dc.w $14F,$162,$179,$18E,$1A5,$1C0,$1DA,$1F4
dc.w $212,$234,$25A,$284
xpos2column
dc.b 3,6,7,8,9,10 convert edit cursor xpos to column
dc.b 12,15,16,17,18,19
dc.b 21,24,25,26,27,28
dc.b 30,33,34,35,36,37
valid_name_chars
dc.b ' abcdefghijklmno'
dc.b 'pqrstuvwxyz01234'
dc.b '56789().-',$27,'#:/',0
hallonsoft
dc.b $25,$20,$28,$28 keycodes for 'HALLONSOFT'
dc.b $18,$36,$21,$18
dc.b $23,$14,$FF,$FF
*------------------------------
* GRAPHICS FILES
charset incbin charset.dat 64 chars 8*8 pixels 2 plane
spectrum_screen
incbin spectrum.img 55 rows * 13 words 2 plane
diskops_screen
incbin diskops.img 99 rows * 13 words 2 plane
onoff_icon
incbin onoff.img 12 rows * 2 words 2 plane
dc.w $000,$555 (UNUSED)
dc.w $AAA,$FFF
rusure_icon
incbin rusure.img 39 rows * 7 words 2 plane
hsoft_ptr dc.l hallonsoft ptr to 'cheat mode' key-string
plst_screen
incbin plst.img 99 rows * 13 words 2 plane
drive_icon
incbin seldrive.img 34 rows * 5 words 2 plane
dc.w $FFFF,0 (UNUSED)
*------------------------------
* VARIABLES
cutvoice_buffer ds.b 256 cut/paste voice buffer
cutwhole_buffer ds.b 1024 cut/paste pattern buffer
fscroll_pending dc.w 0 diskop file scroll 0=none/1=up/2=down
pscroll_pending dc.w 0 plst file scroll
sprite_addrs ds.l 8 only used to setup
copper_init dc.l 0 old copper
screen_ptr dc.l 0 ptr to 3rd plane of screen (info+scroller)
char_offset dc.l 0 screen offset for character printer
rpd_row dc.l 0 local
edit_mode dc.l 0 0=off/'edit'=on
play_mode dc.l 0 0=off/'patt'=pattern/'patp'=play
temp dc.l 0
string_index dc.l 0 index to printed string
string_addr dc.l 0 ptr to printed string
string_size dc.l 0 size of printed string
pattern_no dc.l 0 current pattern displayed
tempo dc.l 0 default playback tempo
octave_periods dc.l 0 ptrs to periods and names of currently
octave_names dc.l 0 selected keyboard octave (1..2 or 2..3)
ain_disable dc.w 0 (UNALTERED)
edh_index dc.w 0 local
key_code dc.w 0 latest key pressed
keyplay_period dc.w 0 period of note played from keyboard
input_cursor_x dc.w 0 for inputroutine
input_cursor_y dc.w 0 :
input_end_addr dc.l 0 :
edit_cursor_y dc.w 0 pattern edit cursor y = row 0..63
edit_cursor_x dc.w 0 cursor x = 0..5/6..11/12..17/18..23
rep_delay dc.w 0 (UNALTERED) 0=delay/-1=no delay
word_to_print dc.w 0 word to print in hex
max_pat_no dc.w 0 max pattern no. in song file
current_instr dc.w 0 current instrument
plst_entry_no dc.w 0 entry no. selected in plst
alter_dir dc.w 0 direction for altering parameters
mouse_oldx dc.w 0 mouse update vars (local)
mouse_oldy dc.w 0 :
mouse_sumx dc.w 0 :
mouse_sumy dc.w 0 :
mouse_x dc.w 0 current mouse x=0..319
mouse_y dc.w 0 current mouse y=0..255
mouse_x2 dc.w 0 copy of mouse_x
mouse_y2 dc.w 0 copy of mouse_y
instr_length dc.w 0 parameters of current instrument
instr_volume dc.w 0 :
instr_repeat dc.w 0 :
instr_replen dc.w 0 :
instr_addr dc.l 0 :
new_pat_flag dc.w 0 set if new pattern to display
prev_pat_no dc.l 0 used to check if update required
pattern_break_flag dc.w 0 set if pattern break/position jump in song
new_pat_no dc.l 0 pattern to use after break/jump
quantize_flag dc.w 0 set if note was played within quantize time
alloc7k_ptr dc.l 0 (UNUSED)
DOSbase dc.l 0 DOS library base
file_nameptr dc.l 0 filename vars
file_addr dc.l 0 :
file_handle dc.l 0 :
file_length dc.l 0 :
selected_filename ds.b 30 :
play_cursor dc.l 0 pattern index while playing = 16*row+column
song_position dc.l 0 current position in song
frame_count dc.l 0 50Hz counter for song update
play_row_index dc.l 0 index to pattern row played (UNUSED)
song_file_ptr dc.l 0 ptr to current song file
keyplay_channel dc.w 0 audio channel played from keyboard
instr_alloc_list ds.l 2*31 alloc'd instrument memory (31 addrs,31 sizes)
instr_addr_list ds.l 32 ptrs to instrument samples
player_channels dc.w 0 audio channels active in player
old_irq2_addr dc.l 0 old keyboard irq vector
old_irq2_patch dc.l 0 :
initialSP dc.l 0 old SP
old_irq3_vect dc.l 0 old vbl irq vector
dc.l 0,0 (UNUSED)
spectrum_new ds.w 23 new/old spectrum analyser lists
spectrum_old ds.w 23 :
disk_fn dc.w 0 disk function awaiting file selection
* 0=none/1=load song/2=delete song
* 3=load module/4=delete module/5=load sample
dc.l 0 (UNUSED)
lock_ptr dc.l 0 ptr from Lock
align must be divisible by 4 !!!!
FileInfoBlock ds.b 256 file info block from Examine
mode dc.w 0 0=entry/1=editor/3=diskops/
old_arrow_colours ds.w 3 saved arrow colours
ipn_temp dc.w 0 local
load_sort_flag dc.w 0 sort list for loading samples
load_sort_list ds.l 31 with a minimum of disk swapping
plst_size dc.l 0 preset list
plst_ptr dc.l 0 :
plst_entries dc.w 0 :
GFXbase dc.l 0 Graphics library base
INTbase dc.l 0 Intuition library base
_WBenchMsg dc.l 0 Message ptr for WB startup
plst_flag dc.w 0 0=off/-1=on
edit_icons_copy ds.b 2200 copy of edit icons
old_volume dc.w 0 local
instr_header ds.l 32 sample header lengths
sample_filename ds.b 16 filename
dir_entry_ptr dc.l 0 ptr to file selected from directory
key_enter dc.w 0 set if enter key pressed
memory_free dc.l 0 memory free
memory_used dc.l 0 memory used
ffi_type dc.w 0 for find_file_type, 0=file/1=dir/2=disk
ffi_type_prev dc.w 0 previous value
plst_active_entries dc.w 0 no. of entries matching search disks
plst_cursor dc.w 0 top row of preset list displayed
plst_active_size dc.l 0 size of above (no.*in_size)
plst_indices ds.l 15 indices of displayed plst entries
cursor_rep_flag dc.w 0 auto-repeat for cursor keys
cursor_rep_count dc.w 0 :
pat_pos_dir dc.l 0 change pattern/position with cursor
pat_pos_flag dc.w 0 :
input_in_progress dc.w 0 =1 if inputroutine active
iff_length dc.l 0 length of sample in IFF file
hsoft_flag dc.w 0 flag set if 'HALLONSOFT' typed in
key_lshift dc.w 0 set if left-shift pressed
stop_request dc.w 0 set to disable Intuition Requester
temp_str ds.b 6 local
arrow_spr_ptr dc.l 0 ptr to arrow sprite
pack_buffer_ptr dc.l 0 cruncher/decruncher vars
pack_source_end dc.l 0 :
unpacked_size dc.l 0 :
pack_dest_start dc.l 0 :
pack_dest_end dc.l 0 :
packed_size dc.l 0 :
pack_best_distance dc.l 0 :
pack_best_mode dc.w 0 :
pack_used_00 dc.w 0 :
pack_used_111 dc.w 0 :
key_lalt dc.w 0 :
cptr_plane3b dc.l 0 ptr to 2nd plane3 addr in copper list
clist_ptr dc.l 0 ptr to copper list
cptr_con0c dc.l 0 ptr to bplcon0 lower screen in copper list
clist_ptr2 dc.l 0 copy of clist_ptr, (UNUSED)
cptr_plane1_2 dc.l 0 (UNUSED)
cptr_arrow_col dc.l 0 ptr to arrow colours in copper list
hex2ascii ds.w 256 converts 0..255 => '00'..'FF'
null_string ds.b 24 string of 0's
memory_flag dc.w 1 set if memory usage changed (init=1)
*------------------------------
copper_list
DC.W spr0pth,0,spr0ptl,0 set sprites
DC.W spr1pth,0,spr1ptl,0
DC.W spr2pth,0,spr2ptl,0
DC.W spr3pth,0,spr3ptl,0
DC.W spr4pth,0,spr4ptl,0
DC.W spr5pth,0,spr5ptl,0
DC.W spr6pth,0,spr6ptl,0
DC.W spr7pth,0,spr7ptl,0
cl_plane1_2
DC.W bpl1pth,0,bpl1ptl,0 set planes 1..3
DC.W bpl2pth,0,bpl2ptl,0
DC.W bpl3pth
cl_plane3
DC.W 0
DC.W bpl3ptl
DC.W 0
cl_arrow_col
DC.W color0+2*17,$E00,color0+2*18,$B00 colours
DC.W color0+2*19,$800,color0+2*16,0
DC.W color0,0
cl_col1 DC.W color0+2*1,$733
DC.W color0+2*2,$A66,color0+2*3,$C99
DC.W color0+2*4,$AFB,color0+2*21,$900
DC.W color0+2*22,$600,color0+2*23,$E00
DC.W diwstrt,$2C81,diwstop,$2CC1 standard 256*320
DC.W ddfstrt,$38,ddfstop,$D0
DC.W bplcon1,0 no scroll
DC.W bplcon2,$24 sprite priority
DC.W $2C07,$FFFE wait v44
DC.W bplcon0,$3200 3 planes
cl_spectrum
DS.W 320 spectrum analyser
DC.W $B807,$FFFE wait v184
DC.W bplcon0,$2200 2 planes
cl_plane3b
DC.W bpl3pth,0,bpl3ptl,0 set plane 3
DC.W color0+2*4
cl_col4b
DC.W $990 set colour 4 lower half
DC.W $B907,$FFFE wait v185
DC.W bplcon0
cl_con0c
DC.W $3200 3 planes
cl_chaneq
DS.W 672 channel eq's
DC.W $E907,$FFFE wait v233
DC.W bpl2mod,-40,bpl1mod,-40 magnify edit line
DC.W $EA07,$FFFE by changing modulos
DC.W bplcon2,$10 change priority
DC.W bpl2mod,0,bpl1mod,0
DC.W $EB07,$FFFE
DC.W bpl2mod,-40,bpl1mod,-40
DC.W $EC07,$FFFE
DC.W bpl2mod,0,bpl1mod,0
DC.W $ED07,$FFFE
DC.W bpl2mod,-40,bpl1mod,-40
DC.W $EE07,$FFFE
DC.W bpl2mod,0,bpl1mod,0
DC.W $EF07,$FFFE
DC.W bpl2mod,-40,bpl1mod,-40
DC.W $F007,$FFFE
DC.W bpl2mod,0,bpl1mod,0
DC.W $F107,$FFFE
DC.W bpl2mod,-40,bpl1mod,-40
DC.W $F207,$FFFE
DC.W bpl2mod,0,bpl1mod,0
DC.W $F307,$FFFE
DC.W bpl2mod,-40,bpl1mod,-40
DC.W $F407,$FFFE
DC.W bpl2mod,0,bpl1mod,0
DC.W $F507,$FFFE
DC.W bpl2mod,-40,bpl1mod,-40
DC.W $F607,$FFFE wait v246
DC.W bpl2mod,0,bpl1mod,0 reset modulos
DC.W color0+2*25,0,color0+2*26,0,color0+2*27,0 clear sprites
DC.W color0+2*29,0,color0+2*30,0,color0+2*31,0
DC.W $FFDF,$FFFE wait v255
DC.W $2907,$FFFE wait v297
DC.W bplcon0,$2200 2 planes
DC.W $2C07,$FFFE wait v300
DC.W bplcon0,$200 0 planes
DC.W $FFFF,$FFFE
s_arrow DC.W 0,0
DC.W %1111111111111111,%1111111111111111 arrow
DC.W %1000000000000010,%1111111111111110
DC.W %1011111111110100,%1100000000001100
DC.W %1011111111101000,%1100000000011000
DC.W %1011111111010000,%1100000000110000
DC.W %1011111111101000,%1100000000011000
DC.W %1011111111110100,%1100000000001100
DC.W %1011111111111010,%1100000000000110
DC.W %1011111111111101,%1100000000000011
DC.W %1011111111111010,%1100000000000110
DC.W %1011011111110100,%1100100000001100
DC.W %1010101111101000,%1101110000011000
DC.W %1001010111010000,%1111011000110000
DC.W %1010001010100000,%1110001101100000
DC.W %1100000101000000,%1100000111000000
DC.W %1000000010000000,%1000000010000000
DC.W 0,0
DC.W 0
s_editcursor
DC.W 0,0
DC.W %1111111111100000,%1111111111100000 edit cursor
DC.W %1111111111100000,%1111111111100000
REPT 10
DC.W %1000000000100000,%0000000000000000
ENDR
DC.W %0000000000000000,%1111111111100000
DC.W %0000000000000000,%1111111111100000
DC.W 0,0
s_inputcursor
DC.W 0,0
DC.W %0000000000000000,%1111111000000000 input cursor
DC.W %0000000000000000,%1111111000000000
DC.W 0,0
DC.W 0,0
s_chaneq1
DC.W $E95B,$EA01
REPT 48
DC.W %1100000011000000,%0011111111000000 channel eq's 1..4
ENDR
DC.W 0,0
s_chaneq2
DC.W $E97F,$EA01
REPT 48
DC.W %1100000011000000,%0011111111000000
ENDR
DC.W 0,0
s_chaneq3
DC.W $E9A3,$EA01
REPT 48
DC.W %1100000011000000,%0011111111000000
ENDR
DC.W 0,0
s_chaneq4
DC.W $E9C7,$EA01
REPT 48
DC.W %1100000011000000,%0011111111000000
ENDR
DC.W 0,0
cl_hallon
DC.W bplcon0,$2000,bplcon1,$CC,bplcon2,0 hallonsoft copper
DC.W bpl1mod,0,bpl2mod,0
DC.W dmacon,$20
DC.W bpl1pth,0,bpl1ptl,0
DC.W bpl2pth,0,bpl2ptl,0
DC.W color0,$4BF,color0+2*1,$166
DC.W color0+2*2,$5AA,color0+2*3,$AFF
DC.W diwstrt,$5071,diwstop,$90C7
DC.W ddfstrt,$60,ddfstop,$98
DC.W $6373,$FFFE,color0+2*3,$3FF
DC.W $63A9,$FFFE,color0+2*3,$AFF
DC.W $6473,$FFFE,color0+2*3,$4FF
DC.W $64A9,$FFFE,color0+2*3,$AFF
DC.W $6573,$FFFE,color0+2*3,$5FF
DC.W $65A9,$FFFE,color0+2*3,$AFF
DC.W $6673,$FFFE,color0+2*3,$6FF
DC.W $66A9,$FFFE,color0+2*3,$AFF
DC.W $6773,$FFFE,color0+2*3,$7FF
DC.W $67A9,$FFFE,color0+2*3,$AFF
DC.W $6873,$FFFE,color0+2*3,$8FF
DC.W $68A9,$FFFE,color0+2*3,$AFF
DC.W $6973,$FFFE,color0+2*3,$9FF
DC.W $69A9,$FFFE,color0+2*3,$AFF
DC.W $6A73,$FFFE,color0+2*3,$AFF
DC.W $6AA9,$FFFE,color0+2*3,$AFF
DC.W $6B73,$FFFE,color0+2*3,$AEF
DC.W $6BA9,$FFFE,color0+2*3,$AFF
DC.W $6C73,$FFFE,color0+2*3,$ADF
DC.W $6CA9,$FFFE,color0+2*3,$AFF
DC.W $6D73,$FFFE,color0+2*3,$ACF
DC.W $6DA9,$FFFE,color0+2*3,$AFF
DC.W $6E73,$FFFE,color0+2*3,$ABF
DC.W $6EA9,$FFFE,color0+2*3,$AFF
DC.W $6F73,$FFFE,color0+2*3,$AAF
DC.W $6FA9,$FFFE,color0+2*3,$AFF
DC.W $7073,$FFFE,color0+2*3,$A9F
DC.W $70A9,$FFFE,color0+2*3,$AFF
DC.W $7173,$FFFE,color0+2*3,$A8F
DC.W $71A9,$FFFE,color0+2*3,$AFF
DC.W $FFFF,$FFFE
*------------------------------
hallon_logo
incbin hallogo.img 64 rows * 8 words 2 plane
main_screen
incbin tracker.img 256 rows * 20 words 2 plane
*------------------------------