Jump to content
IGNORED

Web Pokey


mrk

Recommended Posts

4 minutes ago, ivop said:

SAP-R has no notion of RMT command 7. It's just a write to AUDCTL. If RMT2LZSS were to intercept such combination, and does something else, that is not part of the SAP-R standard. Even though I was proposing such non-standard extensions earlier, after the feedback, I changed my mind back to needing a new type (either R2 or Q) if we want SKCTL/STIMER support. Luckily STEREO and FASTPLAY are already part of type R.

Yeah don't mind me there, that was irrelevant anyway :D

That was only thoughts about how to use that idea combined to that theoretical SAP format.

  • Like 1
Link to comment
Share on other sites

1 minute ago, VinsCool said:

Yeah don't mind me there, that was irrelevant anyway :D

That was only thoughts about how to use that idea combined to that theoretical SAP format.

Yes. What RMT2LZSS does, and what is encoded in the RMT file, can be anything you agree on. But that is not related to SAP-R or its theoretical successor :)

  • Like 1
Link to comment
Share on other sites

1 hour ago, VinsCool said:

Is it still SAP-R only currently? :) 

 

It is another web-pokey example - RMT song player (only vanilla v1.28 now, but supporting all these patches should also be possible)

 

Edited by mrk
  • Like 3
Link to comment
Share on other sites

Few RMT 1.28 example songs ;)30minutes.rmt ->link<-
4tk35.rmt ->link<-
astrosphere.rmt ->link<-
bazalt.rmt ->link<-
hightide.rmt ->link<-
ilusia.rmt ->link<-
m4700rk4.rmt ->link<-
naue.rmt ->link<-
shorty_noises.rmt ->link<-
sunset_on_the_moon.rmt ->link<-
thrust.rmt ->link<-

examples/audctl.rmt ->link<-
examples/bassandnoise.rmt ->link<-
examples/humblebee.rmt ->link<-
examples/likeac64.rmt ->link<-
examples/multiecho.rmt ->link<-
examples/speedchanges.rmt ->link<-
examples/trackloops.rmt ->link<-
examples/volumeonly.rmt ->link<-

kjmann/actrsr1-3ch.rmt ->link<-
kjmann/actrsr1.rmt ->link<-
kjmann/actrsr1-stereo.rmt ->link<-
kjmann/AXELF.rmt ->link<-
kjmann/axk8.rmt ->link<-
kjmann/baby_elephant_walk.rmt ->link<-
kjmann/battle_march.rmt ->link<-
kjmann/Battle_Squadron.rmt ->link<-
kjmann/Battle_Squadron-stereo.rmt ->link<-
kjmann/BE_store.rmt ->link<-
kjmann/bmaster1-4ch.rmt ->link<-
kjmann/bmaster1.rmt ->link<-
kjmann/bmaster1-stereo.rmt ->link<-
kjmann/bubble_bobble.rmt ->link<-
kjmann/crockett.rmt ->link<-
kjmann/cybernoid_II.rmt ->link<-
kjmann/Duke_Nuke'Em.rmt ->link<-
kjmann/elite-mono1.rmt ->link<-
kjmann/elite-stereo.rmt ->link<-
kjmann/everybreath.rmt ->link<-
kjmann/Final_Fantasy.rmt ->link<-
kjmann/frogger.rmt ->link<-
kjmann/Hybris.rmt ->link<-
kjmann/mm3.rmt ->link<-
kjmann/mm3-stereo.rmt ->link<-
kjmann/mule-remix4ch.rmt ->link<-
kjmann/mule.rmt ->link<-
kjmann/obliterator-mono.rmt ->link<-
kjmann/obliterator-stereo.rmt ->link<-
kjmann/outrun/last_wave.rmt ->link<-
kjmann/outrun/magi-mono.rmt ->link<-
kjmann/outrun_medley.rmt ->link<-
kjmann/outrun/OR_Magi-stereo.rmt ->link<-
kjmann/outrun/passing_breeze-mono.rmt ->link<-
kjmann/outrun/passing_breeze-stereo.rmt ->link<-
kjmann/outrun/splash_wave-mono.rmt ->link<-
kjmann/outrun/splash_wave-stereo.rmt ->link<-
kjmann/popcorn2-16bit.rmt ->link<-
kjmann/rtype.rmt ->link<-
kjmann/Shadows.rmt ->link<-
kjmann/shot.rmt ->link<-
kjmann/skidrow.rmt ->link<-
kjmann/smb2.rmt ->link<-
kjmann/SPH_Main16.rmt ->link<-
kjmann/stardust.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Mono3ch_Bonus.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Mono3ch_Sng1.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Mono3ch_Sng2.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Mono3ch_Sng3.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Mono4ch_Sng1.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Mono_Title.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Stereo_Sng1.rmt ->link<-
kjmann/Tempest/Tempest_Xtrm-Stereo_Title.rmt ->link<-
kjmann/toobin.rmt ->link<-
kjmann/toobin_title.rmt ->link<-
kjmann/trans_Atlantic.rmt ->link<-
kjmann/unveiled.rmt ->link<-

