1 2 incdir "Amiga:Includes/" 3 include "misc/DeliPlayer.i" 4 5; 6; 7 SECTION Player,Code 8; 9; 10 11 PLAYERHEADER PlayerTagArray 12 13 dc.b '$VER: Ultimate Soundtracker player 1.1 (Jan 2003)',0 14 even 15 16PlayerTagArray 17 dc.l DTP_PlayerVersion,1 18 dc.l DTP_PlayerName,PName 19 dc.l DTP_Creator,CName 20 dc.l DTP_Check2,Chk 21* dc.l DTP_StartInt,START_MUZAK 22* dc.l DTP_StopInt,STOP_MUZAK 23 dc.l DTP_Interrupt,REPLAY_MUZAK 24 dc.l DTP_Config,Config 25 dc.l DTP_InitPlayer,InitPlay 26 dc.l DTP_EndPlayer,EndPlay 27 dc.l DTP_InitSound,InitSnd 28 dc.l DTP_EndSound,RemSnd 29 dc.l DTP_Flags,PLYF_SONGEND 30 dc.l TAG_DONE 31 32*-----------------------------------------------------------------------* 33; 34; Player/Creatorname und lokale Daten 35 36PName dc.b 'The Ultimate Soundtracker',0 37CName dc.b "87/88 by Karsten Obarski",10 38 dc.b 'adapted for UADE by mld',0 39songendflag dc.b 0 40 41mod15flag dc.b 0 ; is it a mod15 42bpmflag dc.b 0 ; mod uses bpm 43samplelenflag dc.b 0 ; samplelen <= 9999 44repeatoffsetflag dc.b 0 ; smp start + repeat *2 > sample end 45samplenameflag dc.b 0 ; no st-xy: ? 46effectsflag dc.b 0 ; 1xy and 2xy && xy >1f 47 48 even 49delibase dc.l 0 50 51 52*-----------------------------------------------------------------------* 53; 54; Testet auf Ultimate Soundtracker-Modul 55 56Chk ; UST ? 57 move.w #-1,d0 58 move.l dtg_ChkData(a5),a0 59 ;move.l dtg_chksize(a5),d2 ; File len 60 move.l a0,ustsong 61 62 bsr mod15_check ; lame 15 inst checks? 63 cmp.b #1,mod15flag 64 bne chk_rts 65 66 bsr do_ust_checks 67 cmp.b #1,samplelenflag 68 bne chk_rts 69 70 cmp.b #1,repeatoffsetflag 71 bne chk_rts 72 73 cmp.b #1,bpmflag 74 beq chk_ok 75 76 cmp.b #1,samplenameflag 77 bne chk_rts 78 79chk_ok 80 moveq #0,d0 81chk_rts 82 rts 83 84mod15_check: ; check if mod15 85 moveq #0,d1 86 87 move.b $1d6(a0),d1 ; max pos 88 tst.b d1 ; 0 ? 89 beq.s mod15_rts ; no mod15 90 91 cmp.w #$78,d1 ; max pos > 78 92 bge mod15_rts ; no mod15 93 94 cmp.b #1,$1f3(a0) ; smpl repeat = 1? 95 beq.s mod15_rts ; nomod 96is_mod15 97 move.b #1,mod15flag 98mod15_rts 99 rts 100 101do_ust_checks: 102 moveq #0,d1 103 move.b $1d7(a0),d1 ; zero bpm? 104 tst.b d1 105 beq duc_end ; can't be ust 106 107 cmp.w #$78,d1 ; BPM value != 78 108 beq duc1 109 move.b #1,bpmflag 110duc1: 111 moveq #$0e,d1 ; smpl check 112 move.l a0,a1 113duc1loop: 114 clr.l d1 115 clr.l d2 116 clr.l d3 117 cmp.l #0,20(a1) ; empty smpl name? 118 beq duc1next ; yup, next Instr. 119 120 move.w 42(a1),d1 ; smpl len < 9999 121 add.l d1,d1 ; *2 122 cmp.l #9999,d1 123 bgt duc_end ; nope no UST 124 125 move.w 46(a1),d2 ; repeat offset 126 move.w 48(a1),d3 ; repeat size 127 add.l d3,d3 ; *2 128 add.l d3,d2 129 130 cmp.l #$ffff,d2 ; it's only words... 131 bgt duc_end 132 133 cmp.l d2,d1 ; repeat offset+ size > smpl len 134 blt duc_end ; yup 135duc1next: 136 add.l #30,a1 137 dbra d1,duc1loop 138 move.b #1,samplelenflag 139 move.b #1,repeatoffsetflag 140 141 moveq #$0e,d1 ; smpl check 142 move.l a0,a1 143duc2loop: ; chk sample name 144 clr.l d1 145 clr.l d2 146 clr.l d3 147 cmp.l #0,20(a1) ; empty smpl name? 148 beq duc2next ; yup, next Instr. 149 150 move.b 25(a1),d1 ; ":"? 151 cmp.b #":",d1 152 bne duc2next 153 154 move.b 22(a1),d1 ; "-"? 155 cmp.b #"-",d1 156 bne duc2next 157 158 move.w 20(a1),d1 ; "st" ? 159 cmp.w #"st",d1 160 beq duc_end 161 cmp.w #"ST",d1 ; ST 162 beq duc_end 163 164duc2next: 165 add.l #30,a1 166 dbra d1,duc2loop 167 move.b #1,samplenameflag 168duc_end 169 rts 170 171*-----------------------------------------------------------------------* 172; 173; Einmalige Initialisierung des Players 174 175Config 176 177 moveq #0,d0 ; no Error 178 rts 179 180*-----------------------------------------------------------------------* 181; 182; Init Player 183 184InitPlay 185 move.l a5,delibase 186 moveq #0,d0 187 move.l dtg_GetListData(a5),a0 ; Function 188 jsr (a0) 189 move.l a0,ustsong 190 191 move.l dtg_AudioAlloc(a5),a0 ; Function 192 jsr (a0) ; returncode is already set ! 193 sf songendflag 194 rts 195 196*-----------------------------------------------------------------------* 197; 198; End Player 199 200EndPlay 201 move.l dtg_AudioFree(a5),a0 ; Function 202 jsr (a0) 203 rts 204 205*-----------------------------------------------------------------------* 206; 207; Init Sound 208 209InitSnd 210 bsr START_MUZAK 211 rts 212 213 214*-----------------------------------------------------------------------* 215; 216; Remove Sound 217 218RemSnd 219 lea $dff000,a0 220 moveq #0,d0 221 move.w d0,$a8(a0) 222 move.w d0,$b8(a0) 223 move.w d0,$c8(a0) 224 move.w d0,$d8(a0) 225 move.w #$000F,$96(a0) ; End Sound 226 rts 227 228SetCIASpeed: 229 movem.l d0-d2/a0-a6,-(sp) 230 move.l delibase(pc),a5 231 move.w d0,dtg_Timer(a5) 232 move.l dtg_SetTimer(a5),a1 233 jsr (a1) 234 movem.l (sp)+,d0-d2/a0-a6 235 rts 236Songend 237 movem.l d0-d7/a0-a6,-(a7) 238 move.l delibase(pc),a5 239 move.l dtg_SongEnd(a5),a1 240 jsr (a1) 241 movem.l (a7)+,d0-d7/a0-a6 242 rts 243 244*-----------------------------------------------------------------------* 245 246 even 247ustsong dc.l 0 248 249 250;������������������������������������������������ 251;� � 252;� The Ultimate Soundtracker Replay-Routine � 253;� Version 27 All bugs removed � 254;� Update 29.03.1988 � 255;� Written 1987/88 by Karsten Obarski � 256;� � 257;������������������������������������������������ 258 259START_MUZAK: 260 move.l ustsong,muzakoffset ;** get offset 261 262init0: move.l muzakoffset,a0 ;** get highest used pattern 263 add.l #472,a0 264 move.l #128,d0 265 clr.l d1 266init1: move.l d1,d2 267 subq.w #1,d0 268init2: move.b (a0)+,d1 269 cmp.b d2,d1 270 bgt init1 271 dbra d0,init2 272 addq.b #1,d2 273 274init3: move.l muzakoffset,a0 ;** calc samplepointers 275 lea.l pointers,a1 276 mulu #1024,d2 277 add.l #600,d2 278 add.l a0,d2 279 move.l #15-1,d0 280init4: move.l d2,(a1)+ 281 move.l d2,a2 282 clr.l (a2) ; clear first four bytes 283 clr.l d1 284 move.w 42(a0),d1 285 lsl.l #1,d1 286 add.l d1,d2 287 add.l #30,a0 288 dbra d0,init4 289 290init5: move.w #$0,$dff0a8 ;** clear used values 291 move.w #$0,$dff0b8 292 move.w #$0,$dff0c8 293 move.w #$0,$dff0d8 294 clr.w timpos 295 clr.l trkpos 296 clr.l patpos 297 298init6: move.l muzakoffset,a0 ;** initialize timer irq 299 move.b 470(a0),numpat+1 ;number of patterns 300 move.l #240,d0 301 sub.b 471(a0),d0 302 mulu #122,d0 303 304 bsr SetCIASpeed 305 306* move.b #$0,$bfde00 ; CIAA 307* move.b d0,$bfd400 308* lsr.w #8,d0 309* move.b d0,$bfd500 310* move.b #$81,$bfdd00 311* move.b #$11,$bfde00 312* move.l $78,lev6save ; Argh! bad, bad irq alloc! 313* move.l #lev6interrupt,$78 314NOPLAY: rts 315 316*STOP_MUZAK: 317* move.b #$1,$bfdd00 ;** restore timer & dma 318* move.l lev6save,$78 319* move.w #$0,$dff0a8 320* move.w #$0,$dff0b8 321* move.w #$0,$dff0c8 322* move.w #$0,$dff0d8 323* move.w #$f,$dff096 324* rts 325 326*lev6interrupt: 327* movem.l d0/d1,-(sp) ;** jump 328* bsr REPLAY_MUZAK 329* move.b $bfdd00,d0 330* move.w #$2000,$dff09c 331* movem.l (sp)+,d0/d1 332* rte 333 334;------------------------------------------------ 335; replay-routine 336;------------------------------------------------ 337 338REPLAY_MUZAK: 339 movem.l d0-d7/a0-a6,-(a7) 340 addq.w #1,timpos 341 cmp.w #6,timpos 342 beq replaystep 343 344;------------------------------------------------ 345; time left to handle effects between steps 346;------------------------------------------------ 347 348chaneleffects: ;** seek effects 349 lea.l datach0,a6 350 cmp.b #0,3(a6) 351 beq.s ceff1 352 lea.l $dff0a0,a5 353 bsr.s ceff5 354ceff1: lea.l datach1,a6 355 cmp.b #0,3(a6) 356 beq.s ceff2 357 lea.l $dff0b0,a5 358 bsr.s ceff5 359ceff2: lea.l datach2,a6 360 cmp.b #0,3(a6) 361 beq.s ceff3 362 lea.l $dff0c0,a5 363 bsr.s ceff5 364ceff3: lea.l datach3,a6 365 cmp.b #0,3(a6) 366 beq.s ceff4 367 lea.l $dff0d0,a5 368 bsr.s ceff5 369ceff4: movem.l (a7)+,d0-d7/a0-a6 370 rts 371ceff5: move.b 2(a6),d0 372 and.b #$0f,d0 373 cmp.b #1,d0 374 beq arpreggiato 375 cmp.b #2,d0 376 beq pitchbend 377 rts 378 379;------------------------------------------------ 380; effect 1 arpreggiato 381;------------------------------------------------ 382 383arpreggiato: ;** spread by time 384 cmp.w #1,timpos 385 beq.s arp1 386 cmp.w #2,timpos 387 beq.s arp2 388 cmp.w #3,timpos 389 beq.s arp3 390 cmp.w #4,timpos 391 beq.s arp1 392 cmp.w #5,timpos 393 beq.s arp2 394 rts 395arp1: clr.l d0 ;** get higher note-values 396 move.b 3(a6),d0 ; or play original 397 lsr.b #4,d0 398 bra.s arp4 399arp2: clr.l d0 400 move.b 3(a6),d0 401 and.b #$0f,d0 402 bra.s arp4 403arp3: move.w 16(a6),d2 404 bra.s arp6 405arp4: lsl.w #1,d0 406 clr.l d1 407 move.w 16(a6),d1 408 lea.l notetable,a0 409arp5: move.w (a0,d0.w),d2 410 cmp.w (a0),d1 411 beq.s arp6 412 addq.l #2,a0 413 bra.s arp5 414arp6: move.w d2,6(a5) 415 rts 416 417;------------------------------------------------ 418; effect 2 pitchbend 419;------------------------------------------------ 420 421pitchbend: ;** increase or decrease 422 clr.l d0 ; period every time 423 move.b 3(a6),d0 424 lsr.b #4,d0 425 beq.s pit2 426 add.w d0,(a6) 427 move.w (a6),6(a5) 428 rts 429pit2: clr.l d0 430 move.b 3(a6),d0 431 and.b #$0f,d0 432 beq.s pit3 433 sub.w d0,(a6) 434 move.w (a6),6(a5) 435pit3: rts 436 437;------------------------------------------------ 438; handle a further step of 16tel data 439;------------------------------------------------ 440 441replaystep: ;** work next pattern-step 442 clr.w timpos 443 move.l muzakoffset,a0 444 move.l a0,a3 445 add.l #12,a3 ;ptr to soundprefs 446 move.l a0,a2 447 add.l #472,a2 ;ptr to pattern-table 448 add.l #600,a0 ;ptr to first pattern 449 clr.l d1 450 move.l trkpos,d0 ;get ptr to current pattern 451 move.b (a2,d0),d1 452 mulu #1024,d1 453 add.l patpos,d1 ;get ptr to current step 454 clr.w enbits 455 lea.l $dff0a0,a5 ;chanel 0 456 lea.l datach0,a6 457 bsr chanelhandler 458 lea.l $dff0b0,a5 ;chanel 1 459 lea.l datach1,a6 460 bsr chanelhandler 461 lea.l $dff0c0,a5 ;chanel 2 462 lea.l datach2,a6 463 bsr chanelhandler 464 lea.l $dff0d0,a5 ;chanel 3 465 lea.l datach3,a6 466 bsr chanelhandler 467 move.l #400,d0 ;** wait a while and set len 468rep1: dbra d0,rep1 ; of oneshot to 1 word 469 move.l #$8000,d0 470 or.w enbits,d0 471 move.w d0,$dff096 472 cmp.w #1,datach0+14 473 bne.s rep2 474 clr.w datach0+14 475 move.w #1,$dff0a4 476rep2: cmp.w #1,datach1+14 477 bne.s rep3 478 clr.w datach1+14 479 move.w #1,$dff0b4 480rep3: cmp.w #1,datach2+14 481 bne.s rep4 482 clr.w datach2+14 483 move.w #1,$dff0c4 484rep4: cmp.w #1,datach3+14 485 bne.s rep5 486 clr.w datach3+14 487 move.w #1,$dff0d4 488 489rep5: add.l #16,patpos ;next step 490 cmp.l #64*16,patpos ;pattern finished ? 491 bne rep6 492 clr.l patpos 493 addq.l #1,trkpos ;next pattern in table 494 clr.l d0 495 move.w numpat,d0 496 cmp.l trkpos,d0 ;song finished ? 497 bne rep6 498 clr.l trkpos 499 st songendflag 500rep6: movem.l (a7)+,d0-d7/a0-a6 501 502 tst.b songendflag 503 beq rep7 504 bsr Songend 505rep7 506 rts 507 508;------------------------------------------------ 509; proof chanel for actions 510;------------------------------------------------ 511 512chanelhandler: 513 move.l (a0,d1.l),(a6) ;get period & action-word 514 addq.l #4,d1 ;point to next chanel 515 clr.l d2 516 move.b 2(a6),d2 ;get nibble for soundnumber 517 lsr.b #4,d2 518 beq chan2 ;no soundchange ! 519 move.l d2,d4 ;** calc ptr to sample 520 lsl.l #2,d2 521 mulu #30,d4 522 lea.l pointers-4,a1 523 move.l 0(a1,d2.l),04(a6) ;store sample-address 524 move.w 0(a3,d4.l),08(a6) ;store sample-len in words 525 move.w 2(a3,d4.l),18(a6) ;store sample-volume 526 move.w 2(a3,d4.l),08(a5) ;change chanel-volume 527 clr.l d3 528 move.w 4(a3,d4),d3 ;** calc repeatstart 529 add.l 4(a6),d3 530 move.l d3,10(a6) ;store repeatstart 531 move.w 6(a3,d4),14(a6) ;store repeatlength 532 cmp.w #1,14(a6) 533 beq chan2 ;no sustainsound ! 534 move.l 10(a6),4(a6) ;repstart = sndstart 535 move.w 6(a3,d4),8(a6) ;replength = sndlength 536chan2: cmp.w #0,(a6) 537 beq chan4 ;no new note set ! 538 move.w 22(a6),$dff096 ;clear dma 539 cmp.w #0,14(a6) 540 bne chan3 ;no oneshot-sample 541 move.w #1,14(a6) ;allow resume (later) 542chan3: move.w (a6),16(a6) ;save note for effect 543 move.l 4(a6),0(a5) ;set samplestart 544 move.w 8(a6),4(a5) ;set samplelength 545 move.w 0(a6),6(a5) ;set period 546 move.w 22(a6),d0 547 or.w d0,enbits ;store dma-bit 548 move.w 18(a6),20(a6) ;volume trigger 549chan4: rts 550 551;------------------------------------------------ 552; used varibles 553;------------------------------------------------ 554; datachx - structure (22 bytes) 555; 556; 00.w current note 557; 02.b sound-number 558; 03.b effect-number 559; 04.l soundstart 560; 08.w soundlenght in words 561; 10.l repeatstart 562; 14.w repeatlength 563; 16.w last saved note 564; 18.w volume 565; 20.w volume trigger (note on dynamic) 566; 22.w dma-bit 567;------------------------------------------------ 568 569datach0: dc.w 0,0,0,0,0,0,0,0,0,0,0,1 570datach1: dc.w 0,0,0,0,0,0,0,0,0,0,0,2 571datach2: dc.w 0,0,0,0,0,0,0,0,0,0,0,4 572datach3: dc.w 0,0,0,0,0,0,0,0,0,0,0,8 573pointers: dc.l 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 574notetable: dc.w 856,808,762,720,678,640,604,570 575 dc.w 538,508,480,453,428,404,381,360 576 dc.w 339,320,302,285,269,254,240,226 577 dc.w 214,202,190,180,170,160,151,143 578 dc.w 135,127,120,113,000 579muzakoffset: dc.l 0 580lev6save: dc.l 0 581trkpos: dc.l 0 582patpos: dc.l 0 583numpat: dc.w 0 584enbits: dc.w 0 585timpos: dc.w 0 586data: blk.b 0,0 587 588 589