1/* 2 * PicoDrive 3 * (C) notaz, 2006 4 * (C) kub, 2020 added SSG-EG and simple output rate interpolation 5 * 6 * This work is licensed under the terms of MAME license. 7 * See COPYING file in the top-level directory. 8 */ 9 10@ this is a rewrite of MAME's ym2612 code, in particular this is only the main sample-generatin loop. 11@ it does not seem to give much performance increase (if any at all), so don't use it if it causes trouble. 12@ - notaz, 2006 13 14@ vim:filetype=armasm 15 16#include "../arm_features.h" 17 18@ very simple YM2612 output rate to sample rate adaption (~500k cycles @44100) 19#define INTERPOL 20#define SSG_EG 21 22.equiv SLOT1, 0 23.equiv SLOT2, 2 24.equiv SLOT3, 1 25.equiv SLOT4, 3 26.equiv SLOT_STRUCT_SIZE, 0x38 27 28.equiv TL_TAB_LEN, 0x1A00 29 30.equiv EG_ATT, 4 31.equiv EG_DEC, 3 32.equiv EG_SUS, 2 33.equiv EG_REL, 1 34.equiv EG_OFF, 0 35 36.equiv EG_SH, 16 @ 16.16 fixed point (envelope generator timing) 37.equiv EG_TIMER_OVERFLOW, (3*(1<<EG_SH)) @ envelope generator timer overflows every 3 samples (on real chip) 38.equiv LFO_SH, 24 /* 8.24 fixed point (LFO calculations) */ 39 40.equiv ENV_QUIET, (2*13*256/8) 41 42.text 43.align 2 44 PIC_LDR_INIT() 45 46@ r5=slot, r1=eg_cnt, trashes: r0,r2,r3 47@ writes output to routp, but only if vol_out changes 48.macro update_eg_phase_slot 49#if defined(INTERPOL) 50 ldrh r0, [r5,#0x34] @ vol_out 51#endif 52 ldrb r2, [r5,#0x17] @ state 53 add r3, r5, #0x1c 54#if defined(INTERPOL) 55 strh r0, [r5,#0x36] @ vol_ipol 56#endif 57 tst r2, r2 58 beq 0f @ EG_OFF 59 60 ldr r2, [r3, r2, lsl #2] @ pack 61 mov r3, #1 62 mov r0, r2, lsr #24 @ shift 63 mov r3, r3, lsl r0 64 sub r3, r3, #1 65 66 tst r1, r3 67 bne 0f @ no volume change 68 69 mov r3, r1, lsr r0 70 ldrb r0, [r5,#0x30] @ ssg 71 and r3, r3, #7 72 add r3, r3, r3, lsl #1 73 mov r3, r2, lsr r3 74 and r3, r3, #7 @ eg_inc_val shift, may be 0 75 ldrb r2, [r5,#0x17] @ state 76 77#if defined(SSG_EG) 78 tst r0, #0x08 @ ssg enabled? 79 tstne r12, #0x02 80 bne 9f 81#endif 82 83 @ non-SSG-EG mode 84 cmp r2, #4 @ EG_ATT 85 ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023) 86 beq 4f 87 88 cmp r2, #2 89 mov r2, #1 90 mov r2, r2, lsl r3 91 mov r2, r2, lsr #1 @ eg_inc_val 92 add r0, r0, r2 93 blt 1f @ EG_REL 94 beq 2f @ EG_SUS 95 963: @ EG_DEC 97 ldr r2, [r5,#0x1c] @ sl (can be 16bit?) 98 mov r3, #EG_SUS 99 cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl ) 100 strgeb r3, [r5,#0x17] @ state 101 b 10f 102 1034: @ EG_ATT 104 subs r3, r3, #1 @ eg_inc_val_shift - 1 105 mvnpl r2, r0 106 movpl r2, r2, lsl r3 107 addpl r0, r0, r2, asr #4 108 cmp r0, #0 @ if (volume <= MIN_ATT_INDEX) 109 bgt 10f 110 ldr r2, [r5,#0x1c] 111 mov r0, #0 112 cmp r2, #0 113 movne r3, #EG_DEC 114 moveq r3, #EG_SUS 115 strb r3, [r5,#0x17] @ state 116 b 10f 117 1182: @ EG_SUS 119 mov r2, #1024 120 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX 121 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX ) 122 movge r0, r2 123 b 10f 124 1251: @ EG_REL 126 mov r2, #1024 127 sub r2, r2, #1 @ r2 = MAX_ATT_INDEX 128 cmp r0, r2 @ if ( volume >= MAX_ATT_INDEX ) 129 movge r0, r2 130 movge r3, #EG_OFF 131 strgeb r3, [r5,#0x17] @ state 132 13310: @ finish 134 ldrh r3, [r5,#0x18] @ tl 135 strh r0, [r5,#0x1a] @ volume 136#if defined(SSG_EG) 137 b 11f 138 1399: @ SSG-EG mode 140 ldrh r0, [r5,#0x1a] @ volume, unsigned (0-1023) 141 cmp r2, #4 @ EG_ATT 142 beq 4f 143 144 cmp r0, #0x200 @ if ( volume < 0x200 ) 145 movlt r0, #1 146 movlt r3, r0, lsl r3 147 ldrlth r0, [r5,#0x1a] @ volume, unsigned (0-1023) 148 movlt r3, r3, lsr #1 @ eg_inc_val 149 addlt r0, r0, r3, lsl #2 150 151 cmp r2, #2 152 blt 1f @ EG_REL 153 beq 10f @ EG_SUS - nothing more to do 154 1553: @ EG_DEC 156 ldr r2, [r5,#0x1c] @ sl (can be 16bit?) 157 mov r3, #EG_SUS 158 cmp r0, r2 @ if ( volume >= (INT32) SLOT->sl ) 159 strgeb r3, [r5,#0x17] @ state 160 b 10f 161 1624: @ EG_ATT 163 subs r3, r3, #1 @ eg_inc_val_shift - 1 164 mvnpl r2, r0 165 movpl r2, r2, lsl r3 166 addpl r0, r0, r2, asr #4 167 cmp r0, #0 @ if (volume <= MIN_ATT_INDEX) 168 bgt 10f 169 ldr r2, [r5,#0x1c] 170 mov r0, #0 171 cmp r2, #0 172 movne r3, #EG_DEC 173 moveq r3, #EG_SUS 174 strb r3, [r5,#0x17] @ state 175 b 10f 176 1771: @ EG_REL 178 mov r2, #0x200 179 cmp r0, r2 @ if ( volume >= 0x200 ) 180 movge r0, #1024 181 subge r0, #1 182 movge r3, #EG_OFF 183 strgeb r3, [r5,#0x17] @ state 184 18510: @ finish 186 ldrb r2, [r5,#0x30] @ ssg 187 ldrb r3, [r5,#0x17] @ state 188 strh r0, [r5,#0x1a] @ volume 189 cmp r2, #0x0c @ if ( ssg&0x04 && state > EG_REL ) 190 cmpge r3, #EG_REL+1 191 ldrh r3, [r5,#0x18] @ tl 192 rsbge r0, r0, #0x200 @ volume = (0x200-volume) & MAX_ATT 193 lslge r0, r0, #22 194 lsrge r0, r0, #22 195 19611: 197#endif 198 add r0, r0, r3 @ volume += tl 199 strh r0, [r5,#0x34] @ vol_out 200 2010: @ EG_OFF 202.endm 203 204#if defined(SSG_EG) 205@ r5=slot, trashes: r0,r2,r3 206.macro update_ssg_eg 207 ldrh r0, [r5,#0x30] @ ssg+ssgn 208 ldrb r2, [r5,#0x17] @ state 209 ldrh r3, [r5,#0x1a] @ volume 210 tst r0, #0x08 @ ssg enabled && 211 beq 9f 212 cmp r2, #EG_REL+1 @ state > EG_REL && 213 cmpge r3, #0x200 @ volume >= 0x200? 214 blt 9f 215 orr r4, r4, #0x10 @ ssg_update 216 217 tst r0, #0x01 218 beq 1f 219 220 tst r0, #0x02 221 eorne r0, r0, lsr #8 @ ssg ^= ssgn ^ 4 222 eorne r0, r0, #0x4 223 orrne r0, r0, #0x400 @ ssgn = 4 224 strneh r0, [r5,#0x30] 225 226 eor r0, r0, #0x4 @ if ( !(ssg&0x04) ) 227 tst r0, #0x4 228 cmpne r2, #EG_ATT @ if ( state != EG_ATT ) 229 movne r3, #0x400 230 subne r3, r3, #1 231 strneh r3, [r5,#0x1a] @ volume = MAX_ATT 232 b 9f 233 2341: tst r0, #0x02 235 eorne r0, r0, #0x4 @ ssg ^= 4 236 eorne r0, r0, #0x400 @ ssgn ^= 4 237 strneh r0, [r5,#0x30] 238 moveq r0, #0 239 streq r0, [r5,#0x0c] @ phase = 0 240 241 cmp r2, #EG_ATT @ if ( state != EG_ATT ) 242 beq 9f 243 244 ldr r0, [r5,#0x1c] @ sl 245 mov r2, #EG_SUS @ state = sl==MIN_ATT ? EG_SUS:EG_DEC 246 cmp r0, #0 247 248 ldrh r0, [r5,#0x32] @ ar+ksr 249 movne r2, #EG_DEC 250 cmp r0, #32+62 @ if ( ar+ksr >= 32+62 ) 251 movge r3, #0 252 strgeh r3, [r5,#0x1a] @ volume = MIN_ATT 253 bge 9f 254 255 cmp r3, #0 256 movgt r2, #EG_ATT 257 strb r2, [r5,#0x17] @ state 2589: 259.endm 260 261@ r5=slot, trashes: r0,r2,r3 262.macro recalc_volout 263#if defined(INTERPOL) 264 ldrh r0, [r5,#0x34] @ vol_out 265#endif 266 ldrb r2, [r5,#0x30] @ ssg 267 ldrb r3, [r5,#0x17] @ state 268#if defined(INTERPOL) 269 strh r0, [r5,#0x36] @ vol_ipol 270#endif 271 ldrh r0, [r5,#0x1a] @ volume 272 273@ and r2, r2, #0x0c 274 cmp r2, #0x0c @ if ( ~ssg&0x0c && state > EG_REL ) 275 cmpge r3, #EG_REL+1 276 ldrh r3, [r5,#0x18] @ tl 277 rsbge r0, r0, #0x200 @ volume = (0x200-volume) & MAX_ATT 278 lslge r0, r0, #22 279 lsrge r0, r0, #22 280 ldrh r0, [r5,#0x1a] @ volume 281 ldrh r3, [r5,#0x18] @ tl 282 283 add r0, r0, r3 @ volume += tl 284 strh r0, [r5,#0x34] @ vol_out 285.endm 286#endif 287 288@ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt, r3=scratch 289.macro advance_lfo_m 290 mov r2, r2, lsr #LFO_SH 291 cmp r2, r1, lsr #LFO_SH 292 beq 0f 293 and r3, r2, #0x3f 294 cmp r2, #0x40 295 eorlt r3, r3, #0x3f 296 bic r12,r12, #0xff000000 @ lfo_ampm &= 0xff 297 orr r12,r12, r3, lsl #1+24 298 299 mov r2, r2, lsr #2 300 cmp r2, r1, lsr #LFO_SH+2 301 bicne r12,r12, #0xff0000 302 orrne r12,r12, r2, lsl #16 303 3040: 305.endm 306 307 308@ result goes to r1, trashes r2 309.macro make_eg_out slot 310 tst r12, #8 311 tstne r12, #(1<<(\slot+8)) 312.if \slot == SLOT1 313 mov r1, r6, lsl #16 314 mov r1, r1, lsr #16 315.elseif \slot == SLOT2 316 mov r1, r6, lsr #16 317.elseif \slot == SLOT3 318 mov r1, r7, lsl #16 319 mov r1, r1, lsr #16 320.elseif \slot == SLOT4 321 mov r1, r7, lsr #16 322.endif 323 andne r2, r12, #0xc0 324 movne r2, r2, lsr #6 325 addne r2, r2, #24 326 addne r1, r1, r12, lsr r2 327 bic r1, r1, #1 328.endm 329 330 331@ \r=sin/result, r1=env, r3=ym_tl_tab 332.macro lookup_tl r 333 tst \r, #0x100 334 eorne \r, \r, #0xff @ if (sin & 0x100) sin = 0xff - (sin&0xff); 335 tst \r, #0x200 336 and \r, \r, #0xff 337 orr \r, \r, r1, lsl #7 338 mov \r, \r, lsl #1 339 ldrh \r, [r3, \r] @ 2ci if ne 340 rsbne \r, \r, #0 341.endm 342 343 344@ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]) 345@ r0-r2=scratch, r3=sin_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out 346.macro upd_algo0_m 347 348 @ SLOT3 349 make_eg_out SLOT3 350 cmp r1, #ENV_QUIET 351 movcs r0, #0 352 bcs 0f 353 ldr r2, [lr, #0x18] 354 ldr r0, [lr, #0x38] @ mem (signed) 355 mov r2, r2, lsr #16 356 add r0, r2, r0, lsr #1 357 lookup_tl r0 @ r0=c2 358 3590: 360 361 @ SLOT4 362 make_eg_out SLOT4 363 cmp r1, #ENV_QUIET 364 movcs r0, #0 365 bcs 1f 366 ldr r2, [lr, #0x1c] 367 mov r0, r0, lsr #1 368 add r0, r0, r2, lsr #16 369 lookup_tl r0 @ r0=output smp 370 3711: 372 @ SLOT2 373 make_eg_out SLOT2 374 cmp r1, #ENV_QUIET 375 movcs r2, #0 376 bcs 2f 377 ldr r2, [lr, #0x14] @ 1ci 378 mov r5, r10, lsr #17 379 add r2, r5, r2, lsr #16 380 lookup_tl r2 @ r2=mem 381 3822: 383 str r2, [lr, #0x38] @ mem 384.endm 385 386 387.macro upd_algo1_m 388 389 @ SLOT3 390 make_eg_out SLOT3 391 cmp r1, #ENV_QUIET 392 movcs r0, #0 393 bcs 0f 394 ldr r2, [lr, #0x18] 395 ldr r0, [lr, #0x38] @ mem (signed) 396 mov r2, r2, lsr #16 397 add r0, r2, r0, lsr #1 398 lookup_tl r0 @ r0=c2 399 4000: 401 @ SLOT4 402 make_eg_out SLOT4 403 cmp r1, #ENV_QUIET 404 movcs r0, #0 405 bcs 1f 406 ldr r2, [lr, #0x1c] 407 mov r0, r0, lsr #1 408 add r0, r0, r2, lsr #16 409 lookup_tl r0 @ r0=output smp 410 4111: 412 @ SLOT2 413 make_eg_out SLOT2 414 cmp r1, #ENV_QUIET 415 movcs r2, #0 416 bcs 2f 417 ldr r2, [lr, #0x14] @ 1ci 418 mov r2, r2, lsr #16 419 lookup_tl r2 @ r2=mem 420 4212: 422 add r2, r2, r10, asr #16 423 str r2, [lr, #0x38] 424.endm 425 426 427.macro upd_algo2_m 428 429 @ SLOT3 430 make_eg_out SLOT3 431 cmp r1, #ENV_QUIET 432 movcs r0, #0 433 bcs 0f 434 ldr r2, [lr, #0x18] 435 ldr r0, [lr, #0x38] @ mem (signed) 436 mov r2, r2, lsr #16 437 add r0, r2, r0, lsr #1 438 lookup_tl r0 @ r0=c2 439 4400: 441 add r0, r0, r10, asr #16 442 443 @ SLOT4 444 make_eg_out SLOT4 445 cmp r1, #ENV_QUIET 446 movcs r0, #0 447 bcs 1f 448 ldr r2, [lr, #0x1c] 449 mov r0, r0, lsr #1 450 add r0, r0, r2, lsr #16 451 lookup_tl r0 @ r0=output smp 452 4531: 454 @ SLOT2 455 make_eg_out SLOT2 456 cmp r1, #ENV_QUIET 457 movcs r2, #0 458 bcs 2f 459 ldr r2, [lr, #0x14] 460 mov r2, r2, lsr #16 @ 1ci 461 lookup_tl r2 @ r2=mem 462 4632: 464 str r2, [lr, #0x38] @ mem 465.endm 466 467 468.macro upd_algo3_m 469 470 @ SLOT3 471 make_eg_out SLOT3 472 cmp r1, #ENV_QUIET 473 ldr r2, [lr, #0x38] @ mem (for future) 474 mov r0, #0 475 bcs 0f 476 ldr r0, [lr, #0x18] @ phase3 477 mov r0, r0, lsr #16 478 lookup_tl r0 @ r0=c2 479 4800: 481 add r0, r0, r2 482 483 @ SLOT4 484 make_eg_out SLOT4 485 cmp r1, #ENV_QUIET 486 movcs r0, #0 487 bcs 1f 488 ldr r2, [lr, #0x1c] 489 mov r0, r0, lsr #1 490 add r0, r0, r2, lsr #16 491 lookup_tl r0 @ r0=output smp 492 4931: 494 @ SLOT2 495 make_eg_out SLOT2 496 cmp r1, #ENV_QUIET 497 movcs r2, #0 498 bcs 2f 499 ldr r2, [lr, #0x14] @ phase2 500 mov r5, r10, lsr #17 501 add r2, r5, r2, lsr #16 502 lookup_tl r2 @ r2=mem 503 5042: 505 str r2, [lr, #0x38] @ mem 506.endm 507 508 509.macro upd_algo4_m 510 511 @ SLOT3 512 make_eg_out SLOT3 513 cmp r1, #ENV_QUIET 514 movcs r0, #0 515 bcs 0f 516 ldr r0, [lr, #0x18] 517 mov r0, r0, lsr #16 @ 1ci 518 lookup_tl r0 @ r0=c2 519 5200: 521 @ SLOT4 522 make_eg_out SLOT4 523 cmp r1, #ENV_QUIET 524 movcs r0, #0 525 bcs 1f 526 ldr r2, [lr, #0x1c] 527 mov r0, r0, lsr #1 528 add r0, r0, r2, lsr #16 529 lookup_tl r0 @ r0=output smp 530 5311: 532 @ SLOT2 533 make_eg_out SLOT2 534 cmp r1, #ENV_QUIET 535 bcs 2f 536 ldr r2, [lr, #0x14] 537 mov r5, r10, lsr #17 538 add r2, r5, r2, lsr #16 539 lookup_tl r2 540 add r0, r0, r2 @ add to smp 541 5422: 543.endm 544 545 546.macro upd_algo5_m 547 548 @ SLOT3 549 make_eg_out SLOT3 550 cmp r1, #ENV_QUIET 551 movcs r0, #0 552 bcs 0f 553 ldr r2, [lr, #0x18] 554 ldr r0, [lr, #0x38] @ mem (signed) 555 mov r2, r2, lsr #16 556 add r0, r2, r0, lsr #1 557 lookup_tl r0 @ r0=output smp 558 5590: 560 @ SLOT4 561 make_eg_out SLOT4 562 cmp r1, #ENV_QUIET 563 bcs 1f 564 ldr r2, [lr, #0x1c] 565 mov r5, r10, lsr #17 566 add r2, r5, r2, lsr #16 567 lookup_tl r2 568 add r0, r0, r2 @ add to smp 569 5701: @ SLOT2 571 make_eg_out SLOT2 572 cmp r1, #ENV_QUIET 573 bcs 2f 574 ldr r2, [lr, #0x14] 575 mov r5, r10, lsr #17 576 add r2, r5, r2, lsr #16 577 lookup_tl r2 578 add r0, r0, r2 @ add to smp 579 5802: 581 mov r1, r10, asr #16 582 str r1, [lr, #0x38] @ mem 583.endm 584 585 586.macro upd_algo6_m 587 588 @ SLOT3 589 make_eg_out SLOT3 590 cmp r1, #ENV_QUIET 591 movcs r0, #0 592 bcs 0f 593 ldr r0, [lr, #0x18] 594 mov r0, r0, lsr #16 @ 1ci 595 lookup_tl r0 @ r0=output smp 596 5970: 598 @ SLOT4 599 make_eg_out SLOT4 600 cmp r1, #ENV_QUIET 601 bcs 1f 602 ldr r2, [lr, #0x1c] 603 mov r2, r2, lsr #16 @ 1ci 604 lookup_tl r2 605 add r0, r0, r2 @ add to smp 606 6071: @ SLOT2 608 make_eg_out SLOT2 609 cmp r1, #ENV_QUIET 610 bcs 2f 611 ldr r2, [lr, #0x14] 612 mov r5, r10, lsr #17 613 add r2, r5, r2, lsr #16 614 lookup_tl r2 615 add r0, r0, r2 @ add to smp 616 6172: 618.endm 619 620 621.macro upd_algo7_m 622 623 @ SLOT3 624 make_eg_out SLOT3 625 cmp r1, #ENV_QUIET 626 movcs r0, #0 627 bcs 0f 628 ldr r0, [lr, #0x18] 629 mov r0, r0, lsr #16 @ 1ci 630 lookup_tl r0 @ r0=output smp 631 6320: 633 add r0, r0, r10, asr #16 634 635 @ SLOT4 636 make_eg_out SLOT4 637 cmp r1, #ENV_QUIET 638 bcs 1f 639 ldr r2, [lr, #0x1c] 640 mov r2, r2, lsr #16 @ 1ci 641 lookup_tl r2 642 add r0, r0, r2 @ add to smp 643 6441: @ SLOT2 645 make_eg_out SLOT2 646 cmp r1, #ENV_QUIET 647 bcs 2f 648 ldr r2, [lr, #0x14] 649 mov r2, r2, lsr #16 @ 1ci 650 lookup_tl r2 651 add r0, r0, r2 @ add to smp 652 6532: 654.endm 655 656 657.macro upd_slot1_m 658 659 make_eg_out SLOT1 660 cmp r1, #ENV_QUIET 661 movcs r10, r10, lsl #16 @ ct->op1_out <<= 16; // op1_out0 = op1_out1; op1_out1 = 0; 662 bcs 0f 663 ands r2, r12, #0xf000 664 moveq r0, #0 665 movne r2, r2, lsr #12 666 addne r0, r10, r10, lsl #16 667 movne r0, r0, asr #16 668 movne r0, r0, lsl r2 669 670 ldr r2, [lr, #0x10] @ phase1 671 add r0, r0, r2 672 mov r0, r0, lsr #16 673 lookup_tl r0 674 mov r10,r10,lsl #16 @ ct->op1_out <<= 16; 675 mov r0, r0, lsl #16 676 orr r10,r10, r0, lsr #16 677 6780: 679.endm 680 681 682@ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]) 683@ r0-r2=scratch, r3=sin_tab/scratch, r4=(length<<8)|unused[3],ssg_update,was_update,algo[3], r5=tl_tab/slot, 684@ r6-r7=vol_out[4], r8=eg_timer, r9=eg_timer_add[31:16], r10=op1_out, r11=buffer 685.global chan_render_loop @ chan_rend_context *ct, int *buffer, int length 686 687chan_render_loop: 688 stmfd sp!, {r4-r11,lr} 689 mov lr, r0 690 mov r4, r2, lsl #8 @ no more 24 bits here 691 ldr r12, [lr, #0x4c] 692 ldr r0, [lr, #0x50] 693 mov r11, r1 694 and r0, r0, #7 695 orr r4, r4, r0 @ (length<<8)|algo 696 ldr r8, [lr, #0x44] @ eg_timer 697 ldr r9, [lr, #0x48] @ eg_timer_add 698 ldr r10, [lr, #0x54] @ op1_out 699 700 tst r12, #8 @ lfo? 701 beq crl_loop 702 703crl_loop_lfo: 704 ldr r1, [lr, #0x30] @ lfo_cnt 705 ldr r2, [lr, #0x34] @ lfo_inc 706 707 subs r4, r4, #0x100 708 bmi crl_loop_end 709 710 add r2, r2, r1 711 str r2, [lr, #0x30] 712 713 @ r12=lfo_ampm[31:16], r1=lfo_cnt_old, r2=lfo_cnt 714 advance_lfo_m 715 716 add r4, r4, #0x100 717 718crl_loop: 719 subs r4, r4, #0x100 720 bmi crl_loop_end 721 722 ldr r5, [lr, #0x40] @ CH 723#if defined(SSG_EG) 724 tst r12, #0x02 @ ssg_enabled? 725 beq ssg_done 726 @ -- SSG -- 727 lsl r7, r8, #EG_SH 728 add r7, r9, r7, lsr #EG_SH 729 subs r7, r7, #1<<EG_SH 730 blt ssg_done 731 732ssg_loop: 733 mov r6, #4 734ssg_upd_loop: 735 update_ssg_eg 736#if 0 737 subs r6, r6, #1 738 addne r5, r5, #SLOT_STRUCT_SIZE 739#else 740 add r5, r5, #SLOT_STRUCT_SIZE*2 741 update_ssg_eg 742 subs r6, r6, #2 743 subne r5, r5, #SLOT_STRUCT_SIZE 744#endif 745 bne ssg_upd_loop 746 sub r5, r5, #SLOT_STRUCT_SIZE*3 747 748 subs r7, r7, #1<<EG_SH 749 bge ssg_loop 750ssg_done: 751#endif 752 753 @ -- EG -- 754 add r8, r8, r9 755 cmp r8, #EG_TIMER_OVERFLOW 756 bcc volout_upd 757 ldr r1, [lr, #0x3c] @ eg_cnt 758eg_loop: 759 sub r8, r8, #EG_TIMER_OVERFLOW 760 add r1, r1, #1 761 cmp r1, #4096 762 movge r1, #1 763 764 mov r6, #4 765eg_upd_loop: 766 update_eg_phase_slot 767#if 1 768 subs r6, r6, #1 769 addne r5, r5, #SLOT_STRUCT_SIZE 770#else 771 add r5, r5, #SLOT_STRUCT_SIZE*2 772 update_eg_phase_slot 773 subs r6, r6, #2 774 subne r5, r5, #SLOT_STRUCT_SIZE 775#endif 776 bne eg_upd_loop 777 778 cmp r8, #EG_TIMER_OVERFLOW 779 sub r5, r5, #SLOT_STRUCT_SIZE*3 780 bhs eg_loop 781 str r1, [lr, #0x3c] 782 b eg_done 783 784volout_upd: 785#if defined(SSG_EG) 786 tst r4, #0x10 @ ssg_update? 787 beq eg_done 788 789 @ recalc vol_out 790 mov r6, #4 791volout_loop: 792 recalc_volout 793#if 0 794 subs r6, r6, #1 795 addne r5, r5, #SLOT_STRUCT_SIZE 796#else 797 add r5, r5, #SLOT_STRUCT_SIZE*2 798 recalc_volout 799 subs r6, r6, #2 800 subne r5, r5, #SLOT_STRUCT_SIZE 801#endif 802 bne volout_loop 803 sub r5, r5, #SLOT_STRUCT_SIZE*3 804#endif 805 806eg_done: 807 @ -- disabled? -- 808 and r0, r12, #0xC 809 cmp r0, #0xC 810 beq crl_loop_lfo 811 cmp r0, #0x4 812 beq crl_loop 813 814 @ output interpolation 815#if defined(INTERPOL) 816#if 1 // possibly too expensive for slow platforms? 817 @ basic interpolator, interpolate in middle region, else use closer value 818 mov r3, r8, lsr #EG_SH @ eg_timer, [0..3<<EG_SH) after loop 819 cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH)/2 820 bne 0f @ mix is vol_out 821 822 ldr r6, [r5, #0x34] @ vol_out, vol_ipol for all slots 823 ldr r2, [r5, #0x34+SLOT_STRUCT_SIZE*2] 824 ldr r7, [r5, #0x34+SLOT_STRUCT_SIZE] 825 ldr r3, [r5, #0x34+SLOT_STRUCT_SIZE*3] 826 add r6, r6, r6, lsl #16 827 lsr r6, r6, #17 828 add r2, r2, r2, lsl #16 829 lsr r2, r2, #17 830 add r7, r7, r7, lsl #16 831 lsr r7, r7, #17 832 add r3, r3, r3, lsl #16 833 lsr r3, r3, #17 834 b 1f 835#else 836 @ super-basic... just take value closest to sample point 837 mov r3, r8, lsr #EG_SH-1 @ eg_timer, [0..3<<EG_SH) after loop 838 cmp r3, #(EG_TIMER_OVERFLOW>>EG_SH) 839#endif 840 8410: ldrgeh r6, [r5, #0x34] @ vol_out values for all slots 842 ldrlth r6, [r5, #0x36] @ vol_ipol values for all slots 843 ldrgeh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2] 844 ldrlth r2, [r5, #0x36+SLOT_STRUCT_SIZE*2] 845 ldrgeh r7, [r5, #0x34+SLOT_STRUCT_SIZE] 846 ldrlth r7, [r5, #0x36+SLOT_STRUCT_SIZE] 847 ldrgeh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3] 848 ldrlth r3, [r5, #0x36+SLOT_STRUCT_SIZE*3] 849 850#else 851 ldrh r6, [r5, #0x34] @ vol_out values for all slots 852 ldrh r2, [r5, #0x34+SLOT_STRUCT_SIZE*2] 853 ldrh r7, [r5, #0x34+SLOT_STRUCT_SIZE] 854 ldrh r3, [r5, #0x34+SLOT_STRUCT_SIZE*3] 855#endif 8561: orr r6, r6, r2, lsl #16 857 orr r7, r7, r3, lsl #16 858 859 @ -- SLOT1 -- 860 PIC_LDR(r3, r2, ym_tl_tab) 861 862 @ lr=context, r12=pack (stereo, ssg_enabled, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]) 863 @ r0-r2=scratch, r3=tl_tab, r5=scratch, r6-r7=vol_out[4], r10=op1_out 864 upd_slot1_m 865 866 @ -- SLOT2+ -- 867 and r0, r4, #7 868 PIC_XB(,r0, lsl #2) 869 nop 870 PIC_BT(crl_algo0) 871 PIC_BT(crl_algo1) 872 PIC_BT(crl_algo2) 873 PIC_BT(crl_algo3) 874 PIC_BT(crl_algo4) 875 PIC_BT(crl_algo5) 876 PIC_BT(crl_algo6) 877 PIC_BT(crl_algo7) 878 .pool 879 880crl_algo0: 881 upd_algo0_m 882 b crl_algo_done 883 .pool 884 885crl_algo1: 886 upd_algo1_m 887 b crl_algo_done 888 .pool 889 890crl_algo2: 891 upd_algo2_m 892 b crl_algo_done 893 .pool 894 895crl_algo3: 896 upd_algo3_m 897 b crl_algo_done 898 .pool 899 900crl_algo4: 901 upd_algo4_m 902 b crl_algo_done 903 .pool 904 905crl_algo5: 906 upd_algo5_m 907 b crl_algo_done 908 .pool 909 910crl_algo6: 911 upd_algo6_m 912 b crl_algo_done 913 .pool 914 915crl_algo7: 916 upd_algo7_m 917 918 919crl_algo_done: 920 @ -- WRITE SAMPLE -- 921 tst r0, r0 922 beq ctl_sample_skip 923 orr r4, r4, #8 @ have_output 924 tst r12, #1 925 beq ctl_sample_mono 926 927 tst r12, #0x20 @ L 928 ldrne r1, [r11] 929 addeq r11, r11, #4 930 addne r1, r0, r1 931 strne r1, [r11], #4 932 tst r12, #0x10 @ R 933 ldrne r1, [r11] 934 addeq r11, r11, #4 935 addne r1, r0, r1 936 strne r1, [r11], #4 937 b crl_do_phase 938 939ctl_sample_mono: 940 ldr r1, [r11] 941 add r1, r0, r1 942 str r1, [r11], #4 943 b crl_do_phase 944 945ctl_sample_skip: 946 and r1, r12, #1 947 add r1, r1, #1 948 add r11,r11, r1, lsl #2 949 950crl_do_phase: 951 @ -- PHASE UPDATE -- 952 add r5, lr, #0x10 953 ldmia r5, {r0-r3,r6-r7} 954 add r0, r0, r6 955 add r1, r1, r7 956 ldr r6, [r5, #0x18] 957 ldr r7, [r5, #0x1c] 958 add r2, r2, r6 959 add r3, r3, r7 960 stmia r5, {r0-r3} 961 962 tst r12, #8 963 bne crl_loop_lfo 964 b crl_loop 965 966 967crl_loop_end: 968 str r8, [lr, #0x44] @ eg_timer 969 str r12, [lr, #0x4c] @ pack (for lfo_ampm) 970 str r4, [lr, #0x50] @ was_update 971 str r10, [lr, #0x54] @ op1_out 972 ldmfd sp!, {r4-r11,pc} 973 974.pool 975 976@ vim:filetype=armasm 977