P
PyBoy5mo ago
Sas2k

Save states not functioning properly when sound flag is used

Hello, I've been testing out Pyboy with Pokemon Crystal, and was using the --sound flag to enable the sound. I used Z to store the save state which it did. But when I came back around and tried reloading it with the --sound flag. the sound was gone and an error was present
14 Replies
Sas2k
Sas2kOP5mo ago
OSError: exception: access violation reading 0x0000016DFCE50000
Exception ignored in: 'pyboy.core.sound.Sound.enqueue_sound'
Traceback (most recent call last):
File "C:\Users\+++++\AppData\Local\Programs\Python\Python312\Lib\site-packages\pyboy\__main__.py", line 172, in main
while pyboy.tick():
^^^^^^^^^^^^
OSError: exception: access violation reading 0x0000016DFCE50000
OSError: exception: access violation reading 0x0000016DFCE50000
Exception ignored in: 'pyboy.core.sound.Sound.enqueue_sound'
Traceback (most recent call last):
File "C:\Users\+++++\AppData\Local\Programs\Python\Python312\Lib\site-packages\pyboy\__main__.py", line 172, in main
while pyboy.tick():
^^^^^^^^^^^^
OSError: exception: access violation reading 0x0000016DFCE50000
the library seems to be trying reference an invalid pointer/file
Bækalfen
Bækalfen5mo ago
I've tried a few things now, and I cannot seem to replicate it on Mac and Linux. I can see you might be on Windows? But that should of course also work And it works fine if you don't load a saved state? Could you run PyBoy with --log-level=DEBUG and paste the whole output from the terminal?
Sas2k
Sas2kOP5mo ago
yeah, it works when I run an entirely new instance
pyboy.core.cartridge.cartridge DEBUG Loading ROM file: 2097152 bytes
pyboy.core.cartridge.cartridge DEBUG Cartridge type: 0x10 - MBC3, SRAM, Battery, RTC
pyboy.core.cartridge.cartridge DEBUG Cartridge size: 128 ROM banks of 16KB, 4 RAM banks of 8KB
pyboy.core.cartridge.base_mbc DEBUG RAM loaded.
pyboy.core.mb DEBUG Cartridge started:
MBC class: MBC3
Filename: C:\Users\++\Downloads\Pokemon - Crystal Version (USA).gbc.ram
Game name: PM_CRYSTAL
GB Color: False
Cartridge type: 0x10
Number of ROM banks: 128
Active ROM bank: 1
Number of RAM banks: 16
Active RAM bank: 0
Battery: True
RTC: True
pyboy.core.mb DEBUG Cartridge type auto-detected to CGB
pyboy.core.lcd DEBUG Starting CGB renderer
pyboy.plugins.base_plugin DEBUG WindowSDL2 initialization
pyboy.plugins.base_plugin DEBUG Scale: x3 (480, 432)
pyboy.core.mb DEBUG Loading state...
pyboy.core.mb DEBUG State version: 12
pyboy.core.cpu DEBUG State loaded:
A: 01, F: 20, B: D6, C: 01, D: 44, E: 5F, HL: D150, SP: C0E3, PC: 045F ()
Opcode: [HALT] Interrupts - IME: True, IE: 00001111, IF: 00000001
LCD Intr.: 0, LY:0, LYC:0
Timer Intr.: 0
halted:True, interrupt_queued:False, stopped:False

pyboy.core.cartridge.base_mbc DEBUG RAM loaded.
pyboy.core.mb DEBUG State loaded.
OSError: exception: access violation reading 0x0000016AD47B9000
Exception ignored in: 'pyboy.core.sound.Sound.enqueue_sound'
Traceback (most recent call last):
File "C:\Users\++\AppData\Local\Programs\Python\Python312\Lib\site-packages\pyboy\__main__.py", line 172, in main
while pyboy.tick():
^^^^^^^^^^^^
OSError: exception: access violation reading 0x0000016AD47B900
pyboy.core.cartridge.cartridge DEBUG Loading ROM file: 2097152 bytes
pyboy.core.cartridge.cartridge DEBUG Cartridge type: 0x10 - MBC3, SRAM, Battery, RTC
pyboy.core.cartridge.cartridge DEBUG Cartridge size: 128 ROM banks of 16KB, 4 RAM banks of 8KB
pyboy.core.cartridge.base_mbc DEBUG RAM loaded.
pyboy.core.mb DEBUG Cartridge started:
MBC class: MBC3
Filename: C:\Users\++\Downloads\Pokemon - Crystal Version (USA).gbc.ram
Game name: PM_CRYSTAL
GB Color: False
Cartridge type: 0x10
Number of ROM banks: 128
Active ROM bank: 1
Number of RAM banks: 16
Active RAM bank: 0
Battery: True
RTC: True
pyboy.core.mb DEBUG Cartridge type auto-detected to CGB
pyboy.core.lcd DEBUG Starting CGB renderer
pyboy.plugins.base_plugin DEBUG WindowSDL2 initialization
pyboy.plugins.base_plugin DEBUG Scale: x3 (480, 432)
pyboy.core.mb DEBUG Loading state...
pyboy.core.mb DEBUG State version: 12
pyboy.core.cpu DEBUG State loaded:
A: 01, F: 20, B: D6, C: 01, D: 44, E: 5F, HL: D150, SP: C0E3, PC: 045F ()
Opcode: [HALT] Interrupts - IME: True, IE: 00001111, IF: 00000001
LCD Intr.: 0, LY:0, LYC:0
Timer Intr.: 0
halted:True, interrupt_queued:False, stopped:False

