Jump to content
IGNORED

How to pause RMT for disk IO and continue from the same place?


ilmenit

Recommended Posts

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 by ilmenit
Link to comment
Share on other sites

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...

 

  • Like 1
Link to comment
Share on other sites

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 by R0ger
  • Like 1
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

 

  • Like 2
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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 by R0ger
Link to comment
Share on other sites

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.

  • Like 2
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...