@Wuerfel_21 said:
On one hand, it's a lot slower and simpler. On the other hand, C64 programmers are from a different plane of existence and have figured out how to glitch the VIC-II video chip into having features it was never intended to have. Normally the screen can only be scrolled 7 pixels back and forth and you always need to copy the tile and color maps around to get full smooth scrolling. Except when you write the vertical scroll register in just the right time window, the state machine in the video chip glitches and starts fetching tile data mid-scanline, which results in the addresses for subsequent lines being shifted by an amount depending on the exact cycle the write was done, allowing for smooth horizontal scrolling without copying the entire screen around. Which sounds like a demoscene effect, but Mayhem in Monsterland is a well-known commercial game that makes use of it. Though on some machines this corrupts the RAM. Very funny.
Wow. Seems like there's probably only one type smarter than demoscene coders and that is those who can fully emulate all the hardware tricks used by demoscene coders so their original code will still run perfectly. LOL
Can now override file to be loaded using argv. So you'd do something like loadp2 misoyume_lower.binary -a /sd/misoyume/smwu.sfc to load a specific file. Still has a hardcoded fallback. I guess this is a good stopgap so I can procrastinate on adding a menu.
ROM should now be appropriately mirrored across the address space (might not be correct for odd-sized ROMs)
Added (broken?) stub implementations for modes 2/4/6
Allow HDMA channels to be turned on mid-frame (mostly fixes Super Ghouls & Ghosts)
Make IRQ masking behave slightly less wrong (fixes Super Ghouls & Ghosts fully)
So I think I'm running out of easy problems. I wanted to use Tetris Attack as a test case for Mode 2 and Bust-A-Move for Mode 4, but it turns out both of these do not boot at all. Amazing. (Non-EDIT: While going through the compat list, I realized Bust-A-Move just takes forever to boot, like Demon's Crest) I added stub implementations for the missing modes that should just ignore OPT, but those don't seem to work properly, either (at least Mode 4 has broken BG2 graphics in Rock'n'Roll Racing).
So remaining avenues:
Fix BG2 in Mode 4 (????)
Debug games that don't boot at all or take a really long time
Implement OPT without a real test (maybe I can find a cromulent homebrew test file)
Debug corrupted graphics in Mario World and Zelda (these both are missing NVRAM - are they abusing NVRAM to bounce GFX?)
Implement NVRAM and/or HiROM (will increase lowest-level game compatiblity and surface many more issues, for better or worse)
optimize DMA transfer sources (still too slow)
implement CPU program queing (should fix timing crust present in all FastROM games to some extent)
Compat list as of alpha 07:
Game
Status
Bust-A-Move
Takes forever to start up, somewhat broken graphics, severe timing crust
Castlevania Dracula X
Ok, minor line glitches (-> Fast ROM timing crust)
Super Castlevania 4
OK?
Demon's Crest
Severe timing crust and takes forever to start up
F-Zero
OK
Jaki Crush
OK
Jurassic Park
OK? (this uses pseudo-hires mode)
Zelda: Link to the Past
Some graphics garbled, can't get ingame due to NVRAM
Cotton 100%
Black screen (used to get slightly further?)
Mega Man X
Takes forever to start. Otherwise no major issue?
Phalanx
Black screen
Plok
OK
Pocky & Rocky
garbled logo screens, works otherwise (minor timing issue on the "I am your adversary" text box)
Kiki Kaikai Nazo no Kuro Manto (japanese Pocky&Rocky)
OK (but why?)
Pocky & Rocky 2
Black screen after logos (this used to get further at some point?)
RPM Racing
Needs NVRAM, attract runs fine though (this uses Mode 5 512x448i graphics!)
Rock'n'Roll Racing
Some menus use buggy video modes, otherwise OK
Super Ghouls & Ghosts
OK
Super Mario All-Stars
Instant crash
Super Mario World
Minor garbled graphics
Super Metroid
Anti-Piracy tripped
Super Tetris 2 + Bombliss
Takes forever to start, can't get ingame (this would use overscan mode)
Tetris Attack
Black screen
Wild Guns
Crashes going ingame (this used to get further at some point?)
Oh, I figured out the graphics corruption for Mario World and Zelda. So basically, to save on ROM space, these games use a very simple compression wherein some graphics are stored with 3 bitplanes instead of 4. The missing bitplane is then set to a constant value when loading the graphics, such that it uses either the "left" or "right" half of palette RAM. Except, when setting the bitplane to 1, any otherwise transparent pixels have to be masked out. This is accomplished by some code using the otherwise rather gormless ORA [d] (opcode $07) instruction. So of course there was a typo in the opcode table and ORA (d) (normally opcode $12) was executed instead. Which is the same thing, but using the current data bank instead of fetching a third indirect byte from the direct page. Owie ouch.
Good thing with these graphics type bugs is you probably know right where to look to find them and can make a very good educated guess as to the problem right away given you've recently coded the graphics emulator and know what data controls what, plus you can see the effect directly on screen while it still runs etc. Some of the other bugs are gonna be quite a bit harder to figure out no doubt.
That one had me stumped quite a bit though. I did think it'd have to be a CPU-side problem, but wasn't 100% sure.
Also, figured out why my mode 4 stub didn't work. Actually a bug that affects all 8bpp rendering (except mode 7), I just didn't notice it before. Since the pixel data takes up the entire byte, the attribute data has to go to one of the other buffers. The compositing code expected it in BG4's buffer, but the rendering code put it in BG3's buffer. Ow.
Got it working! It turned out to be just a lame wall-wart: "5V, 2A" - yeah, maybe more like .2A...that's been running my Edge all this time shakes head
Tested F-Zero, SMW, Castlevania IV, Zelda...my results all line up with your table above. Here's a few others, just as possible points of interest (not complaining )
Bubsy: Accolade splash screen then nothing
Contra 3: Konami screen looks/sounds good. Some parts of the intro flicker. Makes it to the prepare for start screen and freezes
Lemmings: Plays fine, text or "status" line during the game flickers, as well as the top 10 or so lines, but good for the most part
Pilotwings: Right from the title screen, many garbled tiles. Some intermediate screens are okay-ish. When the light-plane gameplay starts, it immediately pulls hard right and sounds like it's at full throttle. The throttle indicator can be changed but nothing actually changes. Pretty heavily garbled screen here
Simcity: long delay (~1min+) before anything happens, but fine after that. Pretty solid - only minor visual issues (a few random tiles in the middle of the play field, and Dr. Wright appears in the wrong location in the advice windows that pop up)
Super Scope 6: Obviously there's no way to control this one but the demos that start look pretty solid for the most part
Starfox: no start (not really surprised; I'm guessing games with the SuperFX chip are a whole other problem)
Really amazing progress so quickly on something this complex...great job
@avsa242 said:
Got it working! It turned out to be just a lame wall-wart: "5V, 2A" - yeah, maybe more like .2A...that's been running my Edge all this time shakes head
Nice.
I'm quite surprised that Pilotwings starts up at all. I would expect it to hang without its expansion chip, like Starfox.
Also, you really didn't run into any HiROM games? Because those are all 100% non-functional, lol. Will be really simple to fix though.
Screen garblings may be reduced if you upgrade to alpha 08 that I just posted.
implement OAM priority rotation (fixes aforementioned minor oddity in Super Mario World)
add workaround for flexspin bug #440 (should work fine with relatively old versions now, may need to remove --compress from the build script; you really should be using at least 6.9.4 though)
I figured out the issue where games take a very long time to start. Basically, when the direct page is not aligned to 256 bytes, an extra penalty cycle needs to be inserted into some addressing modes. Of course I forgot to initialize the variable used for this (rk_dp_penalty). So these games (or at least Mega Man X) clear out memory using an STZ $00,X instruction in a loop, relying on the DP register being zeroed on reset (setting the DP register using TCD or PLD will set the variable). Due to the uninitialized penalty variable, each iteration will consume thousands of virtual cycles and cause the CPU cog to spend a lot of time just waiting for real time to catch up.
Just started working on cartridge NVRAM. Zelda can now actually go ingame (and seems to work fine as far as I played). However, something, it seems to me, is very slightly off with the sound effects? Maybe I'm just going mental.
Super Metroid and Earthbound now get past their piracy check, too (it really just verifies size/mirroring of cartridge RAM, since most copy devices at the time didn't bother to mask the unused address bits). Metroid crashes during the station escape sequence in the room that's supposed to tilt. Earthbound is OK? Slight timing-related screen glitch, etc.
Haven't made any inroads on MisoYume today, but I did look into the Tempest thing a bit.
So the source that's posted on github is somewhat incomplete and they just coped by pulling the missing bits as binary blobs. (the image it builds does match the actual cartridge MD5 though!). I think originally the data files were included into the image through some mechanism outside of the normal assembly linker, so their addresses are hardcoded, both in the source and in some of the binary blobs (that whoever previously tried to fix the build assumed were just padding garbage?). Also apparently the program section is a few bytes longer than intended and cuts into some unused graphics data. Anyways, after a little bit of effort, I managed to replace all hardcoded ROM pointers, so code can be added and removed without breaking everything.
Also prototyped CRY to RGB conversion in PASM.
EDIT: Apparently only 11 or so places in the main code where I needed to comment out something to get it to assemble without Jaguar register defines (not counting stubbing out vidinit/gpu/audio/eeprom, which live in their own files)
LLamasoft? Wait a moment, this sounds familiar... Jeff Minter! My very first computer game and one of my favorites was "Matrix" by Jeff Minter for the C64. It was a ROM catridge with only 8kB. It was a mixture of centipede and space invaders with dozens of different levels. It's amazing how all that could be fitted into 8kB. A lot of games theese days don't fit into 8GB and are less fun.
added support for cartridge RAM (not actually saved to disk yet, also I think there's a second way LoROM may map it)
fix aforementioned direct page penalty bug (should fix every game that took a long time to boot)
Add support for HyperRAM
@rogloh do you have a more recent version of the psram8 driver? With the T2000 thing I think I ran into an issue with reading bursts from odd word addresses or soemthing like that. The 4-bit and hyperram drivers don't break like that. But a good excuse to spend the few minutes to fix up the hyper support in misoyume I guess.
@Wuerfel_21 said:
Here's MisoYume alpha 10 all bundled up:
made vain attempt to fix IRQ timing a bit
added support for ExHiROM games
added support for cartridge RAM (not actually saved to disk yet, also I think there's a second way LoROM may map it)
fix aforementioned direct page penalty bug (should fix every game that took a long time to boot)
Add support for HyperRAM
@rogloh do you have a more recent version of the psram8 driver? With the T2000 thing I think I ran into an issue with reading bursts from odd word addresses or soemthing like that. The 4-bit and hyperram drivers don't break like that. But a good excuse to spend the few minutes to fix up the hyper support in misoyume I guess.
I'll have a quick look but I don't think I do have any more recent updates. If you can pinpoint an exact reproducible/isolated case of read failures, I'll try to fix it.
@rogloh said:
I'll have a quick look but I don't think I do have any more recent updates. If you can pinpoint an exact reproducible/isolated case of read failures, I'll try to fix it.
Try setting it up with a video driver displaying a 320x240 16bpp bitmap and then move the pointer 2 bytes forwards. You can see the issue very clearly then. It appears to sometimes skip a word. May be row boundary related.
Ok thanks, I'll take a look today. Looks like the 8 bit version has a few variants amongst my filesystem. I must have been throwing special custom builds over to you for testing with different features back then, it seems like it was not well tracked unfortunately.
Also, I just noticed that MisoYume now can somewhat run SD3/Trials of Mana. One of the audio tracks has a really terrible distortion to it. Could it be that my DSP emulation has a bug afterall? Or maybe it grew one while transplanting it into the emulator at large?
(terrible in the sense that it upsets my inner audiophile and perfectionist, not actually unlistenable)
@Wuerfel_21 said:
Check the misoyume ZIP I posted, that's the latest versions I have.
Ok I have been able to reproduce a corruption problem by offsetting frame buffer read addresses by 16 bits with your 8 bit driver variant - I'm actually doing a 640x480 screen buffer in 8bpp. Corruption fixes itself on next aligned 32 bit boundary. This demo should be normally showing readable text when working correctly.
I'll try to figure out what's going on. Maybe some of my other variants are better and this sysclk/3 capable option is somehow bad, or there is some common underlying issue. Update: So my non-sysclk/3 driver variant also has this issue. It's really weird - with this corrupted text output every 3rd scanline is good and it's then seemingly followed by 2 bad ones yet the cycle also repeats every 16 scanlines. A strange pattern which I would not have expected. Still digging.
@Wuerfel_21 I've found the problem. The read burst code path was sharing some other common code that was incorrectly 32 bit aligning PSRAM addresses for all cases. Adding the skipf below appears to fix it and I no longer see corruption when offsetting the graphics source buffer read address byte by byte. Give it a go in your own code to see if it fixes your issues.
setword xrecvdata, c, #0 'set the transfer clocks needed in streamer
skipf #%100 ' <<< ADD THIS LINE FOR THE FIX
readcommon
mov cmdaddr, addr1 'get start address of transfer
shr cmdaddr, #1 'convert to 16 bit address
andn cmdaddr, #1 'but aligned to 32 bit boundary
setbyte cmdaddr, #$EB, #3 'add quad read command
On the DSP front, I did realize that my BRR decoding is still not properly bit-accurate (some +1/-1 rounding oddities), but also that that has nothing to do with the mysterious distortion. I guess that means I can stick with the faster code there though (2 SCAS + 2 ADD vs a lot of shifts)
Okay, I figured it out: It's just distortion from noise-mode DAC. It took me double checking every part of the code and eventually logging out the raw values over serial to get to that conclusion. I'd have noticed earlier if not for the fact that clkfreq in Spin doesn't set exactly to the value you asked for...
On the upside, I don't think I ever tried PWM mode on non-multiple-of-256 sampling periods before. It's actually better than noise mode, I would say. Would have to use some brain to calculate the non-linearity induced by this, but just empirically, there's less background noise and less weird quantization noises. Actually, is there even a linearity error? I always assumed that when the period is unaligned, the PWM phase just resets when the new sample starts, but the docs don't say that anywhere, I think? Maybe the PWM phase is free-running?
The PWM mode's period will be like the Pulse/Transition modes, where it cycles at a constant rate, set by X register, and Y register is only read, "captured", at completion of each pulse cycle. Updating Y makes no change to the pulse in the active period.
EDIT: DAC with PWM is the same. The only PWM difference is the frame period doesn't have a pre-scaler. Or you could argue that the prescaler is 256 and the frame period is 8-bit, X[15:8].
PWM does have a noise problem of its own. It has much higher noise at 50% than 1% or 99%. PDM is superior. Something to look into if Chip ever does a respin.
Comments
Wow. Seems like there's probably only one type smarter than demoscene coders and that is those who can fully emulate all the hardware tricks used by demoscene coders so their original code will still run perfectly. LOL
Today's funny nonsense:
loadp2 misoyume_lower.binary -a /sd/misoyume/smwu.sfc
to load a specific file. Still has a hardcoded fallback. I guess this is a good stopgap so I can procrastinate on adding a menu.So I think I'm running out of easy problems. I wanted to use Tetris Attack as a test case for Mode 2 and Bust-A-Move for Mode 4, but it turns out both of these do not boot at all. Amazing. (Non-EDIT: While going through the compat list, I realized Bust-A-Move just takes forever to boot, like Demon's Crest) I added stub implementations for the missing modes that should just ignore OPT, but those don't seem to work properly, either (at least Mode 4 has broken BG2 graphics in Rock'n'Roll Racing).
So remaining avenues:
Compat list as of alpha 07:
Oh, I figured out the graphics corruption for Mario World and Zelda. So basically, to save on ROM space, these games use a very simple compression wherein some graphics are stored with 3 bitplanes instead of 4. The missing bitplane is then set to a constant value when loading the graphics, such that it uses either the "left" or "right" half of palette RAM. Except, when setting the bitplane to 1, any otherwise transparent pixels have to be masked out. This is accomplished by some code using the otherwise rather gormless
ORA [d]
(opcode $07) instruction. So of course there was a typo in the opcode table andORA (d)
(normally opcode $12) was executed instead. Which is the same thing, but using the current data bank instead of fetching a third indirect byte from the direct page. Owie ouch.Good thing with these graphics type bugs is you probably know right where to look to find them and can make a very good educated guess as to the problem right away given you've recently coded the graphics emulator and know what data controls what, plus you can see the effect directly on screen while it still runs etc. Some of the other bugs are gonna be quite a bit harder to figure out no doubt.
That one had me stumped quite a bit though. I did think it'd have to be a CPU-side problem, but wasn't 100% sure.
Also, figured out why my mode 4 stub didn't work. Actually a bug that affects all 8bpp rendering (except mode 7), I just didn't notice it before. Since the pixel data takes up the entire byte, the attribute data has to go to one of the other buffers. The compositing code expected it in BG4's buffer, but the rendering code put it in BG3's buffer. Ow.
Okay, alpha 08
Note: may or may not currently work quite right without this flexspin PR branch: https://github.com/totalspectrum/spin2cpp/pull/441
Got it working! It turned out to be just a lame wall-wart: "5V, 2A" - yeah, maybe more like .2A...that's been running my Edge all this time shakes head
Tested F-Zero, SMW, Castlevania IV, Zelda...my results all line up with your table above. Here's a few others, just as possible points of interest (not complaining )
Bubsy: Accolade splash screen then nothing
Contra 3: Konami screen looks/sounds good. Some parts of the intro flicker. Makes it to the prepare for start screen and freezes
Lemmings: Plays fine, text or "status" line during the game flickers, as well as the top 10 or so lines, but good for the most part
Pilotwings: Right from the title screen, many garbled tiles. Some intermediate screens are okay-ish. When the light-plane gameplay starts, it immediately pulls hard right and sounds like it's at full throttle. The throttle indicator can be changed but nothing actually changes. Pretty heavily garbled screen here
Simcity: long delay (~1min+) before anything happens, but fine after that. Pretty solid - only minor visual issues (a few random tiles in the middle of the play field, and Dr. Wright appears in the wrong location in the advice windows that pop up)
Super Scope 6: Obviously there's no way to control this one but the demos that start look pretty solid for the most part
Starfox: no start (not really surprised; I'm guessing games with the SuperFX chip are a whole other problem)
Really amazing progress so quickly on something this complex...great job
Cheers
Nice.
I'm quite surprised that Pilotwings starts up at all. I would expect it to hang without its expansion chip, like Starfox.
Also, you really didn't run into any HiROM games? Because those are all 100% non-functional, lol. Will be really simple to fix though.
Screen garblings may be reduced if you upgrade to alpha 08 that I just posted.
How is it going with super Mario world?
Think that was the most popular game…
Works great except that you can't save the game. Maybe it pulls some special effects in later levels that don't work, idk.
EDIT: actually, the little mario next to the life counter on the map screen is missing due to an unimplemented feature
So, uh, alpha 09:
Short compat list of HiROM games I had already on my SD card:
I figured out the issue where games take a very long time to start. Basically, when the direct page is not aligned to 256 bytes, an extra penalty cycle needs to be inserted into some addressing modes. Of course I forgot to initialize the variable used for this (
rk_dp_penalty
). So these games (or at least Mega Man X) clear out memory using an STZ $00,X instruction in a loop, relying on the DP register being zeroed on reset (setting the DP register using TCD or PLD will set the variable). Due to the uninitialized penalty variable, each iteration will consume thousands of virtual cycles and cause the CPU cog to spend a lot of time just waiting for real time to catch up.Just started working on cartridge NVRAM. Zelda can now actually go ingame (and seems to work fine as far as I played). However, something, it seems to me, is very slightly off with the sound effects? Maybe I'm just going mental.
Super Metroid and Earthbound now get past their piracy check, too (it really just verifies size/mirroring of cartridge RAM, since most copy devices at the time didn't bother to mask the unused address bits). Metroid crashes during the station escape sequence in the room that's supposed to tilt. Earthbound is OK? Slight timing-related screen glitch, etc.
Haven't made any inroads on MisoYume today, but I did look into the Tempest thing a bit.
So the source that's posted on github is somewhat incomplete and they just coped by pulling the missing bits as binary blobs. (the image it builds does match the actual cartridge MD5 though!). I think originally the data files were included into the image through some mechanism outside of the normal assembly linker, so their addresses are hardcoded, both in the source and in some of the binary blobs (that whoever previously tried to fix the build assumed were just padding garbage?). Also apparently the program section is a few bytes longer than intended and cuts into some unused graphics data. Anyways, after a little bit of effort, I managed to replace all hardcoded ROM pointers, so code can be added and removed without breaking everything.
Also prototyped CRY to RGB conversion in PASM.
EDIT: Apparently only 11 or so places in the main code where I needed to comment out something to get it to assemble without Jaguar register defines (not counting stubbing out vidinit/gpu/audio/eeprom, which live in their own files)
Huh, I remember Llamasoft's Llamatron on the Amiga. That'll be where Tempest 2000's Amiga roots came from.
LLamasoft? Wait a moment, this sounds familiar... Jeff Minter! My very first computer game and one of my favorites was "Matrix" by Jeff Minter for the C64. It was a ROM catridge with only 8kB. It was a mixture of centipede and space invaders with dozens of different levels. It's amazing how all that could be fitted into 8kB. A lot of games theese days don't fit into 8GB and are less fun.
Here's MisoYume alpha 10 all bundled up:
@rogloh do you have a more recent version of the psram8 driver? With the T2000 thing I think I ran into an issue with reading bursts from odd word addresses or soemthing like that. The 4-bit and hyperram drivers don't break like that. But a good excuse to spend the few minutes to fix up the hyper support in misoyume I guess.
I'll have a quick look but I don't think I do have any more recent updates. If you can pinpoint an exact reproducible/isolated case of read failures, I'll try to fix it.
Try setting it up with a video driver displaying a 320x240 16bpp bitmap and then move the pointer 2 bytes forwards. You can see the issue very clearly then. It appears to sometimes skip a word. May be row boundary related.
Ok thanks, I'll take a look today. Looks like the 8 bit version has a few variants amongst my filesystem. I must have been throwing special custom builds over to you for testing with different features back then, it seems like it was not well tracked unfortunately.
Check the misoyume ZIP I posted, that's the latest versions I have.
Also, I just noticed that MisoYume now can somewhat run SD3/Trials of Mana. One of the audio tracks has a really terrible distortion to it. Could it be that my DSP emulation has a bug afterall? Or maybe it grew one while transplanting it into the emulator at large?
(terrible in the sense that it upsets my inner audiophile and perfectionist, not actually unlistenable)
Ok I have been able to reproduce a corruption problem by offsetting frame buffer read addresses by 16 bits with your 8 bit driver variant - I'm actually doing a 640x480 screen buffer in 8bpp. Corruption fixes itself on next aligned 32 bit boundary. This demo should be normally showing readable text when working correctly.
I'll try to figure out what's going on. Maybe some of my other variants are better and this sysclk/3 capable option is somehow bad, or there is some common underlying issue.
Update: So my non-sysclk/3 driver variant also has this issue. It's really weird - with this corrupted text output every 3rd scanline is good and it's then seemingly followed by 2 bad ones yet the cycle also repeats every 16 scanlines. A strange pattern which I would not have expected. Still digging.
@Wuerfel_21 I've found the problem. The read burst code path was sharing some other common code that was incorrectly 32 bit aligning PSRAM addresses for all cases. Adding the skipf below appears to fix it and I no longer see corruption when offsetting the graphics source buffer read address byte by byte. Give it a go in your own code to see if it fixes your issues.
@rogloh Thanks! That does appear to fix the issue
On the DSP front, I did realize that my BRR decoding is still not properly bit-accurate (some +1/-1 rounding oddities), but also that that has nothing to do with the mysterious distortion. I guess that means I can stick with the faster code there though (2 SCAS + 2 ADD vs a lot of shifts)
Okay, I figured it out: It's just distortion from noise-mode DAC. It took me double checking every part of the code and eventually logging out the raw values over serial to get to that conclusion. I'd have noticed earlier if not for the fact that clkfreq in Spin doesn't set exactly to the value you asked for...
On the upside, I don't think I ever tried PWM mode on non-multiple-of-256 sampling periods before. It's actually better than noise mode, I would say. Would have to use some brain to calculate the non-linearity induced by this, but just empirically, there's less background noise and less weird quantization noises. Actually, is there even a linearity error? I always assumed that when the period is unaligned, the PWM phase just resets when the new sample starts, but the docs don't say that anywhere, I think? Maybe the PWM phase is free-running?
The PWM mode's period will be like the Pulse/Transition modes, where it cycles at a constant rate, set by X register, and Y register is only read, "captured", at completion of each pulse cycle. Updating Y makes no change to the pulse in the active period.
EDIT: DAC with PWM is the same. The only PWM difference is the frame period doesn't have a pre-scaler. Or you could argue that the prescaler is 256 and the frame period is 8-bit, X[15:8].
Enlightening. Hmm... Does it latch the entire Y or just the bottom byte?
PWM does have a noise problem of its own. It has much higher noise at 50% than 1% or 99%. PDM is superior. Something to look into if Chip ever does a respin.
It would be a flaw if it wasn't the whole 16 bits latched. And it does state Y15:0] is "captured".