Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

raw ym registers dump #86

Open
cyberic99 opened this issue Mar 31, 2021 · 13 comments
Open

raw ym registers dump #86

cyberic99 opened this issue Mar 31, 2021 · 13 comments

Comments

@cyberic99
Copy link

Hello,

I'm trying to reuse some of your code for another project.

What I would like to achieve is a list of register dumps in the following format:
clock reg_number reg_value

I started playing with ym2txt, and at the end I added another Roll class in vis.py with a custom update() function.

But I wonder if there is a simpler way, for instance to have a callback that would be called on each register write.

Thank you

@combatopera
Copy link
Owner

Hi,

The Roll class supports visualising chip data that comes from any source not just ym files, so it may be one layer of indirection too many if your requirement is dumping ym files only.

I would try to use the YMOpen class directly. You should be able to instantiate it with a fake config object e.g. SimpleNamespace, and call start to actually load the file. Then try passing in a callback to the frames method. You can use trial and error to work out what the callback needs, in combination with searching for where chip is used in ymformat.py . It looks like you'll need an R array for the registers, and more when it comes to timer effects.

Let me know if you get stuck.

@cyberic99
Copy link
Author

Thanks for offering your help!

For now here is what I got:

from pym2149.ymformat import YMOpen
from types import SimpleNamespace
from pym2149.iface import Chip
from pym2149.reg import Reg

config = SimpleNamespace()
config.inpath = "bestpart.ym"
config.ignoreloop = True

class YMO(YMOpen):
    def __init__(self, config):
        super().__init__(config)

chip = Chip()
chip.R = tuple(Reg() for _ in range(16))

ymo = YMO(config)
ymo.start()
for frame in ymo.ym:
    for i, x in enumerate(frame.data):
        if 0xD != i or 255 != x:
            chip.R[i].value = x
            print(i, x)

With this, I can see the register values, great!

Thanks for your explainations.

I still miss the time information.

I suppose I have to call processtimerttls() from time to time?

I tried to test if the frame has an updatetimers attribute, but I never get any

Thx

@combatopera
Copy link
Owner

There are no explicit timestamps, each frame lasts 1/ymo.updaterate seconds.
Frame objects will have updatetimers attribute when your YM file version is at least 5.

@cyberic99
Copy link
Author

thank you very much.

Now I got can dump the registers and play them on a real ym2149, and it sounds correct.

However, I tried with a song containing digis. with ym2wav, I can hear the digis in the .wav.

Should they appear in the register dump too, or are they handled differently?

should effects be mixed with each frame?

@cyberic99
Copy link
Author

even when calling frame.applydata(chip) on each frame before reading the registers, I can´t hear the digis

Maybe the Chip itself is not initialized correctly?

@combatopera
Copy link
Owner

For timer effects such as digis you'll need to manipulate a volume register at audio frequency, on a real Atari this is done using an MFP timer interrupt.

@cyberic99
Copy link
Author

In fact I am sending the registers to a ym2149 chip wired with a teensy.

Is there a way to get the needed volume register changes and their clocks?

somehow, this has to be simulated somewhere in ym2wav, isn´t it?

@combatopera
Copy link
Owner

Here's the pym2149 code that implements digi drums: https://github.com/combatopera/pym2149/blob/trunk/pym2149/dac.py#L85
This simulates the effect of a timer interrupt on the chip during a frame, optimised for speed. The rtone is a virtual ym oscillator that samples the effect of an audio frequency MFP timer on a level register. When a digi drum is active we've preloaded a chunk of the 5-bit (scaled from 4-bit) sample data into rtone, and just copy it into the buffer for the frame.

If you're using a real ym, you'll need to get the teensy to manipulate a level register at audio frequency. I don't know whether it's performant or stable enough to do this and you'll have fun finding out.

Alternatively, you can cheat by not using the ym for digi drums. If you play them back as samples using modern hardware they should sound less noisy.

The data you need is written here: https://github.com/combatopera/pym2149/blob/trunk/pym2149/ymformat.py#L254
If you use real mfp.Timer objects in your chip you should be able to read out the sample frequency using timer.freq.value and the sample data will be in the timer.effect.value of type DigiDrumEffect.

If the above looks tough, that's because it is. Timer effects push the limits of what the ym can do.

@cyberic99
Copy link
Author

Hello @combatopera , thank you for your detailed answer.

I don't have much time to work on this right now, but I'll keep you updated.

If you're using a real ym, you'll need to get the teensy to manipulate a level register at audio frequency. I don't know whether it's performant or stable enough to do this and you'll have fun finding out.

yeah... you're right, it was fun to do, and... hard too ;-)

We can play some really heavy .sndh files already, look here for instance: https://www.youtube.com/watch?v=8CtrsLeX-0o

@combatopera
Copy link
Owner

awesome, thanks for the update. and thanks for the video!

@cyberic99
Copy link
Author

Glad you liked the video. And thanks to you for implementing some missing features in pym2149 ;-)
So now we have the choice between playing the drums on the ym2149, or... externally, on an amiga ;-)
But before that, I need to get/dump the sample data correctly!

@cyberic99
Copy link
Author

btw, sorry it is a bit oftopic. but your website is showing some errors right now ;-(

@combatopera
Copy link
Owner

yeah, my server died a few weeks ago and i'm gradually building a new one. i also moved house so right now i don't have as much time to work on the server as i'd like

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants