Jump to content
IGNORED

RMT Hacking Ideas and Progress


Recommended Posts

Preliminary support of additional 16-bit tables, based on the original 'tabbegandistor' map code, so they can be added really easily between modes without any side effect over other distortions :) 
Here, I used a Distortion A and Distortion E 16-bit table, within the same instrument, all based entirely on the AUDCTL itself instead of the hijacked Distortion 6 method used in the original rmtplayr code.

 

 

  • Like 4
Link to comment
Share on other sites

This isn't directly a RMT update, but since the Visual Player is tightly bond to it, it's worth sharing here as well.
Updating the POKEY registers during VBI then buffering the next frame just after makes a big difference over the sound stability.
Each subsequent playbacks will sound almost identical now.

 

Now, I am aware that is not exactly the best situation if a VBI interrupts a play, while the player runs out of region, or several times a frame, but I'm already working on that :P 
Regardless, it's still quite a nice improvement just for the stability, I wonder why this was not done earlier, because other than some issues that can be worked around, this seems to be a much more optimal setup, in my opinion :D 

 

It will play mostly fine in NTSC, but now there skipped frames will be a little more obvious.
Hopefully I can help this later :) 

Ode to Schnism.obx

  • Like 3
Link to comment
Share on other sites

One more idea, I'm currently persueing.

Quote

As for Pokey, here are some options:

6. link fake sa_pokey.dll with libatari800, which runs a simple assembly loop that copies a shadow Pokey (including SKCTL) to the emulated Pokey. Retrieve audio through the libatari800 API and feed it back to Rmt.exe.

 

I totally forgot about libatari800, which is fairly new I think?

 

Working on it now. I was already able to cross-compile libatari800.a for win32 with minor reshuffling of header includes (all errors were related to these freaking Windows types).

Now let's see what happens if I try to run emulated frames from within sa_pokey.dll :) Fun thing, two 6502 emulators will be running at the same time then :P

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

Observations so far:

 

- atari800, and hence libatari800, has no command line option to enable stereo pokey

 

Fixed that by loading a local atari800.cfg file (not a dot file), which enables stereo and all that jazz. 44.1kHz 8-bit stereo audio. That's what Rmt.exe wants. And NTSC and PAL can be switched there, too.

 

- libatari800 has no API call for a certain amount of cycles, just libatari800_next_frame (input_template_t * input), which processes a full PAL or NTSC frame. Which is a problem if you run a double, triple, or quadruple speed player. I added some code to the fake sa_pokey DLL to see if I can detect at which speed we are playing, and yes we can :) The average sndn value moves along with the replay speed, so we can detect at what speed we are playing. Works for both PAL and NTSC. Now we need a small mirror.xex program running on libatari800 to copy a shadow pokey to the "real" emulated pokey, and afterwards retrieve the audio data. That mirror.xex needs to be fed timer data somehow, so it knows when to update pokey for up to four times per call to libatari800_next_frame().

 

Edit: sorry for rambling, but this helps to get things clear in my head :) Sort of related to https://en.wikipedia.org/wiki/Rubber_duck_debugging

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

2 hours ago, ivop said:

Edit: sorry for rambling, but this helps to get things clear in my head :) Sort of related to https://en.wikipedia.org/wiki/Rubber_duck_debugging

That was literally how I learned how to do some things at all from zero, and rambling about what was going on ultimately came to a moment of "wait a second there, I KNOW!"

 

Not later than yesterday while I was rambling about a buffered registers update theory, I figured out how to get it to work then how to work around a potential issue that was confirmed being present... Fun time haha

 

Now the only piece of puzzle is to find a way to consistently know when a play was interrupted by the vbi to then skip a setpokey call, finish the play, run setpokey as soon as possible, then loopwait for the next play, and so on, regardless of the moment a player was called, or how many times a frame it was called.

 

I was just rambling about it on a discord server with some friends and as I was writing, things started to make sense and basically just solved itself from breaking down into explanation of what the code did or was intended to do lol

 

Sort of related but a very similar logic could then be used for hijacked tables and infos display on the screen for the visual player, which may gain a significant boost in execution if I don't have to pretty much do the same checks in 2 different places lol

 

Like the vbi interrupting a play, it's not to know when it happens, but if something was interrupted, so adding some flags in memory would do the trick possibly.

A lot like the Distortion 2 idea but backwards, haha.

 

 

 

Rambles aside, I'm excited to see your ideas in action there! :D

 

 

  • Like 1
Link to comment
Share on other sites

5 hours ago, VinsCool said:

Rambles aside, I'm excited to see your ideas in action there! :D

Maybe tomorrow. I have a lot of the plumbing in place right now (see github), at least for 1x speed playing, but I need some sleep now ?

 

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

https://github.com/ivop/rmt-sa-libs/tree/main/real/sa_pokey_libatari800

 

It's alive! But not as we want it :(

 

RMT is really a complete and utter mess as timing is concerned:

 

Pokey_Process: 1520 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1484 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1498 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1518 bytes requested
Pokey_Process: added 1470 bytes to temp_buffer
Pokey_Process: 1476 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1494 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1514 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1472 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
Pokey_Process: 1492 bytes requested
Pokey_Process: added 1472 bytes to temp_buffer
 

The 1472/1470 value is exactly what you would expect running an NTSC system, but look at the values RMT requests for each frame :(

 

Looking further. Perhaps I made a mistake somewhere else. It produces sound, but way distorted, even though you can make out which song it is. PAL is the same.

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

IT WORKS! :D

 

New day, fresh eyes, found bug in two minutes :) temp_buffer was of the wrong type, so everything went haywire. If you want to test it out:

 

https://github.com/ivop/rmt-sa-libs/tree/main/real/sa_pokey_libatari800

 

Copy both cfg files, libgcc_s_sjlj-1.dll, mirror.xex and sa_pokey.dll in a test directory with Rmt.exe etc... and run Rmt.exe

 

Pokey_Initialise: argc=0
Pokey_SoundInit: freq17=1789790 playback_freq=44100 num_pokeys=2
Pokey_SoundInit: NTSC detected

Using Atari800 config file: atari800-ntsc.cfg
Created by Atari 800 Emulator, Version 4.2.0

Pokey_SoundInit: libatari800_init succeeded
Pokey_SoundInit: reboot with mirror.xex
Pokey_SoundInit: libatari800_reboot_with_file succeeded
Pokey_SoundInit: libatari800_next_frame succeeded
Pokey_SoundInit: libatari800_next_frame succeeded
Pokey_SoundInit: libatari800_next_frame succeeded
Pokey_SoundInit: libatari800_next_frame succeeded
Pokey_SoundInit: libatari800_get_sound_frequency = 44100
Pokey_SoundInit: libatari800_get_num_sound_channels = 2
Pokey_SoundInit: libatari800_get_sound_sample_size = 8-bit audio
Pokey_SoundInit: libatari800_get_fps = 59.922745
Pokey_SoundInit: copied memory pointer
C6502_Initialise: memory is zeroed

C6502_JSR: tracker memory changed (0)
loc 3182  cur: 54  prev: 00
loc 3183  cur: 52  prev: 00
loc 3184  cur: 41  prev: 00
loc 3185  cur: 43  prev: 00
loc 3186  cur: 4b  prev: 00
loc 3187  cur: 45  prev: 00
loc 3188  cur: 52  prev: 00
loc 3189  cur: 20  prev: 00
loc 35fc  cur: 60  prev: 00
C6502_JSR: TRACKER tag found, load tracker.obx
load_xex: load tracker.obx
load_xex: load 3182 - 3a59
load_xex: injected 2264 bytes
 

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

Oh fuck this is great!

Can't wait to give it a try.

10 minutes ago, ivop said:

New day, fresh eyes, found bug in two minutes :)

This has been my kind of mood since Monday honestly LOL

 

Spend hours to get stuck, find the solution in the 5 minutes following a new day opening the file lmao

  • Like 1
Link to comment
Share on other sites

35 minutes ago, VinsCool said:

Oh fuck this is great!

Can't wait to give it a try.

There are still some limitations though.

 

Only single speed. Fixing that will be difficult because atari800 only emulates full frames, but not impossible, I think.

 

When switching between PAL and NTSC, you need to restart Rmt.exe so the right atari800-*.cfg file is loaded. I plan on automatic switching, which I think can be done, but is also cumbersome.

 

35 minutes ago, VinsCool said:

This has been my kind of mood since Monday honestly LOL

 

Spend hours to get stuck, find the solution in the 5 minutes following a new day opening the file lmao

Yes, sometimes it really helps to take a pause. I did that yesterday evening by playing some SLAP bass, but the pause wasn't long enough ;)

 

I'll probably continue working on this tomorrow, as I have other stuff to do, too :)

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, ivop said:

There are still some limitations though.

 

Only single speed. Fixing that will be difficult because atari800 only emulates full frames, but not impossible, I think.

Awesome!
Multispeed could possibly work with some additional code in the intermediate gate between the emulator and RMT. 

If I am not mistaken about it, the RMT Visualizer code has a pretty simple initialisation sequence, it calls for rmt_init, which will fetch the module speed and store it into memory, and the loop routine will then handle the number of calls per frame.

I believe RMT itself works mostly the same way, so multispeed setting may be possible to toggle on the fly that way :) 

1 hour ago, ivop said:

When switching between PAL and NTSC, you need to restart Rmt.exe so the right atari800-*.cfg file is loaded. I plan on automatic switching, which I think can be done, but is also cumbersome.

Not a problem for me :) Just a little slower.

1 hour ago, ivop said:

Yes, sometimes it really helps to take a pause. I did that yesterday evening by playing some SLAP bass, but the pause wasn't long enough ;)

 

I'll probably continue working on this tomorrow, as I have other stuff to do, too :)

That's fine!

You've done some really awesome stuff for the possibilities of the music tracker.
You deserve a nice break :D 

Thanks again for this, I'll give it a shot now that I am at my computer again, with some coffee

I also planned to work on some other stuff too (some of which I actually owe to rensoup still ? ), and I've got my Visualizer graphic code rewrite still in the work and that one will definitely be a case of "4 hours wasted breaking stuff, 2 minutes fixing it"! hahaha :D 

I'll post in this thread again with my observations and experiments, I love when I can break things by doing things that were not expected, :P 

  • Like 1
Link to comment
Share on other sites

31 minutes ago, VinsCool said:

Awesome!
Multispeed could possibly work with some additional code in the intermediate gate between the emulator and RMT. 

If I am not mistaken about it, the RMT Visualizer code has a pretty simple initialisation sequence, it calls for rmt_init, which will fetch the module speed and store it into memory, and the loop routine will then handle the number of calls per frame.

I believe RMT itself works mostly the same way, so multispeed setting may be possible to toggle on the fly that way :) 

I think the problem is that sa_pokey has no way to call rmt_init. It runs in a completely different environment. Similar with PAL/NTSC. There are two places where I can detect the TV-mode:

 

1. During Pokey_SoundInit(), provided you have a patched PAL Rmt.exe. You either receive 1789790 (NTSC) or 1773447 (PAL) as the freq17 variable. Depending on that, either atari800-ntsc.cfg or atari800-pal.cfg is loaded. This function is only called once, hence the need to restart after changing it.

 

2. During Pokey_Process(). Even though the timing of Rmt is an utter mess, you can detect PAL or NTSC by the sndn variable. They can be classified in buckets and one can detect whether it is PAL/NTSC and 1x/2x/3x/4x speed.

 

To make multispeed work, we need to know the TV-mode and the replay speed, and hence eight different mirror.xex binaries, and have Pokey_PutByte() put the bytes in the right shadow pokey before it gets mirrored. Everytime we detect a change, we either restart the emulator with the other cfg file, or we reboot with a new mirror.xex.

 

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

1 hour ago, VinsCool said:

Not a problem for me :) Just a little slower.

Oops, this was not right. You need to run either the standard Rmt.exe binary, which is 1789790 i.e. NTSC, or a patched Rmt.exe binary which feeds the library 1773447. Otherwise the resampling is not correct.

 

Hopefully, this will be fixed in the future where sa_pokey.dll (libatari800 version) constantly monitors the TV-Mode and replay rate. Restart emulator when TV-Mode changes (new cfg file), and in all cases reboot with a new mirror.xex

  • Thanks 1
Link to comment
Share on other sites

8 minutes ago, ivop said:

Oops, this was not right. You need to run either the standard Rmt.exe binary, which is 1789790 i.e. NTSC, or a patched Rmt.exe binary which feeds the library 1773447. Otherwise the resampling is not correct.

 

Hopefully, this will be fixed in the future where sa_pokey.dll (libatari800 version) constantly monitors the TV-Mode and replay rate. Restart emulator when TV-Mode changes (new cfg file), and in all cases reboot with a new mirror.xex

Ahh so I was not crazy about the pitch being off haha
Good to know it was not me :D 

  • Haha 1
Link to comment
Share on other sites

