123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979 |
- /*
- * PicoDrive
- * (C) notaz, 2006
- * (C) kub, 2020 added SSG-EG and simple output rate interpolation
- *
- * This work is licensed under the terms of MAME license.
- * See COPYING file in the top-level directory.
- */
- @ this is a rewrite of MAME's ym2612 code, in particular this is only the main sample-generatin loop.
- @ it does not seem to give much performance increase (if any at all), so don't use it if it causes trouble.
- @ - notaz, 2006
- @ vim:filetype=armasm
- #include <pico/arm_features.h>
- @ very simple YM2612 output rate to sample rate adaption (~500k cycles @44100)
- #define INTERPOL
- #define SSG_EG
- .equiv SLOT1, 0
- .equiv SLOT2, 2
- .equiv SLOT3, 1
- .equiv SLOT4, 3
- .equiv SLOT_STRUCT_SIZE, 0x38
- .equiv TL_TAB_LEN, 0x1A00
- .equiv EG_ATT, 4
- .equiv EG_DEC, 3
- .equiv EG_SUS, 2
- .equiv EG_REL, 1
- .equiv EG_OFF, 0
- .equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing)
- .equiv EG_TIMER_OVERFLOW, (3*(1<<EG_SH)) @ envelope generator timer overflows every 3 samples (on real chip)
- .equiv LFO_SH, 24 /* 8.24 fixed point (LFO calculations) */
- .equiv ENV_QUIET, (2*13*256/8)
- .text
- .align 2
- PIC_LDR_INIT()
- @ r5=slot, r1=eg_cnt, trashes: r0,r2,r3
- @ writes output to routp, but only if vol_out changes
- .macro update_eg_phase_slot
- #if defined(INTERPOL)
- ldrh r0, [r5,#0x34] @ vol_out
- #endif
- ldrb r2, [r5,#0x17] @ state
- add r3, r5, #0x1c
- #if defined(INTERPOL)
- strh r0, [r5,#0x36] @ vol_ipol
- #endif
- tst r2, r2
- beq 0f @ EG_OFF
- ldr r2, [r3, r2, lsl #2] @ pack
- mov r3, #1
- mov r0, r2, lsr #24 @ shift
- mov r3, r3, lsl r0
- sub r3, r3, #1
- tst r1, r3
- bne 0f @ no volume change
- mov r3, r1, lsr r0
- ldrb r0, [r5,#0x30] @ ssg
- and r3, r3, #7
- add r3, r3, r3, lsl #1
- mov r3, r2, lsr r3
- and r3, r3, #7 @ eg_inc_val shift, may be 0
- ldrb r2, [r5,#0x17] @ state
- #if defined(SSG_EG)
- tst r0, #0x08 @ ssg enabled?
- tstne r12, #0x02
- bne 9f
- #endif
- @ non-SSG-EG mode
- cmp r2, #4 @ EG_ATT
- ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
- beq 4f
- cmp r2, #2
- mov r2, #1
- mov r2, r2, lsl r3
- mov r2, r2, lsr #1 @ eg_inc_val
- add r0, r0, r2
- blt 1f @ EG_REL
- beq 2f @ EG_SUS
- 3: @ EG_DEC
- ldr r2, [r5,#0x1c] @ sl (can be 16bit?)
- mov r3, #EG_SUS
- cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl )
- strgeb r3, [r5,#0x17] @ state
- b 10f
- 4: @ EG_ATT
- subs r3, r3, #1 @ eg_inc_val_shift - 1
- mvnpl r2, r0
- movpl r2, r2, lsl r3
- addpl r0, r0, r2, asr #4
- cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
- bgt 10f
- ldr r2, [r5,#0x1c]
- mov r0, #0
- cmp r2, #0
- movne r3, #EG_DEC
- moveq r3, #EG_SUS
- strb r3, [r5,#0x17] @ state
- b 10f
- 2: @ EG_SUS
- mov r2, #1024
- sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
- cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
- movge r0, r2
- b 10f
- 1: @ EG_REL
- mov r2, #1024
- sub r2, r2, #1 @ r2 = MAX_ATT_INDEX
- cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX )
- movge r0, r2
- movge r3, #EG_OFF
- strgeb r3, [r5,#0x17] @ state
- 10: @ finish
- ldrh r3, [r5,#0x18] @ tl
- strh r0, [r5,#0x1a] @ volume
- #if defined(SSG_EG)
- b 11f
- 9: @ SSG-EG mode
- ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023)
- cmp r2, #4 @ EG_ATT
- beq 4f
- cmp r0, #0x200 @ if ( volume < 0x200 )
- movlt r0, #1
- movlt r3, r0, lsl r3
- ldrlth r0, [r5,#0x1a] @ volume, unsigned (0-1023)
- movlt r3, r3, lsr #1 @ eg_inc_val
- addlt r0, r0, r3, lsl #2
- cmp r2, #2
- blt 1f @ EG_REL
- beq 10f @ EG_SUS - nothing more to do
- 3: @ EG_DEC
- ldr r2, [r5,#0x1c] @ sl (can be 16bit?)
- mov r3, #EG_SUS
- cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl )
- strgeb r3, [r5,#0x17] @ state
- b 10f
- 4: @ EG_ATT
- subs r3, r3, #1 @ eg_inc_val_shift - 1
- mvnpl r2, r0
- movpl r2, r2, lsl r3
- addpl r0, r0, r2, asr #4
- cmp r0, #0 @ if (volume <= MIN_ATT_INDEX)
- bgt 10f
- ldr r2, [r5,#0x1c] @ sl
- mov r0, #0
- cmp r2, #0
- movne r3, #EG_DEC
- moveq r3, #EG_SUS
- strb r3, [r5,#0x17] @ state
- b 10f
- 1: @ EG_REL
- cmp r0, #0x200 @ if ( volume >= 0x200 )
- movge r0, #1024
- subge r0, #1
- movge r3, #EG_OFF
- strgeb r3, [r5,#0x17] @ state
- 10: @ finish
- ldrb r2, [r5,#0x30] @ ssg
- ldrb r3, [r5,#0x17] @ state
- strh r0, [r5,#0x1a] @ volume
- cmp r2, #0x0c @ if ( ssg&0x04 && state > EG_REL )
- cmpge r3, #EG_REL+1
- ldrh r3, [r5,#0x18] @ tl
- rsbge r0, r0, #0x200 @ volume = (0x200-volume) & MAX_ATT
- lslge r0, r0, #22
- lsrge r0, r0, #22
- 11:
- #endif
- add r0, r0, r3 @ volume += tl
- strh r0, [r5,#0x34] @ vol_out
- 0: @ EG_OFF
- .endm
- #if defined(SSG_EG)
- @ r5=slot, trashes: r0,r2,r3
- .macro update_ssg_eg
- ldrh r0, [r5,#0x30] @ ssg+ssgn
- ldrb r2, [r5,#0x17] @ state
- ldrh r3, [r5,#0x1a] @ volume
- tst r0, #0x08 @ ssg enabled &&
- beq 9f
- cmp r2, #EG_REL+1 @ state > EG_REL &&
- cmpge r3, #0x200 @ volume >= 0x200?
- blt 9f
- orr r4, r4, #0x10 @ ssg_update
- tst r0, #0x01
- beq 1f
- tst r0, #0x02
- eorne r0, r0, lsr #8 @ ssg ^= ssgn ^ 4
- eorne r0, r0, #0x4
- orrne r0, r0, #0x400 @ ssgn = 4
- strneh r0, [r5,#0x30]
- eor r0, r0, #0x4 @ if ( !(ssg&0x04) )
- tst r0, #0x4
- cmpne r2, #EG_ATT @ if ( state != EG_ATT )
- movne r3, #0x400
- subne r3, r3, #1
- strneh r3, [r5,#0x1a] @ volume = MAX_ATT
- b 9f
- 1: tst r0, #0x02
- eorne r0, r0, #0x4 @ ssg ^= 4
- eorne r0, r0, #0x400 @ ssgn ^= 4
- strneh r0, [r5,#0x30]
- moveq r0, #0
- streq r0, [lr,#0x10] @ phase = 0
- cmp r2, #EG_ATT @ if ( state != EG_ATT )
- beq 9f
- ldr r0, [r5,#0x1c] @ sl
- mov r2, #EG_SUS @ state = sl==MIN_ATT ? EG_SUS:EG_DEC
- cmp r0, #0
- ldrh r0, [r5,#0x32] @ ar+ksr
- movne r2, #EG_DEC
- cmp r0, #32+62 @ if ( ar+ksr >= 32+62 )
- movge r3, #0
- strgeh r3, [r5,#0x1a] @ volume = MIN_ATT
- bge 8f
- cmp r3, #0
- movgt r2, #EG_ATT
- 8: strb r2, [r5,#0x17] @ state
- 9:
- .endm
- @ r5=slot, trashes: r0,r2,r3
- .macro recalc_volout
- #if defined(INTERPOL)
- ldrh r0, [r5,#0x34] @ vol_out
- #endif
- ldrb r2, [r5,#0x30] @ ssg
- ldrb r3, [r5,#0x17] @ state
- #if defined(INTERPOL)
- strh r0, [r5,#0x36] @ vol_ipol
- #endif
- ldrh r0, [r5,#0x1a] @ volume
- @ and r2, r2, #0x0c
- cmp r2, #0x0c @ if ( ~ssg&0x0c && state > EG_REL )
- cmpge r3, #EG_REL+1
- ldrh r3, [r5,#0x18] @ tl
- rsbge r0, r0, #0x200 @ volume = (0x200-volume) & MAX_ATT
- lslge r0, r0, #22
- lsrge r0, r0, #22
- add r0, r0, r3 @ volume += tl
- strh r0, [r5,#0x34] @ vol_out
- .endm
- #endif
- @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch
- .macro advance_lfo_m
- mov r2, r2, lsr #LFO_SH
- cmp r2, r1, lsr #LFO_SH
- beq 0f
- and r3, r2, #0x3f
- cmp r2, #0x40
- eorlt r3, r3, #0x3f
- bic r12,r12, #0xff000000 @ lfo_ampm &= 0xff
- orr r12,r12, r3, lsl #1+24
- mov r2, r2, lsr #2
- cmp r2, r1, lsr #LFO_SH+2
- bicne r12,r12, #0xff0000
- orrne r12,r12, r2, lsl #16
- 0:
- .endm
- @ result goes to r1, trashes r2
- .macro make_eg_out slot
- tst r12, #8
- tstne r12, #(1<<(\slot+8))
- .if \slot == SLOT1
- mov r1, r6, lsl #16
- mov r1, r1, lsr #16
- .elseif \slot == SLOT2
- mov r1, r6, lsr #16
- .elseif \slot == SLOT3
- mov r1, r7, lsl #16
- mov r1, r1, lsr #16
- .elseif \slot == SLOT4
- mov r1, r7, lsr #16
- .endif
- andne r2, r12, #0xc0
- movne r2, r2, lsr #6
- addne r2, r2, #24
- addne r1, r1, r12, lsr r2
- bic r1, r1, #1
- .endm
- @ \r=sin/result, r1=env, r3=ym_tl_tab
- .macro lookup_tl r
- tst \r, #0x100
- eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff);
- tst \r, #0x200
- and \r, \r, #0xff
- orr \r, \r, r1, lsl #7
- mov \r, \r, lsl #1
- ldrh \r, [r3, \r] @ 2ci if ne
- rsbne \r, \r, #0
- .endm
- @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
- @ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
- .macro upd_algo0_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r2, [lr, #0x18]
- ldr r0, [lr, #0x38] @ mem (signed)
- mov r2, r2, lsr #16
- add r0, r2, r0, lsr #1
- lookup_tl r0 @ r0=c2
- 0:
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r0, r0, lsr #1
- add r0, r0, r2, lsr #16
- lookup_tl r0 @ r0=output smp
- 1:
- @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- movcs r2, #0
- bcs 2f
- ldr r2, [lr, #0x14] @ 1ci
- mov r5, r10, lsr #17
- add r2, r5, r2, lsr #16
- lookup_tl r2 @ r2=mem
- 2:
- str r2, [lr, #0x38] @ mem
- .endm
- .macro upd_algo1_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r2, [lr, #0x18]
- ldr r0, [lr, #0x38] @ mem (signed)
- mov r2, r2, lsr #16
- add r0, r2, r0, lsr #1
- lookup_tl r0 @ r0=c2
- 0:
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r0, r0, lsr #1
- add r0, r0, r2, lsr #16
- lookup_tl r0 @ r0=output smp
- 1:
- @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- movcs r2, #0
- bcs 2f
- ldr r2, [lr, #0x14] @ 1ci
- mov r2, r2, lsr #16
- lookup_tl r2 @ r2=mem
- 2:
- add r2, r2, r10, asr #16
- str r2, [lr, #0x38]
- .endm
- .macro upd_algo2_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r2, [lr, #0x18]
- ldr r0, [lr, #0x38] @ mem (signed)
- mov r2, r2, lsr #16
- add r0, r2, r0, lsr #1
- lookup_tl r0 @ r0=c2
- 0:
- add r0, r0, r10, asr #16
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r0, r0, lsr #1
- add r0, r0, r2, lsr #16
- lookup_tl r0 @ r0=output smp
- 1:
- @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- movcs r2, #0
- bcs 2f
- ldr r2, [lr, #0x14]
- mov r2, r2, lsr #16 @ 1ci
- lookup_tl r2 @ r2=mem
- 2:
- str r2, [lr, #0x38] @ mem
- .endm
- .macro upd_algo3_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- ldr r2, [lr, #0x38] @ mem (for future)
- mov r0, #0
- bcs 0f
- ldr r0, [lr, #0x18] @ phase3
- mov r0, r0, lsr #16
- lookup_tl r0 @ r0=c2
- 0:
- add r0, r0, r2
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r0, r0, lsr #1
- add r0, r0, r2, lsr #16
- lookup_tl r0 @ r0=output smp
- 1:
- @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- movcs r2, #0
- bcs 2f
- ldr r2, [lr, #0x14] @ phase2
- mov r5, r10, lsr #17
- add r2, r5, r2, lsr #16
- lookup_tl r2 @ r2=mem
- 2:
- str r2, [lr, #0x38] @ mem
- .endm
- .macro upd_algo4_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r0, [lr, #0x18]
- mov r0, r0, lsr #16 @ 1ci
- lookup_tl r0 @ r0=c2
- 0:
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r0, r0, lsr #1
- add r0, r0, r2, lsr #16
- lookup_tl r0 @ r0=output smp
- 1:
- @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- bcs 2f
- ldr r2, [lr, #0x14]
- mov r5, r10, lsr #17
- add r2, r5, r2, lsr #16
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 2:
- .endm
- .macro upd_algo5_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r2, [lr, #0x18]
- ldr r0, [lr, #0x38] @ mem (signed)
- mov r2, r2, lsr #16
- add r0, r2, r0, lsr #1
- lookup_tl r0 @ r0=output smp
- 0:
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r5, r10, lsr #17
- add r2, r5, r2, lsr #16
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 1: @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- bcs 2f
- ldr r2, [lr, #0x14]
- mov r5, r10, lsr #17
- add r2, r5, r2, lsr #16
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 2:
- mov r1, r10, asr #16
- str r1, [lr, #0x38] @ mem
- .endm
- .macro upd_algo6_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r0, [lr, #0x18]
- mov r0, r0, lsr #16 @ 1ci
- lookup_tl r0 @ r0=output smp
- 0:
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r2, r2, lsr #16 @ 1ci
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 1: @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- bcs 2f
- ldr r2, [lr, #0x14]
- mov r5, r10, lsr #17
- add r2, r5, r2, lsr #16
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 2:
- .endm
- .macro upd_algo7_m
- @ SLOT3
- make_eg_out SLOT3
- cmp r1, #ENV_QUIET
- movcs r0, #0
- bcs 0f
- ldr r0, [lr, #0x18]
- mov r0, r0, lsr #16 @ 1ci
- lookup_tl r0 @ r0=output smp
- 0:
- add r0, r0, r10, asr #16
- @ SLOT4
- make_eg_out SLOT4
- cmp r1, #ENV_QUIET
- bcs 1f
- ldr r2, [lr, #0x1c]
- mov r2, r2, lsr #16 @ 1ci
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 1: @ SLOT2
- make_eg_out SLOT2
- cmp r1, #ENV_QUIET
- bcs 2f
- ldr r2, [lr, #0x14]
- mov r2, r2, lsr #16 @ 1ci
- lookup_tl r2
- add r0, r0, r2 @ add to smp
- 2:
- .endm
- .macro upd_slot1_m
- make_eg_out SLOT1
- cmp r1, #ENV_QUIET
- movcs r10, r10, lsl #16 @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0;
- bcs 0f
- ands r2, r12, #0xf000
- moveq r0, #0
- movne r2, r2, lsr #12
- addne r0, r10, r10, lsl #16
- movne r0, r0, asr #16
- movne r0, r0, lsl r2
- ldr r2, [lr, #0x10] @ phase1
- add r0, r0, r2
- mov r0, r0, lsr #16
- lookup_tl r0
- mov r10,r10,lsl #16 @ ct->op1_out <<= 16;
- mov r0, r0, lsl #16
- orr r10,r10, r0, lsr #16
- 0:
- .endm
- @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
- @ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[3],ssg_update,was_update,algo[3], r5=tl_tab/slot,
- @ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer
- .global chan_render_loop @ chan_rend_context *ct, int *buffer, int length
- chan_render_loop:
- stmfd sp!, {r4-r11,lr}
- mov lr, r0
- mov r4, r2, lsl #8 @ no more 24 bits here
- ldr r12, [lr, #0x4c]
- ldr r0, [lr, #0x50]
- mov r11, r1
- and r0, r0, #7
- orr r4, r4, r0 @ (length<<8)|algo
- ldr r8, [lr, #0x44] @ eg_timer
- ldr r9, [lr, #0x48] @ eg_timer_add
- ldr r10, [lr, #0x54] @ op1_out
- tst r12, #8 @ lfo?
- beq crl_loop
- crl_loop_lfo:
- ldr r1, [lr, #0x30] @ lfo_cnt
- ldr r2, [lr, #0x34] @ lfo_inc
- subs r4, r4, #0x100
- bmi crl_loop_end
- add r2, r2, r1
- str r2, [lr, #0x30]
- @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt
- advance_lfo_m
- add r4, r4, #0x100
- crl_loop:
- subs r4, r4, #0x100
- bmi crl_loop_end
- ldr r5, [lr, #0x40] @ CH
- #if defined(SSG_EG)
- tst r12, #0x02 @ ssg_enabled?
- beq ssg_done
- @ -- SSG --
- lsl r7, r8, #EG_SH
- add r7, r9, r7, lsr #EG_SH
- subs r7, r7, #1<<EG_SH
- blt ssg_done
- ssg_loop:
- mov r6, #4
- bic r4, r4, #0x10 @ ssg_update
- ssg_upd_loop:
- @ use lr as a pointer to the slot phases stored in the context
- update_ssg_eg
- #if 0
- subs r6, r6, #1
- addne lr, lr, #4
- addne r5, r5, #SLOT_STRUCT_SIZE
- #else
- add lr, lr, #4*2
- add r5, r5, #SLOT_STRUCT_SIZE*2
- update_ssg_eg
- subs r6, r6, #2
- subne lr, lr, #4
- subne r5, r5, #SLOT_STRUCT_SIZE
- #endif
- bne ssg_upd_loop
- sub lr, lr, #4*3
- sub r5, r5, #SLOT_STRUCT_SIZE*3
- subs r7, r7, #1<<EG_SH
- bge ssg_loop
- ssg_done:
- #endif
- @ -- EG --
- add r8, r8, r9
- cmp r8, #EG_TIMER_OVERFLOW
- blo volout_upd
- ldr r1, [lr, #0x3c] @ eg_cnt
- eg_loop:
- sub r8, r8, #EG_TIMER_OVERFLOW
- add r1, r1, #1
- cmp r1, #4096
- movge r1, #1
- mov r6, #4
- eg_upd_loop:
- update_eg_phase_slot
- #if 1
- subs r6, r6, #1
- addne r5, r5, #SLOT_STRUCT_SIZE
- #else
- add r5, r5, #SLOT_STRUCT_SIZE*2
- update_eg_phase_slot
- subs r6, r6, #2
- subne r5, r5, #SLOT_STRUCT_SIZE
- #endif
- bne eg_upd_loop
- cmp r8, #EG_TIMER_OVERFLOW
- sub r5, r5, #SLOT_STRUCT_SIZE*3
- bhs eg_loop
- str r1, [lr, #0x3c]
- b eg_done
- volout_upd:
- #if defined(SSG_EG)
- tst r4, #0x10 @ ssg_update?
- beq eg_done
- @ recalc vol_out
- mov r6, #4
- volout_loop:
- recalc_volout
- #if 0
- subs r6, r6, #1
- addne r5, r5, #SLOT_STRUCT_SIZE
- #else
- add r5, r5, #SLOT_STRUCT_SIZE*2
- recalc_volout
- subs r6, r6, #2
- subne r5, r5, #SLOT_STRUCT_SIZE
- #endif
- bne volout_loop
- sub r5, r5, #SLOT_STRUCT_SIZE*3
- #endif
- eg_done:
- @ -- disabled? --
- and r0, r12, #0xC
- cmp r0, #0xC
- beq crl_loop_lfo
- cmp r0, #0x4
- beq crl_loop
- @ output interpolation
- #if defined(INTERPOL)
- #if 1 // possibly too expensive for slow platforms?
- @ basic interpolator, interpolate in middle region, else use closer value
- mov r3, r8, lsr #EG_SH @ eg_timer, [0..3<<EG_SH) after loop
- cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)/2
- bne 0f @ mix is vol_out
- ldr r6, [r5, #0x34] @ vol_out, vol_ipol for all slots
- ldr r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
- ldr r7, [r5, #0x34+SLOT_STRUCT_SIZE]
- ldr r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
- add r6, r6, r6, lsl #16
- lsr r6, r6, #17
- add r2, r2, r2, lsl #16
- lsr r2, r2, #17
- add r7, r7, r7, lsl #16
- lsr r7, r7, #17
- add r3, r3, r3, lsl #16
- lsr r3, r3, #17
- b 1f
- #else
- @ super-basic... just take value closest to sample point
- mov r3, r8, lsr #EG_SH-1 @ eg_timer, [0..3<<EG_SH) after loop
- cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)
- #endif
- 0: ldrgeh r6, [r5, #0x34] @ vol_out values for all slots
- ldrlth r6, [r5, #0x36] @ vol_ipol values for all slots
- ldrgeh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
- ldrlth r2, [r5, #0x36+SLOT_STRUCT_SIZE*2]
- ldrgeh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
- ldrlth r7, [r5, #0x36+SLOT_STRUCT_SIZE]
- ldrgeh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
- ldrlth r3, [r5, #0x36+SLOT_STRUCT_SIZE*3]
- #else
- ldrh r6, [r5, #0x34] @ vol_out values for all slots
- ldrh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2]
- ldrh r7, [r5, #0x34+SLOT_STRUCT_SIZE]
- ldrh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3]
- #endif
- 1: orr r6, r6, r2, lsl #16
- orr r7, r7, r3, lsl #16
- @ -- SLOT1 --
- PIC_LDR(r3, r2, ym_tl_tab)
- @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16])
- @ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out
- upd_slot1_m
- @ -- SLOT2+ --
- and r0, r4, #7
- PIC_XB(,r0, lsl #2)
- nop
- PIC_BT(crl_algo0)
- PIC_BT(crl_algo1)
- PIC_BT(crl_algo2)
- PIC_BT(crl_algo3)
- PIC_BT(crl_algo4)
- PIC_BT(crl_algo5)
- PIC_BT(crl_algo6)
- PIC_BT(crl_algo7)
- .pool
- crl_algo0:
- upd_algo0_m
- b crl_algo_done
- .pool
- crl_algo1:
- upd_algo1_m
- b crl_algo_done
- .pool
- crl_algo2:
- upd_algo2_m
- b crl_algo_done
- .pool
- crl_algo3:
- upd_algo3_m
- b crl_algo_done
- .pool
- crl_algo4:
- upd_algo4_m
- b crl_algo_done
- .pool
- crl_algo5:
- upd_algo5_m
- b crl_algo_done
- .pool
- crl_algo6:
- upd_algo6_m
- b crl_algo_done
- .pool
- crl_algo7:
- upd_algo7_m
- crl_algo_done:
- @ -- WRITE SAMPLE --
- tst r0, r0
- beq ctl_sample_skip
- orr r4, r4, #8 @ have_output
- tst r12, #1
- beq ctl_sample_mono
- tst r12, #0x20 @ L
- ldrne r1, [r11]
- addeq r11, r11, #4
- addne r1, r0, r1
- strne r1, [r11], #4
- tst r12, #0x10 @ R
- ldrne r1, [r11]
- addeq r11, r11, #4
- addne r1, r0, r1
- strne r1, [r11], #4
- b crl_do_phase
- ctl_sample_mono:
- ldr r1, [r11]
- add r1, r0, r1
- str r1, [r11], #4
- b crl_do_phase
- ctl_sample_skip:
- and r1, r12, #1
- add r1, r1, #1
- add r11,r11, r1, lsl #2
- crl_do_phase:
- @ -- PHASE UPDATE --
- add r5, lr, #0x10
- ldmia r5, {r0-r3,r6-r7}
- add r0, r0, r6
- add r1, r1, r7
- ldr r6, [r5, #0x18]
- ldr r7, [r5, #0x1c]
- add r2, r2, r6
- add r3, r3, r7
- stmia r5, {r0-r3}
- tst r12, #8
- bne crl_loop_lfo
- b crl_loop
- crl_loop_end:
- str r8, [lr, #0x44] @ eg_timer
- str r12, [lr, #0x4c] @ pack (for lfo_ampm)
- str r4, [lr, #0x50] @ was_update
- str r10, [lr, #0x54] @ op1_out
- ldmfd sp!, {r4-r11,pc}
- .pool
- @ vim:filetype=armasm
|