Merge branch 'master' into medusa

This commit is contained in:
Vicki Pfau 2022-06-29 01:39:39 -07:00
commit 1d57e86fd5
22 changed files with 241 additions and 99 deletions

View File

@ -88,11 +88,13 @@ Emulation fixes:
- GBA Video: Fix sprites with mid-frame palette changes in GL (fixes mgba.io/i/2476)
- GBA Video: Fix OBJ tile wrapping with 2D char mapping (fixes mgba.io/i/2443)
- GBA Video: Fix horizontal lines in GL when charbase is changed (fixes mgba.io/i/1631)
- GBA Video: Fix sprite layer priority updating in GL
Other fixes:
- ARM: Disassemble Thumb mov pseudo-instruction properly
- Core: Don't attempt to restore rewind diffs past start of rewind
- Core: Fix the runloop resuming after a game has crashed (fixes mgba.io/i/2451)
- Core: Fix crash if library can't be opened
- Debugger: Fix crash with extremely long CLI strings
- FFmpeg: Fix crash when encoding audio with some containers
- FFmpeg: Fix GIF recording (fixes mgba.io/i/2393)
- GB: Fix temporary saves

View File

@ -98,6 +98,7 @@ CXX_GUARD_START
} \
DECLARE_VECTOR(StringList, char*);
DECLARE_VECTOR(IntList, int);
CXX_GUARD_END

View File

@ -23,6 +23,7 @@ DECL_BITS(mMapCacheSystemInfo, TilesWide, 8, 4);
DECL_BITS(mMapCacheSystemInfo, TilesHigh, 12, 4);
DECL_BITS(mMapCacheSystemInfo, MacroTileSize, 16, 7);
DECL_BITS(mMapCacheSystemInfo, MapAlign, 23, 2);
DECL_BITS(mMapCacheSystemInfo, WriteAlign, 25, 2);
DECL_BITFIELD(mMapCacheEntryFlags, uint16_t);
DECL_BITS(mMapCacheEntryFlags, PaletteId, 0, 4);

View File