lisu/funny.rmt ->link<-
lisu/gerappaa.rmt ->link<-
lisu/kurczak.rmt ->link<-
lisu/przyrada.rmt ->link<-
lisu/wyjasnijmy_to_sobie.rmt ->link<-

miker/7_gates_of_jambala.rmt ->link<-
miker/acidjazzed_evening.rmt ->link<-
miker/astaroth.rmt ->link<-
miker/bomb_jack.rmt ->link<-
miker/disturbance.rmt ->link<-
miker/easter_chickens.rmt ->link<-
miker/enchanted_lands.rmt ->link<-
miker/flimbo.rmt ->link<-
miker/flowers_mania.rmt ->link<-
miker/ghosts_n_goblins.rmt ->link<-
miker/jetboy.rmt ->link<-
miker/logical_3.rmt ->link<-
miker/menace_song.rmt ->link<-
miker/my_first_one_in_rmt.rmt ->link<-
miker/tempest2000_blue_level.rmt ->link<-
miker/the_last_ninja_2_central_park.rmt ->link<-
miker/torvak_level_2.rmt ->link<-
miker/tyrian_zanac5.rmt ->link<-
miker/wings_of_death_lv2.rmt ->link<-

nilsfeske/delight.rmt ->link<-
nilsfeske/nothing.rmt ->link<-
nilsfeske/takeoff.rmt ->link<-

nooly/amelie.rmt ->link<-
nooly/aoki.rmt ->link<-
nooly/summer.rmt ->link<-

pg/against_time.rmt ->link<-
pg/brainless.rmt ->link<-
pg/deflektor.rmt ->link<-
pg/devils.rmt ->link<-
pg/gpc.rmt ->link<-
pg/hammastahna.rmt ->link<-
pg/happy_sundays.rmt ->link<-
pg/jozin_z_bazin.rmt ->link<-
pg/kaviar.rmt ->link<-
pg/krakout.rmt ->link<-
pg/lcd3cd3.rmt ->link<-
pg/radixex.rmt ->link<-
pg/somewhere.rmt ->link<-
pg/stardust_memories.rmt ->link<-
pg/strangled_mind.rmt ->link<-
pg/summerdays.rmt ->link<-
pg/vietnamska_mise.rmt ->link<-
pg/xmasmix.rmt ->link<-

raster/3d.rmt ->link<-
raster/aspir332.rmt ->link<-
raster/astro4road.rmt ->link<-
raster/aurora_m.rmt ->link<-
raster/aurora_s.rmt ->link<-
raster/basix.rmt ->link<-
raster/cervi2.rmt ->link<-
raster/cubico.rmt ->link<-
raster/delta.rmt ->link<-
raster/first.rmt ->link<-
raster/gearup.rmt ->link<-
raster/gemx.rmt ->link<-
raster/glu.rmt ->link<-
raster/hexxagon.rmt ->link<-
raster/horror.rmt ->link<-
raster/imsure.rmt ->link<-
raster/indianajones4.rmt ->link<-
raster/itdoesnt.rmt ->link<-
raster/l45tm1nut3.rmt ->link<-
raster/mab.rmt ->link<-
raster/nopromis.rmt ->link<-
raster/paulthep.rmt ->link<-
raster/satellit.rmt ->link<-
raster/threeht.rmt ->link<-
raster/timett.rmt ->link<-
raster/turrican2_rev2m.rmt ->link<-
raster/turrican2_rev2s.rmt ->link<-
raster/whoknows.rmt ->link<-

