mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Initial implementation of partial_embedded_buffer_dirty handling (#5548)
* Initial implementation of partial_embedded_buffer_dirty handling * Apply suggestions from code review Co-authored-by: Marshall Mohror <mohror64@gmail.com> * Serialize physical address, fix LOG_TRACE * Add bracket * Avoid crash in partial update behavior Co-authored-by: Marshall Mohror <mohror64@gmail.com>
This commit is contained in:
		
							parent
							
								
									02d6032afb
								
							
						
					
					
						commit
						1aaec7938f
					
				
					 2 changed files with 68 additions and 0 deletions
				
			
		|  | @ -169,6 +169,71 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, | |||
|         // This will be the starting sample for the first time the buffer is played.
 | ||||
|     } | ||||
| 
 | ||||
|     // TODO(xperia64): Is this in the correct spot in terms of the bit handling order?
 | ||||
|     if (config.partial_embedded_buffer_dirty) { | ||||
|         config.partial_embedded_buffer_dirty.Assign(0); | ||||
| 
 | ||||
|         // As this bit is set by the game, three config options are also updated:
 | ||||
|         // buffer_id (after a check comparing the buffer_id to something, probably to make sure it's
 | ||||
|         // the same buffer?), flags2_raw.is_looping, and length.
 | ||||
| 
 | ||||
|         // A quick and dirty way of extending the current buffer is to just read the whole thing
 | ||||
|         // again with the new length. Note that this uses the latched physical address instead of
 | ||||
|         // whatever is in config, because that may be invalid.
 | ||||
|         const u8* const memory = | ||||
|             memory_system->GetPhysicalPointer(state.current_buffer_physical_address & 0xFFFFFFFC); | ||||
| 
 | ||||
|         // TODO(xperia64): This could potentially be optimized by only decoding the new data and
 | ||||
|         // appending that to the buffer.
 | ||||
|         if (memory) { | ||||
|             const unsigned num_channels = state.mono_or_stereo == MonoOrStereo::Stereo ? 2 : 1; | ||||
|             bool valid = false; | ||||
|             switch (state.format) { | ||||
|             case Format::PCM8: | ||||
|                 // TODO(xperia64): This may just work fine like PCM16, but I haven't tested and
 | ||||
|                 // couldn't find any test case games
 | ||||
|                 UNIMPLEMENTED_MSG("{} not handled for partial buffer updates", "PCM8"); | ||||
|                 // state.current_buffer = Codec::DecodePCM8(num_channels, memory, config.length);
 | ||||
|                 break; | ||||
|             case Format::PCM16: | ||||
|                 state.current_buffer = Codec::DecodePCM16(num_channels, memory, config.length); | ||||
|                 valid = true; | ||||
|                 break; | ||||
|             case Format::ADPCM: | ||||
|                 // TODO(xperia64): Are partial embedded buffer updates even valid for ADPCM? What
 | ||||
|                 // about the adpcm state?
 | ||||
|                 UNIMPLEMENTED_MSG("{} not handled for partial buffer updates", "ADPCM"); | ||||
|                 /* state.current_buffer =
 | ||||
|                     Codec::DecodeADPCM(memory, config.length, state.adpcm_coeffs, | ||||
|                    state.adpcm_state); */ | ||||
|                 break; | ||||
|             default: | ||||
|                 UNIMPLEMENTED(); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             // Again, because our interpolation consumes samples instead of using an index, let's
 | ||||
|             // just re-consume the samples up to the current sample number. There may be some
 | ||||
|             // imprecision here with the current sample number, as Detective Pikachu sounds a little
 | ||||
|             // rough at times.
 | ||||
|             if (valid) { | ||||
| 
 | ||||
|                 // TODO(xperia64): Tomodachi life apparently can decrease config.length when the
 | ||||
|                 // user skips dialog. I don't know the correct behavior, but to avoid crashing, just
 | ||||
|                 // reset the current sample number to 0 and don't try to truncate the buffer
 | ||||
|                 if (state.current_buffer.size() < state.current_sample_number) { | ||||
|                     state.current_sample_number = 0; | ||||
|                 } else { | ||||
|                     state.current_buffer.erase( | ||||
|                         state.current_buffer.begin(), | ||||
|                         std::next(state.current_buffer.begin(), state.current_sample_number)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         LOG_TRACE(Audio_DSP, "partially updating embedded buffer addr={:#010x} len={} id={}", | ||||
|                   state.current_buffer_physical_address, config.length, config.buffer_id); | ||||
|     } | ||||
| 
 | ||||
|     if (config.embedded_buffer_dirty) { | ||||
|         config.embedded_buffer_dirty.Assign(0); | ||||
|         // HACK
 | ||||
|  | @ -343,6 +408,7 @@ bool Source::DequeueBuffer() { | |||
|     // the first playthrough starts at play_position, loops start at the beginning of the buffer
 | ||||
|     state.current_sample_number = (!buf.has_played) ? buf.play_position : 0; | ||||
|     state.next_sample_number = state.current_sample_number; | ||||
|     state.current_buffer_physical_address = buf.physical_address; | ||||
|     state.current_buffer_id = buf.buffer_id; | ||||
|     state.buffer_update = buf.from_queue && !buf.has_played; | ||||
| 
 | ||||
|  |  | |||
|  | @ -137,6 +137,7 @@ private: | |||
| 
 | ||||
|         u32 current_sample_number = 0; | ||||
|         u32 next_sample_number = 0; | ||||
|         PAddr current_buffer_physical_address = 0; | ||||
|         AudioInterp::StereoBuffer16 current_buffer = {}; | ||||
| 
 | ||||
|         // buffer_id state
 | ||||
|  | @ -170,6 +171,7 @@ private: | |||
|             ar& format; | ||||
|             ar& current_sample_number; | ||||
|             ar& next_sample_number; | ||||
|             ar& current_buffer_physical_address; | ||||
|             ar& current_buffer; | ||||
|             ar& buffer_update; | ||||
|             ar& current_buffer_id; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue