|
Author |
Message |
sdw
Member |
I want to play good old normal 4 channel modules in my demo/intro. In my first little "comeback" on the Amiga scene (http://www.pouet.net/prod.php?which=61596) I wrote everything in pure assembler (like I did back in the 90ies) and reused the same old Noistetracker replay code from Kaktus & Mahoney (C) 1990. Worked fine, just call mt_init at startup and mt_music every frame and all is OK.
Now I have moved along to a bit more modern way of developing, so I have setup a VBCC+VASM based build system, where my main code is in C and then I call assembler functions where extra speed is needed. It also works fine, at least until I added music. The Noisetracker replayer simply does not get along with this new setup, at all. Somehow just calling mt_init manages to mess up bitplane pointers, and while running mt_music every frame actually plays the music, I get some kind of system error on every exit and have to reboot my (emulated) Amiga. I have tried looking at the replayer code and see if I can find what is going wrong, but no luck.
Is there any better and easier option to replay 4 channel modules (A500 OCS is my target)?
I looked into P61Play, but that was just way to hard to get going. 1) The code didn't even compile in VASM 2) Looking at page iupon page ofl the strange options I have to setup makes my eyes glaze over. I want to call init, play and that's it. 3) It requires converting the modules from mod to p61.
So, are there any small, quick and easy .mod replayers with source that I can drop in and see if it works better than the Noisetracker replayer?
|
sdw
Member |
Oh, for reference, here's the replay code I am trying to use that isn't working anymore: ;ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ ;ญ NoisetrackerV2.0 FASTreplay ญ ;ญ Uses lev6irq - takes 8 rasterlines ญ ;ญ Do not disable Master irq in $dff09a ญ ;ญ Used registers: d0-d3/a0-a7| =INTENA ญ ;ญ Mahoney & Kaktus - (C) E.A.S. 1990 ญ ;ญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญญ
mt_init:lea mt_data,a0 lea mt_mulu(pc),a1 move.l #mt_data+$c,d0 moveq #$1f,d1 moveq #$1e,d3 mt_lop4:move.l d0,(a1)+ add.l d3,d0 dbf d1,mt_lop4
lea $3b8(a0),a1 moveq #$7f,d0 moveq #0,d1 moveq #0,d2 mt_lop2:move.b (a1)+,d1 cmp.b d2,d1 ble.s mt_lop move.l d1,d2 mt_lop: dbf d0,mt_lop2 addq.w #1,d2
asl.l #8,d2 asl.l #2,d2 lea 4(a1,d2.l),a2 lea mt_samplestarts(pc),a1 add.w #$2a,a0 moveq #$1e,d0 mt_lop3:clr.l (a2) move.l a2,(a1)+ moveq #0,d1 move.b d1,2(a0) move.w (a0),d1 asl.l #1,d1 add.l d1,a2 add.l d3,a0 dbf d0,mt_lop3
move.l $78.w,mt_oldirq-mt_samplestarts-$7c(a1) or.b #2,$bfe001 move.b #6,mt_speed-mt_samplestarts-$7c(a1) moveq #0,d0 lea $dff000,a0 move.w d0,$a8(a0) move.w d0,$b8(a0) move.w d0,$c8(a0) move.w d0,$d8(a0) move.b d0,mt_songpos-mt_samplestarts-$7c(a1) move.b d0,mt_counter-mt_samplestarts-$7c(a1) move.w d0,mt_pattpos-mt_samplestarts-$7c(a1) rts
mt_end: moveq #0,d0 lea $dff000,a0 move.w d0,$a8(a0) move.w d0,$b8(a0) move.w d0,$c8(a0) move.w d0,$d8(a0) move.w #$f,$dff096 rts
mt_music: lea mt_data,a0 lea mt_voice1(pc),a4 addq.b #1,mt_counter-mt_voice1(a4) move.b mt_counter(pc),d0 cmp.b mt_speed(pc),d0 blt mt_nonew moveq #0,d0 move.b d0,mt_counter-mt_voice1(a4) move.w d0,mt_dmacon-mt_voice1(a4) lea mt_data,a0 lea $3b8(a0),a2 lea $43c(a0),a0
moveq #0,d1 move.b mt_songpos(pc),d0 move.b (a2,d0.w),d1 lsl.w #8,d1 lsl.w #2,d1 add.w mt_pattpos(pc),d1
lea $dff0a0,a5 lea mt_samplestarts-4(pc),a1 lea mt_playvoice(pc),a6 jsr (a6) addq.l #4,d1 lea $dff0b0,a5 lea mt_voice2(pc),a4 jsr (a6) addq.l #4,d1 lea $dff0c0,a5 lea mt_voice3(pc),a4 jsr (a6) addq.l #4,d1 lea $dff0d0,a5 lea mt_voice4(pc),a4 jsr (a6)
move.w mt_dmacon(pc),d0 beq.s mt_nodma
lea $bfd000,a3 move.b #$7f,$d00(a3) move.w #$2000,$dff09c move.w #$a000,$dff09a move.l #mt_irq1,$78.w moveq #0,d0 move.b d0,$e00(a3) move.b #$a8,$400(a3) move.b d0,$500(a3) or.w #$8000,mt_dmacon-mt_voice4(a4) move.b #$11,$e00(a3) move.b #$81,$d00(a3)
mt_nodma: add.w #$10,mt_pattpos-mt_voice4(a4) cmp.w #$400,mt_pattpos-mt_voice4(a4) bne.s mt_exit mt_next:clr.w mt_pattpos-mt_voice4(a4) clr.b mt_break-mt_voice4(a4) addq.b #1,mt_songpos-mt_voice4(a4) and.b #$7f,mt_songpos-mt_voice4(a4) move.b -2(a2),d0 cmp.b mt_songpos(pc),d0 bne.s mt_exit move.b -1(a2),mt_songpos-mt_voice4(a4) mt_exit:tst.b mt_break-mt_voice4(a4) bne.s mt_next rts
mt_nonew: lea $dff0a0,a5 lea mt_com(pc),a6 jsr (a6) lea mt_voice2(pc),a4 lea $dff0b0,a5 jsr (a6) lea mt_voice3(pc),a4 lea $dff0c0,a5 jsr (a6) lea mt_voice4(pc),a4 lea $dff0d0,a5 jsr (a6) tst.b mt_break-mt_voice4(a4) bne.s mt_next rts
mt_irq1:tst.b $bfdd00 move.w mt_dmacon(pc),$dff096 move.l #mt_irq2,$78.w move.w #$2000,$dff09c rte
mt_irq2:tst.b $bfdd00 movem.l a3/a4,-(a7) lea mt_voice1(pc),a4 lea $dff000,a3 move.l $a(a4),$a0(a3) move.w $e(a4),$a4(a3) move.l $a+$1c(a4),$b0(a3) move.w $e+$1c(a4),$b4(a3) move.l $a+$38(a4),$c0(a3) move.w $e+$38(a4),$c4(a3) move.l $a+$54(a4),$d0(a3) move.w $e+$54(a4),$d4(a3) movem.l (a7)+,a3/a4 move.b #0,$bfde00 move.b #$7f,$bfdd00 move.l mt_oldirq(pc),$78.w move.w #$2000,$dff09c move.w #$2000,$dff09a rte
mt_playvoice: move.l (a0,d1.l),(a4) moveq #0,d2 move.b 2(a4),d2 lsr.b #4,d2 move.b (a4),d0 and.b #$f0,d0 or.b d0,d2 beq mt_oldinstr
asl.w #2,d2 move.l (a1,d2.l),4(a4) move.l mt_mulu(pc,d2.w),a3 move.w (a3)+,8(a4) move.w (a3)+,$12(a4) move.l 4(a4),d0 moveq #0,d3 move.w (a3)+,d3 beq mt_noloop asl.w #1,d3 add.l d3,d0 move.l d0,$a(a4) move.w -2(a3),d0 add.w (a3),d0 move.w d0,8(a4) bra mt_hejaSverige
mt_mulu:blk.l $120,0
mt_noloop: add.l d3,d0 move.l d0,$a(a4) mt_hejaSverige: move.w (a3),$e(a4) move.w $12(a4),8(a5)
mt_oldinstr: move.w (a4),d3 and.w #$fff,d3 beq mt_com2 tst.w 8(a4) beq.s mt_stopsound move.b 2(a4),d0 and.b #$f,d0 cmp.b #5,d0 beq.s mt_setport cmp.b #3,d0 beq.s mt_setport
move.w d3,$10(a4) move.w $1a(a4),$dff096 clr.b $19(a4)
move.l 4(a4),(a5) move.w 8(a4),4(a5) move.w $10(a4),6(a5)
move.w $1a(a4),d0 or.w d0,mt_dmacon-mt_playvoice(a6) bra mt_com2
mt_stopsound: move.w $1a(a4),$dff096 bra mt_com2
mt_setport: move.w (a4),d2 and.w #$fff,d2 move.w d2,$16(a4) move.w $10(a4),d0 clr.b $14(a4) cmp.w d0,d2 beq.s mt_clrport bge mt_com2 move.b #1,$14(a4) bra mt_com2 mt_clrport: clr.w $16(a4) rts
mt_port:moveq #0,d0 move.b 3(a4),d2 beq.s mt_port2 move.b d2,$15(a4) move.b d0,3(a4) mt_port2: tst.w $16(a4) beq.s mt_rts move.b $15(a4),d0 tst.b $14(a4) bne.s mt_sub add.w d0,$10(a4) move.w $16(a4),d0 cmp.w $10(a4),d0 bgt.s mt_portok move.w $16(a4),$10(a4) clr.w $16(a4) mt_portok: move.w $10(a4),6(a5) mt_rts: rts
mt_sub: sub.w d0,$10(a4) move.w $16(a4),d0 cmp.w $10(a4),d0 blt.s mt_portok move.w $16(a4),$10(a4) clr.w $16(a4) move.w $10(a4),6(a5) rts
mt_sin: dc.b $00,$18,$31,$4a,$61,$78,$8d,$a1,$b4,$c5,$d4,$e0,$eb,$f4,$fa,$fd dc.b $ff,$fd,$fa,$f4,$eb,$e0,$d4,$c5,$b4,$a1,$8d,$78,$61,$4a,$31,$18
mt_vib: move.b $3(a4),d0 beq.s mt_vib2 move.b d0,$18(a4)
mt_vib2:move.b $19(a4),d0 lsr.w #2,d0 and.w #$1f,d0 moveq #0,d2 move.b mt_sin(pc,d0.w),d2 move.b $18(a4),d0 and.w #$f,d0 mulu d0,d2 lsr.w #7,d2 move.w $10(a4),d0 tst.b $19(a4) bmi.s mt_vibsub add.w d2,d0 bra.s mt_vib3 mt_vibsub: sub.w d2,d0 mt_vib3:move.w d0,6(a5) move.b $18(a4),d0 lsr.w #2,d0 and.w #$3c,d0 add.b d0,$19(a4) rts
mt_arplist: dc.b 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1
mt_arp: moveq #0,d0 move.b mt_counter(pc),d0 move.b mt_arplist(pc,d0.w),d0 beq.s mt_normper cmp.b #2,d0 beq.s mt_arp2 mt_arp1:move.b 3(a4),d0 lsr.w #4,d0 bra.s mt_arpdo mt_arp2:move.b 3(a4),d0 and.w #$f,d0 mt_arpdo: asl.w #1,d0 move.w $10(a4),d1 lea mt_periods(pc),a0 mt_arp3:cmp.w (a0)+,d1 blt.s mt_arp3 move.w -2(a0,d0.w),6(a5) rts
mt_normper: move.w $10(a4),6(a5) rts
mt_com: move.w 2(a4),d0 and.w #$fff,d0 beq.s mt_normper move.b 2(a4),d0 and.b #$f,d0 beq.s mt_arp cmp.b #6,d0 beq.s mt_volvib cmp.b #4,d0 beq mt_vib cmp.b #5,d0 beq.s mt_volport cmp.b #3,d0 beq mt_port cmp.b #1,d0 beq.s mt_portup cmp.b #2,d0 beq.s mt_portdown move.w $10(a4),6(a5) cmp.b #$a,d0 beq.s mt_volslide rts
mt_portup: moveq #0,d0 move.b 3(a4),d0 sub.w d0,$10(a4) move.w $10(a4),d0 cmp.w #$71,d0 bpl.s mt_portup2 move.w #$71,$10(a4) mt_portup2: move.w $10(a4),6(a5) rts
mt_portdown: moveq #0,d0 move.b 3(a4),d0 add.w d0,$10(a4) move.w $10(a4),d0 cmp.w #$358,d0 bmi.s mt_portdown2 move.w #$358,$10(a4) mt_portdown2: move.w $10(a4),6(a5) rts
mt_volvib: bsr mt_vib2 bra.s mt_volslide mt_volport: bsr mt_port2
mt_volslide: moveq #0,d0 move.b 3(a4),d0 lsr.b #4,d0 beq.s mt_vol3 add.b d0,$13(a4) cmp.b #$40,$13(a4) bmi.s mt_vol2 move.b #$40,$13(a4) mt_vol2:move.w $12(a4),8(a5) rts
mt_vol3:move.b 3(a4),d0 and.b #$f,d0 sub.b d0,$13(a4) bpl.s mt_vol4 clr.b $13(a4) mt_vol4:move.w $12(a4),8(a5) rts
mt_com2:move.b 2(a4),d0 and.b #$f,d0 beq mt_rts cmp.b #$e,d0 beq.s mt_filter cmp.b #$d,d0 beq.s mt_pattbreak cmp.b #$b,d0 beq.s mt_songjmp cmp.b #$c,d0 beq.s mt_setvol cmp.b #$f,d0 beq.s mt_setspeed rts
mt_filter: move.b 3(a4),d0 and.b #1,d0 asl.b #1,d0 and.b #$fd,$bfe001 or.b d0,$bfe001 rts
mt_pattbreak: move.b #1,mt_break-mt_playvoice(a6) rts
mt_songjmp: move.b #1,mt_break-mt_playvoice(a6) move.b 3(a4),d0 subq.b #1,d0 move.b d0,mt_songpos-mt_playvoice(a6) rts
mt_setvol: cmp.b #$40,3(a4) bls.s mt_sv2 move.b #$40,3(a4) mt_sv2: moveq #0,d0 move.b 3(a4),d0 move.b d0,$13(a4) move.w d0,8(a5) rts
mt_setspeed: moveq #0,d0 move.b 3(a4),d0 cmp.b #$1f,d0 bls.s mt_sp2 moveq #$1f,d0 mt_sp2: tst.w d0 bne.s mt_sp3 moveq #1,d0 mt_sp3: move.b d0,mt_speed-mt_playvoice(a6) rts
mt_periods: dc.w $0358,$0328,$02fa,$02d0,$02a6,$0280,$025c,$023a,$021a,$01fc,$01e0 dc.w $01c5,$01ac,$0194,$017d,$0168,$0153,$0140,$012e,$011d,$010d,$00fe dc.w $00f0,$00e2,$00d6,$00ca,$00be,$00b4,$00aa,$00a0,$0097,$008f,$0087 dc.w $007f,$0078,$0071,$0000
mt_speed: dc.b 6 mt_counter: dc.b 0 mt_pattpos: dc.w 0 mt_songpos: dc.b 0 mt_break: dc.b 0 mt_dmacon: dc.w 0 mt_samplestarts:blk.l $1f,0 mt_voice1: blk.w 13,0 dc.w 1 mt_voice2: blk.w 13,0 dc.w 2 mt_voice3: blk.w 13,0 dc.w 4 mt_voice4: blk.w 13,0 dc.w 8 mt_oldirq: dc.l 0
|
Ambient
Member |
Photon got a tutorial on youtube how to get set playing a mod with the P61 playroutine, the player tutorial. :)
|
ZEROblue
Member |
I would also recommend using The Player 6.1, and you can build it with vasm using the devpac compatibility mode, but if you want to get this replayer working then you need to preserve registers D2-D7/A2-A6 on all calls to the player, this is what the Amiga M68K ABI specifies and what VBCC expects from external functions.
You also have to fix mt_init, mt_music, mt_irq1, and mt_irq2 so they take the vector base into account when setting the level 6 interrupt vector.
|
sdw
Member |
Ambient: Yes, i saw that there was a tutorial, but that was using AsmOne and an Amiga.native mod-to-p61 converter, I'd like to keep my toolchain on Windows for cross-development.
ZEROblue: I think I have the register-preservation correct, all functions are declared with stuff like this: __regsused("d0/d1/d2/d3/d4/d5/d6/d7/a0/a1/a2/a3/a4/a5/a6") void mod_play(); (The mod-play then does the jsr to mt_music) Perhaps it is the vector base stuff that you touch upon that is the problem, that bit goes a bit above my head.
But for now I'll do one more attempt to get P61 player compiled and working from VBCC/VASM, as it seems to be the preferred solution.
|
noname
Member |
IIRC regsused is not enough for the compiler to satisfy the calling convention. I just always saved registers d2-d7 and a2-a6 in an ASM function that gets called from C and restored them before rts. That always worked.
|
sdw
Member |
noname: thanks for the tip, I did an attempt at that, but it made no difference. Also, I call a lot of my own asm-functions that uses all kind of registers from C, and everything works just fine, it's just that damn tracker-replayer that messes it up. Well, other than that I have spent many, many hours now trying to get P61play to work. And I have made at least "some" progress. If I just take the entire sample code from P61Play and put that into a single C function that I call, it works. So my main program looks like this: void main() { PlayP61Module(); }
And then the entire assembler source from the P61 replayer example source is in an assembler subroutine that gets called, so it sets up the system, plays music, waits for mouseclick and the brings everything down again, and returns. However, what I rally want to do is this: void main() { setup(); part1(); part2(); ... bringdown() }
Where setup initializes everything in the system, and bringdown restores the system, and between that I can run my demo code. This works absolutely fine if I just do my own stuff, but as soon as I add the P61player stuff in the setup (I'm using the CIA-timer method), it doesn't work. I've tried two methods: 1) Keep the working setup/bringdown code I already have, copy relevant parts to start playing P61 into startup. 2) Try to split the P61 example source code in two and use that as setup/bringdown. Neither 1 nor 2 works, at all... If I use method 1, the music doesn't play. If I use method 2, the music plays but I can't get any graphics on screen, and the system isn't restored properly. I think the problem is that I have absolutely no clue what is needed in the startup and bringdown parts, and which IRQ this and DMA that and what strange calls to -(somenumber)a6 is the right ones. Yeah, I guess I really should learn all that, but I am much more interested in actually coding demos, not doing framework/system OS stuff. I'll give it a few more days of trying, and if I don't have any luck I guess I'll head back to the 8-bit machines, where things generally seem a bit simpler! :)
|
sdw
Member |
Alright, some progress! By modifying the code from P61 example to not use any stack related stuff at all, and remove some stuff from my main code that apparently was touching the IRQ/DMA setup my "split P61 example it into two"-method seems to *almost* work now. Music plays, graphics is shown, and most of the time you can quit to system OK. Sometimes it still seems to hang on exit though. I wonder if people will be upset if my little demo/intro hangs their Amiga on exit occasionally..? ;)
|
sdw
Member |
Well, I take that back, it turns out that the code is completely and utterly fucked, adding and removing lines of code from the end of the program can affect whether the player works or not, eventhough the code is not even running. So it seems like whether things works or not at the moment depends on exactly where certain code happens to end up. Something (either P61 player, or the code generated by VBCC) seems to be writing somewhere it shouldn't. I give up.
|
ZEROblue
Member |
Does this example work?
http://pastebin.com/f676pKVT
|
sdw
Member |
Thanks for the support ZEROblue! I couldn't get that to build (it was refering some P61Player.i that I didn't have, and when I removed that I had soem undefined varables).
HOWEVER!!! I *think* I actually have something that works now. By combining some of my "old" setup/bringdown code with the IRQ-setup stuff from the P61player example, it seems to work! Yay!
|
sdw
Member |
Here's the end result:
http://www.pouet.net/prod.php?which=67673
Unfortunately some notes didn't sound *quite* right in P61, but we suspect it's because Mr.Death did the tune in a "Protracker-compatible" mode in a PC-tracker and that in fact did not end up being 100% compatible.
|
Angry Retired Bastard
Member |
I think it turned out nicely and the different bob patterns provided enough variation to keep it interesting while reading the text. :) The music *did* sound a bit off, as you mentioned. I'd recommend testing the unpacked mod in protracker during development and then investigate further whenever P61 sounds different.
|
Jazzcat
Member |
Confirming. Music sounded out of tune at times (especially at 0:08).
|
wasp
Member |
Without having seen the actual mod, it sounds like the 3-command isn't set properly. A higher value would probably fix it. I tried to gather more information in Mr. Death's compomod from Gubbdata, but the error isn't there, or at least not as obvious. A classic 0 command error is there however, when exceeding B-3 with the 00C command, but I digress. The tune(s) are great as well as the intro. Well done!
|
|
|