sack_cosine/commando.rmt ->link<-
sack_cosine/freedom.rmt ->link<-
sack_cosine/maynoaise.rmt ->link<-
sack_cosine/monty.rmt ->link<-
sack_cosine/parallax.rmt ->link<-
sack_cosine/plasticpop.rmt ->link<-
sack_cosine/smells.rmt ->link<-

tatqoo/anmen3_stereo.rmt ->link<-
tatqoo/byzex.rmt ->link<-
tatqoo/deluxe8ch.rmt ->link<-
tatqoo/forgotten_low.rmt ->link<-
tatqoo/garydenise.rmt ->link<-
tatqoo/grtfun.rmt ->link<-
tatqoo/monday.rmt ->link<-
tatqoo/ninjas.rmt ->link<-
tatqoo/oldschool.rmt ->link<-
tatqoo/ramaja.rmt ->link<-
tatqoo/thermostat7.rmt ->link<-
tatqoo/white_lamp.rmt ->link<-

Edited by mrk
sorted
  • Like 3
  • Thanks 2
Link to comment
Share on other sites

this is so much fun lol

I also spent an hour trying to just mimick 1 of my patches for Distortion 2 AUDCTL trigger... I am not very smart lol

Edit: I just realised I recorded the screen with an incorrect crop... welp. It shows as much as necessary anyway, but sadly the Console tracker view is not there as a result... my bad lol

Edited by VinsCool
I'm very unsmart
  • Like 2
Link to comment
Share on other sites

Had another little playaround, using the latest commit version, combined to the few experiments I was doing.

Got most of my own tables working and picking up as expected (well sorta, I fail to find how to actually use the correct channels and combined AUDCTL registers, but that's probably just my very limited experience in javascript hehe).

 

Works very well for sure! :D 

Noticeably choppier than yesterday for some reason, but it's probably just my computer, lol

  • Like 3
Link to comment
Share on other sites

5 hours ago, VinsCool said:

Got most of my own tables working and picking up as expected (well sorta, I fail to find how to actually use the correct channels and combined AUDCTL registers, but that's probably just my very limited experience in javascript hehe).

Great! I would suggest making github fork of https://github.com/mrk-its/web-rmt and pushing your changes there - this way it will be easy to create PR and maybe merge changes upstream :)

 

Why so exotic sampleRate? Some sync issues?

 

 

Edited by mrk
  • Like 1
Link to comment
Share on other sites

12 hours ago, mrk said:

Great! I would suggest making github fork of https://github.com/mrk-its/web-rmt and pushing your changes there - this way it will be easy to create PR and maybe merge changes upstream :)

Yeah I was going to do this once I was able to get what I wanted to work :)

 

12 hours ago, mrk said:

Why so exotic sampleRate? Some sync issues?

Tuning reasons. I couldn't find how to have divisions using decimal numbers so using the nearest whole numbers for it was the best compromise I found, not sure if this was related to the slowdowns I experienced yesterday however.

 

Something else I wanted to do was to try adding a quick PAL and NTSC toggle from index.html for the same reason.

Link to comment
Share on other sites

8 minutes ago, mrk said:

 

changing this value to 60 https://github.com/mrk-its/web-rmt/blob/main/rmt.js#L459 should do the trick, I can add method `setFrameRate()` for changing fps `on the fly`

Yep this was exactly what I was doing, switch between 50 and 60 when I was playing with it :)

Adding a setFrameRate() would make it even easier, it's pretty much what I wanted to do as well, haha.

 

