mirror of https://github.com/mgba-emu/mgba.git
GBA e-Reader: Initial error detection and retrying
This commit is contained in:
parent
92080793b3
commit
3b781c00e6
|
@ -119,7 +119,8 @@ void EReaderScanFilterAnchors(struct EReaderScan*);
|
||||||
void EReaderScanConnectAnchors(struct EReaderScan*);
|
void EReaderScanConnectAnchors(struct EReaderScan*);
|
||||||
void EReaderScanCreateBlocks(struct EReaderScan*);
|
void EReaderScanCreateBlocks(struct EReaderScan*);
|
||||||
void EReaderScanDetectBlockThreshold(struct EReaderScan*, int block);
|
void EReaderScanDetectBlockThreshold(struct EReaderScan*, int block);
|
||||||
bool EReaderScanScanBlock(struct EReaderScan*, int block);
|
bool EReaderScanRecalibrateBlock(struct EReaderScan*, int block);
|
||||||
|
bool EReaderScanScanBlock(struct EReaderScan*, int block, bool strict);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
||||||
|
|
|
@ -778,6 +778,12 @@ struct EReaderBlock {
|
||||||
uint8_t min;
|
uint8_t min;
|
||||||
uint8_t max;
|
uint8_t max;
|
||||||
|
|
||||||
|
unsigned errors;
|
||||||
|
unsigned missing;
|
||||||
|
unsigned extra;
|
||||||
|
|
||||||
|
bool hFlip;
|
||||||
|
bool vFlip;
|
||||||
bool dots[36 * 36];
|
bool dots[36 * 36];
|
||||||
|
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
|
@ -1277,11 +1283,40 @@ void EReaderScanDetectBlockThreshold(struct EReaderScan* scan, int blockId) {
|
||||||
block->threshold = offset / 2;
|
block->threshold = offset / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EReaderScanScanBlock(struct EReaderScan* scan, int blockId) {
|
bool EReaderScanRecalibrateBlock(struct EReaderScan* scan, int blockId) {
|
||||||
if (blockId < 0 || (unsigned) blockId >= EReaderBlockListSize(&scan->blocks)) {
|
if (blockId < 0 || (unsigned) blockId >= EReaderBlockListSize(&scan->blocks)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct EReaderBlock* block = EReaderBlockListGetPointer(&scan->blocks, blockId);
|
struct EReaderBlock* block = EReaderBlockListGetPointer(&scan->blocks, blockId);
|
||||||
|
if (block->missing && block->extra) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int errors = block->errors;
|
||||||
|
if (block->missing) {
|
||||||
|
while (errors > 0) {
|
||||||
|
errors -= block->histogram[block->threshold];
|
||||||
|
while (!block->histogram[block->threshold] && block->threshold < 254) {
|
||||||
|
++block->threshold;
|
||||||
|
}
|
||||||
|
++block->threshold;
|
||||||
|
if (block->threshold >= 255) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EReaderScanScanBlock(struct EReaderScan* scan, int blockId, bool strict) {
|
||||||
|
if (blockId < 0 || (unsigned) blockId >= EReaderBlockListSize(&scan->blocks)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct EReaderBlock* block = EReaderBlockListGetPointer(&scan->blocks, blockId);
|
||||||
|
block->errors = 0;
|
||||||
|
block->missing = 0;
|
||||||
|
block->extra = 0;
|
||||||
|
|
||||||
bool dots[36 * 36] = {0};
|
bool dots[36 * 36] = {0};
|
||||||
size_t y;
|
size_t y;
|
||||||
|
@ -1301,26 +1336,65 @@ bool EReaderScanScanBlock(struct EReaderScan* scan, int blockId) {
|
||||||
}
|
}
|
||||||
int horizontal = 0;
|
int horizontal = 0;
|
||||||
int vertical = 0;
|
int vertical = 0;
|
||||||
|
int hMissing = 0;
|
||||||
|
int hExtra = 0;
|
||||||
|
int vMissing = 0;
|
||||||
|
int vExtra = 0;
|
||||||
static const bool alignment[36] = { 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 };
|
static const bool alignment[36] = { 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 };
|
||||||
int i;
|
int i;
|
||||||
for (i = 3; i < 33; ++i) {
|
for (i = 3; i < 33; ++i) {
|
||||||
if (horizontal && dots[i] != alignment[i]) {
|
if (dots[i] != alignment[i]) {
|
||||||
++horizontal;
|
++horizontal;
|
||||||
|
if (alignment[i]) {
|
||||||
|
++hMissing;
|
||||||
|
} else {
|
||||||
|
++hExtra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (dots[i + 36 * 35] != alignment[i]) {
|
if (dots[i + 36 * 35] != alignment[i]) {
|
||||||
++horizontal;
|
++horizontal;
|
||||||
|
if (alignment[i]) {
|
||||||
|
++hMissing;
|
||||||
|
} else {
|
||||||
|
++hExtra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (horizontal && dots[i * 36] != alignment[i]) {
|
if (dots[i * 36] != alignment[i]) {
|
||||||
++vertical;
|
++vertical;
|
||||||
|
if (alignment[i]) {
|
||||||
|
++vMissing;
|
||||||
|
} else {
|
||||||
|
++vExtra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (dots[i * 36 + 35] != alignment[i]) {
|
if (dots[i * 36 + 35] != alignment[i]) {
|
||||||
++vertical;
|
++vertical;
|
||||||
|
if (alignment[i]) {
|
||||||
|
++vMissing;
|
||||||
|
} else {
|
||||||
|
++vExtra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!!horizontal == !!vertical) {
|
int errors;
|
||||||
|
if (horizontal < vertical) {
|
||||||
|
errors = horizontal;
|
||||||
|
block->errors += horizontal;
|
||||||
|
block->extra += hExtra;
|
||||||
|
block->missing += hMissing;
|
||||||
|
horizontal = 0;
|
||||||
|
} else {
|
||||||
|
errors = vertical;
|
||||||
|
block->errors += vertical;
|
||||||
|
block->extra += vExtra;
|
||||||
|
block->missing += vMissing;
|
||||||
|
vertical = 0;
|
||||||
|
}
|
||||||
|
if (strict && errors) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sector[2] = {0};
|
int sector[2] = {0};
|
||||||
if (!vertical) {
|
if (!vertical) {
|
||||||
for (i = 5; i < 30; ++i) {
|
for (i = 5; i < 30; ++i) {
|
||||||
|
@ -1338,9 +1412,12 @@ bool EReaderScanScanBlock(struct EReaderScan* scan, int blockId) {
|
||||||
int yFlip = 1;
|
int yFlip = 1;
|
||||||
int xBias = 0;
|
int xBias = 0;
|
||||||
int yBias = 0;
|
int yBias = 0;
|
||||||
|
block->hFlip = false;
|
||||||
|
block->vFlip = false;
|
||||||
if ((sector[0] & 0x1FF) == 1) {
|
if ((sector[0] & 0x1FF) == 1) {
|
||||||
yFlip = -1;
|
yFlip = -1;
|
||||||
yBias = 35;
|
yBias = 35;
|
||||||
|
block->vFlip = true;
|
||||||
int s0 = 0;
|
int s0 = 0;
|
||||||
int s1 = 0;
|
int s1 = 0;
|
||||||
for (i = 0; i < 16; ++i) {
|
for (i = 0; i < 16; ++i) {
|
||||||
|
@ -1355,6 +1432,7 @@ bool EReaderScanScanBlock(struct EReaderScan* scan, int blockId) {
|
||||||
if (sector[1] < sector[0]) {
|
if (sector[1] < sector[0]) {
|
||||||
xFlip = -1;
|
xFlip = -1;
|
||||||
xBias = 35;
|
xBias = 35;
|
||||||
|
block->hFlip = true;
|
||||||
int sector0 = sector[0];
|
int sector0 = sector[0];
|
||||||
sector[0] = sector[1];
|
sector[0] = sector[1];
|
||||||
sector[1] = sector0;
|
sector[1] = sector0;
|
||||||
|
@ -1402,8 +1480,15 @@ bool EReaderScanCard(struct EReaderScan* scan) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < blocks; ++i) {
|
for (i = 0; i < blocks; ++i) {
|
||||||
EReaderScanDetectBlockThreshold(scan, i);
|
EReaderScanDetectBlockThreshold(scan, i);
|
||||||
if (!EReaderScanScanBlock(scan, i)) {
|
int errors = 36 * 36;
|
||||||
return false;
|
while (!EReaderScanScanBlock(scan, i, true)) {
|
||||||
|
if (errors < EReaderBlockListGetPointer(&scan->blocks, i)->errors) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
errors = EReaderBlockListGetPointer(&scan->blocks, i)->errors;
|
||||||
|
if (!EReaderScanRecalibrateBlock(scan, i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qsort(EReaderBlockListGetPointer(&scan->blocks, 0), EReaderBlockListSize(&scan->blocks), sizeof(struct EReaderBlock), _compareBlocks);
|
qsort(EReaderBlockListGetPointer(&scan->blocks, 0), EReaderBlockListSize(&scan->blocks), sizeof(struct EReaderBlock), _compareBlocks);
|
||||||
|
|
Loading…
Reference in New Issue