@ -43,7 +43,7 @@ enum Operation {
struct Token {
enum TokenType {
TOKEN_ERROR_TYPE,
TOKEN_ERROR_TYPE = 0,
TOKEN_UINT_TYPE,
TOKEN_IDENTIFIER_TYPE,
TOKEN_OPERATOR_TYPE,
@ -60,8 +60,10 @@ struct Token {
struct ParseTree {
struct Token token;
struct ParseTree* p;
struct ParseTree* lhs;
struct ParseTree* rhs;
int precedence;
};
size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol);

BIN
res/gb-icon-128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
res/gb-icon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

2
res/gb-icon.svg Normal file
View File

@ -0,0 +1,2 @@
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-1.9946)"><path d="m101.49 9.18c0-1.656-1.343-3-3-3h-64.262c-1.656 0-3 1.344-3 3v109.64c0 1.656 1.344 3 3 3h51.262c8.837 0 16-7.164 16-16v-96.64z" fill="#d8d6d1" stroke="#000" stroke-width="1px"/><g transform="matrix(1 0 5.5511e-17 1 0 .34429)"><path d="m31.5 12.156h69.989" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><path d="M72.2,121.82L101.489,106" fill="none" stroke="#f2ebe2" stroke-width="1px"/><g transform="translate(-.95405)"><path d="M96.408,6.18L96.5,12.5" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(-59.954)"><path d="M96.408,6.18L96.5,12.5" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><path d="m101.49 9.5c0-0.796-0.316-1.559-0.878-2.121-0.563-0.563-1.326-0.879-2.122-0.879h-64.989c-0.796 0-1.559 0.316-2.121 0.879-0.563 0.562-0.879 1.325-0.879 2.121v109c0 0.796 0.316 1.559 0.879 2.121 0.562 0.563 1.325 0.879 2.121 0.879h51.989c8.837 0 16-7.163 16-16v-96z" fill="none" stroke="#000" stroke-width="3px"/><g transform="matrix(.83673 -.3777 .31287 .69311 -23.362 51.852)"><path d="m61.877 104.68c0-0.726-0.488-1.315-1.089-1.315h-6.536c-0.601 0-1.089 0.589-1.089 1.315s0.488 1.315 1.089 1.315h6.536c0.601 0 1.089-0.589 1.089-1.315z" fill="#4e5247" stroke="#000" stroke-width="1.19px"/></g><g transform="matrix(.83673 -.3777 .31287 .69311 -11.362 51.852)"><path d="m61.877 104.68c0-0.726-0.488-1.315-1.089-1.315h-6.536c-0.601 0-1.089 0.589-1.089 1.315s0.488 1.315 1.089 1.315h6.536c0.601 0 1.089-0.589 1.089-1.315z" fill="#4e5247" stroke="#000" stroke-width="1.19px"/></g><circle cx="80.996" cy="87.339" r="3.822" fill="#c11c40" stroke="#000" stroke-width="1px"/><g transform="translate(11.504 -5.7393)"><circle cx="80.996" cy="87.339" r="3.822" fill="#c11c40" stroke="#000" stroke-width="1px"/></g><g transform="translate(-3.7654 1.1875)"><path d="m79.313 108.69 5.505 9.25" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(-.2654 -.5125)"><path d="m79.313 108.69 5.505 9.25" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(3.2346 -2.2125)"><path d="m79.313 108.69 5.505 9.25" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(6.7346 -3.9125)"><path d="m79.313 108.69 5.505 9.25" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(10.235 -5.6125)"><path d="m79.313 108.69 5.505 9.25" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(13.735 -7.3125)"><path d="m79.313 108.69 5.505 9.25" fill="none" stroke="#b9b4ad" stroke-width="1px"/></g><g transform="translate(0 .40778)"><path d="m96.5 18.203c0-1.104-0.895-2-2-2h-56.964c-1.105 0-2 0.896-2 2v40.778c0 1.105 0.895 2 2 2h49.964c4.971 0 9-4.029 9-9v-33.778z" fill="#848484" stroke="#000" stroke-width="1px"/></g><g transform="matrix(.98813 0 0 .99674 .59124 .25498)"><rect x="47.472" y="21.314" width="37.444" height="34.111" fill="#809a24" stroke="#000" stroke-width="1.01px"/></g><circle cx="40.583" cy="33.426" r="1.389" fill="#ff0025"/><path d="m48.5 82.456h6v5h-6v6h-5v-6h-6v-5h6v-6h5v6z" fill="#4e5247" stroke="#000" stroke-width="1px"/></g></svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
res/gba-icon-128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
res/gba-icon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

2
res/gba-icon.svg Normal file
View File

@ -0,0 +1,2 @@
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1.1259)"><path d="m115.98 43.503 1.894-0.666s-0.87-2.15-1.894-3.481-2.356-2.151-4.25-2.867c-1.894-0.717-7.834-0.82-10.496-1.434s-7.117-1.331-8.909-1.536-1.997 1.843-1.997 1.843l25.652 8.141z" fill="#a4a6b4" stroke="#000" stroke-width="1px"/><g transform="matrix(-1 0 0 1 128 0)"><path d="m115.98 43.503 1.894-0.666s-0.87-2.15-1.894-3.481-2.356-2.151-4.25-2.867c-1.894-0.717-7.834-0.82-10.496-1.434s-7.117-1.331-8.909-1.536-1.997 1.843-1.997 1.843l25.652 8.141z" fill="#a4a6b4" stroke="#000" stroke-width="1px"/></g><g transform="translate(1.55)"><path d="m62.45 97.95c9.766 0 23.582-1.214 29.8-3.2 1.966-0.628 4.816-2.128 6.8-2.6 4.2-1 8.8-2.6 13-4 3.78-1.26 5.739-4.265 6.4-7.2 1.6-7.1-1.6-32.6-2.2-34.9s-1.2-5.1-4.2-5.7-11.4-2.6-16.4-5.2-9.5-2.5-9.5-2.5-39.5-0.333-47.4 0c0 0-4.5-0.1-9.5 2.5s-13.4 4.6-16.4 5.2-3.6 3.4-4.2 5.7-3.8 27.8-2.2 34.9c0.661 2.935 2.62 5.94 6.4 7.2 4.2 1.4 8.8 3 13 4 1.984 0.472 4.834 1.972 6.8 2.6 6.218 1.986 20.034 3.2 29.8 3.2" fill="#aa86d5" stroke="#000" stroke-width="3px"/></g><g transform="translate(.1024 -.0512)"><circle cx="100.67" cy="43.964" r=".947" fill="#a0ff2a"/></g><path d="m64 39.462c-9.152 0-23.024 1.18-25.584 1.82s-2.687 1.92-2.944 3.264c-1.152 6.016-2.713 30.078-2.048 37.608 0.221 2.507 1.28 3.935 4.16 5.151 3.43 1.448 13.536 3.52 26.416 3.52s22.986-2.072 26.416-3.52c2.88-1.216 3.939-2.644 4.16-5.151 0.665-7.53-0.896-31.592-2.048-37.608-0.257-1.344-0.384-2.624-2.944-3.264s-16.432-1.82-25.584-1.82"/><g transform="matrix(1.0064 0 0 .98449 -.23513 1.695)"><rect x="38.984" y="44.803" width="49.68" height="33.52" fill="#a4a6b4" stroke="#000" stroke-width="1px"/></g><g transform="translate(.48 .30537)"><circle cx="100.79" cy="61.303" r="3.84" fill="#a4a6b4" stroke="#000" stroke-width="1px"/></g><g transform="translate(10.2 -3.5346)"><circle cx="100.79" cy="61.303" r="3.84" fill="#a4a6b4" stroke="#000" stroke-width="1px"/></g><g transform="matrix(.97364 .22811 -.22811 .97364 17.954 -4.6988)"><path d="m29.304 77.118h-8.619c-0.994 0-1.8-0.806-1.8-1.8 0-0.993 0.806-1.8 1.8-1.8h8.619c0.993 0 1.8 0.807 1.8 1.8 0 0.994-0.807 1.8-1.8 1.8z" fill="none" stroke="#986cc4" stroke-width="1px"/></g><g transform="translate(.24 1.7764e-15)"><circle cx="29.064" cy="75.318" r="1.8" fill="#a4a6b4" stroke="#000" stroke-width="1px"/></g><g transform="translate(0 6.4648)"><g transform="matrix(.97364 .22811 -.22811 .97364 17.954 -4.6988)"><path d="m29.304 77.118h-8.619c-0.994 0-1.8-0.806-1.8-1.8 0-0.993 0.806-1.8 1.8-1.8h8.619c0.993 0 1.8 0.807 1.8 1.8 0 0.994-0.807 1.8-1.8 1.8z" fill="none" stroke="#986cc4" stroke-width="1px"/></g><g transform="translate(.24 1.7764e-15)"><circle cx="29.064" cy="75.318" r="1.8" fill="#a4a6b4" stroke="#000" stroke-width="1px"/></g></g><g transform="matrix(1.0302 0 0 1.0302 -.40806 -2.0201)"><path d="m24.051 57.052h4.98v4.6h-4.98v4.98h-4.6v-4.98h-4.98v-4.6h4.98v-4.98h4.6v4.98z" fill="#a4a6b4" stroke="#000" stroke-width=".97px"/></g><path d="m97.413 74.335 11.879-2.783" fill="none" stroke="#986cc4" stroke-width="1px"/><g transform="translate(0 2.3565)"><path d="m97.413 74.335 11.879-2.783" fill="none" stroke="#986cc4" stroke-width="1px"/></g><g transform="translate(0 4.7565)"><path d="m97.413 74.335 11.879-2.783" fill="none" stroke="#986cc4" stroke-width="1px"/></g><g transform="translate(0 7.1565)"><path d="m97.413 74.335 11.879-2.783" fill="none" stroke="#986cc4" stroke-width="1px"/></g><g transform="translate(0 9.4565)"><path d="m97.413 74.335 11.879-2.783" fill="none" stroke="#986cc4" stroke-width="1px"/></g></g></svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
res/gbc-icon-128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
res/gbc-icon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

2
res/gbc-icon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -189,14 +189,12 @@ static struct ARMDebugBreakpoint* _lookupBreakpoint(struct ARMDebugBreakpointLis
static void _destroyBreakpoint(struct ARMDebugBreakpoint* breakpoint) {
if (breakpoint->d.condition) {
parseFree(breakpoint->d.condition);
free(breakpoint->d.condition);
}
}
static void _destroyWatchpoint(struct mWatchpoint* watchpoint) {
if (watchpoint->condition) {
parseFree(watchpoint->condition);
free(watchpoint->condition);
}
}

View File

@ -70,12 +70,21 @@ void mMapCacheDeinit(struct mMapCache* cache) {
void mMapCacheWriteVRAM(struct mMapCache* cache, uint32_t address) {
if (address >= cache->mapStart && address < cache->mapStart + cache->mapSize) {
uint32_t align = 1 << (mMapCacheSystemInfoGetWriteAlign(cache->sysConfig) - mMapCacheSystemInfoGetMapAlign(cache->sysConfig));
address -= cache->mapStart;
struct mMapCacheEntry* status = &cache->status[address >> mMapCacheSystemInfoGetMapAlign(cache->sysConfig)];
address >>= mMapCacheSystemInfoGetMapAlign(cache->sysConfig);
uint32_t i;
for (i = 0; i < align; ++i) {
if (address + i >= (cache->mapSize >> mMapCacheSystemInfoGetMapAlign(cache->sysConfig))) {
break;
}
struct mMapCacheEntry* status = &cache->status[address + i];
++status->vramVersion;
status->flags = mMapCacheEntryFlagsClearVramClean(status->flags);
status->tileStatus[mMapCacheEntryFlagsGetPaletteId(status->flags)].vramClean = 0;
}
}
}
static inline void _cleanTile(struct mMapCache* cache, const color_t* tile, color_t* mapOut, const struct mMapCacheEntry* status) {

View File

@ -226,11 +226,9 @@ static bool _parseExpression(struct mDebugger* debugger, struct CLIDebugVector*
}
if (!mDebuggerEvaluateParseTree(debugger, tree, intValue, segmentValue)) {
parseFree(tree);
free(tree);
return false;
}
parseFree(tree);
free(tree);
return true;
}
@ -599,7 +597,6 @@ static struct ParseTree* _parseTree(const char** string) {
if (error) {
if (tree) {
parseFree(tree);
free(tree);
}
return NULL;
} else {

View File

@ -11,6 +11,8 @@
DEFINE_VECTOR(LexVector, struct Token);
DEFINE_VECTOR(IntList, int32_t);
enum LexState {
LEX_ERROR = -1,
LEX_ROOT = 0,
@ -493,16 +495,21 @@ static const int _operatorPrecedence[] = {
[OP_DEREFERENCE] = 2,
};
static struct ParseTree* _parseTreeCreate() {
static struct ParseTree* _parseTreeCreate(void) {
struct ParseTree* tree = malloc(sizeof(struct ParseTree));
tree->token.type = TOKEN_ERROR_TYPE;
tree->rhs = 0;
tree->lhs = 0;
tree->p = NULL;
tree->rhs = NULL;
tree->lhs = NULL;
tree->precedence = INT_MAX;
return tree;
}
static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, size_t i, int precedence, int* openParens) {
struct ParseTree* newTree = 0;
static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, int* openParens) {
struct ParseTree* newTree = NULL;
bool pop = false;
int precedence = INT_MAX;
size_t i = 0;
while (i < LexVectorSize(lv)) {
struct Token* token = LexVectorGetPointer(lv, i);
int newPrecedence;
@ -517,27 +524,36 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, siz
++i;
} else {
tree->token.type = TOKEN_ERROR_TYPE;
return i + 1;
++i;
pop = true;
}
break;
case TOKEN_SEGMENT_TYPE:
tree->lhs = _parseTreeCreate();
tree->lhs->token.type = TOKEN_UINT_TYPE;
tree->lhs->token.uintValue = token->uintValue;
tree->lhs->p = tree;
tree->lhs->precedence = precedence;
tree->rhs = _parseTreeCreate();
tree->rhs->p = tree;
tree->rhs->precedence = precedence;
tree->token.type = TOKEN_SEGMENT_TYPE;
i = _parseExpression(tree->rhs, lv, i + 1, precedence, openParens);
tree = tree->rhs;
++i;
break;
case TOKEN_OPEN_PAREN_TYPE:
++*openParens;
i = _parseExpression(tree, lv, i + 1, INT_MAX, openParens);
precedence = INT_MAX;
++i;
break;
case TOKEN_CLOSE_PAREN_TYPE:
if (*openParens <= 0) {
tree->token.type = TOKEN_ERROR_TYPE;
}
--*openParens;
return i + 1;
++i;
pop = true;
break;
case TOKEN_OPERATOR_TYPE:
if (tree->token.type == TOKEN_ERROR_TYPE) {
switch (token->operatorValue) {
@ -557,21 +573,44 @@ static size_t _parseExpression(struct ParseTree* tree, struct LexVector* lv, siz
newPrecedence = _operatorPrecedence[token->operatorValue];
if (newPrecedence < precedence) {
newTree = _parseTreeCreate();
*newTree = *tree;
memcpy(newTree, tree, sizeof(*tree));
if (newTree->lhs) {
newTree->lhs->p = newTree;
}
if (newTree->rhs) {
newTree->rhs->p = newTree;
}
newTree->p = tree;
tree->lhs = newTree;
tree->rhs = _parseTreeCreate();
tree->rhs->p = tree;
tree->rhs->precedence = newPrecedence;
precedence = newPrecedence;
tree->token = *token;
i = _parseExpression(tree->rhs, lv, i + 1, newPrecedence, openParens);
if (tree->token.type == TOKEN_ERROR_TYPE) {
tree->token.type = TOKEN_ERROR_TYPE;
}
tree = tree->rhs;
++i;
} else {
return i;
pop = true;
}
break;
case TOKEN_ERROR_TYPE:
tree->token.type = TOKEN_ERROR_TYPE;
return i + 1;
++i;
pop = true;
break;
}
if (pop) {
if (tree->token.type == TOKEN_ERROR_TYPE && tree->p) {
tree->p->token.type = TOKEN_ERROR_TYPE;
}
tree = tree->p;
pop = false;
if (!tree) {
break;
} else {
precedence = tree->precedence;
}
}
}
@ -584,11 +623,13 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
}
tree->token.type = TOKEN_ERROR_TYPE;
tree->lhs = 0;
tree->rhs = 0;
tree->lhs = NULL;
tree->rhs = NULL;
tree->p = NULL;
tree->precedence = INT_MAX;
int openParens = 0;
_parseExpression(tree, lv, 0, INT_MAX, &openParens);
_parseExpression(tree, lv, &openParens);
if (openParens) {
if (tree->token.type == TOKEN_IDENTIFIER_TYPE) {
free(tree->token.identifierValue);
@ -607,23 +648,40 @@ void lexFree(struct LexVector* lv) {
}
}
void parseFree(struct ParseTree* tree) {
if (!tree) {
return;
}
if (tree->lhs) {
parseFree(tree->lhs);
free(tree->lhs);
}
if (tree->rhs) {
parseFree(tree->rhs);
free(tree->rhs);
}
static void _freeTree(struct ParseTree* tree) {
if (tree->token.type == TOKEN_IDENTIFIER_TYPE) {
free(tree->token.identifierValue);
}
free(tree);
}
void parseFree(struct ParseTree* tree) {
while (tree) {
if (tree->lhs) {
tree = tree->lhs;
continue;
}
if (tree->rhs) {
tree = tree->rhs;
continue;
}
if (tree->p) {
if (tree->p->lhs == tree) {
tree = tree->p;
_freeTree(tree->lhs);
tree->lhs = NULL;
} else if (tree->p->rhs == tree) {
tree = tree->p;
_freeTree(tree->rhs);
tree->rhs = NULL;
} else {
abort();
}
} else {
_freeTree(tree);
break;
}
}
}
static bool _performOperation(struct mDebugger* debugger, enum Operation operation, int32_t current, int32_t next, int32_t* value, int* segment) {
@ -721,19 +779,22 @@ bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tr
if (!value) {
return false;
}
int32_t lhs, rhs;
struct IntList stack;
int nextBranch;
bool ok = true;
int32_t tmpVal, tmpSegment;
IntListInit(&stack, 0);
while (ok) {
switch (tree->token.type) {
case TOKEN_UINT_TYPE:
if (segment) {
*segment = -1;
}
*value = tree->token.uintValue;
return true;
nextBranch = 2;
tmpSegment = -1;
tmpVal = tree->token.uintValue;
break;
case TOKEN_SEGMENT_TYPE:
if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, value, segment)) {
return false;
}
return mDebuggerEvaluateParseTree(debugger, tree->lhs, segment, NULL);
nextBranch = 0;
break;
case TOKEN_OPERATOR_TYPE:
switch (tree->token.operatorValue) {
case OP_ASSIGN:
@ -755,22 +816,87 @@ bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tr
case OP_GE:
case OP_SHIFT_L:
case OP_SHIFT_R:
if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) {
return false;
}
// Fall through
nextBranch = 0;
break;
default:
if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) {
return false;
}
nextBranch = 1;
break;
}
return _performOperation(debugger, tree->token.operatorValue, lhs, rhs, value, segment);
break;
case TOKEN_IDENTIFIER_TYPE:
return mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, value, segment);
if (!mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, &tmpVal, &tmpSegment)) {
ok = false;
}
nextBranch = 2;
break;
case TOKEN_ERROR_TYPE:
default:
ok = false;
break;
}
return false;
if (!ok) {
break;
}
bool gotTree = false;
while (!gotTree && tree) {
int32_t lhs, rhs;
switch (nextBranch) {
case 0:
*IntListAppend(&stack) = tmpVal;
*IntListAppend(&stack) = tmpSegment;
*IntListAppend(&stack) = nextBranch;
tree = tree->lhs;
gotTree = true;
break;
case 1:
*IntListAppend(&stack) = tmpVal;
*IntListAppend(&stack) = tmpSegment;
*IntListAppend(&stack) = nextBranch;
tree = tree->rhs;
gotTree = true;
break;
case 2:
if (!IntListSize(&stack)) {
tree = NULL;
break;
}
nextBranch = *IntListGetPointer(&stack, IntListSize(&stack) - 1);
IntListResize(&stack, -1);
tree = tree->p;
if (nextBranch == 0) {
++nextBranch;
} else if (tree) {
nextBranch = 2;
switch (tree->token.type) {
case TOKEN_OPERATOR_TYPE:
rhs = tmpVal;
lhs = *IntListGetPointer(&stack, IntListSize(&stack) - 2);
tmpSegment = *IntListGetPointer(&stack, IntListSize(&stack) - 1);
ok = _performOperation(debugger, tree->token.operatorValue, lhs, rhs, &tmpVal, &tmpSegment);
break;
case TOKEN_SEGMENT_TYPE:
tmpSegment = *IntListGetPointer(&stack, IntListSize(&stack) - 2);
break;
default:
break;
}
}
IntListResize(&stack, -2);
break;
}
}
if (!tree) {
break;
}
}
IntListDeinit(&stack);
if (ok) {
*value = tmpVal;
if (segment) {
*segment = tmpSegment;
}
}
return ok;
}

View File

@ -9,7 +9,7 @@
struct LPTest {
struct LexVector lv;
struct ParseTree tree;
struct ParseTree* tree;
};
#define PARSE(STR) \
@ -18,7 +18,8 @@ struct LPTest {
LexVectorClear(&lp->lv); \
size_t adjusted = lexExpression(&lp->lv, STR, strlen(STR), ""); \
assert_false(adjusted > strlen(STR)); \
struct ParseTree* tree = &lp->tree; \
lp->tree = malloc(sizeof(*lp->tree)); \
struct ParseTree* tree = lp->tree; \
parseLexedExpression(tree, &lp->lv)
static int parseSetup(void** state) {
@ -30,7 +31,7 @@ static int parseSetup(void** state) {
static int parseTeardown(void** state) {
struct LPTest* lp = *state;
parseFree(&lp->tree);
parseFree(lp->tree);
lexFree(&lp->lv);
LexVectorDeinit(&lp->lv);
free(lp);

View File

@ -119,6 +119,7 @@ void GBVideoCacheWriteVideoRegister(struct mCacheSet* cache, uint16_t address, u
sysconfig = mMapCacheSystemInfoSetMacroTileSize(sysconfig, 5);
sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 1);
sysconfig = mMapCacheSystemInfoSetMapAlign(sysconfig, 0);
sysconfig = mMapCacheSystemInfoSetWriteAlign(sysconfig, 0);
sysconfig = mMapCacheSystemInfoSetTilesHigh(sysconfig, 5);
sysconfig = mMapCacheSystemInfoSetTilesWide(sysconfig, 5);
mMapCacheConfigureSystem(map, sysconfig);

View File

@ -160,7 +160,7 @@ static void GBAVideoCacheWriteBGCNT(struct mCacheSet* cache, size_t bg, uint16_t
int size = GBARegisterBGCNTGetSize(value);
int tilesWide = 0;
int tilesHigh = 0;
mMapCacheSystemInfo sysconfig = 0;
mMapCacheSystemInfo sysconfig = mMapCacheSystemInfoSetWriteAlign(0, 1);
if (map->mapParser == mapParser0) {
map->tileCache = mTileCacheSetGetPointer(&cache->tiles, p);
sysconfig = mMapCacheSystemInfoSetPaletteBPP(sysconfig, 2 + p);

View File

@ -1808,9 +1808,9 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
glUniformMatrix2fv(uniforms[GBA_GL_OBJ_TRANSFORM], 1, GL_FALSE, (GLfloat[]) { flipX, 0, 0, flipY });
}
glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight);
glDisable(GL_STENCIL_TEST);
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) {
// OBJWIN writes do not affect pixel priority
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glStencilMask(0);
@ -1818,6 +1818,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
glUniform3i(uniforms[GBA_GL_OBJ_OBJWIN], window, renderer->bldb, renderer->bldy);
glDrawBuffers(3, (GLenum[]) { GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2 });
} else {
glEnable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glStencilMask(1);
@ -1842,7 +1843,6 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
// Update the pixel priority for already-written pixels
shader = &renderer->objShader[2];
uniforms = shader->uniforms;
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 1);
glUseProgram(shader->program);
glDrawBuffers(2, (GLenum[]) { GL_NONE, GL_COLOR_ATTACHMENT1 });

View File

@ -28,14 +28,12 @@ static struct mBreakpoint* _lookupBreakpoint(struct mBreakpointList* breakpoints
static void _destroyBreakpoint(struct mBreakpoint* breakpoint) {
if (breakpoint->condition) {
parseFree(breakpoint->condition);
free(breakpoint->condition);
}
}
static void _destroyWatchpoint(struct mWatchpoint* watchpoint) {
if (watchpoint->condition) {
parseFree(watchpoint->condition);
free(watchpoint->condition);
}
}