GithubHelp home page GithubHelp logo

Comments (7)

mvdnes avatar mvdnes commented on September 2, 2024

This can be done by hooking a SerialCallback to the serial module. Both sides transfer a byte at the same time.

In the current implementation, the transfer of data happens instantly. In a real gameboy, it would take several clock cycles. When implementing such a function, this might also be useful since you can keep the emulator running while waiting for the network.

from rboy.

greenfox1505 avatar greenfox1505 commented on September 2, 2024

I'm using rboy in Godot. My gameboys are pickup-able object and they update with they physics update. But they update 60 times per sec in order, not at the same time. I should re-implement that as simultaneous updates. The challenge will be multi threading that to be somewhat lockstep (so that no one Device gets too far ahead or behind any other Device it's connected to.

My object currently uses Device, and Device does not currently expose a pub read-to or write-to serial function. I suppose I could re-implement some of Device and give my struct a CPU instead.

from rboy.

greenfox1505 avatar greenfox1505 commented on September 2, 2024

mod cpu; is private. Device does not implement a way to interface with the Serial connection.

from rboy.

greenfox1505 avatar greenfox1505 commented on September 2, 2024

I think this is right? I'm not great with lifetimes yet, this will work, but I'm not sure it's the best way to handle this. And I'm only 60% that read address is correct.

impl Device {
...
    pub fn attach_serial_callback(&mut self, a:SerialCallback<'static>) {
        self.cpu.mmu.serial.set_callback(a);
    }

    pub fn write_serial_data(&mut self,data:u8)  {
        self.cpu.mmu.serial.wb(0xFF01,data)
    }

Let me know if there is anything I should change or if I can PR that as-is.

from rboy.

mvdnes avatar mvdnes commented on September 2, 2024

I do not think that the devices need to be in perfect sync. Normal gameboys probably would not be either. They do sync a clock for transferring data, but that is handled by the callback mechanism.

Using attach_serial_callback is a good idea. This does only work for callbacks with a 'static lifetime though. If that is enough then I am fine with this, otherwise we may need to rethink the Device::new function. With all the options currently a builder would maybe be a better idea.

I do not think write_serial_data should be exposed. In your current implementation, this will set the data to be transferred from the local Device, to the remote. I think you want it the other way around, which the callback is for.

from rboy.

greenfox1505 avatar greenfox1505 commented on September 2, 2024

You're right that they don't need to be "perfectly" in sync, but they should definitely be more in sync than I'm doing. I'm only updating them in order 60x per sec. Every single frame, they'll go one or two frame, 70k-140k cycles, out of sync before catching up. I think I need move my cycler to a separate thread that pushes all the Devices together.

The callback is reading from the Device, so the the other function should write to the Device, no? I want Device->Device communication, right? The callback doesn't include writeback or any kind of return, does it?

This is what I spun up for audio using mpsc::channel()s. I think 'static would be fine for serial callbacks.

struct GodotBoyAudio {
    pipe_in: Sender<Vec<(f32, f32)>>,
}
impl GodotBoyAudio {
    fn new(pipe_in: Sender<Vec<(f32, f32)>>) -> Self {
        Self { pipe_in }
    }
}

impl AudioPlayer for GodotBoyAudio {
    fn play(&mut self, left_channel: &[f32], right_channel: &[f32]) {
        let g: Vec<(f32, f32)> = left_channel
            .iter()
            .zip(right_channel.iter())
            .map(|(l, r)| (l.clone(), r.clone()))
            .collect();
        self.pipe_in.send(g).unwrap();
    }

    fn samples_rate(&self) -> u32 {
        44100
    }

    fn underflowed(&self) -> bool {
        true
    }
}

from rboy.

mvdnes avatar mvdnes commented on September 2, 2024

The callback is a function is a function that has an u8 argument that returns an Option.
The value put in the argument is the value that is send from the Device to the outside. If the return value from the function is a Some(u8), then that u8 is the value that will be sent from the outside to the Device.

from rboy.

Related Issues (10)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.