btw I've forked the repos a bit earlier, I edited rmt.js for now but there is some experimental stuff involving the other files that I have not sent to github yet, the joy of being on and off the pc due to job stuff :D 

Link to comment
Share on other sites

21 minutes ago, VinsCool said:

Yep this was exactly what I was doing, switch between 50 and 60 when I was playing with it :)

Adding a setFrameRate() would make it even easier, it's pretty much what I wanted to do as well, haha.

Here it is:

1850036437_Screenshotfrom2021-10-0423-21-42.thumb.png.88bb2f7c49aba946fe721fda6219dae1.png

it works on the fly, without reloading

 

Edited by mrk
  • Thanks 1
Link to comment
Share on other sites

8 minutes ago, mrk said:

Here it is:

1850036437_Screenshotfrom2021-10-0423-21-42.thumb.png.88bb2f7c49aba946fe721fda6219dae1.png

it works on the fly, without reloading

 

Awesome!

Had troubles too get localhost pick up some changes sometime, so this will come very handy!

 

Thanks a lot, you're fast!

I was off for a moment and come back to see you did it already, haha :D

 

Link to comment
Share on other sites

I'm getting a bit frustrated so I think I can ask here for now.

What is the best way to pick up the pokey register values in memory for comparison purposes?

I couldn't find how to actually grab the AUDCTL register value, the one that is sent to the POKEY.

The only thing I was getting was... very inconsistent, sometime, working, sometime, not even the value I wanted.

 

Been trying to get something to work but I've been stuck with this for a few hours now, I feel stupid, as if I were a horse with a carrot hanging on a stick taunting me, and I couldn't reach it, lol

One of my friends has been trying to help me there, and none of us were able to figure it out.

I hate having to ask something that is probably obvious but I'm frustrated, especially since I did eventually find a way in 6502 ASM, despite the limitations of itself ? 

 

[Edit] My friend told me about an interesting observation.

Is it correct that the way AUDCTL is handled in the rmt.js player is from an OR operation on each ones of them in sequential order, starting from 0 with the first channel, which is then checked every player call?

I was wondering because the way I remember the 6502 code operating, the combined AUDCTL was processed all at once after instruments were all initialised, from which the value can be read in memory and re-used for the next call (I have labeled this a 1 frame lag effect for that reason).

Not a big deal in itself but that may explain why I would get different outputs between channels, despite using the same player.getAudctl(pokey_idx) number each time.

If this is indeed what is mostly going on, then I may have wasted my time on something that was designed a little differently than what the original 6502 code was doing, oops :P

 

Speaking of which, I was able to make a mockup of the tables I wanted to use based on the AUDCTL (since now I know my theory was technically correct, I just executed it with an incorrect assumption in mind), as well as implement my hijacked RMT Command 7 into the mix (which was using the instrument.audtl), so that's some more things to experiment later today.

 

I also wanted to apologise if I am being wrong with anything I experimented so far, I am entirely new to programming into a different language right now, so it's a matter of learning the bare minimum of as well.

 

Speaking of rmt.js, I think there may be an error in the instruments processing, specifically, the notes/frequencies tables part, they seem to ignore the +- mode, so doing certain effects gets interpreted incorrectly, but it's very minor in my opinion, just worth mentioning ?

 

Overall, things work incredibly well with the most recent version I think!

I did not notice horrible slowdowns, or dropped frames to be as bad as they were 2 days ago, during my tests before I went to sleep :)

 

It is a lot of fun to see progress! I really like the built in oscilloscope now ?

 

Edited by VinsCool
  • Like 1
Link to comment
Share on other sites

5 hours ago, VinsCool said:

[Edit] My friend told me about an interesting observation.

Is it correct that the way AUDCTL is handled in the rmt.js player is from an OR operation on each ones of them in sequential order, starting from 0 with the first channel, which is then checked every player call?

I was wondering because the way I remember the 6502 code operating, the combined AUDCTL was processed all at once after instruments were all initialised, from which the value can be read in memory and re-used for the next call (I have labeled this a 1 frame lag effect for that reason).

