empty_sample        macro(buffer_size, start, steps, divisor)

    db start / divisor
    offset = steps

    next_pos = $ + buffer_size
    until_pos = next_pos - (next_pos mod buffer_size)
    loop_counter = until_pos - $


    loop loop_counter
        db (LOW (start + offset)) / divisor
        offset = offset + steps

    lend

mend

; ============================================

current_tab_label = ""
current_align_val = 0
current_start_pos = 0

; declares a table that must not span a 256-byte
; page boundary.
;
; Since the assembler won't let us decide beforehand
; whether a table should be aligned, we have to do
; things the cheap 'n nasty way.
BEGIN_PAGE_TABLE    macro(tab_label, align_val)

    if (::current_tab_label <> "")
        zeuserror "Trying to declare table \"", tab_label, "\"when the declaration of table \"", ::current_tab_label, "\" is still in progress!"
    endif

    ::current_tab_label = tab_label
    ::current_align_val = align_val
    ::current_start_pos = $

    if (align_val)
        align 256
    endif

    ::LABEL(tab_label)

mend

END_PAGE_TABLE      macro(tab_label)

    if (::current_tab_label = "")
        zeuserror "Trying to end declaration of table \"", tab_label, "\" which has not started!"
    endif

    ::LABEL(tab_label + "_end")

    tab_start = LABEL(tab_label)
    tab_end = LABEL(tab_label + "_end")
    tab_size = tab_end - tab_start

    tab_unaligned_start = current_start_pos
    tab_unaligned_end = current_start_pos + tab_size

    if ((tab_unaligned_start <> tab_unaligned_end) and ((HIGH tab_unaligned_start) <> (HIGH (tab_unaligned_end - 1))))
        if (not current_align_val)
            zeuserror tab_label, " should be aligned!"
        endif
    else
        if (current_align_val)
            zeuserror tab_label, " should not be aligned!"
        endif
    endif

    ::current_tab_label = ""

mend

; ============================================

current_sample = ""
current_sample_addr = 0

BEGIN_SAMPLE        macro(sample_label)

    if (::current_sample <> "")
        zeuserror "Trying to declare sample \"", sample_label, "\"when the declaration of sample \"", ::current_sample, "\" is still in progress!"
    endif

    ::current_sample = sample_label
    ::current_sample_addr = $

    ::LABEL(sample_label)

mend

END_SAMPLE          macro(sample_label)

    if (::current_sample = "")
        zeuserror "Trying to end declaration of sample \"", sample_label, "\" which has not started!"
    endif

    while ((($ - current_sample_addr) % 60) <> 0)
        db $20
    wend

    ::LABEL(sample_label + "_end")

    ::LABEL(sample_label + "_length", (::LABEL(sample_label + "_end") - ::LABEL(sample_label)) / 60)

    ::current_sample = ""

mend

; ============================================

; plants four bytes as lookup entries for the
; waveform drawing function.
GenVolumeEntry      macro (index)

    ; scale to 0-15 (this should probably be improved)
    volume = abs(index - $20)

    left_word = $0001
    right_word = $8000

    loop volume
        left_word   = (left_word << 1)  | $0001
        right_word  = (right_word >> 1) | $8000
    lend

    ; output a single byte at a time
    ; because they should be big-endian
    db (left_word >> 8) & $ff
    db (left_word) & $ff

    db (right_word >> 8) & $ff
    db (right_word) & $ff

mend

; ============================================
