fix HLE BitUnPack and clarify historical crc16 bugs.

This commit is contained in:
zeromus 2013-08-12 06:08:57 +00:00
parent b18f284799
commit a850bc64d3
1 changed files with 95 additions and 89 deletions

View File

@ -858,7 +858,8 @@ TEMPLATE static u32 BitUnPack()
case 4: case 4:
case 8: case 8:
break; break;
default: return (0); // error default:
return (0); // error
} }
dataSize = _MMU_read08<PROCNUM>(header+3); dataSize = _MMU_read08<PROCNUM>(header+3);
switch (dataSize) switch (dataSize)
@ -870,12 +871,12 @@ TEMPLATE static u32 BitUnPack()
case 16: case 16:
case 32: case 32:
break; break;
default: return (0); // error default:
return (0); // error
} }
revbits = 8 - bits; revbits = 8 - bits;
// u32 value = 0; base = _MMU_read32<PROCNUM>(header+4);
base = _MMU_read08<PROCNUM>(header+4);
addBase = (base & 0x80000000) ? 1 : 0; addBase = (base & 0x80000000) ? 1 : 0;
base &= 0x7fffffff; base &= 0x7fffffff;
@ -894,21 +895,27 @@ TEMPLATE static u32 BitUnPack()
while(1) { while(1) {
if(bitcount >= 8) if(bitcount >= 8)
break; break;
d = b & mask; temp = b & mask;
temp = d >> bitcount; if(temp)
if(!temp && addBase) {
temp += base; temp += base;
} else if(addBase)
temp += base;
//you might think you should do this. but you would be wrong!
//this is meant for palette adjusting things, i.e. 16col data to 256col data in colors 240..255. In that case theres no modulo normally.
//Users expecting modulo have done something wrong anyway.
//temp &= (1<<bits)-1;
data |= temp << bitwritecount; data |= temp << bitwritecount;
bitwritecount += dataSize; bitwritecount += dataSize;
if(bitwritecount >= 32) { if(bitwritecount >= 32) {
_MMU_write08<PROCNUM>(dest, data); _MMU_write32<PROCNUM>(dest, data);
dest += 4; dest += 4;
data = 0; data = 0;
bitwritecount = 0; bitwritecount = 0;
} }
mask <<= bits;
bitcount += bits; bitcount += bits;
b >>= bits;
} }
} }
return 1; return 1;
@ -1029,41 +1036,40 @@ TEMPLATE static u32 getVolumeTab()
} }
//TEMPLATE static u32 getCRC16_old_and_broken(u32 crc, u32 datap, u32 size) TEMPLATE static u32 getCRC16_old_and_broken(u32 crc, u32 datap, u32 size)
//{ {
// unsigned int i,j; unsigned int i,j;
//
// const u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; const u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
// for(i = 0; i < size; i++) for(i = 0; i < size; i++)
// { {
// crc = crc ^ _MMU_read08<PROCNUM>(datap + i); crc = crc ^ _MMU_read08<PROCNUM>(datap + i);
//
// for(j = 0; j < 8; j++) { for(j = 0; j < 8; j++) {
// int do_bit = 0; int do_bit = 0;
//
// if ( crc & 0x1) if ( crc & 0x1)
// do_bit = 1; do_bit = 1;
//
// crc = crc >> 1; crc = crc >> 1;
//
// if ( do_bit) { if ( do_bit) {
// crc = crc ^ (val[j] << (7-j)); crc = crc ^ (val[j] << (7-j));
// } }
// } }
// } }
// return crc; return crc;
//} }
TEMPLATE static u32 getCRC16() TEMPLATE static u32 getCRC16()
{ {
//gbatek is wrong.. for ARM9, at least.
//someone should check how the ARM7 version works.
//dawn of sorrow uses this to checksum its save data; //dawn of sorrow uses this to checksum its save data;
//if this implementation is wrong, then it won't match what the real bios returns, //if this implementation is wrong, then it won't match what the real bios returns,
//and savefiles created with a bios will be invalid when loaded with non-bios (and vice-versa) //and savefiles created with a bios will be invalid when loaded with non-bios (and vice-versa).
//Once upon a time, desmume was doing this wrongly; this was due to its mis-use of high bits of the input CRC.
//u32 old = getCRC16_old<PROCNUM>(cpu->R[0],cpu->R[1],cpu->R[2]); //Additionally, that implementation was not handling odd sizes and addresses correctly (but this was discovered independently)
//The following call is left here so we can A/B test with the old version. Glad I left it, because we keep coming back to this code.
//u32 old = getCRC16_old_and_broken<PROCNUM>(cpu->R[0],cpu->R[1],cpu->R[2]);
u16 crc = (u16)cpu->R[0]; u16 crc = (u16)cpu->R[0];
u32 datap = cpu->R[1]; u32 datap = cpu->R[1];
@ -1091,7 +1097,7 @@ TEMPLATE static u32 getCRC16()
cpu->R[0] = crc; cpu->R[0] = crc;
//R3 contains the last processed halfword //R3 contains the last processed halfword
//this is significant -- WHY? //this is significant -- why? Can we get a test case? Supposedly there is one..
cpu->R[3] = currVal; cpu->R[3] = currVal;
return 1; return 1;