Ha, taking a look on it, on start I want to be 100% compatible with original RMT player, so I definitely want to mimic the same behavior. 

Quote

Speaking of which, I was able to make a mockup of the tables I wanted to use based on the AUDCTL (since now I know my theory was technically correct, I just executed it with an incorrect assumption in mind), as well as implement my hijacked RMT Command 7 into the mix (which was using the instrument.audtl), so that's some more things to experiment later today.

Great!

Quote

Speaking of rmt.js, I think there may be an error in the instruments processing, specifically, the notes/frequencies tables part, they seem to ignore the +- mode, so doing certain effects gets interpreted incorrectly, but it's very minor in my opinion, just worth mentioning ?

Thanks, I'll also take a look on that, I probably forgot about implementing this +- mode :) 

EDIT: @tatqoo let me recently know that his song is played incorrectly: https://mrk.sed.pl/web-pokey/examples/rmt-player/#https://atari.ha.sed.pl/songs/tatqoo/oldschool.rmt (position 38 / 01 - pure tones played instead of drums) - and it seems it is because of lack of this += mode implementation, kudos for noticing that! 

 

 

Edited by mrk
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Awesome! Thanks for the fix.

 

Right now I'm not having a good time with javascript.

I'm feeling stupid to fail to literally copy a value from 1 spot to another.

Been wasting like 2 hours of my afternoon on this and I'm really frustrated.

I know I don't have a lot of programming experience, but I have had much less troubles figuring out stuff in 6502 ASM, so either I'm out of this world or javascript was invented to be the most counter-intuitive possible, lol ?

Link to comment
Share on other sites

1 minute ago, VinsCool said:

Awesome! Thanks for the fix.

 

Right now I'm not having a good time with javascript.

I'm feeling stupid to fail to literally copy a value from 1 spot to another.

Been wasting like 2 hours of my afternoon on this and I'm really frustrated.

I know I don't have a lot of programming experience, but I have had much less troubles figuring out stuff in 6502 ASM, so either I'm out of this world or javascript was invented to be the most counter-intuitive possible, lol ?

Be patient, it will click finally  ;)

My code is probably over-engineered a bit - maybe whole RMTTune object is not necessary and everything should be implemented directly in RMTPlayer.

 

 

 

  • Thanks 1
Link to comment
Share on other sites

9 hours ago, VinsCool said:

[Edit] My friend told me about an interesting observation.

Is it correct that the way AUDCTL is handled in the rmt.js player is from an OR operation on each ones of them in sequential order, starting from 0 with the first channel, which is then checked every player call?
I was wondering because the way I remember the 6502 code operating, the combined AUDCTL was processed all at once after instruments were all initialised, from which the value can be read in memory and re-used for the next call (I have labeled this a 1 frame lag effect for that reason).

Ok, I took a look again on player assembly:

rmt_play
rmt_p0
    // update pokey registers computed in previous frame (rmt_play call)
	jsr SetPokey

    // do the rmt stuff and compute pokey registers

rmt_p4
	lda trackn_audctl+0
	ora trackn_audctl+1
	ora trackn_audctl+2
	ora trackn_audctl+3
	tax
	stx v_audctl

    // apply filters / BASS16 stuff and update X register (audctl value) if necessary

    stx v_audctl
    ...
    rts


SetPokey
	ldy #$ff
v_audctl equ *-1
    ...
	sty $d208
    ret

 

So you are right, there is a one frame delay - rmt_play starts with setting pokey registers to values computed in previous frame. And this is for a reason: this way pokey registers are always set in very precise points of time (exactly on start of each frame, independently of number of cycles of rmt_play routine). But audclt is always reseted in each frame (at rmt_p4 label), so I think I'm doing very similar thing in rmt.js.
I'm sending pokey regs to pokey backend directly after computing all they values, but it should not matter because registers are timestamped and also will be applied (by pokey backend) in very precise point of time (after short latency period)

 

Edited by mrk
  • Like 1
Link to comment
Share on other sites

