@@ -88,12 +88,14 @@ struct ChannelState
8888
8989 static constexpr u32 WRITE_MASK = 0b01110001'01110111'00000111'00000011 ;
9090
91- // Only bits 24, 28 and 30 can be set in OTC. All other bits are hardwired to zero.
92- static constexpr u32 OTC_MASK = 0b01010001'00000000'00000000'00000000 ;
91+ // Only bits 24, 28 and 30 can be set in OTC. All other bits are hardwired to zero, except bit 1 which is 1.
92+ static constexpr u32 OTC_WRITE_MASK = 0b01010001'00000000'00000000'00000000 ;
93+ static constexpr u32 OTC_FIXED_BITS = 0b00000000'00000000'00000000'00000010 ;
9394 } channel_control = {};
9495
9596 bool request = false ;
9697};
98+ static_assert (std::is_trivially_copyable_v<ChannelState>, " ChannelState is trivially copyable" );
9799
98100union DPCRRegister
99101{
@@ -122,6 +124,7 @@ union DPCRRegister
122124 return ConvertToBoolUnchecked ((bits >> (static_cast <u8 >(channel) * 4 + 3 )) & u32 (1 ));
123125 }
124126};
127+ static_assert (std::is_trivially_copyable_v<DPCRRegister>, " DPCRRegister is trivially copyable" );
125128
126129static constexpr u32 DICR_WRITE_MASK = 0b00000000'11111111'10000000'01111111 ;
127130static constexpr u32 DICR_RESET_MASK = 0b01111111'00000000'00000000'00000000 ;
@@ -172,6 +175,8 @@ union DICRRegister
172175 (((bits & (1u << 23 )) != 0u ) != 0u && (bits & (0b1111111u << 24 )) != 0u )); // master enable + irq on any channel
173176 }
174177};
178+ static_assert (std::is_trivially_copyable_v<DICRRegister>, " DICRRegister is trivially copyable" );
179+
175180} // namespace
176181
177182static void ClearState ();
@@ -262,14 +267,8 @@ void DMA::Reset()
262267
263268void DMA::ClearState ()
264269{
265- for (u32 i = 0 ; i < NUM_CHANNELS ; i++)
266- {
267- ChannelState& cs = s_state.channels [i];
268- cs.base_address = 0 ;
269- cs.block_control .bits = 0 ;
270- cs.channel_control .bits = 0 ;
271- cs.request = false ;
272- }
270+ s_state.channels = {};
271+ s_state.channels [static_cast <u32 >(Channel::OTC )].channel_control .bits = ChannelState::ChannelControl::OTC_FIXED_BITS ;
273272
274273 s_state.DPCR .bits = 0x07654321 ;
275274 s_state.DICR .bits = 0 ;
@@ -295,6 +294,15 @@ bool DMA::DoState(StateWrapper& sw)
295294
296295 if (sw.IsReading ())
297296 {
297+ // Fix up missing OTC bits which old save states were not forcing to 1.
298+ if (sw.GetVersion () < 85 ) [[unlikely]]
299+ {
300+ s_state.channels [static_cast <u32 >(Channel::OTC )].channel_control .bits =
301+ (s_state.channels [static_cast <u32 >(Channel::OTC )].channel_control .bits &
302+ ChannelState::ChannelControl::OTC_WRITE_MASK ) |
303+ ChannelState::ChannelControl::OTC_FIXED_BITS ;
304+ }
305+
298306 if (s_state.halt_ticks_remaining > 0 )
299307 s_state.unhalt_event .SetIntervalAndSchedule (s_state.halt_ticks_remaining );
300308 else
@@ -379,12 +387,10 @@ void DMA::WriteRegister(u32 offset, u32 value)
379387 // transfer is happening, and the SPU transfer gets delayed until the GPU transfer unhalts and finishes, and
380388 // breaks the interrupt.
381389 const bool ignore_halt = !state.channel_control .enable_busy && (value & (1u << 24 ));
382-
383- state.channel_control .bits = (state.channel_control .bits & ~ChannelState::ChannelControl::WRITE_MASK ) |
384- (value & ChannelState::ChannelControl::WRITE_MASK );
385- state.channel_control .bits = (static_cast <Channel>(channel_index) == Channel::OTC ) ?
386- (state.channel_control .bits & ChannelState::ChannelControl::OTC_MASK ) :
387- state.channel_control .bits ;
390+ const u32 write_mask = (static_cast <Channel>(channel_index) != Channel::OTC ) ?
391+ ChannelState::ChannelControl::WRITE_MASK :
392+ ChannelState::ChannelControl::OTC_WRITE_MASK ;
393+ state.channel_control .bits = (state.channel_control .bits & ~write_mask) | (value & write_mask);
388394 TRACE_LOG (" DMA channel {} channel control <- 0x{:08X}" , static_cast <Channel>(channel_index),
389395 state.channel_control .bits );
390396
0 commit comments