I love the Unix command line :D

 

wine Rmt.exe 2>&1 | grep Pokey_Process | tail -n 300 | sort | uniq > ntsc-1.txt

 

And run it eight times for all combinations, and with different output files obviously :) None of them overlap!

 

pal-1:      1708    - 1778
ntsc-1:     1466    - 1528
pal-2:      880     - 886
ntsc-2:     730     - 766
pal-3:      568     - 592
ntsc-3:     488     - 510
pal-4:      440     - 442
ntsc-4:     366     - 382

 

When switching modes, either PAL/NTSC, or 1x/2x/3x/4x, there are sndn values that are outside of these ranges, because Rmt slowly catches up (hence the tail -n 300, about the last 5-6 seconds). But if in doubt (i.e. outside one of the aforementioned ranges), just do nothing. In a few frames, it settles down and can be detected.

 

Edit: and we are going to totally ignore the freq17 value, because it makes no sense :) 

Edited by ivop
clarify tail
  • Like 2
Link to comment
Share on other sites

22 minutes ago, ivop said:

Haha! But you managed to get some sound out of it?

Ohhhh totally! I even got the Two-Tone filter working through the Atari800 bridge!!
It was a little odd to setup, because my own rmtplayr code did not work for some reason, but I managed to work around it by changing the SKCTL values of 03 to 8B in the mirror.s, the only for now is that it's permanently enabled

I thought I could hijack that by writing my own values in the shadow registers I'd EQU to the exact same addresses, but that also failed, so either I am doing it wrong, or something specifically made it so that value can never be changed, ahaha

 

So manually writing #$8B to either $D20F/$D21F or $820F/$821F from the player itself with the exact same code I used in my visual player failed unfortunately :P 

I even tried to literally NOP the code writing into SKCTL but that failed, which surprised me there! I wonder if something else is related to that (not that this is a priority, and the code is there so I will eventually figure it out haha)
Kinda sad because that was precisely the very first thing I wanted to test after I did run a bunch of tunes with no problem so far :D 

Link to comment
Share on other sites

3 minutes ago, VinsCool said:

Kinda sad because that was precisely the very first thing I wanted to test after I did run a bunch of tunes with no problem so far :D 

Well, that's at least a good thing IMHO :) I only had a few test tunes which did not really used the more advanced features. One of them was a single pure tone :)

 

I'll look into the SKCTL thing. It defaults to $03, but Pokey_PutByte() should overwrite it. At least, that's what I want it to do  :)

 

  • Thanks 1
Link to comment
Share on other sites

1 minute ago, ivop said:

Well, that's at least a good thing IMHO :) I only had a few test tunes which did not really used the more advanced features. One of them was a single pure tone :)

 

I'll look into the SKCTL thing. It defaults to $03, but Pokey_PutByte() should overwrite it. At least, that's what I want it to do  :)

 

Ahh cool!
In my opinion it could proceed exactly the same as the main AUDx registers, since I was originally writing to it using a hijacked Distortion 6
if it defaults to loading the #3 that would explain why I was able to overwrite them to #$8B but not actually "overwrite" them from the rmtplayr side :D 

Link to comment
Share on other sites

4 minutes ago, VinsCool said:

Ah yeah, and from what I could tell, I CANNOT edit anything yet?
There's just nothing happening.
I can load and play modules, however :P 

Oh, that's weird! I just checked again, and with RMT 1.28 with the TRACKER tag, my sa_c6502.dll and sa_pokey.dll (libatari800 version), I can edit whatever I want. Instruments, patterns, song data.

Link to comment
Share on other sites

2 minutes ago, ivop said:

Oh, that's weird! I just checked again, and with RMT 1.28 with the TRACKER tag, my sa_c6502.dll and sa_pokey.dll (libatari800 version), I can edit whatever I want. Instruments, patterns, song data.

Oh shit, I totally forgot about this ?
I was using the stripped 1.30 hack here, oops!

Now I need to see if anything different happens hahahaha

Link to comment
Share on other sites

5 minutes ago, VinsCool said:

Ahh cool!
In my opinion it could proceed exactly the same as the main AUDx registers, since I was originally writing to it using a hijacked Distortion 6
if it defaults to loading the #3 that would explain why I was able to overwrite them to #$8B but not actually "overwrite" them from the rmtplayr side :D 

Aah, I know. PutByte() to SKCTL is never done by Rmt.exe.

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