Skip to content

Commit 5017dc7

Browse files
committed
Rewrite calculateChecksum(), add tests
1 parent c97ce65 commit 5017dc7

5 files changed

Lines changed: 228 additions & 79 deletions

File tree

.vscode/launch.json

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
{
2-
"version": "0.2.0",
3-
"configurations": [
4-
{
5-
"name": "Debug",
6-
"type": "lldb",
7-
"request": "launch",
8-
"program": "${workspaceFolder}/build/superfamicheck",
9-
"args": ["test/data/public/rom1.sfc"],
10-
"preLaunchTask": "${defaultBuildTask}"
11-
}
12-
]
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Debug",
6+
"type": "lldb",
7+
"request": "launch",
8+
"program": "${workspaceFolder}/build/superfamicheck",
9+
"args": [
10+
"test/data/public/rom1.sfc"
11+
],
12+
"preLaunchTask": "${defaultBuildTask}",
13+
}
14+
]
1315
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ superfamicheck is programmed by David Lindecrantz and distributed under the term
55

66

77
## building
8-
in a unix-like environment simply `make` the binary. on windows use cmake to generate a build environment.
8+
use cmake to generate a build environment, or simply type `make` which will run cmake for you.
99

1010
## operation
1111

src/sfcRom.cpp

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,16 @@ sfcRom::sfcRom(const string& path) {
9292
{
9393
if ((mode & 0xe0) != 0x20) {
9494
correctedMode = headerLocation >= 0x8000 ? 0x21 : 0x20;
95-
hasLegalMode = false;
9695
hasSevereIssues = true;
9796
++issues;
97+
} else {
98+
hasLegalMode = true;
9899
}
99100

100101
if (mapperName.empty()) {
101-
hasKnownMapper = false;
102102
++issues;
103+
} else {
104+
hasKnownMapper = true;
103105
}
104106
}
105107

@@ -124,17 +126,20 @@ sfcRom::sfcRom(const string& path) {
124126
// Check RAM size
125127
{
126128
if ((hasRam && ramSize > 0x0f) || (!hasRam && ramSize != 0)) {
127-
hasCorrectRamSize = false;
128129
++issues;
130+
} else {
131+
hasCorrectRamSize = true;
129132
}
130133
}
131134

132135
// Calculate checksum
133136
{
134137
correctedChecksum = calculateChecksum();
135138
correctedComplement = ~correctedChecksum;
136-
if (checksum != correctedChecksum) {
139+
if ((checksum != correctedChecksum) || complement != correctedComplement) {
137140
++issues;
141+
} else {
142+
hasCorrectChecksum = true;
138143
}
139144
}
140145

@@ -246,7 +251,7 @@ string sfcRom::description(bool silent) const {
246251
os << " RAM size should be 0x00" << '\n';
247252
}
248253
}
249-
if (checksum != correctedChecksum || complement != correctedComplement) {
254+
if (!hasCorrectChecksum) {
250255
os << " Checksum/complement should be 0x" << setw(4) << correctedChecksum << "/0x" << setw(4) << correctedComplement
251256
<< '\n';
252257
}
@@ -621,58 +626,53 @@ void sfcRom::getHeaderInfo(const vector<uint8_t>& header) {
621626
}
622627

623628
uint16_t sfcRom::calculateChecksum() const {
624-
size_t imageSize = image.size();
625-
size_t mappedSize;
629+
vector<uint8_t> img = image;
630+
putWord(img, headerLocation + 0x2c, 0xffff);
631+
putWord(img, headerLocation + 0x2e, 0x0000);
626632

627-
// Base and mask for out of bounds mirroring
628-
uint32_t base = 0;
629-
uint32_t offsetMask = 0xffffffff;
630-
uint32_t offsetMod = 0xffffffff;
633+
size_t imageSize = img.size();
634+
size_t mappedSize;
631635

632636
if (mapper == 0x0a && chipset == 0xf9 && chipsetSubtype == 0x00) {
633637
// Extended HiROM/SPC7110+RTC+Battery
634638
mappedSize = imageSize;
635639
} else if (mapper == 0x0a && chipset == 0xf5 && chipsetSubtype == 0x00) {
636640
// Extended HiROM/SPC7110+Battery
637641
mappedSize = imageSize > 0x200000 ? imageSize << 1 : imageSize;
638-
offsetMod = imageSize;
642+
while (mappedSize > img.size()) {
643+
size_t remaining = mappedSize - img.size();
644+
if (remaining > image.size()) {
645+
remaining = image.size();
646+
}
647+
if ((remaining + img.size()) > mappedSize) {
648+
remaining = mappedSize - img.size();
649+
}
650+
vector<uint8_t> mirror(img.begin(), img.begin() + remaining);
651+
img.insert(img.end(), mirror.begin(), mirror.end());
652+
}
639653
} else {
654+
// Standard mapping
640655
mappedSize = 1 << (correctedRomSize != 0 ? correctedRomSize + 10 : romSize + 10);
641-
uint32_t mask = 1;
642-
uint32_t t = imageSize;
643-
while (t >>= 1) {
644-
mask <<= 1;
645-
mask += 1;
656+
while (mappedSize > img.size()) {
657+
vector<uint8_t> mirror(img.begin() + (mappedSize >> 1), img.end());
658+
img.insert(img.end(), mirror.begin(), mirror.end());
646659
}
647-
mask >>= 1;
648-
base = mask + 1;
649-
offsetMask = imageSize - base - 1;
650660
}
651661

652-
// Add sum
653-
auto img = image;
654-
putWord(img, headerLocation + 0x2c, 0xffff);
655-
putWord(img, headerLocation + 0x2e, 0x0000);
656662
uint16_t sum = 0;
657-
658-
for (size_t offset = 0; offset < mappedSize; ++offset) {
659-
size_t imgOffset = offset % offsetMod;
660-
if (imgOffset < imageSize) {
661-
sum += img[imgOffset];
662-
} else {
663-
size_t mirrorOffset = base + (imgOffset & offsetMask);
664-
sum += img[mirrorOffset];
665-
}
663+
size_t length = img.size();
664+
for (size_t offset = 0; offset < length; ++offset) {
665+
sum += img[offset];
666666
}
667667
return sum;
668668
}
669669

670-
671-
// Get/put little endian word
670+
// Get little endian word
672671
uint16_t getWord(const vector<uint8_t>& vec, size_t offset) {
673672
return (uint16_t)((vec[offset]) + ((uint8_t)(vec[offset + 1]) << 8));
674673
}
675674

675+
// Put little endian word
676676
void putWord(vector<uint8_t>& vec, size_t offset, uint16_t value) {
677677
vec[offset] = (uint8_t)(value & 0xff);
678678
vec[offset + 1] = (uint8_t)(value >> 8);

src/sfcRom.hpp

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ struct sfcRom {
1616

1717
bool hasCopierHeader = false;
1818
bool hasCorrectTitle = false;
19-
bool hasCorrectRamSize = true;
20-
bool hasLegalMode = true;
21-
bool hasKnownMapper = true;
19+
bool hasCorrectRamSize = false;
20+
bool hasCorrectChecksum = false;
21+
bool hasLegalMode = false;
22+
bool hasKnownMapper = false;
2223
bool hasNewFormatHeader = false;
2324

2425
std::string title;
@@ -29,19 +30,28 @@ struct sfcRom {
2930
std::string version;
3031
std::string country;
3132

32-
uint8_t mode;
33-
uint8_t mapper;
34-
bool fast;
33+
uint8_t mode = 0;
34+
uint8_t mapper = 0;
35+
bool fast = false;
3536
bool hasRam = false;
3637

37-
uint8_t chipset;
38+
uint8_t chipset = 0;
3839
uint8_t chipsetSubtype = 0;
39-
uint8_t romSize;
40-
uint8_t ramSize;
41-
uint8_t countryCode;
40+
uint8_t romSize = 0;
41+
uint8_t ramSize = 0;
42+
uint8_t countryCode = 0;
4243

43-
uint16_t checksum;
44-
uint16_t complement;
44+
uint16_t checksum = 0;
45+
uint16_t complement = 0;
46+
47+
size_t imageSize = 0;
48+
size_t imageOffset = 0;
49+
size_t headerLocation = 0;
50+
51+
uint8_t correctedMode = 0;
52+
uint8_t correctedRomSize = 0;
53+
uint16_t correctedChecksum = 0;
54+
uint16_t correctedComplement = 0;
4555

4656
private:
4757
std::string filepath;
@@ -50,13 +60,4 @@ struct sfcRom {
5060
void getHeaderInfo(const std::vector<uint8_t>& header);
5161
int scoreHeaderLocation(size_t location) const;
5262
uint16_t calculateChecksum() const;
53-
54-
size_t imageSize;
55-
size_t imageOffset = 0;
56-
size_t headerLocation = 0;
57-
58-
uint8_t correctedMode = 0;
59-
uint8_t correctedRomSize = 0;
60-
uint16_t correctedChecksum;
61-
uint16_t correctedComplement;
6263
};

0 commit comments

Comments
 (0)