ilmenit Posted March 12, 2020 Share Posted March 12, 2020 (edited) Hi, I can stop the music for disk IO and play it again properly "from start", however considering very short time of disk IO (saving game) I'd like to fade music out (with global fade) and continue it after IO. Initially I thought that for "pausing" music in RMT (and to continue from the same place) it will be enough to: - disable my deferred vblank handler in which "jsr RASTERMUSICTRACKER+3" (rmt_play) is called - call rmt_silence which resets Pokey (lda #0, sta $d208, ldy #3, sty $d20f) [Make the disk IO here] And to continue after the disk IO: - call rmt_silence to reset Pokey - call SetPokey to initialize the other stuff (this one is also called by rmt_play at the beginning) - enable my vblank handler to continue playing the music It works in Altirra in different configs, however breaks on real Atari and leads to random sounds playing or even crashes in RMT code (which is self-modifying and writes jumps to middle of instructions) ? Any hints or experience how it should be done? [EDIT: Sorry, I just realized I did not post it in the Programming section where it should belong] Edited March 12, 2020 by ilmenit Quote Link to comment Share on other sites More sharing options...
shanti77 Posted March 13, 2020 Share Posted March 13, 2020 Maybe system change variable on page0. Quote Link to comment Share on other sites More sharing options...
Rybags Posted March 13, 2020 Share Posted March 13, 2020 It's been a while but yeah, I'd have thought you were doing the right thing. And agreed, possibly something's being corrupted in the meantime. Quote Link to comment Share on other sites More sharing options...
ilmenit Posted March 13, 2020 Author Share Posted March 13, 2020 I'll check first with write access breakpoints what is modifying zero page . Code of RMT is really hard to read due to these IFDEFs and even WUSDN IDE is not helping because collapsing sections does not work on it ? Quote Link to comment Share on other sites More sharing options...
ivop Posted March 13, 2020 Share Posted March 13, 2020 1 hour ago, ilmenit said: I'll check first with write access breakpoints what is modifying zero page . Code of RMT is really hard to read due to these IFDEFs and even WUSDN IDE is not helping because collapsing sections does not work on it ? Yeah, it's difficult to read, especially because there is nearly no indentation. I have been thinking about cleaning it up and converting it to mads, but well, so many things to do... 1 Quote Link to comment Share on other sites More sharing options...
R0ger Posted March 13, 2020 Share Posted March 13, 2020 (edited) It should work. SetPokey actually does nothing with RMT itself, it just sends the values computed in previous step into pokey. You don't need to call it, as you said, it's called anyway as first thing when calling rmt_play. You also don't need to call rmt_silence before starting again, that also only fills pokey, which you are going to do anyway in rmt_play. It must be something being changed outside RMT, most likely in zero page. Reading RMT source code won't help you I'm afraid. Make breakpoints in Altirra when you are stopping RMT, and then again when you are starting it up. Display RMT zero page variables in memory window, and run the code from first breakpoint to the second one. Memory window will show in red if some value was changed. Edited March 13, 2020 by R0ger 1 Quote Link to comment Share on other sites More sharing options...
ilmenit Posted March 13, 2020 Author Share Posted March 13, 2020 32 minutes ago, R0ger said: It should work. SetPokey actually does nothing with RMT itself, it just sends the values computed in previous step into pokey. You don't need to call it, as you said, it's called anyway as first thing when calling rmt_play. You also don't need to call rmt_silence before starting again, that also only fills pokey, which you are going to do anyway in rmt_play. You are correct SetPokey seems to be unnecessary. I checked and nothing is writing to zero page area of RMT. I will check if something is maybe writing to area where RMT data is stored, otherwise I have no other idea. Here it how it crashes: 47619:255: 77 | A=FF X=FF Y=03 (NV C) | 8403: 4C E9 85 L8403 JMP RMT_P0 ; to rmt_play = rmt_p0 + 47619:255: 80 | A=FF X=FF Y=03 (NV C) | 85E9: 20 37 87 RMT_P0 JSR SETPOKEY 47619:256: 56 | A=0F X=A4 Y=00 (NV C) | 85EC: CE 54 81 RMT_P2 DEC V_ASPEED 47619:256: 63 | A=0F X=A4 Y=00 ( V C) | 85EF: D0 12 BNE RMT_P3 47619:256: 67 | A=0F X=A4 Y=00 ( V C) | 8603: A9 82 RMT_P3 LDA #$82 47619:256: 69 | A=82 X=A4 Y=00 (NV C) | 8605: 85 D6 STA $D6 47619:256: 72 | A=82 X=A4 Y=00 (NV C) | 8607: A2 03 XTRACKS05SUB1 LDX #$03 47619:256: 74 | A=82 X=03 Y=00 ( V C) | 8609: BD 08 81 PP1 LDA TRACKN_INSTRHB,X ;$810B 47619:256: 78 | A=88 X=03 Y=00 (NV C) | 860C: F0 F2 BEQ GO_PPNEXT 47619:256: 80 | A=88 X=03 Y=00 (NV C) | 860E: 85 D4 STA FR0 47619:256: 83 | A=88 X=03 Y=00 (NV C) | 8610: BD 04 81 LDA TRACKN_INSTRDB,X ;$8107 47619:256: 87 | A=00 X=03 Y=00 ( V ZC) | 8613: 85 D3 STA NS 47619:256: 90 | A=00 X=03 Y=00 ( V ZC) | 8615: BC 0C 81 LDY TRACKN_INSTRIDX,X ;$810F 47619:256: 94 | A=00 X=03 Y=3D ( V C) | 8618: B1 D3 LDA (NS),Y ;$883D 47619:256: 99 | A=8B X=03 Y=3D (NV C) | 861A: 85 D9 STA REG1 47619:256:102 | A=8B X=03 Y=3D (NV C) | 861C: C8 INY 47619:256:104 | A=8B X=03 Y=3E ( V C) | 861D: B1 D3 LDA (NS),Y ;$883E 47619:256:109 | A=B5 X=03 Y=3E (NV C) | 861F: 85 DA STA REG2 47619:256:112 | A=B5 X=03 Y=3E (NV C) | 8621: C8 INY 47619:257: 0 | A=B5 X=03 Y=3F ( V C) | 8622: B1 D3 LDA (NS),Y ;$883F 47619:257: 5 | A=8B X=03 Y=3F (NV C) | 8624: 85 DB STA REG3 47619:257: 8 | A=8B X=03 Y=3F (NV C) | 8626: C8 INY 47619:257: 10 | A=8B X=03 Y=40 ( V C) | 8627: 98 TYA 47619:257: 12 | A=40 X=03 Y=40 ( V C) | 8628: DD 10 81 CMP TRACKN_INSTRLEN,X ;$8113 47619:257: 16 | A=40 X=03 Y=40 (NV ) | 862B: 90 0A BCC PP2 47619:257: 19 | A=40 X=03 Y=40 (NV ) | 8637: 9D 0C 81 PP2 STA TRACKN_INSTRIDX,X ;$810F 47619:257: 24 | A=40 X=03 Y=40 (NV ) | 863A: A5 D9 LDA REG1 47619:257: 28 | A=8B X=03 Y=40 (NV ) | 863C: 29 0F AND #$0F 47619:257: 31 | A=0B X=03 Y=40 ( V ) | 863E: 1D F4 80 ORA TRACKN_VOLUME,X ;$80F7 47619:257: 36 | A=5B X=03 Y=40 ( V ) | 8641: A8 TAY 47619:257: 39 | A=5B X=03 Y=5B ( V ) | 8642: B9 00 83 LDA VOLUMETAB,Y ;$835B 47619:257: 44 | A=04 X=03 Y=5B ( V ) | 8645: 85 DC STA TMP 47619:257: 48 | A=04 X=03 Y=5B ( V ) | 8647: A5 DA LDA REG2 47619:257: 52 | A=B5 X=03 Y=5B (NV ) | 8649: 29 0E AND #$0E 47619:257: 55 | A=04 X=03 Y=5B ( V ) | 864B: A8 TAY 47619:257: 58 | A=04 X=03 Y=04 ( V ) | 864C: B9 82 81 LDA TABBEGANDDISTOR,Y ;$8186 47619:257: 62 | A=80 X=03 Y=04 (NV ) | 864F: 85 D5 STA NR 47619:257: 65 | A=80 X=03 Y=04 (NV ) | 8651: A5 DC LDA TMP 47619:257: 68 | A=04 X=03 Y=04 ( V ) | 8653: 19 83 81 ORA $8183,Y ;$8187 47619:257: 72 | A=44 X=03 Y=04 ( V ) | 8656: 9D 50 81 STA TRACKN_AUDC,X ;$8153 47619:257: 77 | A=44 X=03 Y=04 ( V ) | 8659: BD 28 81 INSTRUMENTSEFFECTS LDA TRACKN_EFFDELAY,X ;$812B 47619:257: 81 | A=0C X=03 Y=04 ( V ) | 865C: F0 21 BEQ EI2 47619:257: 83 | A=0C X=03 Y=04 ( V ) | 865E: C9 01 CMP #$01 47619:257: 85 | A=0C X=03 Y=04 ( V C) | 8660: D0 1A BNE EI1 47619:257: 88 | A=0C X=03 Y=04 ( V C) | 867C: DE 28 81 EI1 DEC TRACKN_EFFDELAY,X ;$812B 47619:257: 95 | A=0C X=03 Y=04 ( V C) | 867F: BC 40 81 EI2 LDY TRACKN_TABLEEND,X ;$8143 47619:257: 99 | A=0C X=03 Y=52 ( V C) | 8682: C0 0D CPY #$0D 47619:257:101 | A=0C X=03 Y=52 ( V C) | 8684: 90 31 BCC EI3 47619:257:103 | A=0C X=03 Y=52 ( V C) | 8686: BD 48 81 LDA TRACKN_TABLESPEEDA,X ;$814B 47619:257:107 | A=3C X=03 Y=52 ( V C) | 8689: 10 26 BPL EI2F 47619:257:110 | A=3C X=03 Y=52 ( V C) | 86B1: 38 EI2F SEC 47619:257:112 | A=3C X=03 Y=52 ( V C) | 86B2: E9 01 SBC #$01 47619:258: 0 | A=3B X=03 Y=52 ( C) | 86B4: 9D 48 81 STA TRACKN_TABLESPEEDA,X ;$814B 47619:258: 5 | A=3B X=03 Y=52 ( C) | 86B7: BD 18 81 EI3 LDA TRACKN_INSTRREACHEND,X ;$811B 47619:258: 9 | A=80 X=03 Y=52 (N C) | 86BA: 10 1F BPL EI4 47619:258: 11 | A=80 X=03 Y=52 (N C) | 86BC: BD F4 80 LDA TRACKN_VOLUME,X ;$80F7 47619:258: 15 | A=50 X=03 Y=52 ( C) | 86BF: F0 1A BEQ EI4 47619:258: 17 | A=50 X=03 Y=52 ( C) | 86C1: DD 24 81 CMP TRACKN_VOLUMEMIN,X ;$8127 47619:258: 21 | A=50 X=03 Y=52 ( C) | 86C4: F0 15 BEQ EI4 47619:258: 23 | A=50 X=03 Y=52 ( C) | 86C6: 90 13 BCC EI4 47619:258: 26 | A=50 X=03 Y=52 ( C) | 86C8: A8 TAY 47619:258: 28 | A=50 X=03 Y=50 ( C) | 86C9: BD 20 81 LDA TRACKN_VOLUMESLIDEVALUE,X ;$8123 47619:258: 34 | A=84 X=03 Y=50 (N C) | 86CC: 18 CLC 47619:258: 36 | A=84 X=03 Y=50 (N ) | 86CD: 7D 1C 81 ADC TRACKN_VOLUMESLIDEDEPTH,X ;$811F 47619:258: 42 | A=85 X=03 Y=50 (N ) | 86D0: 9D 20 81 STA TRACKN_VOLUMESLIDEVALUE,X ;$8123 47619:258: 48 | A=85 X=03 Y=50 (N ) | 86D3: 90 06 BCC EI4 47619:258: 52 | A=85 X=03 Y=50 (N ) | 86DB: A9 00 EI4 LDA #$00 47619:258: 55 | A=00 X=03 Y=50 ( Z ) | 86DD: 85 DD STA FRQADDCMD2 47619:258: 59 | A=00 X=03 Y=50 ( Z ) | 86DF: A5 DA LDA REG2 ; there must be wrong value in REG2 47619:258: 62 | A=B5 X=03 Y=50 (N ) | 86E1: 29 70 AND #$70 47619:258: 64 | A=30 X=03 Y=50 ( ) | 86E3: 4A LSR 47619:258: 66 | A=18 X=03 Y=50 ( ) | 86E4: 4A LSR 47619:258: 68 | A=0C X=03 Y=50 ( ) | 86E5: 8D E9 86 STA $86E9 ; writes wrong value to BCC parameter 47619:258: 72 | A=0C X=03 Y=50 ( ) | 86E8: 90 0C JMX BCC $86F6 ; jumps to middle of instruction 47619:258: 75 | A=0C X=03 Y=50 ( ) | 86F6: DB 4C 23 L86F6 DCP $234C,Y ;$239C - and this is causing my crash Quote Link to comment Share on other sites More sharing options...
R0ger Posted March 13, 2020 Share Posted March 13, 2020 Interesting. I agree, Reg2 seems to be destroyed. First some context for the code .. Instrument table has record consisting of 3 bytes. During processing, current record is stored in reg1,reg2 and reg3. reg1 is 4+4 bits volume for left and right channel (doesn't matter if the song is in stereo or not). reg2 is for distortion + command. From top of my head I'm not sure about what bits exactly do what, but based on this code $70 mask is the command. reg3 is command argument. This part of code decodes the 'command' part from the instrument. It takes the command part of the reg2, and jumps based on the current command. The command part of the reg2 is $30, in other words command 3. lsr,lsr makes it 12. That can be good value or bad value depending on commands used in the song. If there were all commands used, after JMX label there would be jump table of 8 records: jmp xxx, nop. So JMX would jump 12 bytes ahead, and it would land in the table, on the JMP instruction. That is clearly not your case. So it seems the song you have does not use all possible commands (which is normal). IFDEFs will make the jump table shorter, and jumping 12 bytes ahead will land behind the jump table, possibly in the middle of instruction. In other words, reg2 contains command which should not be used in the song. OR the IFDEFs are wrong (I mean variables exported from RMT, which affect the IFDEFs). If the song plays correctly without your pause & continue, it means the IFDEFs are correct. Btw. Altirra can use memory write breakpoints, or you can use CPU history to find where reg2 was accessed. 2 Quote Link to comment Share on other sites More sharing options...
ilmenit Posted March 13, 2020 Author Share Posted March 13, 2020 Investigation continues... 1. I exported again the RMT file and for sure copy-pasted the stuff to rmt_feat.a65 2. I dumped the RMT module area from memory on crash and binary compared it with the stripped version on disk - they are equal. 3. I set write access breakpoints to: - zero page RMT area - RMT module area - RMT player area No breakpoint fired in between pause-disk IO-continue (!). Seems that RMT zp and RMT player are not modified out of RMT routines. 4. I dumped .pokey values on crash and except the first 4 lines (AUDF1-AUDF4), the other pokey values are equal situation when music is playing OK. AUDF1: 4c AUDC1: 00 Output: 1 (1320 cycles until fire) (passive: 2156 cycles) AUDF2: 4c AUDC2: 00 Output: 1 (1320 cycles until fire) (passive: 2156 cycles) AUDF3: cc AUDC3: a0 Output: 1 (1740 cycles until fire) (passive: 5740 cycles) AUDF4: 4c AUDC4: 00 Output: 1 (1376 cycles until fire) (passive: 2156 cycles) AUDCTL: 00, 17-bit poly, 64KHz SKCTL: 03 | recv ext | send ext | keyboard scan enabled | SERIN: C0 SEROUT: 84 (done) shift register 84 (0: done) IRQEN: c0, break key, keyboard IRQST: f7, sertrans ALLPOT: 00 5. I verified that PLAYER is compiled from the begin of the memory page as stated in the code Any other ideas what to check or what can be wrong? Quote Link to comment Share on other sites More sharing options...
R0ger Posted March 13, 2020 Share Posted March 13, 2020 (edited) The error is caused by wrong value of reg2. Check when the value gets there. Dump all writes to reg2, or try checking them using CPU history window. It is somewhat short though, like few frames. It most likely won't cover the whole IO operation. Does RMT work before the pause ? The RMT alignment is most important for freq tables. If the alignment was wrong, it would play wrong notes. But that's it (AFAIK). It wouldn't crash. Does it work if you just pause and restart, without the actual IO ? Or you can PM send me the code, (with LAB pls) I can take a look at it. I've been recently digging into RMT a lot, I think I would be able to find any RMT related problem. Edited March 13, 2020 by R0ger Quote Link to comment Share on other sites More sharing options...
shanti77 Posted March 13, 2020 Share Posted March 13, 2020 You must also remember , RMT use memory before PLAYER (PLAYER-$300) . Page0 variables can be set in different place. Quote Link to comment Share on other sites More sharing options...
ilmenit Posted March 14, 2020 Author Share Posted March 14, 2020 Thanks guys for your help! It allowed me to check all the potential things why RMT may not work and it seems that I have a "race condition" in the code. How? Interrupts. It seems that I was enabling VBI routine to continue playing the music and later I was "changing the music to other track" with rmt_init. Problem was that call to rmt_init was interrupted by VBI (with jsr rmt_play) which caused all this mess, therefore indeed there was nothing "externally" breaking the reg2 as all the changes were done withing RMT player. 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.