Fix CPU bugs, KIRBY BOOTS!

- Bad LSR emulation caused an edge-case making allmost all of the game I tested fail to boot past intro.
- Incorrect sign extension of offset5 in THUMB caused bad address calculation.

Kirby boots with rendering glitches, I played past the first 2 boses
without crashes.


Former-commit-id: 8ea0ad6eb0f70e6dc23d1f2fcc44c8c0b3448fba
This commit is contained in:
Michel Heily 2019-11-16 18:13:18 +02:00
parent ccfff31123
commit 46931a1f6a
2 changed files with 10 additions and 21 deletions

View file

@ -123,14 +123,11 @@ impl Core {
} }
pub fn lsr(&mut self, val: u32, amount: u32, _carry_in: bool, immediate: bool) -> u32 { pub fn lsr(&mut self, val: u32, amount: u32, _carry_in: bool, immediate: bool) -> u32 {
let amount = if immediate && amount == 0 { 32 } else { amount };
match amount { match amount {
0 | 32 => { 32 => {
if immediate { self.bs_carry_out = val.bit(31);
self.bs_carry_out = val.bit(31); 0
0
} else {
val
}
} }
x if x < 32 => { x if x < 32 => {
self.bs_carry_out = val >> (amount - 1) & 1 == 1; self.bs_carry_out = val >> (amount - 1) & 1 == 1;
@ -143,20 +140,12 @@ impl Core {
} }
} }
pub fn asr(&mut self, val: u32, amount: u32, _carry_in: bool, immediate: bool) -> u32 { pub fn asr(&mut self, val: u32, amount: u32, carry_in: bool, immediate: bool) -> u32 {
let amount = if immediate && amount == 0 { 32 } else { amount };
match amount { match amount {
0 => { 0 => {
if immediate { self.bs_carry_out = carry_in;
let bit31 = (val as i32 as u32).bit(31); val
self.bs_carry_out = bit31;
if bit31 {
0xffffffff
} else {
0
}
} else {
val
}
} }
x if x < 32 => { x if x < 32 => {
self.bs_carry_out = val.wrapping_shr(amount - 1) & 1 == 1; self.bs_carry_out = val.wrapping_shr(amount - 1) & 1 == 1;

View file

@ -282,8 +282,8 @@ impl ThumbInstruction {
ThumbAluOps::from_u16(self.raw.bit_range(6..10)).unwrap() ThumbAluOps::from_u16(self.raw.bit_range(6..10)).unwrap()
} }
pub fn offset5(&self) -> i8 { pub fn offset5(&self) -> u8 {
self.raw.bit_range(6..11) as i8 self.raw.bit_range(6..11) as u8
} }
pub fn bcond_offset(&self) -> i32 { pub fn bcond_offset(&self) -> i32 {