mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
cx16: romsubs of the audio routines now have the rom bank tag.
cx16: removed 'audio' module again, no longer needed to have these stubs
This commit is contained in:
parent
155896c4c7
commit
0fc9aa6b2d
@ -1,459 +0,0 @@
|
|||||||
%import syslib
|
|
||||||
|
|
||||||
; Stubs for the audio routines in rom bank 10
|
|
||||||
; They use JSRFAR to select the correct bank, so user code doesn't have to bother.
|
|
||||||
;
|
|
||||||
; The stubs here still use the romsub definitions of the routines from syslib, but those are
|
|
||||||
; just the jump addresses and are unaware of the kernal bank. Wrapping in JSRFAR fixes this.
|
|
||||||
|
|
||||||
audio {
|
|
||||||
const ubyte rom_bank = $0a
|
|
||||||
asmsub audio_init() clobbers(A,X,Y) -> bool @Pc { ; (re)initialize both vera PSG and YM audio chips
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.audio_init
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_fmfreq(ubyte channel @A, uword freq @XY, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_fmfreq
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_fmnote(ubyte channel @A, ubyte note @X, ubyte fracsemitone @Y, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_fmnote
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_fmplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_fmplaystring
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_fmvib(ubyte speed @A, ubyte depth @X) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_fmvib
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_playstringvoice(ubyte channel @A) clobbers(Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_playstringvoice
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_psgfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_psgfreq
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_psgnote(ubyte voice @A, ubyte note @X, ubyte fracsemitone @Y) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_psgnote
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_psgwav(ubyte voice @A, ubyte waveform @X) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_psgwav
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_psgplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_psgplaystring
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_fmchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_fmchordstring
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub bas_psgchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.bas_psgchordstring
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_bas2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_bas2fm
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_bas2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_bas2midi
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_bas2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_bas2psg
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_fm2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_fm2bas
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_fm2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_fm2midi
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_fm2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_fm2psg
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_freq2bas(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_freq2bas
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_freq2fm(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_freq2fm
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_freq2midi(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_freq2midi
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_freq2psg(uword freqHz @XY) clobbers(A) -> uword @XY, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_freq2psg
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_midi2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_midi2bas
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_midi2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_midi2fm
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_midi2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_midi2psg
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_psg2bas(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_psg2bas
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_psg2fm(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_psg2fm
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub notecon_psg2midi(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.notecon_psg2midi
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_init() clobbers(A,X,Y) { ; (re)init Vera PSG
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_init
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_playfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_playfreq
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_read(ubyte offset @X, bool cookedVol @Pc) clobbers(Y) -> ubyte @A{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_read
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_setatten(ubyte voice @A, ubyte attenuation @X) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_setatten
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_setfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_setfreq
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_setpan(ubyte voice @A, ubyte panning @X) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_setpan
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_setvol(ubyte voice @A, ubyte volume @X) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_setvol
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_write(ubyte value @A, ubyte offset @X) clobbers(Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_write
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_write_fast(ubyte value @A, ubyte offset @X) clobbers(Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_write_fast
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_getatten(ubyte voice @A) clobbers(Y) -> ubyte @X{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_getatten
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub psg_getpan(ubyte voice @A) clobbers(Y) -> ubyte @X{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.psg_getpan
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_init() clobbers(A,X,Y) -> bool @Pc { ; (re)init YM chip
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_init
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_loaddefpatches() clobbers(A,X,Y) -> bool @Pc { ; load default YM patches
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_loaddefpatches
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_loadpatch(ubyte channel @A, uword patchOrAddress @XY, bool what @Pc) clobbers(A,X,Y){
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_loadpatch
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_loadpatchlfn(ubyte channel @A, ubyte lfn @X) clobbers(X,Y) -> ubyte @A, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_loadpatchlfn
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_playdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_playdrum
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_playnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y, bool notrigger @Pc) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_playnote
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_setatten(ubyte channel @A, ubyte attenuation @X) clobbers(Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_setatten
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_setdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_setdrum
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_setnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_setnote
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_setpan(ubyte channel @A, ubyte panning @X) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_setpan
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_read(ubyte register @X, bool cooked @Pc) clobbers(Y) -> ubyte @A, bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_read
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_release(ubyte channel @A) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_release
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_trigger(ubyte channel @A, bool noRelease @Pc) clobbers(A,X,Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_trigger
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_write(ubyte value @A, ubyte register @X) clobbers(Y) -> bool @Pc{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_write
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_getatten(ubyte channel @A) clobbers(Y) -> ubyte @X{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_getatten
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_getpan(ubyte channel @A) clobbers(Y) -> ubyte @X{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_getpan
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
asmsub ym_get_chip_type() clobbers(X) -> ubyte @A{
|
|
||||||
%asm{{
|
|
||||||
jsr cx16.JSRFAR
|
|
||||||
.word cx16.ym_get_chip_type
|
|
||||||
.byte p8c_rom_bank
|
|
||||||
rts
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
}
|
|
@ -483,63 +483,63 @@ romsub $C006 = x16edit_loadfile_options(ubyte firstbank @X, ubyte lastbank @Y, s
|
|||||||
uword filenameLengthAndOptions @R1, uword tabstopAndWordwrap @R2,
|
uword filenameLengthAndOptions @R1, uword tabstopAndWordwrap @R2,
|
||||||
uword disknumberAndColors @R3, uword headerAndStatusColors @R4) clobbers(A,X,Y)
|
uword disknumberAndColors @R3, uword headerAndStatusColors @R4) clobbers(A,X,Y)
|
||||||
|
|
||||||
; Audio (rom bank 10 - you have to activate this bank manually first! Or use the stubs in the audio module. Or use callfar/JSRFAR manually.)
|
; Audio (rom bank 10)
|
||||||
romsub $C09F = audio_init() clobbers(A,X,Y) -> bool @Pc ; (re)initialize both vera PSG and YM audio chips
|
romsub @rombank 10 $C09F = audio_init() clobbers(A,X,Y) -> bool @Pc ; (re)initialize both vera PSG and YM audio chips
|
||||||
romsub $C000 = bas_fmfreq(ubyte channel @A, uword freq @XY, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C000 = bas_fmfreq(ubyte channel @A, uword freq @XY, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C003 = bas_fmnote(ubyte channel @A, ubyte note @X, ubyte fracsemitone @Y, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C003 = bas_fmnote(ubyte channel @A, ubyte note @X, ubyte fracsemitone @Y, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C006 = bas_fmplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
romsub @rombank 10 $C006 = bas_fmplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
||||||
romsub $C009 = bas_fmvib(ubyte speed @A, ubyte depth @X) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C009 = bas_fmvib(ubyte speed @A, ubyte depth @X) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C00C = bas_playstringvoice(ubyte channel @A) clobbers(Y)
|
romsub @rombank 10 $C00C = bas_playstringvoice(ubyte channel @A) clobbers(Y)
|
||||||
romsub $C00F = bas_psgfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C00F = bas_psgfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C012 = bas_psgnote(ubyte voice @A, ubyte note @X, ubyte fracsemitone @Y) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C012 = bas_psgnote(ubyte voice @A, ubyte note @X, ubyte fracsemitone @Y) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C015 = bas_psgwav(ubyte voice @A, ubyte waveform @X) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C015 = bas_psgwav(ubyte voice @A, ubyte waveform @X) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C018 = bas_psgplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
romsub @rombank 10 $C018 = bas_psgplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
||||||
romsub $C08D = bas_fmchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
romsub @rombank 10 $C08D = bas_fmchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
||||||
romsub $C090 = bas_psgchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
romsub @rombank 10 $C090 = bas_psgchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
|
||||||
romsub $C01B = notecon_bas2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
romsub @rombank 10 $C01B = notecon_bas2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
||||||
romsub $C01E = notecon_bas2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
romsub @rombank 10 $C01E = notecon_bas2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
||||||
romsub $C021 = notecon_bas2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
|
romsub @rombank 10 $C021 = notecon_bas2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
|
||||||
romsub $C024 = notecon_fm2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
romsub @rombank 10 $C024 = notecon_fm2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
||||||
romsub $C027 = notecon_fm2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
romsub @rombank 10 $C027 = notecon_fm2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
||||||
romsub $C02A = notecon_fm2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
|
romsub @rombank 10 $C02A = notecon_fm2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
|
||||||
romsub $C02D = notecon_freq2bas(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
romsub @rombank 10 $C02D = notecon_freq2bas(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
||||||
romsub $C030 = notecon_freq2fm(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
romsub @rombank 10 $C030 = notecon_freq2fm(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
||||||
romsub $C033 = notecon_freq2midi(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
romsub @rombank 10 $C033 = notecon_freq2midi(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
||||||
romsub $C036 = notecon_freq2psg(uword freqHz @XY) clobbers(A) -> uword @XY, bool @Pc
|
romsub @rombank 10 $C036 = notecon_freq2psg(uword freqHz @XY) clobbers(A) -> uword @XY, bool @Pc
|
||||||
romsub $C039 = notecon_midi2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
romsub @rombank 10 $C039 = notecon_midi2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
||||||
romsub $C03C = notecon_midi2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
romsub @rombank 10 $C03C = notecon_midi2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
|
||||||
romsub $C03F = notecon_midi2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
|
romsub @rombank 10 $C03F = notecon_midi2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
|
||||||
romsub $C042 = notecon_psg2bas(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
romsub @rombank 10 $C042 = notecon_psg2bas(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
||||||
romsub $C045 = notecon_psg2fm(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
romsub @rombank 10 $C045 = notecon_psg2fm(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
||||||
romsub $C048 = notecon_psg2midi(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
romsub @rombank 10 $C048 = notecon_psg2midi(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
|
||||||
romsub $C04B = psg_init() clobbers(A,X,Y) ; (re)init Vera PSG
|
romsub @rombank 10 $C04B = psg_init() clobbers(A,X,Y) ; (re)init Vera PSG
|
||||||
romsub $C04E = psg_playfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
|
romsub @rombank 10 $C04E = psg_playfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
|
||||||
romsub $C051 = psg_read(ubyte offset @X, bool cookedVol @Pc) clobbers(Y) -> ubyte @A
|
romsub @rombank 10 $C051 = psg_read(ubyte offset @X, bool cookedVol @Pc) clobbers(Y) -> ubyte @A
|
||||||
romsub $C054 = psg_setatten(ubyte voice @A, ubyte attenuation @X) clobbers(A,X,Y)
|
romsub @rombank 10 $C054 = psg_setatten(ubyte voice @A, ubyte attenuation @X) clobbers(A,X,Y)
|
||||||
romsub $C057 = psg_setfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
|
romsub @rombank 10 $C057 = psg_setfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
|
||||||
romsub $C05A = psg_setpan(ubyte voice @A, ubyte panning @X) clobbers(A,X,Y)
|
romsub @rombank 10 $C05A = psg_setpan(ubyte voice @A, ubyte panning @X) clobbers(A,X,Y)
|
||||||
romsub $C05D = psg_setvol(ubyte voice @A, ubyte volume @X) clobbers(A,X,Y)
|
romsub @rombank 10 $C05D = psg_setvol(ubyte voice @A, ubyte volume @X) clobbers(A,X,Y)
|
||||||
romsub $C060 = psg_write(ubyte value @A, ubyte offset @X) clobbers(Y)
|
romsub @rombank 10 $C060 = psg_write(ubyte value @A, ubyte offset @X) clobbers(Y)
|
||||||
romsub $C0A2 = psg_write_fast(ubyte value @A, ubyte offset @X) clobbers(Y)
|
romsub @rombank 10 $C0A2 = psg_write_fast(ubyte value @A, ubyte offset @X) clobbers(Y)
|
||||||
romsub $C093 = psg_getatten(ubyte voice @A) clobbers(Y) -> ubyte @X
|
romsub @rombank 10 $C093 = psg_getatten(ubyte voice @A) clobbers(Y) -> ubyte @X
|
||||||
romsub $C096 = psg_getpan(ubyte voice @A) clobbers(Y) -> ubyte @X
|
romsub @rombank 10 $C096 = psg_getpan(ubyte voice @A) clobbers(Y) -> ubyte @X
|
||||||
romsub $C063 = ym_init() clobbers(A,X,Y) -> bool @Pc ; (re)init YM chip
|
romsub @rombank 10 $C063 = ym_init() clobbers(A,X,Y) -> bool @Pc ; (re)init YM chip
|
||||||
romsub $C066 = ym_loaddefpatches() clobbers(A,X,Y) -> bool @Pc ; load default YM patches
|
romsub @rombank 10 $C066 = ym_loaddefpatches() clobbers(A,X,Y) -> bool @Pc ; load default YM patches
|
||||||
romsub $C069 = ym_loadpatch(ubyte channel @A, uword patchOrAddress @XY, bool what @Pc) clobbers(A,X,Y)
|
romsub @rombank 10 $C069 = ym_loadpatch(ubyte channel @A, uword patchOrAddress @XY, bool what @Pc) clobbers(A,X,Y)
|
||||||
romsub $C06C = ym_loadpatchlfn(ubyte channel @A, ubyte lfn @X) clobbers(X,Y) -> ubyte @A, bool @Pc
|
romsub @rombank 10 $C06C = ym_loadpatchlfn(ubyte channel @A, ubyte lfn @X) clobbers(X,Y) -> ubyte @A, bool @Pc
|
||||||
romsub $C06F = ym_playdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C06F = ym_playdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C072 = ym_playnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y, bool notrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C072 = ym_playnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y, bool notrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C075 = ym_setatten(ubyte channel @A, ubyte attenuation @X) clobbers(Y) -> bool @Pc
|
romsub @rombank 10 $C075 = ym_setatten(ubyte channel @A, ubyte attenuation @X) clobbers(Y) -> bool @Pc
|
||||||
romsub $C078 = ym_setdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C078 = ym_setdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C07B = ym_setnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C07B = ym_setnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C07E = ym_setpan(ubyte channel @A, ubyte panning @X) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C07E = ym_setpan(ubyte channel @A, ubyte panning @X) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C081 = ym_read(ubyte register @X, bool cooked @Pc) clobbers(Y) -> ubyte @A, bool @Pc
|
romsub @rombank 10 $C081 = ym_read(ubyte register @X, bool cooked @Pc) clobbers(Y) -> ubyte @A, bool @Pc
|
||||||
romsub $C084 = ym_release(ubyte channel @A) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C084 = ym_release(ubyte channel @A) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C087 = ym_trigger(ubyte channel @A, bool noRelease @Pc) clobbers(A,X,Y) -> bool @Pc
|
romsub @rombank 10 $C087 = ym_trigger(ubyte channel @A, bool noRelease @Pc) clobbers(A,X,Y) -> bool @Pc
|
||||||
romsub $C08A = ym_write(ubyte value @A, ubyte register @X) clobbers(Y) -> bool @Pc
|
romsub @rombank 10 $C08A = ym_write(ubyte value @A, ubyte register @X) clobbers(Y) -> bool @Pc
|
||||||
romsub $C099 = ym_getatten(ubyte channel @A) clobbers(Y) -> ubyte @X
|
romsub @rombank 10 $C099 = ym_getatten(ubyte channel @A) clobbers(Y) -> ubyte @X
|
||||||
romsub $C09C = ym_getpan(ubyte channel @A) clobbers(Y) -> ubyte @X
|
romsub @rombank 10 $C09C = ym_getpan(ubyte channel @A) clobbers(Y) -> ubyte @X
|
||||||
romsub $C0A5 = ym_get_chip_type() clobbers(X) -> ubyte @A
|
romsub @rombank 10 $C0A5 = ym_get_chip_type() clobbers(X) -> ubyte @A
|
||||||
|
|
||||||
; extapi call numbers
|
; extapi call numbers
|
||||||
const ubyte EXTAPI_clear_status = $01
|
const ubyte EXTAPI_clear_status = $01
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
; all library modules for the cx16 compiler target
|
; all library modules for the cx16 compiler target
|
||||||
|
|
||||||
%import audio
|
|
||||||
%import anyall
|
%import anyall
|
||||||
%import buffers
|
%import buffers
|
||||||
%import bmx
|
%import bmx
|
||||||
|
@ -955,18 +955,6 @@ Read the `psg source code <https://github.com/irmen/prog8/tree/master/compiler/r
|
|||||||
to see what's in there.
|
to see what's in there.
|
||||||
|
|
||||||
|
|
||||||
audio (cx16 only)
|
|
||||||
------------------
|
|
||||||
Available for the Cx16 target.
|
|
||||||
Contains stub routines for all of the kernal audio routines available in rom bank 10.
|
|
||||||
The stubs use JSRFAR calls so you don't have to bother with selecting the correct rom bank in your own program code.
|
|
||||||
See the cx16/audioroutines.p8 example on how to use them.
|
|
||||||
|
|
||||||
Read the `audio source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/cx16/audio.p8>`_
|
|
||||||
to see what's in there.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sprites (cx16 only)
|
sprites (cx16 only)
|
||||||
--------------------
|
--------------------
|
||||||
Available for the Cx16 target. Simple routines to manipulate sprites.
|
Available for the Cx16 target. Simple routines to manipulate sprites.
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
get rid of audio.p8 module , rewrite audio romsubs , rewrite audio example to use syslib routines
|
|
||||||
|
|
||||||
add docs for @rombank @rambank on romsubs. Add promo in docs that prog8 does automatic bank switching when calling such a romsub (on cx16 and c128)
|
add docs for @rombank @rambank on romsubs. Add promo in docs that prog8 does automatic bank switching when calling such a romsub (on cx16 and c128)
|
||||||
|
|
||||||
rename 'romsub' to 'extsub' ?
|
rename 'romsub' to 'extsub' ?
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import audio
|
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
@ -31,32 +30,28 @@ main {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
; Note: the audio module contains stubs for every kernal audio call,
|
cx16.psg_init()
|
||||||
; they use JSRFAR to automatically switch to the correct ROM bank (and back).
|
|
||||||
; So we don't have to switch rom banks ourselves to access the audio routines in bank 10!
|
|
||||||
|
|
||||||
audio.psg_init()
|
cx16.bas_playstringvoice(15)
|
||||||
|
cx16.bas_psgchordstring(6, "o3g>ce")
|
||||||
|
|
||||||
audio.bas_playstringvoice(15)
|
cx16.bas_playstringvoice(14)
|
||||||
audio.bas_psgchordstring(6, "o3g>ce")
|
cx16.bas_psgplaystring(10, ">c<dgb>cde")
|
||||||
|
|
||||||
audio.bas_playstringvoice(14)
|
cx16.bas_playstringvoice(15)
|
||||||
audio.bas_psgplaystring(10, ">c<dgb>cde")
|
cx16.bas_psgchordstring(3, "rrr")
|
||||||
|
|
||||||
audio.bas_playstringvoice(15)
|
cx16.bas_playstringvoice(14)
|
||||||
audio.bas_psgchordstring(3, "rrr")
|
cx16.bas_psgplaystring(9, "o4cag>c<a")
|
||||||
|
|
||||||
audio.bas_playstringvoice(14)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_psgplaystring(9, "o4cag>c<a")
|
cx16.bas_psgchordstring(6, "o3a>cf")
|
||||||
|
|
||||||
audio.bas_playstringvoice(0)
|
cx16.bas_playstringvoice(14)
|
||||||
audio.bas_psgchordstring(6, "o3a>cf")
|
cx16.bas_psgplaystring(14, "l16fgab->cdef4")
|
||||||
|
|
||||||
audio.bas_playstringvoice(14)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_psgplaystring(14, "l16fgab->cdef4")
|
cx16.bas_psgchordstring(3, "rrr")
|
||||||
|
|
||||||
audio.bas_playstringvoice(0)
|
|
||||||
audio.bas_psgchordstring(3, "rrr")
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,44 +74,44 @@ main {
|
|||||||
150 FMCHORD 1,"RRR" : REM RELEASE THE CHANNELS THAT ARE PLAYING THE CHORD
|
150 FMCHORD 1,"RRR" : REM RELEASE THE CHANNELS THAT ARE PLAYING THE CHORD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void audio.ym_init()
|
void cx16.ym_init()
|
||||||
void audio.bas_fmvib(195, 10)
|
void cx16.bas_fmvib(195, 10)
|
||||||
audio.ym_loadpatch(1,16,true)
|
cx16.ym_loadpatch(1,16,true)
|
||||||
audio.ym_loadpatch(2,16,true)
|
cx16.ym_loadpatch(2,16,true)
|
||||||
audio.ym_loadpatch(3,16,true)
|
cx16.ym_loadpatch(3,16,true)
|
||||||
void audio.ym_setatten(1,64-50)
|
void cx16.ym_setatten(1,64-50)
|
||||||
void audio.ym_setatten(2,64-50)
|
void cx16.ym_setatten(2,64-50)
|
||||||
void audio.ym_setatten(3,64-50)
|
void cx16.ym_setatten(3,64-50)
|
||||||
audio.ym_loadpatch(0,11,true)
|
cx16.ym_loadpatch(0,11,true)
|
||||||
|
|
||||||
audio.bas_playstringvoice(1)
|
cx16.bas_playstringvoice(1)
|
||||||
audio.bas_fmchordstring(11, "o3cg>e t130")
|
cx16.bas_fmchordstring(11, "o3cg>e t130")
|
||||||
|
|
||||||
audio.bas_playstringvoice(0)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_fmplaystring(12, "o4g4.a8g4e2.")
|
cx16.bas_fmplaystring(12, "o4g4.a8g4e2.")
|
||||||
audio.bas_playstringvoice(0)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_fmplaystring(12, "o4g4.a8g4e2.")
|
cx16.bas_fmplaystring(12, "o4g4.a8g4e2.")
|
||||||
|
|
||||||
audio.bas_playstringvoice(1)
|
cx16.bas_playstringvoice(1)
|
||||||
audio.bas_fmchordstring(6, "o2g>db")
|
cx16.bas_fmchordstring(6, "o2g>db")
|
||||||
|
|
||||||
audio.bas_playstringvoice(0)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_fmplaystring(9, "o5d2d4<b2")
|
cx16.bas_fmplaystring(9, "o5d2d4<b2")
|
||||||
|
|
||||||
audio.bas_playstringvoice(1)
|
cx16.bas_playstringvoice(1)
|
||||||
audio.bas_fmchordstring(3, "o2f")
|
cx16.bas_fmchordstring(3, "o2f")
|
||||||
|
|
||||||
audio.bas_playstringvoice(0)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_fmplaystring(2, "r4")
|
cx16.bas_fmplaystring(2, "r4")
|
||||||
|
|
||||||
audio.bas_playstringvoice(1)
|
cx16.bas_playstringvoice(1)
|
||||||
audio.bas_fmchordstring(5, "o3ceg")
|
cx16.bas_fmchordstring(5, "o3ceg")
|
||||||
|
|
||||||
audio.bas_playstringvoice(0)
|
cx16.bas_playstringvoice(0)
|
||||||
audio.bas_fmplaystring(10, "o5c2c4<g2.")
|
cx16.bas_fmplaystring(10, "o5c2c4<g2.")
|
||||||
|
|
||||||
audio.bas_playstringvoice(1)
|
cx16.bas_playstringvoice(1)
|
||||||
audio.bas_fmchordstring(3, "rrr")
|
cx16.bas_fmchordstring(3, "rrr")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user