#include "sample_player.h"

#define SAMPLE_BUSYWAIT 19

static const uint8_t voltable[] = {
    0xff,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xff,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xef,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xef,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xdf,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xcf,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xcf,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xbf,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f,
    0xaf,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0xaf,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x9f,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x9f,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x9f,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8f,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8f,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8f,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f,
    0x8e,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8e,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8d,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8c,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8b,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8b,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8a,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x8a,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f,
    0x89,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x89,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0f, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0e, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0e, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0d,
    0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0c, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0c, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0b, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0a, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x0a, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x09, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x09, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x09,
    0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x88,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x78,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x78,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x78,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08,
    0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x08, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x77,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x67,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x67,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07,
    0x67,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x67,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x07, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06,
    0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x66,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x56,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x56,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x56,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x56,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06,
    0x56,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x06, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05,
    0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x55,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05,
    0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x45,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05,
    0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x05, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04,
    0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x44,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04,
    0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x34,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04,
    0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x04, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03,
    0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x33,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03,
    0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03,
    0x23,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03,
    0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x03, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02,
    0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02,
    0x22,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02,
    0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x12,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02,
    0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02,
    0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x02, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x11,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x01,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x01,
    0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00, 0x00,(PSG_LATCH|PSG_CH2|PSG_VOLUME)|0x00
};

void play_sample(uint8_t * sample, uint16_t size) NAKED {
    sample; size;
    __asm
        di
        push hl
        pop iy                              ; iy = hl

        ; set tone to 0
        ld c, #<_PSG
        xor a
        ld b, #(PSG_LATCH | PSG_CH0)        ; ch 0 tone 0
        out (c), b
        out (c), a
        ld b, #(PSG_LATCH | PSG_CH1)        ; ch 1
        out (c), b
        out (c), a
        ld b, #(PSG_LATCH | PSG_CH2)        ; ch 2
        out (c), b
        out (c), a

1$:
        ld bc, #_voltable
        ld h, #0
        ld l, 0(iy)
        inc iy
        add hl, hl
        add hl, bc                          ; hl = &_voltable[(sample[iy+0] * 2)]

        ld a, (hl)
        .rept 4
            rlca
        .endm
        and #0x0f
        or #(PSG_LATCH | PSG_CH0 | PSG_VOLUME)
        ld b, a
        ld a, (hl)
        inc hl
        and #0x0f
        or #(PSG_LATCH | PSG_CH1 | PSG_VOLUME)

        ld c, #<_PSG
        out (c), b
        out (c), a
        outi

        ld b, #SAMPLE_BUSYWAIT              ; delay, need to be calculated properly
2$:
        djnz 2$

        dec de
        ld a, e
        or d
        jp nz, 1$

        ei
        in a, (_VDP_STATUS)  ; cancel pending VDP interrupts
        ret
    __endasm;
}

void cut_sample(uint8_t mask) NAKED {
    mask;
    __asm
        ld c, #<_PSG
        ld b, a
        ld e, #-1
1$:
        inc e
        srl b
        jr c, 2$
        ret z
        jr 1$
2$:
        ld a, e
        .rept 3
            rrca
        .endm
        or #(PSG_LATCH | PSG_VOLUME | 0x0f)
        out (c), a
        jr 1$
    __endasm;
}