3 minutes ago, mrk said:

Ok, I took a look again on player assembly:


rmt_play
rmt_p0
    // update pokey registers computed in previous frame (rmt_play call)
	jsr SetPokey

    // do the rmt stuff and compute pokey registers

rmt_p4
	lda trackn_audctl+0
	ora trackn_audctl+1
	ora trackn_audctl+2
	ora trackn_audctl+3
	tax
	stx v_audctl

    // apply filters / BASS16 stuff and update X register (audctl value) if necessary

    stx v_audctl
    ...
    rts


SetPokey
	ldy #$ff
v_audctl equ *-1
    ...
	sty $d208
    ret

 

So you are right, there is a one frame delay - rmt_play starts with setting pokey registers to values computed in previous frame. And this is for a reason: this way pokey registers are always set in very precise points of time (exactly on start of each frame, independently of number of cycles of rmt_play routine). But audclt is always reseted in each frame (at rmt_p4 label), so I think I'm doing very similar thing in rmt.js.
I'm sending pokey regs to pokey backend directly after computing all they values, but it should not matter because registers are timestamped and also will be applied in very precise point of time (after short latency period)

 

Yeah this makes sense, I still do think of ways to work around this for my own patch, but it's a big puzzle haha

Now speaking of rmt.js, this is precisely where I am stuck.

 

I am trying grab what is sent to the POKEY at the end of a player call, I can find where to get the value as a whole, but I fail to make a copy of its value somewhere in memory.

The reason I wanted to do this was to replicate the behaviour of my RMT patch (ie the 1 frame delay AUDCTL instrument freqtable pickup), but I just couldn't get it working at all, and it's pretty embarrassing to say the least lol

 

from what I noticed, rmt.js does it progressively, instead of the rmt_p4 successive ORAs, it would be 1 channel at the time, then reset to 0 each new play.

So what I could observe was channel 0 will always give a 0, but the 4th channel would have most of the AUDCTL bits except the postplay values that seem to only be added after all channels were processed, which was also the same behaviour from the original rmtplayr.

At the end, the output is exactly the same like you said, since they were all written at once, and technically the AUDCTL was not needed anywhere else in this normal setup.

My own patched player does rely on the AUDCTL for the very purpose of loading frequencies tables at the right places at the right time (*1 frame late at worst).

 

Anyway, I haven't been able to just find something left over in memory, and I haven't yet found how to do it manually either, haha ?

My understanding of javascript is very poor, so if you could help me with copying the "combined" audctls values that are sent into the POKEY to another memory location as well, I could fetch them as early as the frequency tables switch/case during the next frame for the use I wanted to make with them.

It would be much appreciated, I am very clueless about this stuff, but on the bright side, I did play a bunch of tunes with what is currently available and it works really nicely :D 

 

Link to comment
Share on other sites

29 minutes ago, VinsCool said:

Anyway, I haven't been able to just find something left over in memory, and I haven't yet found how to do it manually either, haha ?

My understanding of javascript is very poor, so if you could help me with copying the "combined" audctls values that are sent into the POKEY to another memory location as well, I could fetch them as early as the frequency tables switch/case during the next frame for the use I wanted to make with them.

 

Something like:

diff --git a/rmt.js b/rmt.js
index 450e396..8641736 100644
--- a/rmt.js
+++ b/rmt.js
@@ -626,6 +626,8 @@ export class RMTPlayer {
                 this.channelTone[i].postPlay(this, i < 4 ? prev_audctl : prev_audctl_r)
             }
         }
+        this.savedAudCtl = [this.getPokeyAudctl(0), this.getPokeyAudctl(1)]
+
         this.sendRegs(this.pokeyRegs)
     }
 

or for mono only simply: 

this.savedAudCtl = this.getPokeyAudctl(0)

??? This way it will be stored in player property and available all the time

 

EDIT:

or simply do your stuff at very begin of step() method, before Audctl is zeroed (this.getPokeyAudctl() should return correct value there)

 

 

 

 

Edited by mrk
  • Thanks 1
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...