pyboy.core.cartridge.base_mbc DEBUG RAM loaded.
pyboy.core.mb DEBUG State loaded.
OSError: exception: access violation reading 0x0000016AD47B9000
Exception ignored in: 'pyboy.core.sound.Sound.enqueue_sound'
Traceback (most recent call last):
File "C:\Users\++\AppData\Local\Programs\Python\Python312\Lib\site-packages\pyboy\__main__.py", line 172, in main
while pyboy.tick():
^^^^^^^^^^^^
OSError: exception: access violation reading 0x0000016AD47B900
Here's the debug statement
Bækalfen
Bækalfen5mo ago
Nothing out of the ordinary Could you try cloning the repo and inside the repo do python3 -m pyboy ... as you did before. It should give some more details
Sas2k
Sas2kOP5mo ago
ah I'll try that, in a moment also, the sound compatibility is still in beta right?
Bækalfen
Bækalfen5mo ago
It's still in beta, but it shouldn't crash. Just not be perfectly accurate, and sometimes stutter a little
Sas2k
Sas2kOP5mo ago
yeah
krs013
krs0135mo ago
I might have an idea what's happening here On load state, the cpu restores its cycle counter to what it was before, causing the sound device to try to process more samples than it's supposed to.
def tick(self, _cycles, double_speed):
cycles = _cycles - self.last_cycles
self.last_cycles = _cycles

if double_speed:
self.clock += cycles // 2
else:
self.clock += cycles
def tick(self, _cycles, double_speed):
cycles = _cycles - self.last_cycles
self.last_cycles = _cycles

if double_speed:
self.clock += cycles // 2
else:
self.clock += cycles
self.last_cycles is initialized to 0 instead of the value of pyboy.mb.cpu.cycles (which probably isn't loaded when the Sound object is made anyway) to make matters worse, there's this:
nsamples = self.clock // self.sampleclocks

for i in range(min(2048, nsamples)):
...
nsamples = self.clock // self.sampleclocks

for i in range(min(2048, nsamples)):
...
I'm not sure why that's min instead of max for the number of samples to generate--I think we've gone back and forth on it before, but whatever the reason is, if nsamples is greater than 2048, it will overrun the sample buffer. Then the access violation is caused in Sound.enqueue_sound(self):
sdl2.SDL_QueueAudio(self.device, self.audiobuffer_p, 2 * nsamples)
sdl2.SDL_QueueAudio(self.device, self.audiobuffer_p, 2 * nsamples)
when SDL_QueueAudio(...) tries to access a values indexed off of self.audiobuffer_p that is outside of the buffer and possibly allocated memory. I don't know when I'll have time to revisit --sound 🥲 but for now it should be sufficient to change that min to max on line 171, and test to make sure that doesn't break anything.
Bækalfen
Bækalfen5mo ago
I think the min is right. It bounds it to be ≤2048
krs013
krs0135mo ago
Oh right, right. I think I messed it up the first time too haha Been a long week Shoot, guess I don't have anything to offer here then
Bækalfen
Bækalfen5mo ago
I also get confused with min/max 😅
BET Adsorption
BET Adsorption4mo ago
Best support thread ever
Bækalfen
Bækalfen4mo ago
I’ll be waiting for your PR I think I've inadvertently fixed this in the next version. I can only reproduce it on master
Sas2k
Sas2kOP3mo ago
ah nice, good job!

Did you find this page helpful?