base:nmi_sample_player
NMI Sample player
Coded using the CA65 assembler.
use like this:
call NMIDIGI_Init once for init, then call NMIDIGI_Play with a pointer (x=hi,y=lo) to a table with parameters (data start lo/hi, data end lo/hi, samplerate lo/hi). NMIDIGI_Off temporarily disables the player, NMIDIGI_On enables it again.
the various compile-time options should be self-explaining (i hope) :)
;------------------------------------------------------------------------- ; NMI Sample player (w) Groepaz/Hitmen ;------------------------------------------------------------------------- .export NMIDIGI_Init .export NMIDIGI_On .export NMIDIGI_Off .export NMIDIGI_Play .export NMIDIGION .export NMIDIGIOFF withsidplayer=0 .if(withsidplayer=1) sidplayervol=D418HLP .endif ;0: high nibble first 1: low nibble first firstnibble=1 ;1: no nibbles nonibbles=1 NMIDIGI_Init: jsr NMIDIGI_Off lda #$00 ldx #$00 @l: sta __SID__,x inx bne @l lda #$00 sta __SID__+$05 ; voice 1 ad lda #$f0 sta __SID__+$06 ; sr lda #$01 sta __SID__+$04 ; ctrl lda #$00 sta __SID__+$0c ; voice 2 ad lda #$f0 sta __SID__+$0d ; sr lda #$01 sta __SID__+$0b ; ctrl lda #$00 sta __SID__+$13 ; voice 3 ad lda #$f0 sta __SID__+$14 ; sr lda #$01 sta __SID__+$12 ; ctrl lda #$00 sta __SID__+$15 ; filter lo lda #$10 sta __SID__+$16 ; filter hi lda #%11110111 sta __SID__+$17 ; filter voices+reso rts NMIDIGI_On: LDA #>NMIDIGION STA $FFFB LDA #<NMIDIGION STA $FFFA LDA #%10000001 ; enable CIA-2 timer A nmi STA $DD0D lda $DD0D LDA #%00000001 ; timer A start STA $DD0E rts NMIDIGI_Off: LDA #%00000000 STA $DD0E ; timer A stop LDA #%01001111 ; disable all CIA-2 nmi's STA $DD0D lda $DD0D LDA #>NMIDIGIOFF STA $FFFB LDA #<NMIDIGIOFF STA $FFFA lda #$00 sta NMIPOINT sta NMIPOINT+1 sta DIGISTOPLO+1 sta DIGISTOPHI+1 rts NMIDIGI_Play: jsr NMIDIGI_Off stx NMIDIGIPTR+1 sty NMIDIGIPTR ldy #$00 lda (NMIDIGIPTR),y sta NMIPOINT iny lda (NMIDIGIPTR),y sta NMIPOINT+1 iny lda (NMIDIGIPTR),y sta DIGISTOPLO+1 iny lda (NMIDIGIPTR),y sta DIGISTOPHI+1 iny lda (NMIDIGIPTR),y sta $DD04 iny lda (NMIDIGIPTR),y sta $DD05 .if(nonibbles=0) lda #$00 sta nib+1 .endif jsr NMIDIGI_On rts ;------------------------------------------- NMIDIGION: STA NMIABUFF STY NMIYBUFF .if (withsidplayer=1) lda sidplayervol and #$f0 .else lda #$10 .endif D418NMI: ora #$00 sta __SID__+$18 ; volume reg .if (withsidplayer=1) sta sidplayervol .endif .if (DEBUG=1) sta $d020 .endif LDA NMIPOINT+1 DIGISTOPHI: CMP #$12 ;ENDHIGH BNE SK1 LDA NMIPOINT DIGISTOPLO: CMP #$00 ;ENDLOW BNE SK1 .if (withsidplayer=1) lda #$08 .else lda #$00 .endif STA D418NMI+1 jsr NMIDIGI_Off LDA NMIABUFF RTI SK1: LDY #$00 .if(nonibbles=0) nib: lda #$00 and #$01 bne s1 .endif LDA (NMIPOINT),Y .if(nonibbles=0) .if(firstnibble=0) ; high nibble first lsr a lsr a lsr a lsr a .else ; low nibble first AND #$0F .endif jmp s2 s1: LDA (NMIPOINT),Y .if(firstnibble=1) ; high nibble second lsr a lsr a lsr a lsr a .else ; low nibble second AND #$0F .endif .endif INC NMIPOINT BNE @SK INC NMIPOINT+1 @SK: s2: STA D418NMI+1 .if(nonibbles=0) inc nib+1 .endif LDA $DD0D NMIABUFF=*+1 LDA #$00 NMIYBUFF=*+1 LDY #$00 NMIDIGIOFF: RTI
(Edit: Suggestion from Algorithm)
the digiboost should be something along the lines of..
lda #$ff sta $d406 sta $d406+7 sta $d496+14 lda #$49 sta $d404 sta $d404+7 sta $d404+14
and the nmi frequency needs to be set. eg
lda #$3c sta $dd04 lda #$00 sta $dd05
(Edit enthusi)
If you are in real need for cycles and have some RAM left you can replace the LSRs with:
tay lda freq_table,y
and set up a table via
ldx #0 loop2 ldy #16 value lda #0 loop sta freq_table,x inx dey bne loop cpx #$00 beq end inc value+1 jmp loop2 end rts
base/nmi_sample_player.txt · Last modified: 2015-04-17 04:33 by 127.0.0.1