some more formating things etc

This commit is contained in:
Zach Bacon 2016-07-09 09:53:13 -04:00
parent a49edee427
commit 48086ba62f
No known key found for this signature in database
GPG Key ID: 7D110798AFE84B3A
16 changed files with 8443 additions and 9028 deletions

File diff suppressed because it is too large Load Diff

View File

@ -19,29 +19,29 @@ typedef union {
extern gbRegister AF, BC, DE, HL, SP, PC; extern gbRegister AF, BC, DE, HL, SP, PC;
extern uint16_t IFF; extern uint16_t IFF;
int gbDis(char *, u16); int gbDis(char*, u16);
bool gbLoadRom(const char *); bool gbLoadRom(const char*);
bool gbUpdateSizes(); bool gbUpdateSizes();
void gbEmulate(int); void gbEmulate(int);
void gbWriteMemory(register uint16_t, register uint8_t); void gbWriteMemory(register uint16_t, register uint8_t);
void gbDrawLine(); void gbDrawLine();
bool gbIsGameboyRom(const char *); bool gbIsGameboyRom(const char*);
void gbGetHardwareType(); void gbGetHardwareType();
void gbReset(); void gbReset();
void gbCleanUp(); void gbCleanUp();
void gbCPUInit(const char *, bool); void gbCPUInit(const char*, bool);
bool gbWriteBatteryFile(const char *); bool gbWriteBatteryFile(const char*);
bool gbWriteBatteryFile(const char *, bool); bool gbWriteBatteryFile(const char*, bool);
bool gbReadBatteryFile(const char *); bool gbReadBatteryFile(const char*);
bool gbWriteSaveState(const char *); bool gbWriteSaveState(const char*);
bool gbWriteMemSaveState(char *, int, long &); bool gbWriteMemSaveState(char*, int, long&);
bool gbReadSaveState(const char *); bool gbReadSaveState(const char*);
bool gbReadMemSaveState(char *, int); bool gbReadMemSaveState(char*, int);
void gbSgbRenderBorder(); void gbSgbRenderBorder();
bool gbWritePNGFile(const char *); bool gbWritePNGFile(const char*);
bool gbWriteBMPFile(const char *); bool gbWriteBMPFile(const char*);
bool gbReadGSASnapshot(const char *); bool gbReadGSASnapshot(const char*);
extern int gbHardware; extern int gbHardware;

View File

@ -1,31 +1,31 @@
#include <string.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <string.h>
#include "../System.h"
#include "../NLS.h" #include "../NLS.h"
#include "../System.h"
#include "../Util.h" #include "../Util.h"
#include "../common/ConfigManager.h"
#include "gb.h"
#include "gbCheats.h" #include "gbCheats.h"
#include "gbGlobals.h" #include "gbGlobals.h"
#include "gb.h"
#include "../common/ConfigManager.h"
gbCheat gbCheatList[MAX_CHEATS]; gbCheat gbCheatList[MAX_CHEATS];
int gbCheatNumber = 0; int gbCheatNumber = 0;
int gbNextCheat = 0; int gbNextCheat = 0;
bool gbCheatMap[0x10000]; bool gbCheatMap[0x10000];
#define GBCHEAT_IS_HEX(a) ( ((a)>='A' && (a) <='F') || ((a) >='0' && (a) <= '9')) #define GBCHEAT_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9'))
#define GBCHEAT_HEX_VALUE(a) ( (a) >= 'A' ? (a) - 'A' + 10 : (a) - '0') #define GBCHEAT_HEX_VALUE(a) ((a) >= 'A' ? (a) - 'A' + 10 : (a) - '0')
void gbCheatUpdateMap() void gbCheatUpdateMap()
{ {
memset(gbCheatMap, 0, 0x10000); memset(gbCheatMap, 0, 0x10000);
for(int i = 0; i < gbCheatNumber; i++) { for (int i = 0; i < gbCheatNumber; i++) {
if(gbCheatList[i].enabled) if (gbCheatList[i].enabled)
gbCheatMap[gbCheatList[i].address] = true; gbCheatMap[gbCheatList[i].address] = true;
} }
} }
@ -33,80 +33,78 @@ void gbCheatUpdateMap()
void gbCheatsSaveGame(gzFile gzFile) void gbCheatsSaveGame(gzFile gzFile)
{ {
utilWriteInt(gzFile, gbCheatNumber); utilWriteInt(gzFile, gbCheatNumber);
if(gbCheatNumber>0) if (gbCheatNumber > 0)
utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat) * gbCheatNumber);
} }
void gbCheatsReadGame(gzFile gzFile, int version) void gbCheatsReadGame(gzFile gzFile, int version)
{ {
if(version <= 8) { if (version <= 8) {
int gbGgOn = utilReadInt(gzFile); int gbGgOn = utilReadInt(gzFile);
if(gbGgOn) { if (gbGgOn) {
int n = utilReadInt(gzFile); int n = utilReadInt(gzFile);
gbXxCheat tmpCheat; gbXxCheat tmpCheat;
for(int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat)); utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat));
gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
} }
} }
int gbGsOn = utilReadInt(gzFile); int gbGsOn = utilReadInt(gzFile);
if(gbGsOn) { if (gbGsOn) {
int n = utilReadInt(gzFile); int n = utilReadInt(gzFile);
gbXxCheat tmpCheat; gbXxCheat tmpCheat;
for(int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat)); utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat));
gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc); gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
} }
} }
} else { } else {
gbCheatNumber = utilReadInt(gzFile); gbCheatNumber = utilReadInt(gzFile);
if(gbCheatNumber>0) { if (gbCheatNumber > 0) {
utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber); utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat) * gbCheatNumber);
} }
} }
gbCheatUpdateMap(); gbCheatUpdateMap();
} }
void gbCheatsReadGameSkip(gzFile gzFile, int version) void gbCheatsReadGameSkip(gzFile gzFile, int version)
{ {
if( version <= 8 ) { if (version <= 8) {
int gbGgOn = utilReadInt( gzFile ); int gbGgOn = utilReadInt(gzFile);
if( gbGgOn ) { if (gbGgOn) {
int n = utilReadInt( gzFile ); int n = utilReadInt(gzFile);
if( n > 0 ) { if (n > 0) {
utilGzSeek( gzFile, n * sizeof(gbXxCheat), SEEK_CUR ); utilGzSeek(gzFile, n * sizeof(gbXxCheat), SEEK_CUR);
} }
} }
int gbGsOn = utilReadInt( gzFile ); int gbGsOn = utilReadInt(gzFile);
if( gbGsOn ) { if (gbGsOn) {
int n = utilReadInt(gzFile); int n = utilReadInt(gzFile);
if( n > 0 ) { if (n > 0) {
utilGzSeek( gzFile, n * sizeof(gbXxCheat), SEEK_CUR ); utilGzSeek(gzFile, n * sizeof(gbXxCheat), SEEK_CUR);
} }
} }
} else { } else {
int n = utilReadInt( gzFile ); int n = utilReadInt(gzFile);
if( n > 0 ) { if (n > 0) {
utilGzSeek( gzFile, n * sizeof(gbCheat), SEEK_CUR ); utilGzSeek(gzFile, n * sizeof(gbCheat), SEEK_CUR);
} }
} }
} }
void gbCheatsSaveCheatList(const char* file)
void gbCheatsSaveCheatList(const char *file)
{ {
if(gbCheatNumber == 0) if (gbCheatNumber == 0)
return; return;
FILE *f = fopen(file, "wb"); FILE* f = fopen(file, "wb");
if(f == NULL) if (f == NULL)
return; return;
int version = 1; int version = 1;
fwrite(&version, 1, sizeof(version), f); fwrite(&version, 1, sizeof(version), f);
@ -117,7 +115,7 @@ void gbCheatsSaveCheatList(const char *file)
fclose(f); fclose(f);
} }
bool gbCheatsLoadCheatList(const char *file) bool gbCheatsLoadCheatList(const char* file)
{ {
gbCheatNumber = 0; gbCheatNumber = 0;
@ -125,19 +123,19 @@ bool gbCheatsLoadCheatList(const char *file)
int count = 0; int count = 0;
FILE *f = fopen(file, "rb"); FILE* f = fopen(file, "rb");
if(f == NULL) if (f == NULL)
return false; return false;
int version = 0; int version = 0;
if(fread(&version, 1, sizeof(version), f) != sizeof(version)) { if (fread(&version, 1, sizeof(version), f) != sizeof(version)) {
fclose(f); fclose(f);
return false; return false;
} }
if(version != 1) { if (version != 1) {
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION, systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
N_("Unsupported cheat list version %d"), version); N_("Unsupported cheat list version %d"), version);
fclose(f); fclose(f);
@ -145,24 +143,24 @@ bool gbCheatsLoadCheatList(const char *file)
} }
int type = 0; int type = 0;
if(fread(&type, 1, sizeof(type), f) != sizeof(type)) { if (fread(&type, 1, sizeof(type), f) != sizeof(type)) {
fclose(f); fclose(f);
return false; return false;
} }
if(type != 1) { if (type != 1) {
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE, systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
N_("Unsupported cheat list type %d"), type); N_("Unsupported cheat list type %d"), type);
fclose(f); fclose(f);
return false; return false;
} }
if(fread(&count, 1, sizeof(count), f) != sizeof(count)) { if (fread(&count, 1, sizeof(count), f) != sizeof(count)) {
fclose(f); fclose(f);
return false; return false;
} }
if(fread(gbCheatList, 1, sizeof(gbCheatList), f) > sizeof(gbCheatList)) { if (fread(gbCheatList, 1, sizeof(gbCheatList), f) > sizeof(gbCheatList)) {
fclose(f); fclose(f);
return false; return false;
} }
@ -173,21 +171,21 @@ bool gbCheatsLoadCheatList(const char *file)
return true; return true;
} }
bool gbVerifyGsCode(const char *code) bool gbVerifyGsCode(const char* code)
{ {
size_t len = strlen(code); size_t len = strlen(code);
if(len == 0) if (len == 0)
return true; return true;
if(len != 8) if (len != 8)
return false; return false;
for(int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
if(!GBCHEAT_IS_HEX(code[i])) if (!GBCHEAT_IS_HEX(code[i]))
return false; return false;
/* int address = GBCHEAT_HEX_VALUE(code[6]) << 12 | /* int address = GBCHEAT_HEX_VALUE(code[6]) << 12 |
GBCHEAT_HEX_VALUE(code[7]) << 8 | GBCHEAT_HEX_VALUE(code[7]) << 8 |
GBCHEAT_HEX_VALUE(code[4]) << 4 | GBCHEAT_HEX_VALUE(code[4]) << 4 |
GBCHEAT_HEX_VALUE(code[5]);*/ GBCHEAT_HEX_VALUE(code[5]);*/
@ -195,15 +193,15 @@ bool gbVerifyGsCode(const char *code)
return true; return true;
} }
bool gbAddGsCheat(const char *code, const char *desc) bool gbAddGsCheat(const char* code, const char* desc)
{ {
if(gbCheatNumber > (MAX_CHEATS - 1)) { if (gbCheatNumber > (MAX_CHEATS - 1)) {
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached.")); N_("Maximum number of cheats reached."));
return false; return false;
} }
if(!gbVerifyGsCode(code)) { if (!gbVerifyGsCode(code)) {
systemMessage(MSG_INVALID_GAMESHARK_CODE, systemMessage(MSG_INVALID_GAMESHARK_CODE,
N_("Invalid GameShark code: %s"), code); N_("Invalid GameShark code: %s"), code);
return false; return false;
@ -214,16 +212,11 @@ bool gbAddGsCheat(const char *code, const char *desc)
strcpy(gbCheatList[i].cheatCode, code); strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc); strcpy(gbCheatList[i].cheatDesc, desc);
gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 | gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 | GBCHEAT_HEX_VALUE(code[1]);
GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 | gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 | GBCHEAT_HEX_VALUE(code[3]);
GBCHEAT_HEX_VALUE(code[3]);
gbCheatList[i].address = GBCHEAT_HEX_VALUE(code[6]) << 12 | gbCheatList[i].address = GBCHEAT_HEX_VALUE(code[6]) << 12 | GBCHEAT_HEX_VALUE(code[7]) << 8 | GBCHEAT_HEX_VALUE(code[4]) << 4 | GBCHEAT_HEX_VALUE(code[5]);
GBCHEAT_HEX_VALUE(code[7]) << 8 |
GBCHEAT_HEX_VALUE(code[4]) << 4 |
GBCHEAT_HEX_VALUE(code[5]);
gbCheatList[i].compare = 0; gbCheatList[i].compare = 0;
@ -231,11 +224,10 @@ bool gbAddGsCheat(const char *code, const char *desc)
int gsCode = gbCheatList[i].code; int gsCode = gbCheatList[i].code;
if ((gsCode !=1) && ((gsCode & 0xF0) !=0x80) && ((gsCode & 0xF0) !=0x90) && if ((gsCode != 1) && ((gsCode & 0xF0) != 0x80) && ((gsCode & 0xF0) != 0x90) && ((gsCode & 0xF0) != 0xA0) && ((gsCode) != 0xF0) && ((gsCode) != 0xF1))
((gsCode & 0xF0) !=0xA0) && ((gsCode) !=0xF0) && ((gsCode) !=0xF1))
systemMessage(MSG_WRONG_GAMESHARK_CODE, systemMessage(MSG_WRONG_GAMESHARK_CODE,
N_("Wrong GameShark code type : %s"), code); N_("Wrong GameShark code type : %s"), code);
else if (((gsCode & 0xF0) ==0xA0) || ((gsCode) ==0xF0) || ((gsCode) ==0xF1)) else if (((gsCode & 0xF0) == 0xA0) || ((gsCode) == 0xF0) || ((gsCode) == 0xF1))
systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE, systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE,
N_("Unsupported GameShark code type : %s"), code); N_("Unsupported GameShark code type : %s"), code);
@ -244,42 +236,39 @@ bool gbAddGsCheat(const char *code, const char *desc)
return true; return true;
} }
bool gbVerifyGgCode(const char *code) bool gbVerifyGgCode(const char* code)
{ {
size_t len = strlen(code); size_t len = strlen(code);
if(len != 11 && if (len != 11 && len != 7 && len != 6 && len != 0)
len != 7 &&
len != 6 &&
len != 0)
return false; return false;
if(len == 0) if (len == 0)
return true; return true;
if(!GBCHEAT_IS_HEX(code[0])) if (!GBCHEAT_IS_HEX(code[0]))
return false; return false;
if(!GBCHEAT_IS_HEX(code[1])) if (!GBCHEAT_IS_HEX(code[1]))
return false; return false;
if(!GBCHEAT_IS_HEX(code[2])) if (!GBCHEAT_IS_HEX(code[2]))
return false; return false;
if(code[3] != '-') if (code[3] != '-')
return false; return false;
if(!GBCHEAT_IS_HEX(code[4])) if (!GBCHEAT_IS_HEX(code[4]))
return false; return false;
if(!GBCHEAT_IS_HEX(code[5])) if (!GBCHEAT_IS_HEX(code[5]))
return false; return false;
if(!GBCHEAT_IS_HEX(code[6])) if (!GBCHEAT_IS_HEX(code[6]))
return false; return false;
if(code[7] != 0) { if (code[7] != 0) {
if(code[7] != '-') if (code[7] != '-')
return false; return false;
if(code[8] != 0) { if (code[8] != 0) {
if(!GBCHEAT_IS_HEX(code[8])) if (!GBCHEAT_IS_HEX(code[8]))
return false; return false;
if(!GBCHEAT_IS_HEX(code[9])) if (!GBCHEAT_IS_HEX(code[9]))
return false; return false;
if(!GBCHEAT_IS_HEX(code[10])) if (!GBCHEAT_IS_HEX(code[10]))
return false; return false;
} }
} }
@ -287,43 +276,39 @@ bool gbVerifyGgCode(const char *code)
// int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) + // int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
// GBCHEAT_HEX_VALUE(code[1]); // GBCHEAT_HEX_VALUE(code[1]);
int address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + int address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + (GBCHEAT_HEX_VALUE(code[4]) << 4) + (GBCHEAT_HEX_VALUE(code[5])) + ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12);
(GBCHEAT_HEX_VALUE(code[4]) << 4) +
(GBCHEAT_HEX_VALUE(code[5])) +
((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12);
if(address >= 0x8000 && address <= 0x9fff) if (address >= 0x8000 && address <= 0x9fff)
return false; return false;
if(address >= 0xc000) if (address >= 0xc000)
return false; return false;
if(code[7] == 0 || code[8] == '0') if (code[7] == 0 || code[8] == '0')
return true; return true;
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + (GBCHEAT_HEX_VALUE(code[10]));
(GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff; compare = compare ^ 0xff;
compare = (compare >> 2) | ( (compare << 6) & 0xc0); compare = (compare >> 2) | ((compare << 6) & 0xc0);
compare ^= 0x45; compare ^= 0x45;
int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9])); int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9]));
if(cloak >=1 && cloak <= 7) if (cloak >= 1 && cloak <= 7)
return false; return false;
return true; return true;
} }
bool gbAddGgCheat(const char *code, const char *desc) bool gbAddGgCheat(const char* code, const char* desc)
{ {
if(gbCheatNumber > (MAX_CHEATS - 1)) { if (gbCheatNumber > (MAX_CHEATS - 1)) {
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS, systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached.")); N_("Maximum number of cheats reached."));
return false; return false;
} }
if(!gbVerifyGgCode(code)) { if (!gbVerifyGgCode(code)) {
systemMessage(MSG_INVALID_GAMEGENIE_CODE, systemMessage(MSG_INVALID_GAMEGENIE_CODE,
N_("Invalid GameGenie code: %s"), code); N_("Invalid GameGenie code: %s"), code);
return false; return false;
@ -337,31 +322,24 @@ bool gbAddGgCheat(const char *code, const char *desc)
strcpy(gbCheatList[i].cheatDesc, desc); strcpy(gbCheatList[i].cheatDesc, desc);
gbCheatList[i].code = 0x101; gbCheatList[i].code = 0x101;
gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + GBCHEAT_HEX_VALUE(code[1]);
GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + gbCheatList[i].address = (GBCHEAT_HEX_VALUE(code[2]) << 8) + (GBCHEAT_HEX_VALUE(code[4]) << 4) + (GBCHEAT_HEX_VALUE(code[5])) + ((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12);
(GBCHEAT_HEX_VALUE(code[4]) << 4) +
(GBCHEAT_HEX_VALUE(code[5])) +
((GBCHEAT_HEX_VALUE(code[6]) ^ 0x0f) << 12);
gbCheatList[i].compare = 0; gbCheatList[i].compare = 0;
if(len != 7 && len != 8) { if (len != 7 && len != 8) {
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + (GBCHEAT_HEX_VALUE(code[10]));
(GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff; compare = compare ^ 0xff;
compare = (compare >> 2) | ( (compare << 6) & 0xc0); compare = (compare >> 2) | ((compare << 6) & 0xc0);
compare ^= 0x45; compare ^= 0x45;
gbCheatList[i].compare = compare; gbCheatList[i].compare = compare;
//gbCheatList[i].code = 0; //gbCheatList[i].code = 0;
gbCheatList[i].code = 0x100; // fix for compare value gbCheatList[i].code = 0x100; // fix for compare value
} }
gbCheatList[i].enabled = true; gbCheatList[i].enabled = true;
gbCheatMap[gbCheatList[i].address] = true; gbCheatMap[gbCheatList[i].address] = true;
@ -373,15 +351,14 @@ bool gbAddGgCheat(const char *code, const char *desc)
void gbCheatRemove(int i) void gbCheatRemove(int i)
{ {
if(i < 0 || i >= gbCheatNumber) { if (i < 0 || i >= gbCheatNumber) {
systemMessage(MSG_INVALID_CHEAT_TO_REMOVE, systemMessage(MSG_INVALID_CHEAT_TO_REMOVE,
N_("Invalid cheat to remove %d"), i); N_("Invalid cheat to remove %d"), i);
return; return;
} }
if((i+1) < gbCheatNumber) { if ((i + 1) < gbCheatNumber) {
memcpy(&gbCheatList[i], &gbCheatList[i+1], sizeof(gbCheat)* memcpy(&gbCheatList[i], &gbCheatList[i + 1], sizeof(gbCheat) * (gbCheatNumber - i - 1));
(gbCheatNumber-i-1));
} }
gbCheatNumber--; gbCheatNumber--;
@ -397,8 +374,8 @@ void gbCheatRemoveAll()
void gbCheatEnable(int i) void gbCheatEnable(int i)
{ {
if(i >=0 && i < gbCheatNumber) { if (i >= 0 && i < gbCheatNumber) {
if(!gbCheatList[i].enabled) { if (!gbCheatList[i].enabled) {
gbCheatList[i].enabled = true; gbCheatList[i].enabled = true;
gbCheatUpdateMap(); gbCheatUpdateMap();
} }
@ -407,19 +384,19 @@ void gbCheatEnable(int i)
void gbCheatDisable(int i) void gbCheatDisable(int i)
{ {
if(i >=0 && i < gbCheatNumber) { if (i >= 0 && i < gbCheatNumber) {
if(gbCheatList[i].enabled) { if (gbCheatList[i].enabled) {
gbCheatList[i].enabled = false; gbCheatList[i].enabled = false;
gbCheatUpdateMap(); gbCheatUpdateMap();
} }
} }
} }
bool gbCheatReadGSCodeFile(const char *fileName) bool gbCheatReadGSCodeFile(const char* fileName)
{ {
FILE *file = fopen(fileName, "rb"); FILE* file = fopen(fileName, "rb");
if(!file) { if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
return false; return false;
} }
@ -432,7 +409,7 @@ bool gbCheatReadGSCodeFile(const char *fileName)
char desc[13]; char desc[13];
char code[9]; char code[9];
int i; int i;
for(i = 0; i < count; i++) { for (i = 0; i < count; i++) {
fread(&dummy, 1, 2, file); fread(&dummy, 1, 2, file);
fread(desc, 1, 12, file); fread(desc, 1, 12, file);
desc[12] = 0; desc[12] = 0;
@ -441,7 +418,7 @@ bool gbCheatReadGSCodeFile(const char *fileName)
gbAddGsCheat(code, desc); gbAddGsCheat(code, desc);
} }
for(i = 0; i < gbCheatNumber; i++) for (i = 0; i < gbCheatNumber; i++)
gbCheatDisable(i); gbCheatDisable(i);
fclose(file); fclose(file);
@ -449,16 +426,16 @@ bool gbCheatReadGSCodeFile(const char *fileName)
} }
// Used to emulated GG codes // Used to emulated GG codes
u8 gbCheatRead(u16 address) uint8_t gbCheatRead(uint16_t address)
{ {
if(!cheatsEnabled) if (!cheatsEnabled)
return gbMemoryMap[address>>12][address & 0xFFF]; return gbMemoryMap[address >> 12][address & 0xFFF];
for(int i = 0; i < gbCheatNumber; i++) { for (int i = 0; i < gbCheatNumber; i++) {
if(gbCheatList[i].enabled && gbCheatList[i].address == address) { if (gbCheatList[i].enabled && gbCheatList[i].address == address) {
switch(gbCheatList[i].code) { switch (gbCheatList[i].code) {
case 0x100: // GameGenie support case 0x100: // GameGenie support
if(gbMemoryMap[address>>12][address&0xFFF] == gbCheatList[i].compare) if (gbMemoryMap[address >> 12][address & 0xFFF] == gbCheatList[i].compare)
return gbCheatList[i].value; return gbCheatList[i].value;
break; break;
case 0x101: // GameGenie 6 digits code support case 0x101: // GameGenie 6 digits code support
@ -467,29 +444,26 @@ u8 gbCheatRead(u16 address)
} }
} }
} }
return gbMemoryMap[address>>12][address&0xFFF]; return gbMemoryMap[address >> 12][address & 0xFFF];
} }
// Used to emulate GS codes. // Used to emulate GS codes.
void gbCheatWrite(bool reboot) void gbCheatWrite(bool reboot)
{ {
if(cheatsEnabled) if (cheatsEnabled) {
{
u16 address = 0; u16 address = 0;
if (gbNextCheat >= gbCheatNumber) if (gbNextCheat >= gbCheatNumber)
gbNextCheat = 0; gbNextCheat = 0;
for(int i = gbNextCheat; i < gbCheatNumber; i++) { for (int i = gbNextCheat; i < gbCheatNumber; i++) {
if(gbCheatList[i].enabled) { if (gbCheatList[i].enabled) {
address = gbCheatList[i].address; address = gbCheatList[i].address;
if ((!reboot) && (address >= 0x8000) && !((address>=0xA000) && (address<0xC000))) if ((!reboot) && (address >= 0x8000) && !((address >= 0xA000) && (address < 0xC000))) { // These codes are executed one per one, at each Vblank
{ // These codes are executed one per one, at each Vblank switch (gbCheatList[i].code) {
switch(gbCheatList[i].code) {
case 0x01: case 0x01:
gbWriteMemory(address, gbCheatList[i].value); gbWriteMemory(address, gbCheatList[i].value);
gbNextCheat = i+1; gbNextCheat = i + 1;
return; return;
case 0x90: case 0x90:
case 0x91: case 0x91:
@ -511,18 +485,17 @@ void gbCheatWrite(bool reboot)
gbWriteMemory(0xff70, gbCheatList[i].code & 0xf); gbWriteMemory(0xff70, gbCheatList[i].code & 0xf);
gbWriteMemory(address, gbCheatList[i].value); gbWriteMemory(address, gbCheatList[i].value);
gbWriteMemory(0xff70, oldbank); gbWriteMemory(0xff70, oldbank);
gbNextCheat = i+1; gbNextCheat = i + 1;
return; return;
} }
} } else // These codes are only executed when the game is booted
else // These codes are only executed when the game is booted
{ {
switch(gbCheatList[i].code & 0xF0) { switch (gbCheatList[i].code & 0xF0) {
case 0x80: case 0x80:
gbWriteMemory(0x0000, 0x0A); gbWriteMemory(0x0000, 0x0A);
gbWriteMemory(0x4000, gbCheatList[i].value & 0xF); gbWriteMemory(0x4000, gbCheatList[i].value & 0xF);
gbWriteMemory(address, gbCheatList[i].value); gbWriteMemory(address, gbCheatList[i].value);
gbNextCheat = i+1; gbNextCheat = i + 1;
return; return;
} }
} }

View File

@ -12,30 +12,30 @@ struct gbXxCheat {
struct gbCheat { struct gbCheat {
char cheatCode[20]; char cheatCode[20];
char cheatDesc[32]; char cheatDesc[32];
u16 address; uint16_t address;
int code; int code;
u8 compare; uint8_t compare;
u8 value; uint8_t value;
bool enabled; bool enabled;
}; };
void gbCheatsSaveGame(gzFile); void gbCheatsSaveGame(gzFile);
void gbCheatsReadGame(gzFile, int); void gbCheatsReadGame(gzFile, int);
void gbCheatsReadGameSkip(gzFile, int); void gbCheatsReadGameSkip(gzFile, int);
void gbCheatsSaveCheatList(const char *); void gbCheatsSaveCheatList(const char*);
bool gbCheatsLoadCheatList(const char *); bool gbCheatsLoadCheatList(const char*);
bool gbCheatReadGSCodeFile(const char *); bool gbCheatReadGSCodeFile(const char*);
bool gbAddGsCheat(const char *, const char *); bool gbAddGsCheat(const char*, const char*);
bool gbAddGgCheat(const char *, const char *); bool gbAddGgCheat(const char*, const char*);
void gbCheatRemove(int); void gbCheatRemove(int);
void gbCheatRemoveAll(); void gbCheatRemoveAll();
void gbCheatEnable(int); void gbCheatEnable(int);
void gbCheatDisable(int); void gbCheatDisable(int);
u8 gbCheatRead(u16); uint8_t gbCheatRead(u16);
void gbCheatWrite(bool); void gbCheatWrite(bool);
bool gbVerifyGsCode(const char *code); bool gbVerifyGsCode(const char* code);
bool gbVerifyGgCode(const char *code); bool gbVerifyGgCode(const char* code);
extern int gbCheatNumber; extern int gbCheatNumber;
extern gbCheat gbCheatList[MAX_CHEATS]; extern gbCheat gbCheatList[MAX_CHEATS];

View File

@ -22,8 +22,7 @@ break;
case 0x05: case 0x05:
// DEC B // DEC B
BC.B.B1--; BC.B.B1--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B1] | ((BC.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B1] | ((BC.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x06: case 0x06:
// LD B, NN // LD B, NN
@ -45,8 +44,7 @@ break;
case 0x09: case 0x09:
// ADD HL,BC // ADD HL,BC
tempRegister.W = (HL.W + BC.W) & 0xFFFF; tempRegister.W = (HL.W + BC.W) & 0xFFFF;
AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ BC.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ BC.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | (((long)HL.W + (long)BC.W) & 0x10000 ? C_FLAG : 0);
(((long)HL.W + (long)BC.W) & 0x10000 ? C_FLAG : 0);
HL.W = tempRegister.W; HL.W = tempRegister.W;
break; break;
case 0x0a: case 0x0a:
@ -65,8 +63,7 @@ break;
case 0x0d: case 0x0d:
// DEC C // DEC C
BC.B.B0--; BC.B.B0--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B0] | ((BC.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B0] | ((BC.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x0e: case 0x0e:
// LD C, NN // LD C, NN
@ -114,8 +111,7 @@ break;
case 0x15: case 0x15:
// DEC D // DEC D
DE.B.B1--; DE.B.B1--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B1] | ((DE.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B1] | ((DE.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x16: case 0x16:
// LD D,NN // LD D,NN
@ -134,8 +130,7 @@ break;
case 0x19: case 0x19:
// ADD HL,DE // ADD HL,DE
tempRegister.W = (HL.W + DE.W) & 0xFFFF; tempRegister.W = (HL.W + DE.W) & 0xFFFF;
AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ DE.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ DE.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | (((long)HL.W + (long)DE.W) & 0x10000 ? C_FLAG : 0);
(((long)HL.W + (long)DE.W) & 0x10000 ? C_FLAG : 0);
HL.W = tempRegister.W; HL.W = tempRegister.W;
break; break;
case 0x1a: case 0x1a:
@ -154,8 +149,7 @@ break;
case 0x1d: case 0x1d:
// DEC E // DEC E
DE.B.B0--; DE.B.B0--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B0] | ((DE.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B0] | ((DE.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x1e: case 0x1e:
// LD E,NN // LD E,NN
@ -197,8 +191,7 @@ break;
case 0x25: case 0x25:
// DEC H // DEC H
HL.B.B1--; HL.B.B1--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B1] | ((HL.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B1] | ((HL.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x26: case 0x26:
// LD H,NN // LD H,NN
@ -221,8 +214,7 @@ break;
case 0x29: case 0x29:
// ADD HL,HL // ADD HL,HL
tempRegister.W = (HL.W + HL.W) & 0xFFFF; tempRegister.W = (HL.W + HL.W) & 0xFFFF;
AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ HL.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ HL.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | (((long)HL.W + (long)HL.W) & 0x10000 ? C_FLAG : 0);
(((long)HL.W + (long)HL.W) & 0x10000 ? C_FLAG : 0);
HL.W = tempRegister.W; HL.W = tempRegister.W;
break; break;
case 0x2a: case 0x2a:
@ -241,8 +233,7 @@ break;
case 0x2d: case 0x2d:
// DEC L // DEC L
HL.B.B0--; HL.B.B0--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B0] | ((HL.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B0] | ((HL.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x2e: case 0x2e:
// LD L,NN // LD L,NN
@ -284,8 +275,7 @@ break;
case 0x35: case 0x35:
// DEC (HL) // DEC (HL)
tempValue = gbReadMemory(HL.W) - 1; tempValue = gbReadMemory(HL.W) - 1;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[tempValue] | ((tempValue & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[tempValue] | ((tempValue & 0x0F) == 0x0F ? H_FLAG : 0);
gbWriteMemory(HL.W, tempValue); gbWriteMemory(HL.W, tempValue);
break; break;
case 0x36: case 0x36:
@ -307,8 +297,7 @@ break;
case 0x39: case 0x39:
// ADD HL,SP // ADD HL,SP
tempRegister.W = (HL.W + SP.W) & 0xFFFF; tempRegister.W = (HL.W + SP.W) & 0xFFFF;
AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ SP.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | AF.B.B0 = (AF.B.B0 & Z_FLAG) | ((HL.W ^ SP.W ^ tempRegister.W) & 0x1000 ? H_FLAG : 0) | (((long)HL.W + (long)SP.W) & 0x10000 ? C_FLAG : 0);
(((long)HL.W + (long)SP.W) & 0x10000 ? C_FLAG : 0);
HL.W = tempRegister.W; HL.W = tempRegister.W;
break; break;
case 0x3a: case 0x3a:
@ -327,8 +316,7 @@ break;
case 0x3d: case 0x3d:
// DEC A // DEC A
AF.B.B1--; AF.B.B1--;
AF.B.B0 = AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[AF.B.B1] | ((AF.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[AF.B.B1] | ((AF.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break; break;
case 0x3e: case 0x3e:
// LD A,NN // LD A,NN
@ -611,165 +599,142 @@ break;
case 0x80: case 0x80:
// ADD B // ADD B
tempRegister.W = AF.B.B1 + BC.B.B1; tempRegister.W = AF.B.B1 + BC.B.B1;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x81: case 0x81:
// ADD C // ADD C
tempRegister.W = AF.B.B1 + BC.B.B0; tempRegister.W = AF.B.B1 + BC.B.B0;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x82: case 0x82:
// ADD D // ADD D
tempRegister.W = AF.B.B1 + DE.B.B1; tempRegister.W = AF.B.B1 + DE.B.B1;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x83: case 0x83:
// ADD E // ADD E
tempRegister.W = AF.B.B1 + DE.B.B0; tempRegister.W = AF.B.B1 + DE.B.B0;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x84: case 0x84:
// ADD H // ADD H
tempRegister.W = AF.B.B1 + HL.B.B1; tempRegister.W = AF.B.B1 + HL.B.B1;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x85: case 0x85:
// ADD L // ADD L
tempRegister.W = AF.B.B1 + HL.B.B0; tempRegister.W = AF.B.B1 + HL.B.B0;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x86: case 0x86:
// ADD (HL) // ADD (HL)
tempValue = gbReadMemory(HL.W); tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 + tempValue; tempRegister.W = AF.B.B1 + tempValue;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x87: case 0x87:
// ADD A // ADD A
tempRegister.W = AF.B.B1 + AF.B.B1; tempRegister.W = AF.B.B1 + AF.B.B1;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x88: case 0x88:
// ADC B: // ADC B:
tempRegister.W = AF.B.B1 + BC.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + BC.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x89: case 0x89:
// ADC C // ADC C
tempRegister.W = AF.B.B1 + BC.B.B0 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + BC.B.B0 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x8a: case 0x8a:
// ADC D // ADC D
tempRegister.W = AF.B.B1 + DE.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + DE.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x8b: case 0x8b:
// ADC E // ADC E
tempRegister.W = AF.B.B1 + DE.B.B0 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + DE.B.B0 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x8c: case 0x8c:
// ADC H // ADC H
tempRegister.W = AF.B.B1 + HL.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + HL.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x8d: case 0x8d:
// ADC L // ADC L
tempRegister.W = AF.B.B1 + HL.B.B0 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + HL.B.B0 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x8e: case 0x8e:
// ADC (HL) // ADC (HL)
tempValue = gbReadMemory(HL.W); tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 + tempValue + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + tempValue + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x8f: case 0x8f:
// ADC A // ADC A
tempRegister.W = AF.B.B1 + AF.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + AF.B.B1 + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x90: case 0x90:
// SUB B // SUB B
tempRegister.W = AF.B.B1 - BC.B.B1; tempRegister.W = AF.B.B1 - BC.B.B1;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x91: case 0x91:
// SUB C // SUB C
tempRegister.W = AF.B.B1 - BC.B.B0; tempRegister.W = AF.B.B1 - BC.B.B0;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x92: case 0x92:
// SUB D // SUB D
tempRegister.W = AF.B.B1 - DE.B.B1; tempRegister.W = AF.B.B1 - DE.B.B1;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x93: case 0x93:
// SUB E // SUB E
tempRegister.W = AF.B.B1 - DE.B.B0; tempRegister.W = AF.B.B1 - DE.B.B0;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x94: case 0x94:
// SUB H // SUB H
tempRegister.W = AF.B.B1 - HL.B.B1; tempRegister.W = AF.B.B1 - HL.B.B1;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x95: case 0x95:
// SUB L // SUB L
tempRegister.W = AF.B.B1 - HL.B.B0; tempRegister.W = AF.B.B1 - HL.B.B0;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x96: case 0x96:
// SUB (HL) // SUB (HL)
tempValue = gbReadMemory(HL.W); tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 - tempValue; tempRegister.W = AF.B.B1 - tempValue;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x97: case 0x97:
@ -780,58 +745,50 @@ break;
case 0x98: case 0x98:
// SBC B // SBC B
tempRegister.W = AF.B.B1 - BC.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - BC.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x99: case 0x99:
// SBC C // SBC C
tempRegister.W = AF.B.B1 - BC.B.B0 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - BC.B.B0 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x9a: case 0x9a:
// SBC D // SBC D
tempRegister.W = AF.B.B1 - DE.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - DE.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x9b: case 0x9b:
// SBC E // SBC E
tempRegister.W = AF.B.B1 - DE.B.B0 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - DE.B.B0 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x9c: case 0x9c:
// SBC H // SBC H
tempRegister.W = AF.B.B1 - HL.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - HL.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x9d: case 0x9d:
// SBC L // SBC L
tempRegister.W = AF.B.B1 - HL.B.B0 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - HL.B.B0 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x9e: case 0x9e:
// SBC (HL) // SBC (HL)
tempValue = gbReadMemory(HL.W); tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 - tempValue - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - tempValue - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0x9f: case 0x9f:
// SBC A // SBC A
tempRegister.W = AF.B.B1 - AF.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - AF.B.B1 - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0xa0: case 0xa0:
@ -960,45 +917,38 @@ break;
case 0xb8: case 0xb8:
// CP B: // CP B:
tempRegister.W = AF.B.B1 - BC.B.B1; tempRegister.W = AF.B.B1 - BC.B.B1;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xb9: case 0xb9:
// CP C // CP C
tempRegister.W = AF.B.B1 - BC.B.B0; tempRegister.W = AF.B.B1 - BC.B.B0;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xba: case 0xba:
// CP D // CP D
tempRegister.W = AF.B.B1 - DE.B.B1; tempRegister.W = AF.B.B1 - DE.B.B1;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xbb: case 0xbb:
// CP E // CP E
tempRegister.W = AF.B.B1 - DE.B.B0; tempRegister.W = AF.B.B1 - DE.B.B0;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xbc: case 0xbc:
// CP H // CP H
tempRegister.W = AF.B.B1 - HL.B.B1; tempRegister.W = AF.B.B1 - HL.B.B1;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xbd: case 0xbd:
// CP L // CP L
tempRegister.W = AF.B.B1 - HL.B.B0; tempRegister.W = AF.B.B1 - HL.B.B0;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xbe: case 0xbe:
// CP (HL) // CP (HL)
tempValue = gbReadMemory(HL.W); tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 - tempValue; tempRegister.W = AF.B.B1 - tempValue;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xbf: case 0xbf:
// CP A // CP A
@ -1056,8 +1006,7 @@ case 0xc6:
// ADD NN // ADD NN
tempValue = gbReadOpcode(PC.W++); tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 + tempValue; tempRegister.W = AF.B.B1 + tempValue;
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0xc7: case 0xc7:
@ -1114,8 +1063,7 @@ case 0xce:
// ADC NN // ADC NN
tempValue = gbReadOpcode(PC.W++); tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 + tempValue + (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 + tempValue + (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0xcf: case 0xcf:
@ -1175,8 +1123,7 @@ case 0xd6:
// SUB NN // SUB NN
tempValue = gbReadOpcode(PC.W++); tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 - tempValue; tempRegister.W = AF.B.B1 - tempValue;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0xd7: case 0xd7:
@ -1235,8 +1182,7 @@ case 0xde:
// SBC NN // SBC NN
tempValue = gbReadOpcode(PC.W++); tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 - tempValue - (AF.B.B0 & C_FLAG ? 1 : 0); tempRegister.W = AF.B.B1 - tempValue - (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
AF.B.B1 = tempRegister.B.B0; AF.B.B1 = tempRegister.B.B0;
break; break;
case 0xdf: case 0xdf:
@ -1286,8 +1232,7 @@ case 0xe8:
// ADD SP,NN // ADD SP,NN
offset = (s8)gbReadOpcode(PC.W++); offset = (s8)gbReadOpcode(PC.W++);
tempRegister.W = SP.W + offset; tempRegister.W = SP.W + offset;
AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) | AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) | ((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_FLAG : 0);
((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_FLAG : 0);
SP.W = tempRegister.W; SP.W = tempRegister.W;
break; break;
case 0xe9: case 0xe9:
@ -1365,8 +1310,7 @@ case 0xf8:
// LD HL,SP+NN // LD HL,SP+NN
offset = (s8)gbReadOpcode(PC.W++); offset = (s8)gbReadOpcode(PC.W++);
tempRegister.W = SP.W + offset; tempRegister.W = SP.W + offset;
AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) | AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) | ((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_FLAG : 0);
((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_FLAG : 0);
HL.W = tempRegister.W; HL.W = tempRegister.W;
break; break;
case 0xf9: case 0xf9:
@ -1402,8 +1346,7 @@ case 0xfe:
// CP NN // CP NN
tempValue = gbReadOpcode(PC.W++); tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 - tempValue; tempRegister.W = AF.B.B1 - tempValue;
AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | AF.B.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break; break;
case 0xff: case 0xff:
// RST 38 // RST 38

View File

@ -5,22 +5,19 @@
#include "gbGlobals.h" #include "gbGlobals.h"
typedef struct { typedef struct {
u8 mask; uint8_t mask;
u8 value; uint8_t value;
const char *mnen; const char* mnen;
} GBOPCODE; } GBOPCODE;
#define GB_READ(x) gbMemoryMap[(x)>>12][(x)&0xfff] #define GB_READ(x) gbMemoryMap[(x) >> 12][(x)&0xfff]
static const char *registers[] = static const char* registers[] = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
{ "B", "C", "D", "E", "H", "L", "(HL)", "A" };
static const char *registers16[] = static const char* registers16[] = { "BC", "DE", "HL", "SP", // for some operations
{ "BC", "DE", "HL", "SP", // for some operations
"BC", "DE", "HL", "AF" }; // for push/pop "BC", "DE", "HL", "AF" }; // for push/pop
static const char *cond[] = static const char* cond[] = { "NZ", "Z", "NC", "C" };
{ "NZ", "Z", "NC", "C" };
static char hexDigits[16] = { static char hexDigits[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '0', '1', '2', '3', '4', '5', '6', '7',
@ -114,40 +111,40 @@ static GBOPCODE cbOpcodes[] = {
{ 0x00, 0x00, "DB CBh,%B" } { 0x00, 0x00, "DB CBh,%B" }
}; };
static char *addHex(char *p, u8 value) static char* addHex(char* p, uint8_t value)
{ {
*p++ = hexDigits[value >> 4]; *p++ = hexDigits[value >> 4];
*p++ = hexDigits[value & 15]; *p++ = hexDigits[value & 15];
return p; return p;
} }
static char *addHex16(char *p, u16 value) static char* addHex16(char* p, uint16_t value)
{ {
p = addHex(p, value>>8); p = addHex(p, value >> 8);
return addHex(p, value & 255); return addHex(p, value & 255);
} }
static char *addStr(char *p, const char *s) static char* addStr(char* p, const char* s)
{ {
while(*s) { while (*s) {
*p++ = *s++; *p++ = *s++;
} }
return p; return p;
} }
int gbDis(char *buffer, u16 address) int gbDis(char* buffer, uint16_t address)
{ {
char *p = buffer; char* p = buffer;
int instr = 1; int instr = 1;
u16 addr = address; uint16_t addr = address;
sprintf(p, "%04x ", address); sprintf(p, "%04x ", address);
p += 12; p += 12;
u8 opcode = GB_READ(address); uint8_t opcode = GB_READ(address);
address++; address++;
const char *mnen; const char* mnen;
GBOPCODE *op; GBOPCODE* op;
if(opcode == 0xcb) { if (opcode == 0xcb) {
opcode = GB_READ(address); opcode = GB_READ(address);
address++; address++;
instr++; instr++;
@ -155,23 +152,24 @@ int gbDis(char *buffer, u16 address)
} else { } else {
op = opcodes; op = opcodes;
} }
while(op->value != (opcode & op->mask)) op++; while (op->value != (opcode & op->mask))
op++;
mnen = op->mnen; mnen = op->mnen;
u8 b0, b1; uint8_t b0, b1;
s8 disp; int8_t disp;
int shift; int shift;
while(*mnen) { while (*mnen) {
if(*mnen == '%') { if (*mnen == '%') {
mnen++; mnen++;
switch(*mnen++) { switch (*mnen++) {
case 'W': case 'W':
b0 = GB_READ(address); b0 = GB_READ(address);
address++; address++;
b1 = GB_READ(address); b1 = GB_READ(address);
address++; address++;
p = addHex16(p, b0|b1<<8); p = addHex16(p, b0 | b1 << 8);
instr += 2; instr += 2;
*p++ = 'h'; *p++ = 'h';
break; break;
@ -183,7 +181,7 @@ int gbDis(char *buffer, u16 address)
break; break;
case 'D': case 'D':
disp = GB_READ(address); disp = GB_READ(address);
if(disp >= 0) if (disp >= 0)
*p++ = '+'; *p++ = '+';
p += sprintf(p, "%d", disp); p += sprintf(p, "%d", disp);
instr++; instr++;
@ -191,7 +189,7 @@ int gbDis(char *buffer, u16 address)
case 'd': case 'd':
disp = GB_READ(address); disp = GB_READ(address);
address++; address++;
p = addHex16(p, address+disp); p = addHex16(p, address + disp);
*p++ = 'h'; *p++ = 'h';
instr++; instr++;
break; break;
@ -209,7 +207,7 @@ int gbDis(char *buffer, u16 address)
break; break;
case 't': case 't':
shift = *mnen++ - '0'; shift = *mnen++ - '0';
p = addStr(p, registers16[4+((opcode >> shift) & 3)]); p = addStr(p, registers16[4 + ((opcode >> shift) & 3)]);
break; break;
case 'P': case 'P':
p = addHex(p, ((opcode >> 3) & 7) * 8); p = addHex(p, ((opcode >> 3) & 7) * 8);
@ -222,9 +220,9 @@ int gbDis(char *buffer, u16 address)
} else } else
*p++ = *mnen++; *p++ = *mnen++;
} }
for(int i = 0; i < instr; i++) { for (int i = 0; i < instr; i++) {
u16 a = addr + i; uint16_t a = addr + i;
addHex(buffer+5+i*2, GB_READ(a)); addHex(buffer + 5 + i * 2, GB_READ(a));
} }
*p = 0; *p = 0;
return instr; return instr;

View File

@ -1,43 +1,43 @@
#include <memory.h> #include <memory.h>
#include "../common/Types.h"
#include "../Util.h" #include "../Util.h"
#include "../common/Types.h"
#include "gbGlobals.h" #include "gbGlobals.h"
#include "gbSGB.h" #include "gbSGB.h"
u8 gbInvertTab[256] = { u8 gbInvertTab[256] = {
0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0, 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
}; };
u16 gbLineMix[160]; u16 gbLineMix[160];
@ -48,9 +48,9 @@ extern int layerSettings;
void gbRenderLine() void gbRenderLine()
{ {
memset(gbLineMix, 0, sizeof(gbLineMix)); memset(gbLineMix, 0, sizeof(gbLineMix));
u8 * bank0; u8* bank0;
u8 * bank1; u8* bank1;
if(gbCgbMode) { if (gbCgbMode) {
bank0 = &gbVram[0x0000]; bank0 = &gbVram[0x0000];
bank1 = &gbVram[0x2000]; bank1 = &gbVram[0x2000];
} else { } else {
@ -59,25 +59,25 @@ void gbRenderLine()
} }
int tile_map = 0x1800; int tile_map = 0x1800;
if((register_LCDC & 8) != 0) if ((register_LCDC & 8) != 0)
tile_map = 0x1c00; tile_map = 0x1c00;
int tile_pattern = 0x0800; int tile_pattern = 0x0800;
if((register_LCDC & 16) != 0) if ((register_LCDC & 16) != 0)
tile_pattern = 0x0000; tile_pattern = 0x0000;
int x = 0; int x = 0;
int y = register_LY; int y = register_LY;
if(y >= 144) if (y >= 144)
return; return;
int SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4); int SpritesTicks = gbSpritesTicks[x] * (gbSpeed ? 2 : 4);
int sx = gbSCXLine[(gbSpeed ? 0 : 4)+SpritesTicks]; int sx = gbSCXLine[(gbSpeed ? 0 : 4) + SpritesTicks];
int sy = gbSCYLine[(gbSpeed ? 11 : 5)+SpritesTicks]; int sy = gbSCYLine[(gbSpeed ? 11 : 5) + SpritesTicks];
sy+=y; sy += y;
sy &= 255; sy &= 255;
@ -92,32 +92,30 @@ void gbRenderLine()
int tile_map_address = tile_map_line_y + tx; int tile_map_address = tile_map_line_y + tx;
u8 attrs = 0; u8 attrs = 0;
if(bank1 != NULL) if (bank1 != NULL)
attrs = bank1[tile_map_address]; attrs = bank1[tile_map_address];
u8 tile = bank0[tile_map_address]; u8 tile = bank0[tile_map_address];
tile_map_address++; tile_map_address++;
if(!(register_LCDC & 0x10)) if (!(register_LCDC & 0x10))
tile ^= 0x80; tile ^= 0x80;
int tile_pattern_address = tile_pattern + tile * 16 + by*2; int tile_pattern_address = tile_pattern + tile * 16 + by * 2;
if(register_LCDC & 0x80) {
if((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) {
while(x < 160) {
if (register_LCDC & 0x80) {
if ((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100)) {
while (x < 160) {
u8 tile_a = 0; u8 tile_a = 0;
u8 tile_b = 0; u8 tile_b = 0;
if(attrs & 0x40) { if (attrs & 0x40) {
tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; tile_pattern_address = tile_pattern + tile * 16 + (7 - by) * 2;
} }
if(attrs & 0x08) { if (attrs & 0x08) {
tile_a = bank1[tile_pattern_address++]; tile_a = bank1[tile_pattern_address++];
tile_b = bank1[tile_pattern_address]; tile_b = bank1[tile_pattern_address];
} else { } else {
@ -125,21 +123,21 @@ void gbRenderLine()
tile_b = bank0[tile_pattern_address]; tile_b = bank0[tile_pattern_address];
} }
if(attrs & 0x20) { if (attrs & 0x20) {
tile_a = gbInvertTab[tile_a]; tile_a = gbInvertTab[tile_a];
tile_b = gbInvertTab[tile_b]; tile_b = gbInvertTab[tile_b];
} }
while(bx > 0) { while (bx > 0) {
u8 c = (tile_a & bx) ? 1 : 0; u8 c = (tile_a & bx) ? 1 : 0;
c += ((tile_b & bx) ? 2 : 0); c += ((tile_b & bx) ? 2 : 0);
gbLineBuffer[x] = c; // mark the gbLineBuffer color gbLineBuffer[x] = c; // mark the gbLineBuffer color
if(attrs & 0x80) if (attrs & 0x80)
gbLineBuffer[x] |= 0x300; gbLineBuffer[x] |= 0x300;
if(gbCgbMode) { if (gbCgbMode) {
// Use the DMG palette if we are in compat mode. // Use the DMG palette if we are in compat mode.
if (gbMemory[0xff6c] & 1) { if (gbMemory[0xff6c] & 1) {
c = gbBgp[c]; c = gbBgp[c];
@ -147,38 +145,37 @@ void gbRenderLine()
c = c + (attrs & 7) * 4; c = c + (attrs & 7) * 4;
} }
} else { } else {
c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+SpritesTicks]>>(c<<1)) &3; c = (gbBgpLine[x + (gbSpeed ? 5 : 11) + SpritesTicks] >> (c << 1)) & 3;
if(gbSgbMode && !gbCgbMode) { if (gbSgbMode && !gbCgbMode) {
int dx = x >> 3; int dx = x >> 3;
int dy = y >> 3; int dy = y >> 3;
int palette = gbSgbATF[dy * 20 + dx]; int palette = gbSgbATF[dy * 20 + dx];
if(c == 0) if (c == 0)
palette = 0; palette = 0;
c = c + 4*palette; c = c + 4 * palette;
} }
} }
gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : gbPalette[c] & 0x7FFF; gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : gbPalette[c] & 0x7FFF;
x++; x++;
if(x >= 160) if (x >= 160)
break; break;
bx >>= 1; bx >>= 1;
} }
bx = 128; bx = 128;
SpritesTicks = gbSpritesTicks[x]*(gbSpeed ? 2 : 4); SpritesTicks = gbSpritesTicks[x] * (gbSpeed ? 2 : 4);
sx = gbSCXLine[x+(gbSpeed ? 0 : 4)+SpritesTicks]; sx = gbSCXLine[x + (gbSpeed ? 0 : 4) + SpritesTicks];
sy = gbSCYLine[x+(gbSpeed ? 11 : 5)+SpritesTicks]; sy = gbSCYLine[x + (gbSpeed ? 11 : 5) + SpritesTicks];
tx = ((sx + x) >> 3) & 0x1f;
tx = ((sx+x)>>3) & 0x1f; sy += y;
sy+=y;
sy &= 255; sy &= 255;
@ -192,12 +189,12 @@ void gbRenderLine()
tile_map_address = tile_map_line_y + tx; tile_map_address = tile_map_line_y + tx;
if(bank1) if (bank1)
attrs = bank1[tile_map_line_y + tx]; attrs = bank1[tile_map_line_y + tx];
tile = bank0[tile_map_line_y + tx]; tile = bank0[tile_map_line_y + tx];
if(!(register_LCDC & 0x10)) if (!(register_LCDC & 0x10))
tile ^= 0x80; tile ^= 0x80;
tile_pattern_address = tile_pattern + tile * 16 + by * 2; tile_pattern_address = tile_pattern + tile * 16 + by * 2;
@ -206,13 +203,10 @@ void gbRenderLine()
// Use gbBgp[0] instead of 0 (?) // Use gbBgp[0] instead of 0 (?)
// (this fixes white flashes on Last Bible II) // (this fixes white flashes on Last Bible II)
// Also added the gbColorOption (fixes Dracula Densetsu II color problems) // Also added the gbColorOption (fixes Dracula Densetsu II color problems)
for(int i = 0; i < 160; i++) for (int i = 0; i < 160; i++) {
{
u16 color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF; u16 color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF;
if (!gbCgbMode) if (!gbCgbMode)
color = gbColorOption ? color = gbColorOption ? gbColorFilter[gbPalette[gbBgpLine[i + (gbSpeed ? 5 : 11) + gbSpritesTicks[i] * (gbSpeed ? 2 : 4)] & 3] & 0x7FFF] : gbPalette[gbBgpLine[i + (gbSpeed ? 5 : 11) + gbSpritesTicks[i] * (gbSpeed ? 2 : 4)] & 3] & 0x7FFF;
gbColorFilter[gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF] :
gbPalette[gbBgpLine[i+(gbSpeed ? 5 : 11)+gbSpritesTicks[i]*(gbSpeed ? 2 : 4)]&3] & 0x7FFF;
gbLineMix[i] = color; gbLineMix[i] = color;
gbLineBuffer[i] = 0; gbLineBuffer[i] = 0;
} }
@ -222,14 +216,13 @@ void gbRenderLine()
// LCDC.0 also enables/disables the window in !gbCgbMode ?!?! // LCDC.0 also enables/disables the window in !gbCgbMode ?!?!
// (tested on real hardware) // (tested on real hardware)
// This fixes Last Bible II & Zankurou Musouken // This fixes Last Bible II & Zankurou Musouken
if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) && (layerSettings & 0x2000) && (gbWindowLine != -2)) { if ((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) && (layerSettings & 0x2000) && (gbWindowLine != -2)) {
int i = 0; int i = 0;
// Fix (accurate emulation) for most of the window display problems // Fix (accurate emulation) for most of the window display problems
// (ie. Zen - Intergalactic Ninja, Urusei Yatsura...). // (ie. Zen - Intergalactic Ninja, Urusei Yatsura...).
if ((gbWindowLine == -1) || (gbWindowLine>144)) if ((gbWindowLine == -1) || (gbWindowLine > 144)) {
{
inUseRegister_WY = oldRegister_WY; inUseRegister_WY = oldRegister_WY;
if (register_LY>oldRegister_WY) if (register_LY > oldRegister_WY)
gbWindowLine = 146; gbWindowLine = 146;
// for (i = 0; i<160; i++) // for (i = 0; i<160; i++)
// gbWindowColor[i] = gbLineMix[i]; // gbWindowColor[i] = gbLineMix[i];
@ -237,23 +230,22 @@ void gbRenderLine()
int wy = inUseRegister_WY; int wy = inUseRegister_WY;
if(y >= inUseRegister_WY) { if (y >= inUseRegister_WY) {
if ((gbWindowLine == -1) || (gbWindowLine>144)) if ((gbWindowLine == -1) || (gbWindowLine > 144))
gbWindowLine = 0; gbWindowLine = 0;
int wx = register_WX; int wx = register_WX;
int swx = 0; int swx = 0;
wx -= 7; wx -= 7;
if( wx <= 159 && gbWindowLine <= 143) { if (wx <= 159 && gbWindowLine <= 143) {
tile_map = 0x1800; tile_map = 0x1800;
if((register_LCDC & 0x40) != 0) if ((register_LCDC & 0x40) != 0)
tile_map = 0x1c00; tile_map = 0x1c00;
tx = 0; tx = 0;
ty = gbWindowLine >> 3; ty = gbWindowLine >> 3;
@ -262,24 +254,20 @@ void gbRenderLine()
// Tries to emulate the 'window scrolling bug' when wx == 0 (ie. wx-7 == -7). // Tries to emulate the 'window scrolling bug' when wx == 0 (ie. wx-7 == -7).
// Nothing close to perfect, but good enought for now... // Nothing close to perfect, but good enought for now...
if (wx == -7) if (wx == -7) {
{ swx = 7 - ((gbSCXLine[0] - 1) & 7);
swx = 7-((gbSCXLine[0]-1) & 7); bx >>= ((gbSCXLine[0] + ((swx != 1) ? 1 : 0)) & 7);
bx >>= ((gbSCXLine[0]+((swx != 1) ? 1 : 0)) & 7);
if (swx == 1) if (swx == 1)
swx = 2; swx = 2;
//bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7); //bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7);
if (swx == 7) if (swx == 7) {
{
//wx = 0; //wx = 0;
if ((gbWindowLine>0) || (wy == 0)) if ((gbWindowLine > 0) || (wy == 0))
swx = 0; swx = 0;
} }
} } else if (wx < 0) {
else
if(wx < 0) {
bx >>= (-wx); bx >>= (-wx);
wx = 0; wx = 0;
} }
@ -292,30 +280,32 @@ void gbRenderLine()
tile = bank0[tile_map_address]; tile = bank0[tile_map_address];
u8 attrs = 0; u8 attrs = 0;
if(bank1) if (bank1)
attrs = bank1[tile_map_address]; attrs = bank1[tile_map_address];
tile_map_address++; tile_map_address++;
if((register_LCDC & 16) == 0) { if ((register_LCDC & 16) == 0) {
if(tile < 128) tile += 128; if (tile < 128)
else tile -= 128; tile += 128;
else
tile -= 128;
} }
tile_pattern_address = tile_pattern + tile * 16 + by*2; tile_pattern_address = tile_pattern + tile * 16 + by * 2;
if (wx) if (wx)
for (i = 0; i<swx; i++) for (i = 0; i < swx; i++)
gbLineMix[i] = gbWindowColor[i]; gbLineMix[i] = gbWindowColor[i];
while(x < 160) { while (x < 160) {
u8 tile_a = 0; u8 tile_a = 0;
u8 tile_b = 0; u8 tile_b = 0;
if(attrs & 0x40) { if (attrs & 0x40) {
tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; tile_pattern_address = tile_pattern + tile * 16 + (7 - by) * 2;
} }
if(attrs & 0x08) { if (attrs & 0x08) {
tile_a = bank1[tile_pattern_address++]; tile_a = bank1[tile_pattern_address++];
tile_b = bank1[tile_pattern_address]; tile_b = bank1[tile_pattern_address];
} else { } else {
@ -323,23 +313,22 @@ void gbRenderLine()
tile_b = bank0[tile_pattern_address]; tile_b = bank0[tile_pattern_address];
} }
if(attrs & 0x20) { if (attrs & 0x20) {
tile_a = gbInvertTab[tile_a]; tile_a = gbInvertTab[tile_a];
tile_b = gbInvertTab[tile_b]; tile_b = gbInvertTab[tile_b];
} }
while(bx > 0) { while (bx > 0) {
u8 c = (tile_a & bx) != 0 ? 1 : 0; u8 c = (tile_a & bx) != 0 ? 1 : 0;
c += ((tile_b & bx) != 0 ? 2 : 0); c += ((tile_b & bx) != 0 ? 2 : 0);
if (x>=0) if (x >= 0) {
{ if (attrs & 0x80)
if(attrs & 0x80)
gbLineBuffer[x] = 0x300 + c; gbLineBuffer[x] = 0x300 + c;
else else
gbLineBuffer[x] = 0x100 + c; gbLineBuffer[x] = 0x100 + c;
if(gbCgbMode) { if (gbCgbMode) {
// Use the DMG palette if we are in compat mode. // Use the DMG palette if we are in compat mode.
if (gbMemory[0xff6c] & 1) { if (gbMemory[0xff6c] & 1) {
c = gbBgp[c]; c = gbBgp[c];
@ -347,37 +336,39 @@ void gbRenderLine()
c = c + (attrs & 7) * 4; c = c + (attrs & 7) * 4;
} }
} else { } else {
c = (gbBgpLine[x+(gbSpeed ? 5 : 11)+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(c<<1)) &3; c = (gbBgpLine[x + (gbSpeed ? 5 : 11) + gbSpritesTicks[x] * (gbSpeed ? 2 : 4)] >> (c << 1)) & 3;
if(gbSgbMode && !gbCgbMode) { if (gbSgbMode && !gbCgbMode) {
int dx = x >> 3; int dx = x >> 3;
int dy = y >> 3; int dy = y >> 3;
int palette = gbSgbATF[dy * 20 + dx]; int palette = gbSgbATF[dy * 20 + dx];
if(c == 0) if (c == 0)
palette = 0; palette = 0;
c = c + 4*palette; c = c + 4 * palette;
} }
} }
gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : gbPalette[c] & 0x7FFF; gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : gbPalette[c] & 0x7FFF;
} }
x++; x++;
if(x >= 160) if (x >= 160)
break; break;
bx >>= 1; bx >>= 1;
} }
tx++; tx++;
if(tx == 32) if (tx == 32)
tx = 0; tx = 0;
bx = 128; bx = 128;
tile = bank0[tile_map_line_y + tx]; tile = bank0[tile_map_line_y + tx];
if(bank1) if (bank1)
attrs = bank1[tile_map_line_y + tx]; attrs = bank1[tile_map_line_y + tx];
if((register_LCDC & 16) == 0) { if ((register_LCDC & 16) == 0) {
if(tile < 128) tile += 128; if (tile < 128)
else tile -= 128; tile += 128;
else
tile -= 128;
} }
tile_pattern_address = tile_pattern + tile * 16 + by * 2; tile_pattern_address = tile_pattern + tile * 16 + by * 2;
} }
@ -387,11 +378,9 @@ void gbRenderLine()
gbWindowLine++; gbWindowLine++;
} }
} }
} } else if (gbWindowLine == -2) {
else if (gbWindowLine == -2)
{
inUseRegister_WY = oldRegister_WY; inUseRegister_WY = oldRegister_WY;
if (register_LY>oldRegister_WY) if (register_LY > oldRegister_WY)
gbWindowLine = 146; gbWindowLine = 146;
else else
gbWindowLine = 0; gbWindowLine = 0;
@ -400,20 +389,19 @@ void gbRenderLine()
u16 color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF; u16 color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF;
if (!gbCgbMode) if (!gbCgbMode)
color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : gbPalette[0] & 0x7FFF; color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : gbPalette[0] & 0x7FFF;
for(int i = 0; i < 160; i++) for (int i = 0; i < 160; i++) {
{
gbLineMix[i] = color; gbLineMix[i] = color;
gbLineBuffer[i] = 0; gbLineBuffer[i] = 0;
} }
} }
} }
void gbDrawSpriteTile(int tile, int x,int y,int t, int flags, void gbDrawSpriteTile(int tile, int x, int y, int t, int flags,
int size,int spriteNumber) int size, int spriteNumber)
{ {
u8 * bank0; u8* bank0;
u8 * bank1; u8* bank1;
if(gbCgbMode) { if (gbCgbMode) {
bank0 = &gbVram[0x0000]; bank0 = &gbVram[0x0000];
bank1 = &gbVram[0x2000]; bank1 = &gbVram[0x2000];
} else { } else {
@ -423,30 +411,29 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
int init = 0x0000; int init = 0x0000;
for (int i = 0; i<4; i++) for (int i = 0; i < 4; i++) {
{ gbObp0[i] = (gbObp0Line[x + 11 + gbSpritesTicks[x] * (gbSpeed ? 2 : 4)] >> (i << 1)) & 3;
gbObp0[i] = (gbObp0Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3; gbObp1[i] = (gbObp1Line[x + 11 + gbSpritesTicks[x] * (gbSpeed ? 2 : 4)] >> (i << 1)) & 3;
gbObp1[i] = (gbObp1Line[x+11+gbSpritesTicks[x]*(gbSpeed ? 2 : 4)]>>(i<<1)) & 3;
} }
u8 *pal = gbObp0; u8* pal = gbObp0;
int flipx = (flags & 0x20); int flipx = (flags & 0x20);
int flipy = (flags & 0x40); int flipy = (flags & 0x40);
if((flags & 0x10)) if ((flags & 0x10))
pal = gbObp1; pal = gbObp1;
if(flipy) { if (flipy) {
t = (size ? 15 : 7) - t; t = (size ? 15 : 7) - t;
} }
int prio = flags & 0x80; int prio = flags & 0x80;
int address = init + tile * 16 + 2*t; int address = init + tile * 16 + 2 * t;
int a = 0; int a = 0;
int b = 0; int b = 0;
if(gbCgbMode && (flags & 0x08)) { if (gbCgbMode && (flags & 0x08)) {
a = bank1[address++]; a = bank1[address++];
b = bank1[address++]; b = bank1[address++];
} else { } else {
@ -454,78 +441,78 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags,
b = bank0[address++]; b = bank0[address++];
} }
for(int xx = 0; xx < 8; xx++) { for (int xx = 0; xx < 8; xx++) {
u8 mask = 1 << (7-xx); u8 mask = 1 << (7 - xx);
u8 c = 0; u8 c = 0;
if( (a & mask)) if ((a & mask))
c++; c++;
if( (b & mask)) if ((b & mask))
c+=2; c += 2;
if(c==0) continue; if (c == 0)
continue;
int xxx = xx+x; int xxx = xx + x;
if(flipx) if (flipx)
xxx = (7-xx+x); xxx = (7 - xx + x);
if(xxx < 0 || xxx > 159) if (xxx < 0 || xxx > 159)
continue; continue;
u16 color = gbLineBuffer[xxx]; u16 color = gbLineBuffer[xxx];
// Fixes OAM-BG priority // Fixes OAM-BG priority
if(prio && (register_LCDC & 1)) { if (prio && (register_LCDC & 1)) {
if(color < 0x200 && ((color & 0xFF) != 0)) if (color < 0x200 && ((color & 0xFF) != 0))
continue; continue;
} }
// Fixes OAM-BG priority for Moorhuhn 2 // Fixes OAM-BG priority for Moorhuhn 2
if(color >= 0x300 && color != 0x300 && (register_LCDC & 1)) if (color >= 0x300 && color != 0x300 && (register_LCDC & 1))
continue; continue;
else if(color >= 0x200 && color < 0x300) { else if (color >= 0x200 && color < 0x300) {
int sprite = color & 0xff; int sprite = color & 0xff;
int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8; int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8;
if(spriteX == x) { if (spriteX == x) {
if(sprite < spriteNumber) if (sprite < spriteNumber)
continue; continue;
} else { } else {
if(gbCgbMode) { if (gbCgbMode) {
if(sprite < spriteNumber) if (sprite < spriteNumber)
continue; continue;
} else { } else {
// Fixes GB sprites priorities (was '< x + 8' before) // Fixes GB sprites priorities (was '< x + 8' before)
// ('A boy and his blob...' sprites' emulation is now correct) // ('A boy and his blob...' sprites' emulation is now correct)
if(spriteX < x) if (spriteX < x)
continue; continue;
} }
} }
} }
gbLineBuffer[xxx] = 0x200 + spriteNumber; gbLineBuffer[xxx] = 0x200 + spriteNumber;
// make sure that sprites will work even in CGB mode // make sure that sprites will work even in CGB mode
if(gbCgbMode) { if (gbCgbMode) {
// Use the DMG palette if we are in compat mode. // Use the DMG palette if we are in compat mode.
if (gbMemory[0xff6c] & 1) { if (gbMemory[0xff6c] & 1) {
c = pal[c] + ((flags & 0x10) >> 4)*4 + 32; c = pal[c] + ((flags & 0x10) >> 4) * 4 + 32;
} else { } else {
c = c + (flags & 0x07)*4 + 32; c = c + (flags & 0x07) * 4 + 32;
} }
} else { } else {
c = pal[c]; c = pal[c];
if(gbSgbMode && !gbCgbMode) { if (gbSgbMode && !gbCgbMode) {
int dx = xxx >> 3; int dx = xxx >> 3;
int dy = y >> 3; int dy = y >> 3;
int palette = gbSgbATF[dy * 20 + dx]; int palette = gbSgbATF[dy * 20 + dx];
if(c == 0) if (c == 0)
palette = 0; palette = 0;
c = c + 4*palette; c = c + 4 * palette;
} else { } else {
c += 4; c += 4;
} }
@ -544,45 +531,43 @@ void gbDrawSprites(bool draw)
int size = (register_LCDC & 4); int size = (register_LCDC & 4);
if (!draw) if (!draw)
memset (gbSpritesTicks, 0, sizeof(gbSpritesTicks)); memset(gbSpritesTicks, 0, sizeof(gbSpritesTicks));
if(!(register_LCDC & 0x80)) if (!(register_LCDC & 0x80))
return; return;
if((register_LCDC & 2) && (layerSettings & 0x1000)) { if ((register_LCDC & 2) && (layerSettings & 0x1000)) {
int yc = register_LY; int yc = register_LY;
int address = 0xfe00; int address = 0xfe00;
for(int i = 0; i < 40; i++) { for (int i = 0; i < 40; i++) {
y = gbMemory[address++]; y = gbMemory[address++];
x = gbMemory[address++]; x = gbMemory[address++];
int tile = gbMemory[address++]; int tile = gbMemory[address++];
if(size) if (size)
tile &= 254; tile &= 254;
int flags = gbMemory[address++]; int flags = gbMemory[address++];
if(x > 0 && y > 0 && x < 168 && y < 160) { if (x > 0 && y > 0 && x < 168 && y < 160) {
// check if sprite intersects current line // check if sprite intersects current line
int t = yc -y + 16; int t = yc - y + 16;
if((size && t >=0 && t < 16) || (!size && t >= 0 && t < 8)) { if ((size && t >= 0 && t < 16) || (!size && t >= 0 && t < 8)) {
if (draw) if (draw)
gbDrawSpriteTile(tile,x-8,yc,t,flags,size,i); gbDrawSpriteTile(tile, x - 8, yc, t, flags, size, i);
else else {
{ for (int j = x - 8; j < 300; j++)
for (int j = x-8; j<300; j++) if (j >= 0) {
if (j>=0)
{
if (gbSpeed) if (gbSpeed)
gbSpritesTicks[j] += 5; gbSpritesTicks[j] += 5;
else else
gbSpritesTicks[j] += 2+(count&1); gbSpritesTicks[j] += 2 + (count & 1);
} }
} }
count++; count++;
} }
} }
// sprite limit reached! // sprite limit reached!
if(count >= 10) if (count >= 10)
break; break;
} }
} }

View File

@ -1,7 +1,7 @@
#include <cstdlib>
#include "../common/Types.h" #include "../common/Types.h"
#include <cstdlib>
u8 *gbMemoryMap[16]; u8* gbMemoryMap[16];
int gbRomSizeMask = 0; int gbRomSizeMask = 0;
int gbRomSize = 0; int gbRomSize = 0;
@ -9,18 +9,18 @@ int gbRamSizeMask = 0;
int gbRamSize = 0; int gbRamSize = 0;
int gbTAMA5ramSize = 0; int gbTAMA5ramSize = 0;
u8 *gbMemory = NULL; u8* gbMemory = NULL;
u8 *gbVram = NULL; u8* gbVram = NULL;
u8 *gbRom = NULL; u8* gbRom = NULL;
u8 *gbRam = NULL; u8* gbRam = NULL;
u8 *gbWram = NULL; u8* gbWram = NULL;
u16 *gbLineBuffer = NULL; u16* gbLineBuffer = NULL;
u8 *gbTAMA5ram = NULL; u8* gbTAMA5ram = NULL;
u16 gbPalette[128]; u16 gbPalette[128];
u8 gbBgp[4] = { 0, 1, 2, 3}; u8 gbBgp[4] = { 0, 1, 2, 3 };
u8 gbObp0[4] = { 0, 1, 2, 3}; u8 gbObp0[4] = { 0, 1, 2, 3 };
u8 gbObp1[4] = { 0, 1, 2, 3}; u8 gbObp1[4] = { 0, 1, 2, 3 };
int gbWindowLine = -1; int gbWindowLine = -1;
bool genericflashcardEnable = false; bool genericflashcardEnable = false;

View File

@ -7,17 +7,17 @@ extern int gbRamSize;
extern int gbRamSizeMask; extern int gbRamSizeMask;
extern int gbTAMA5ramSize; extern int gbTAMA5ramSize;
extern u8 *bios; extern u8* bios;
extern u8 *gbRom; extern u8* gbRom;
extern u8 *gbRam; extern u8* gbRam;
extern u8 *gbVram; extern u8* gbVram;
extern u8 *gbWram; extern u8* gbWram;
extern u8 *gbMemory; extern u8* gbMemory;
extern u16 *gbLineBuffer; extern u16* gbLineBuffer;
extern u8 *gbTAMA5ram; extern u8* gbTAMA5ram;
extern u8 *gbMemoryMap[16]; extern u8* gbMemoryMap[16];
extern int gbFrameSkip; extern int gbFrameSkip;
extern u16 gbColorFilter[32768]; extern u16 gbColorFilter[32768];

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
#include <stdio.h>
#include <memory.h>
#include "../System.h" #include "../System.h"
#include <memory.h>
#include <stdio.h>
u8 gbPrinterStatus = 0; u8 gbPrinterStatus = 0;
int gbPrinterState = 0; int gbPrinterState = 0;
u8 gbPrinterData[0x280*9]; u8 gbPrinterData[0x280 * 9];
u8 gbPrinterPacket[0x400]; u8 gbPrinterPacket[0x400];
int gbPrinterCount = 0; int gbPrinterCount = 0;
int gbPrinterDataCount = 0; int gbPrinterDataCount = 0;
@ -15,12 +15,11 @@ bool gbPrinterCheckCRC()
{ {
u16 crc = 0; u16 crc = 0;
for(int i = 2; i < (6+gbPrinterDataSize); i++) { for (int i = 2; i < (6 + gbPrinterDataSize); i++) {
crc += gbPrinterPacket[i]; crc += gbPrinterPacket[i];
} }
int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] + int msgCrc = gbPrinterPacket[6 + gbPrinterDataSize] + (gbPrinterPacket[7 + gbPrinterDataSize] << 8);
(gbPrinterPacket[7+gbPrinterDataSize]<<8);
return msgCrc == crc; return msgCrc == crc;
} }
@ -89,13 +88,13 @@ void gbPrinterShowData()
void gbPrinterReceiveData() void gbPrinterReceiveData()
{ {
int i = gbPrinterDataCount; int i = gbPrinterDataCount;
if(gbPrinterPacket[3]) { // compressed if (gbPrinterPacket[3]) { // compressed
u8 *data = &gbPrinterPacket[6]; u8* data = &gbPrinterPacket[6];
u8 *dest = &gbPrinterData[gbPrinterDataCount]; u8* dest = &gbPrinterData[gbPrinterDataCount];
int len = 0; int len = 0;
while(len < gbPrinterDataSize) { while (len < gbPrinterDataSize) {
u8 control = *data++; u8 control = *data++;
if(control & 0x80) { // repeated data if (control & 0x80) { // repeated data
control &= 0x7f; control &= 0x7f;
control += 2; control += 2;
memset(dest, *data++, control); memset(dest, *data++, control);
@ -120,7 +119,7 @@ void gbPrinterReceiveData()
void gbPrinterCommand() void gbPrinterCommand()
{ {
switch(gbPrinterPacket[2]) { switch (gbPrinterPacket[2]) {
case 0x01: case 0x01:
// reset/initialize packet // reset/initialize packet
gbPrinterDataCount = 0; gbPrinterDataCount = 0;
@ -142,11 +141,11 @@ void gbPrinterCommand()
u8 gbPrinterSend(u8 b) u8 gbPrinterSend(u8 b)
{ {
switch(gbPrinterState) { switch (gbPrinterState) {
case 0: case 0:
gbPrinterCount = 0; gbPrinterCount = 0;
// receiving preamble // receiving preamble
if(b == 0x88) { if (b == 0x88) {
gbPrinterPacket[gbPrinterCount++] = b; gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++; gbPrinterState++;
} else { } else {
@ -156,7 +155,7 @@ u8 gbPrinterSend(u8 b)
break; break;
case 1: case 1:
// receiving preamble // receiving preamble
if(b == 0x33) { if (b == 0x33) {
gbPrinterPacket[gbPrinterCount++] = b; gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++; gbPrinterState++;
} else { } else {
@ -167,16 +166,16 @@ u8 gbPrinterSend(u8 b)
case 2: case 2:
// receiving header // receiving header
gbPrinterPacket[gbPrinterCount++] = b; gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == 6) { if (gbPrinterCount == 6) {
gbPrinterState++; gbPrinterState++;
gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8); gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5] << 8);
} }
break; break;
case 3: case 3:
// receiving data // receiving data
if(gbPrinterDataSize) { if (gbPrinterDataSize) {
gbPrinterPacket[gbPrinterCount++] = b; gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == (6+gbPrinterDataSize)) { if (gbPrinterCount == (6 + gbPrinterDataSize)) {
gbPrinterState++; gbPrinterState++;
} }
break; break;
@ -191,7 +190,7 @@ u8 gbPrinterSend(u8 b)
case 5: case 5:
// receiving CRC-2 // receiving CRC-2
gbPrinterPacket[gbPrinterCount++] = b; gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCheckCRC()) { if (gbPrinterCheckCRC()) {
gbPrinterCommand(); gbPrinterCommand();
} }
gbPrinterState++; gbPrinterState++;

View File

@ -1,13 +1,13 @@
#include <stdlib.h>
#include <memory.h> #include <memory.h>
#include <stdlib.h>
#include "../System.h" #include "../System.h"
#include "../common/Port.h"
#include "../Util.h" #include "../Util.h"
#include "../common/Port.h"
#include "gb.h" #include "gb.h"
#include "gbGlobals.h" #include "gbGlobals.h"
extern u8 *pix; extern u8* pix;
extern bool speedup; extern bool speedup;
extern bool gbSgbResetFlag; extern bool gbSgbResetFlag;
@ -15,8 +15,8 @@ extern bool gbSgbResetFlag;
#define GBSGB_RESET 1 #define GBSGB_RESET 1
#define GBSGB_PACKET_TRANSMIT 2 #define GBSGB_PACKET_TRANSMIT 2
u8 *gbSgbBorderChar = NULL; u8* gbSgbBorderChar = NULL;
u8 *gbSgbBorder = NULL; u8* gbSgbBorder = NULL;
int gbSgbCGBSupport = 0; int gbSgbCGBSupport = 0;
int gbSgbMask = 0; int gbSgbMask = 0;
@ -25,7 +25,7 @@ int gbSgbPacketState = GBSGB_NONE;
int gbSgbBit = 0; int gbSgbBit = 0;
int gbSgbPacketTimeout = 0; int gbSgbPacketTimeout = 0;
int GBSGB_PACKET_TIMEOUT = 66666; int GBSGB_PACKET_TIMEOUT = 66666;
u8 gbSgbPacket[16*7]; u8 gbSgbPacket[16 * 7];
int gbSgbPacketNBits = 0; int gbSgbPacketNBits = 0;
int gbSgbPacketByte = 0; int gbSgbPacketByte = 0;
int gbSgbPacketNumber = 0; int gbSgbPacketNumber = 0;
@ -33,22 +33,22 @@ int gbSgbMultiplayer = 0;
int gbSgbFourPlayers = 0; int gbSgbFourPlayers = 0;
u8 gbSgbNextController = 0x0f; u8 gbSgbNextController = 0x0f;
u8 gbSgbReadingController = 0; u8 gbSgbReadingController = 0;
u16 gbSgbSCPPalette[4*512]; u16 gbSgbSCPPalette[4 * 512];
u8 gbSgbATF[20 * 18]; u8 gbSgbATF[20 * 18];
u8 gbSgbATFList[45 * 20 * 18]; u8 gbSgbATFList[45 * 20 * 18];
u8 gbSgbScreenBuffer[4160]; u8 gbSgbScreenBuffer[4160];
inline void gbSgbDraw24Bit(u8 *p, u16 v) inline void gbSgbDraw24Bit(u8* p, u16 v)
{ {
memcpy(p, &systemColorMap32[v], 3); memcpy(p, &systemColorMap32[v], 3);
} }
inline void gbSgbDraw32Bit(u32 *p, u16 v) inline void gbSgbDraw32Bit(u32* p, u16 v)
{ {
*p = systemColorMap32[v]; *p = systemColorMap32[v];
} }
inline void gbSgbDraw16Bit(u16 *p, u16 v) inline void gbSgbDraw16Bit(u16* p, u16 v)
{ {
*p = systemColorMap16[v]; *p = systemColorMap16[v];
} }
@ -67,42 +67,42 @@ void gbSgbReset()
gbSgbNextController = 0x0f; gbSgbNextController = 0x0f;
gbSgbReadingController = 0; gbSgbReadingController = 0;
memset(gbSgbSCPPalette, 0, 512*4); memset(gbSgbSCPPalette, 0, 512 * 4);
memset(gbSgbATF, 0, 20*18); memset(gbSgbATF, 0, 20 * 18);
memset(gbSgbATFList, 0, 45 * 20 * 18); memset(gbSgbATFList, 0, 45 * 20 * 18);
memset(gbSgbPacket, 0, 16 * 7); memset(gbSgbPacket, 0, 16 * 7);
memset(gbSgbBorderChar, 0, 32*256); memset(gbSgbBorderChar, 0, 32 * 256);
memset(gbSgbBorder, 0, 2048); memset(gbSgbBorder, 0, 2048);
int i; int i;
for(i = 1; i < 2048; i+=2) { for (i = 1; i < 2048; i += 2) {
gbSgbBorder[i] = 1 << 2; gbSgbBorder[i] = 1 << 2;
} }
for(i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
gbPalette[i*4] = (0x1f) | (0x1f << 5) | (0x1f << 10); gbPalette[i * 4] = (0x1f) | (0x1f << 5) | (0x1f << 10);
gbPalette[i*4+1] = (0x15) | (0x15 << 5) | (0x15 << 10); gbPalette[i * 4 + 1] = (0x15) | (0x15 << 5) | (0x15 << 10);
gbPalette[i*4+2] = (0x0c) | (0x0c << 5) | (0x0c << 10); gbPalette[i * 4 + 2] = (0x0c) | (0x0c << 5) | (0x0c << 10);
gbPalette[i*4+3] = 0; gbPalette[i * 4 + 3] = 0;
} }
} }
void gbSgbInit() void gbSgbInit()
{ {
gbSgbBorderChar = (u8 *)malloc(32 * 256); gbSgbBorderChar = (u8*)malloc(32 * 256);
gbSgbBorder = (u8 *)malloc(2048); gbSgbBorder = (u8*)malloc(2048);
gbSgbReset(); gbSgbReset();
} }
void gbSgbShutdown() void gbSgbShutdown()
{ {
if(gbSgbBorderChar != NULL) { if (gbSgbBorderChar != NULL) {
free(gbSgbBorderChar); free(gbSgbBorderChar);
gbSgbBorderChar = NULL; gbSgbBorderChar = NULL;
} }
if(gbSgbBorder != NULL) { if (gbSgbBorder != NULL) {
free(gbSgbBorder); free(gbSgbBorder);
gbSgbBorder = NULL; gbSgbBorder = NULL;
} }
@ -110,77 +110,70 @@ void gbSgbShutdown()
void gbSgbFillScreen(u16 color) void gbSgbFillScreen(u16 color)
{ {
switch(systemColorDepth) { switch (systemColorDepth) {
case 16: case 16: {
{ for (int y = 0; y < 144; y++) {
for(int y = 0; y < 144; y++) { int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 2) + gbBorderColumnSkip;
int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+2) + u16* dest = (u16*)pix + yLine;
gbBorderColumnSkip; for (register int x = 0; x < 160; x++)
u16 *dest = (u16*)pix + yLine;
for(register int x = 0; x < 160; x++)
gbSgbDraw16Bit(dest++, color); gbSgbDraw16Bit(dest++, color);
} }
} } break;
break; case 24: {
case 24: for (int y = 0; y < 144; y++) {
{ int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip + gbBorderColumnSkip;
for(int y = 0; y < 144; y++) { u8* dest = (u8*)pix + yLine * 3;
int yLine = (y+gbBorderRowSkip)*gbBorderLineSkip + gbBorderColumnSkip; for (register int x = 0; x < 160; x++) {
u8 *dest = (u8 *)pix + yLine*3;
for(register int x = 0; x < 160; x++) {
gbSgbDraw24Bit(dest, color); gbSgbDraw24Bit(dest, color);
dest += 3; dest += 3;
} }
} }
} } break;
break; case 32: {
case 32: for (int y = 0; y < 144; y++) {
{ int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 1) + gbBorderColumnSkip;
for(int y = 0; y < 144; y++) { u32* dest = (u32*)pix + yLine;
int yLine = (y+gbBorderRowSkip+1)*(gbBorderLineSkip+1) + gbBorderColumnSkip; for (register int x = 0; x < 160; x++) {
u32 *dest = (u32 *)pix + yLine;
for(register int x = 0; x < 160; x++) {
gbSgbDraw32Bit(dest++, color); gbSgbDraw32Bit(dest++, color);
} }
} }
} } break;
break;
} }
} }
#define getmem(x) gbMemoryMap[(x) >> 12][(x) & 0xfff] #define getmem(x) gbMemoryMap[(x) >> 12][(x)&0xfff]
void gbSgbRenderScreenToBuffer() void gbSgbRenderScreenToBuffer()
{ {
u16 mapAddress = 0x9800; u16 mapAddress = 0x9800;
if(register_LCDC & 0x08) if (register_LCDC & 0x08)
mapAddress = 0x9c00; mapAddress = 0x9c00;
u16 patternAddress = 0x8800; u16 patternAddress = 0x8800;
int flag = 1; int flag = 1;
if(register_LCDC & 0x10) { if (register_LCDC & 0x10) {
patternAddress = 0x8000; patternAddress = 0x8000;
flag = 0; flag = 0;
} }
u8 *toAddress = gbSgbScreenBuffer; u8* toAddress = gbSgbScreenBuffer;
for(int i = 0; i < 13; i++) { for (int i = 0; i < 13; i++) {
for(int j = 0; j < 20; j++) { for (int j = 0; j < 20; j++) {
int tile = getmem(mapAddress); int tile = getmem(mapAddress);
mapAddress++; mapAddress++;
if(flag) { if (flag) {
if(tile > 127) if (tile > 127)
tile -= 128; tile -= 128;
else else
tile += 128; tile += 128;
} }
for(int k = 0; k < 16; k++) for (int k = 0; k < 16; k++)
*toAddress++ = getmem(patternAddress + tile*16 + k); *toAddress++ = getmem(patternAddress + tile * 16 + k);
} }
mapAddress += 12; mapAddress += 12;
} }
@ -188,18 +181,18 @@ void gbSgbRenderScreenToBuffer()
void gbSgbDrawBorderTile(int x, int y, int tile, int attr) void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
{ {
u16 *dest = (u16*)pix + ((y+1) * (256+2)) + x; u16* dest = (u16*)pix + ((y + 1) * (256 + 2)) + x;
u8 *dest8 = (u8*)pix + ((y*256)+x)*3; u8* dest8 = (u8*)pix + ((y * 256) + x) * 3;
u32 *dest32 = (u32*)pix + ((y+1)*257) + x; u32* dest32 = (u32*)pix + ((y + 1) * 257) + x;
u8 *tileAddress = &gbSgbBorderChar[tile * 32]; u8* tileAddress = &gbSgbBorderChar[tile * 32];
u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16]; u8* tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
u8 l = 8; u8 l = 8;
u8 palette = ((attr >> 2 ) & 7); u8 palette = ((attr >> 2) & 7);
if(palette < 4) if (palette < 4)
palette += 4; palette += 4;
palette *= 16; palette *= 16;
@ -210,37 +203,35 @@ void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
int flipX = attr & 0x40; int flipX = attr & 0x40;
int flipY = attr & 0x80; int flipY = attr & 0x80;
while(l > 0) { while (l > 0) {
u8 mask = 0x80; u8 mask = 0x80;
u8 a = *tileAddress++; u8 a = *tileAddress++;
u8 b = *tileAddress++; u8 b = *tileAddress++;
u8 c = *tileAddress2++; u8 c = *tileAddress2++;
u8 d = *tileAddress2++; u8 d = *tileAddress2++;
u8 yyy; u8 yyy;
if(!flipY) if (!flipY)
yyy = yy; yyy = yy;
else else
yyy = 7 - yy; yyy = 7 - yy;
while(mask > 0) { while (mask > 0) {
u8 color = 0; u8 color = 0;
if(a & mask) if (a & mask)
color++; color++;
if(b & mask) if (b & mask)
color+=2; color += 2;
if(c & mask) if (c & mask)
color+=4; color += 4;
if(d & mask) if (d & mask)
color+=8; color += 8;
if (color || (y + yy < 40 || y + yy >= 184) || (x + xx < 48 || x + xx >= 208)) { if (color || (y + yy < 40 || y + yy >= 184) || (x + xx < 48 || x + xx >= 208)) {
u8 xxx; u8 xxx;
if(!flipX) if (!flipX)
xxx = xx; xxx = xx;
else else
xxx = 7 - xx; xxx = 7 - xx;
@ -252,15 +243,15 @@ void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
cc = gbPalette[0]; cc = gbPalette[0];
} }
switch(systemColorDepth) { switch (systemColorDepth) {
case 16: case 16:
gbSgbDraw16Bit(dest + yyy*(256+2) + xxx, cc); gbSgbDraw16Bit(dest + yyy * (256 + 2) + xxx, cc);
break; break;
case 24: case 24:
gbSgbDraw24Bit(dest8 + (yyy*256+xxx)*3, cc); gbSgbDraw24Bit(dest8 + (yyy * 256 + xxx) * 3, cc);
break; break;
case 32: case 32:
gbSgbDraw32Bit(dest32 + yyy*(256+1)+xxx, cc); gbSgbDraw32Bit(dest32 + yyy * (256 + 1) + xxx, cc);
break; break;
} }
} }
@ -278,15 +269,15 @@ void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
void gbSgbRenderBorder() void gbSgbRenderBorder()
{ {
if(gbBorderOn) { if (gbBorderOn) {
u8 *fromAddress = gbSgbBorder; u8* fromAddress = gbSgbBorder;
for(u8 y = 0; y < 28; y++) { for (u8 y = 0; y < 28; y++) {
for(u8 x = 0; x< 32; x++) { for (u8 x = 0; x < 32; x++) {
u8 tile = *fromAddress++; u8 tile = *fromAddress++;
u8 attr = *fromAddress++; u8 attr = *fromAddress++;
gbSgbDrawBorderTile(x*8,y*8,tile,attr); gbSgbDrawBorderTile(x * 8, y * 8, tile, attr);
} }
} }
} }
@ -298,23 +289,23 @@ void gbSgbPicture()
memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048); memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048);
u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048]; u16* paletteAddr = (u16*)&gbSgbScreenBuffer[2048];
for(int i = 64; i < 128; i++) { for (int i = 64; i < 128; i++) {
gbPalette[i] = READ16LE(paletteAddr++); gbPalette[i] = READ16LE(paletteAddr++);
} }
gbSgbCGBSupport |= 4; gbSgbCGBSupport |= 4;
if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) { if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) {
gbBorderOn = 1; gbBorderOn = 1;
systemGbBorderOn(); systemGbBorderOn();
} }
if(gbBorderOn && !gbSgbMask) if (gbBorderOn && !gbSgbMask)
gbSgbRenderBorder(); gbSgbRenderBorder();
if(gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) { if (gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) {
gbSgbCGBSupport = 0; gbSgbCGBSupport = 0;
gbSgbMode = 0; gbSgbMode = 0;
gbSgbMask = 0; gbSgbMask = 0;
@ -322,25 +313,25 @@ void gbSgbPicture()
gbReset(); gbReset();
} }
if(gbSgbCGBSupport > 4) if (gbSgbCGBSupport > 4)
gbSgbCGBSupport = 0; gbSgbCGBSupport = 0;
} }
void gbSgbSetPalette(int a,int b,u16 *p) void gbSgbSetPalette(int a, int b, u16* p)
{ {
u16 bit00 = READ16LE(p++); u16 bit00 = READ16LE(p++);
int i; int i;
for(i = 1; i < 4; i++) { for (i = 1; i < 4; i++) {
gbPalette[a*4+i] = READ16LE(p++); gbPalette[a * 4 + i] = READ16LE(p++);
} }
for(i = 1; i < 4; i++) { for (i = 1; i < 4; i++) {
gbPalette[b*4+i] = READ16LE(p++); gbPalette[b * 4 + i] = READ16LE(p++);
} }
gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00; gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00;
if(gbBorderOn && !gbSgbMask) if (gbBorderOn && !gbSgbMask)
gbSgbRenderBorder(); gbSgbRenderBorder();
} }
@ -348,66 +339,66 @@ void gbSgbScpPalette()
{ {
gbSgbRenderScreenToBuffer(); gbSgbRenderScreenToBuffer();
u16 *fromAddress = (u16 *)gbSgbScreenBuffer; u16* fromAddress = (u16*)gbSgbScreenBuffer;
for(int i = 0; i < 512*4; i++) { for (int i = 0; i < 512 * 4; i++) {
gbSgbSCPPalette[i] = READ16LE(fromAddress++); gbSgbSCPPalette[i] = READ16LE(fromAddress++);
} }
} }
void gbSgbSetATF(int n) void gbSgbSetATF(int n)
{ {
if(n < 0) if (n < 0)
n = 0; n = 0;
if(n > 44) if (n > 44)
n = 44; n = 44;
memcpy(gbSgbATF,&gbSgbATFList[n * 20 * 18], 20 * 18); memcpy(gbSgbATF, &gbSgbATFList[n * 20 * 18], 20 * 18);
if(gbSgbPacket[1] & 0x40) { if (gbSgbPacket[1] & 0x40) {
gbSgbMask = 0; gbSgbMask = 0;
if(gbBorderOn) if (gbBorderOn)
gbSgbRenderBorder(); gbSgbRenderBorder();
} }
} }
void gbSgbSetPalette() void gbSgbSetPalette()
{ {
u16 pal = READ16LE((((u16 *)&gbSgbPacket[1])))&511; u16 pal = READ16LE((((u16*)&gbSgbPacket[1]))) & 511;
memcpy(&gbPalette[0], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); memcpy(&gbPalette[0], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
pal = READ16LE((((u16 *)&gbSgbPacket[3])))&511; pal = READ16LE((((u16*)&gbSgbPacket[3]))) & 511;
memcpy(&gbPalette[4], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); memcpy(&gbPalette[4], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
pal = READ16LE((((u16 *)&gbSgbPacket[5])))&511; pal = READ16LE((((u16*)&gbSgbPacket[5]))) & 511;
memcpy(&gbPalette[8], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); memcpy(&gbPalette[8], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
pal = READ16LE((((u16 *)&gbSgbPacket[7])))&511; pal = READ16LE((((u16*)&gbSgbPacket[7]))) & 511;
memcpy(&gbPalette[12], &gbSgbSCPPalette[pal*4], 4 * sizeof(u16)); memcpy(&gbPalette[12], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
u8 atf = gbSgbPacket[9]; u8 atf = gbSgbPacket[9];
if(atf & 0x80) { if (atf & 0x80) {
gbSgbSetATF(atf & 0x3f); gbSgbSetATF(atf & 0x3f);
} }
if(atf & 0x40) { if (atf & 0x40) {
gbSgbMask = 0; gbSgbMask = 0;
if(gbBorderOn) if (gbBorderOn)
gbSgbRenderBorder(); gbSgbRenderBorder();
} }
} }
void gbSgbAttributeBlock() void gbSgbAttributeBlock()
{ {
u8 *fromAddress = &gbSgbPacket[1]; u8* fromAddress = &gbSgbPacket[1];
u8 nDataSet = *fromAddress++; u8 nDataSet = *fromAddress++;
if(nDataSet > 12) if (nDataSet > 12)
nDataSet = 12; nDataSet = 12;
if(nDataSet == 0) if (nDataSet == 0)
nDataSet = 1; nDataSet = 1;
while(nDataSet) { while (nDataSet) {
u8 controlCode = (*fromAddress++) & 7; u8 controlCode = (*fromAddress++) & 7;
u8 paletteDesignation = (*fromAddress++) & 0x3f; u8 paletteDesignation = (*fromAddress++) & 0x3f;
u8 startH = (*fromAddress++) & 0x1f; u8 startH = (*fromAddress++) & 0x1f;
@ -415,25 +406,23 @@ void gbSgbAttributeBlock()
u8 endH = (*fromAddress++) & 0x1f; u8 endH = (*fromAddress++) & 0x1f;
u8 endV = (*fromAddress++) & 0x1f; u8 endV = (*fromAddress++) & 0x1f;
u8 * toAddress = gbSgbATF; u8* toAddress = gbSgbATF;
for(u8 y = 0; y < 18; y++) { for (u8 y = 0; y < 18; y++) {
for(u8 x = 0; x < 20; x++) { for (u8 x = 0; x < 20; x++) {
if(x < startH || y < startV || if (x < startH || y < startV || x > endH || y > endV) {
x > endH || y > endV) {
// outside // outside
if(controlCode & 0x04) if (controlCode & 0x04)
*toAddress = (paletteDesignation >> 4) & 0x03; *toAddress = (paletteDesignation >> 4) & 0x03;
} else if(x > startH && x < endH && } else if (x > startH && x < endH && y > startV && y < endV) {
y > startV && y < endV) {
// inside // inside
if(controlCode & 0x01) if (controlCode & 0x01)
*toAddress = paletteDesignation & 0x03; *toAddress = paletteDesignation & 0x03;
} else { } else {
// surrounding line // surrounding line
if(controlCode & 0x02) if (controlCode & 0x02)
*toAddress = (paletteDesignation>>2) & 0x03; *toAddress = (paletteDesignation >> 2) & 0x03;
else if(controlCode == 0x01) else if (controlCode == 0x01)
*toAddress = paletteDesignation & 0x03; *toAddress = paletteDesignation & 0x03;
} }
toAddress++; toAddress++;
@ -447,14 +436,14 @@ void gbSgbSetColumnPalette(u8 col, u8 p)
{ {
// if(col < 0) // if(col < 0)
// col = 0; // col = 0;
if(col > 19) if (col > 19)
col = 19; col = 19;
p &= 3; p &= 3;
u8 *toAddress = &gbSgbATF[col]; u8* toAddress = &gbSgbATF[col];
for(u8 y = 0; y < 18; y++) { for (u8 y = 0; y < 18; y++) {
*toAddress = p; *toAddress = p;
toAddress += 20; toAddress += 20;
} }
@ -464,14 +453,14 @@ void gbSgbSetRowPalette(u8 row, u8 p)
{ {
// if(row < 0) // if(row < 0)
// row = 0; // row = 0;
if(row > 17) if (row > 17)
row = 17; row = 17;
p &= 3; p &= 3;
u8 *toAddress = &gbSgbATF[row*20]; u8* toAddress = &gbSgbATF[row * 20];
for(u8 x = 0; x < 20; x++) { for (u8 x = 0; x < 20; x++) {
*toAddress++ = p; *toAddress++ = p;
} }
} }
@ -484,26 +473,26 @@ void gbSgbAttributeDivide()
u8 colorAL = (control >> 2) & 3; u8 colorAL = (control >> 2) & 3;
u8 colorOL = (control >> 4) & 3; u8 colorOL = (control >> 4) & 3;
if(control & 0x40) { if (control & 0x40) {
if(coord > 17) if (coord > 17)
coord = 17; coord = 17;
for(u8 i = 0; i < 18; i++) { for (u8 i = 0; i < 18; i++) {
if(i < coord) if (i < coord)
gbSgbSetRowPalette(i, colorAL); gbSgbSetRowPalette(i, colorAL);
else if ( i > coord) else if (i > coord)
gbSgbSetRowPalette(i, colorBR); gbSgbSetRowPalette(i, colorBR);
else else
gbSgbSetRowPalette(i, colorOL); gbSgbSetRowPalette(i, colorOL);
} }
} else { } else {
if(coord > 19) if (coord > 19)
coord = 19; coord = 19;
for(u8 i = 0; i < 20; i++) { for (u8 i = 0; i < 20; i++) {
if(i < coord) if (i < coord)
gbSgbSetColumnPalette(i, colorAL); gbSgbSetColumnPalette(i, colorAL);
else if ( i > coord) else if (i > coord)
gbSgbSetColumnPalette(i, colorBR); gbSgbSetColumnPalette(i, colorBR);
else else
gbSgbSetColumnPalette(i, colorOL); gbSgbSetColumnPalette(i, colorOL);
@ -513,25 +502,25 @@ void gbSgbAttributeDivide()
void gbSgbAttributeLine() void gbSgbAttributeLine()
{ {
u8 *fromAddress = &gbSgbPacket[1]; u8* fromAddress = &gbSgbPacket[1];
u8 nDataSet = *fromAddress++; u8 nDataSet = *fromAddress++;
if(nDataSet > 0x6e) if (nDataSet > 0x6e)
nDataSet = 0x6e; nDataSet = 0x6e;
while(nDataSet) { while (nDataSet) {
u8 line = *fromAddress++; u8 line = *fromAddress++;
u8 num = line & 0x1f; u8 num = line & 0x1f;
u8 pal = (line >> 5) & 0x03; u8 pal = (line >> 5) & 0x03;
if(line & 0x80) { if (line & 0x80) {
if(num > 17) if (num > 17)
num = 17; num = 17;
gbSgbSetRowPalette(num,pal); gbSgbSetRowPalette(num, pal);
} else { } else {
if(num > 19) if (num > 19)
num = 19; num = 19;
gbSgbSetColumnPalette(num,pal); gbSgbSetColumnPalette(num, pal);
} }
nDataSet--; nDataSet--;
} }
@ -541,30 +530,30 @@ void gbSgbAttributeCharacter()
{ {
u8 startH = gbSgbPacket[1] & 0x1f; u8 startH = gbSgbPacket[1] & 0x1f;
u8 startV = gbSgbPacket[2] & 0x1f; u8 startV = gbSgbPacket[2] & 0x1f;
int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3])); int nDataSet = READ16LE(((u16*)&gbSgbPacket[3]));
int style = gbSgbPacket[5] & 1; int style = gbSgbPacket[5] & 1;
if(startH > 19) if (startH > 19)
startH = 19; startH = 19;
if(startV > 17) if (startV > 17)
startV = 17; startV = 17;
u8 s = 6; u8 s = 6;
u8 *fromAddress = &gbSgbPacket[6]; u8* fromAddress = &gbSgbPacket[6];
u8 v = *fromAddress++; u8 v = *fromAddress++;
if(style) { if (style) {
while(nDataSet) { while (nDataSet) {
u8 p = (v >> s) & 3; u8 p = (v >> s) & 3;
gbSgbATF[startV * 20 + startH] = p; gbSgbATF[startV * 20 + startH] = p;
startV++; startV++;
if(startV == 18) { if (startV == 18) {
startV = 0; startV = 0;
startH++; startH++;
if(startH == 20) if (startH == 20)
break; break;
} }
if(s) if (s)
s -= 2; s -= 2;
else { else {
s = 6; s = 6;
@ -573,18 +562,18 @@ void gbSgbAttributeCharacter()
} }
} }
} else { } else {
while(nDataSet) { while (nDataSet) {
u8 p = (v >> s) & 3; u8 p = (v >> s) & 3;
gbSgbATF[startV * 20 + startH] = p; gbSgbATF[startV * 20 + startH] = p;
startH++; startH++;
if(startH == 20) { if (startH == 20) {
startH = 0; startH = 0;
startV++; startV++;
if(startV == 18) if (startV == 18)
break; break;
} }
if(s) if (s)
s -= 2; s -= 2;
else { else {
s = 6; s = 6;
@ -599,16 +588,16 @@ void gbSgbSetATFList()
{ {
gbSgbRenderScreenToBuffer(); gbSgbRenderScreenToBuffer();
u8 *fromAddress = gbSgbScreenBuffer; u8* fromAddress = gbSgbScreenBuffer;
u8 *toAddress = gbSgbATFList; u8* toAddress = gbSgbATFList;
for(int i = 0; i < 45; i++) { for (int i = 0; i < 45; i++) {
for(int j = 0; j < 90; j++) { for (int j = 0; j < 90; j++) {
u8 v = *fromAddress++; u8 v = *fromAddress++;
u8 s = 6; u8 s = 6;
if(i == 2) if (i == 2)
s = 6; s = 6;
for(int k = 0; k < 4; k++) { for (int k = 0; k < 4; k++) {
*toAddress++ = (v >> s) & 0x03; *toAddress++ = (v >> s) & 0x03;
s -= 2; s -= 2;
} }
@ -622,7 +611,7 @@ void gbSgbMaskEnable()
gbSgbMask = gbSgbMaskFlag; gbSgbMask = gbSgbMaskFlag;
switch(gbSgbMaskFlag) { switch (gbSgbMaskFlag) {
case 1: case 1:
break; break;
case 2: case 2:
@ -633,8 +622,8 @@ void gbSgbMaskEnable()
gbSgbFillScreen(gbPalette[0]); gbSgbFillScreen(gbPalette[0]);
break; break;
} }
if(!gbSgbMask) { if (!gbSgbMask) {
if(gbBorderOn) if (gbBorderOn)
gbSgbRenderBorder(); gbSgbRenderBorder();
} }
} }
@ -643,24 +632,24 @@ void gbSgbChrTransfer()
{ {
gbSgbRenderScreenToBuffer(); gbSgbRenderScreenToBuffer();
int address = (gbSgbPacket[1] & 1) * (128*32); int address = (gbSgbPacket[1] & 1) * (128 * 32);
if(gbSgbPacket[1] & 1) if (gbSgbPacket[1] & 1)
gbSgbCGBSupport |= 2; gbSgbCGBSupport |= 2;
else else
gbSgbCGBSupport |= 1; gbSgbCGBSupport |= 1;
memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32); memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32);
if(gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) { if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) {
gbBorderOn = 1; gbBorderOn = 1;
systemGbBorderOn(); systemGbBorderOn();
} }
if(gbBorderOn && !gbSgbMask) if (gbBorderOn && !gbSgbMask)
gbSgbRenderBorder(); gbSgbRenderBorder();
if(gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) { if (gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) {
gbSgbCGBSupport = 0; gbSgbCGBSupport = 0;
gbSgbMode = 0; gbSgbMode = 0;
gbSgbMask = 0; gbSgbMask = 0;
@ -668,15 +657,15 @@ void gbSgbChrTransfer()
gbReset(); gbReset();
} }
if(gbSgbCGBSupport > 4) if (gbSgbCGBSupport > 4)
gbSgbCGBSupport = 0; gbSgbCGBSupport = 0;
} }
void gbSgbMultiRequest() void gbSgbMultiRequest()
{ {
if(gbSgbPacket[1] & 1) { if (gbSgbPacket[1] & 1) {
gbSgbMultiplayer = 1; gbSgbMultiplayer = 1;
if(gbSgbPacket[1] & 2) if (gbSgbPacket[1] & 2)
gbSgbFourPlayers = 1; gbSgbFourPlayers = 1;
else else
gbSgbFourPlayers = 0; gbSgbFourPlayers = 0;
@ -693,18 +682,18 @@ void gbSgbCommand()
int command = gbSgbPacket[0] >> 3; int command = gbSgbPacket[0] >> 3;
// int nPacket = gbSgbPacket[0] & 7; // int nPacket = gbSgbPacket[0] & 7;
switch(command) { switch (command) {
case 0x00: case 0x00:
gbSgbSetPalette(0,1,(u16 *)&gbSgbPacket[1]); gbSgbSetPalette(0, 1, (u16*)&gbSgbPacket[1]);
break; break;
case 0x01: case 0x01:
gbSgbSetPalette(2,3,(u16 *)&gbSgbPacket[1]); gbSgbSetPalette(2, 3, (u16*)&gbSgbPacket[1]);
break; break;
case 0x02: case 0x02:
gbSgbSetPalette(0,3,(u16 *)&gbSgbPacket[1]); gbSgbSetPalette(0, 3, (u16*)&gbSgbPacket[1]);
break; break;
case 0x03: case 0x03:
gbSgbSetPalette(1,2,(u16 *)&gbSgbPacket[1]); gbSgbSetPalette(1, 2, (u16*)&gbSgbPacket[1]);
break; break;
case 0x04: case 0x04:
gbSgbAttributeBlock(); gbSgbAttributeBlock();
@ -754,22 +743,22 @@ void gbSgbResetPacketState()
void gbSgbDoBitTransfer(u8 value) void gbSgbDoBitTransfer(u8 value)
{ {
value = value & 0x30; value = value & 0x30;
switch(gbSgbPacketState) { switch (gbSgbPacketState) {
case GBSGB_NONE: case GBSGB_NONE:
if(value == 0) { if (value == 0) {
gbSgbPacketState = GBSGB_RESET; gbSgbPacketState = GBSGB_RESET;
gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
} else if (value == 0x30) { } else if (value == 0x30) {
if(gbSgbMultiplayer) { if (gbSgbMultiplayer) {
if((gbSgbReadingController & 7) == 7) { if ((gbSgbReadingController & 7) == 7) {
gbSgbReadingController = 0; gbSgbReadingController = 0;
if(gbSgbMultiplayer) { if (gbSgbMultiplayer) {
gbSgbNextController--; gbSgbNextController--;
if(gbSgbFourPlayers) { if (gbSgbFourPlayers) {
if(gbSgbNextController == 0x0b) if (gbSgbNextController == 0x0b)
gbSgbNextController = 0x0f; gbSgbNextController = 0x0f;
} else { } else {
if(gbSgbNextController == 0x0d) if (gbSgbNextController == 0x0d)
gbSgbNextController = 0x0f; gbSgbNextController = 0x0f;
} }
} }
@ -779,21 +768,21 @@ void gbSgbDoBitTransfer(u8 value)
} }
gbSgbPacketTimeout = 0; gbSgbPacketTimeout = 0;
} else { } else {
if(value == 0x10) if (value == 0x10)
gbSgbReadingController |= 0x2; gbSgbReadingController |= 0x2;
else if(value == 0x20) else if (value == 0x20)
gbSgbReadingController |= 0x01; gbSgbReadingController |= 0x01;
gbSgbPacketTimeout = 0; gbSgbPacketTimeout = 0;
} }
gbSgbPacketTimeout = 0; gbSgbPacketTimeout = 0;
break; break;
case GBSGB_RESET: case GBSGB_RESET:
if(value == 0x30) { if (value == 0x30) {
gbSgbPacketState = GBSGB_PACKET_TRANSMIT; gbSgbPacketState = GBSGB_PACKET_TRANSMIT;
gbSgbPacketByte = 0; gbSgbPacketByte = 0;
gbSgbPacketNBits = 0; gbSgbPacketNBits = 0;
gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
} else if(value == 0x00) { } else if (value == 0x00) {
gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
gbSgbPacketState = GBSGB_RESET; gbSgbPacketState = GBSGB_RESET;
} else { } else {
@ -802,34 +791,34 @@ void gbSgbDoBitTransfer(u8 value)
} }
break; break;
case GBSGB_PACKET_TRANSMIT: case GBSGB_PACKET_TRANSMIT:
if(value == 0) { if (value == 0) {
gbSgbPacketState = GBSGB_RESET; gbSgbPacketState = GBSGB_RESET;
gbSgbPacketTimeout = 0; gbSgbPacketTimeout = 0;
} else if (value == 0x30){ } else if (value == 0x30) {
if(gbSgbPacketNBits == 128) { if (gbSgbPacketNBits == 128) {
gbSgbPacketNBits = 0; gbSgbPacketNBits = 0;
gbSgbPacketByte = 0; gbSgbPacketByte = 0;
gbSgbPacketNumber++; gbSgbPacketNumber++;
gbSgbPacketTimeout = 0; gbSgbPacketTimeout = 0;
if(gbSgbPacketNumber == (gbSgbPacket[0] & 7)) { if (gbSgbPacketNumber == (gbSgbPacket[0] & 7)) {
gbSgbCommand(); gbSgbCommand();
gbSgbPacketNumber = 0; gbSgbPacketNumber = 0;
gbSgbPacketState = GBSGB_NONE; gbSgbPacketState = GBSGB_NONE;
gbSgbPacketTimeout = 0; gbSgbPacketTimeout = 0;
} }
} else { } else {
if(gbSgbPacketNBits < 128) { if (gbSgbPacketNBits < 128) {
gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1; gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1;
gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit; gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit;
gbSgbPacketNBits++; gbSgbPacketNBits++;
if(!(gbSgbPacketNBits & 7)) { if (!(gbSgbPacketNBits & 7)) {
gbSgbPacketByte++; gbSgbPacketByte++;
} }
gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
} }
} }
} else { } else {
if(value == 0x20) if (value == 0x20)
gbSgbBit = 0x00; gbSgbBit = 0x00;
else else
gbSgbBit = 0x80; gbSgbBit = 0x80;
@ -876,9 +865,9 @@ void gbSgbSaveGame(gzFile gzFile)
utilWriteData(gzFile, gbSgbSaveStructV3); utilWriteData(gzFile, gbSgbSaveStructV3);
utilGzWrite(gzFile, gbSgbBorder, 2048); utilGzWrite(gzFile, gbSgbBorder, 2048);
utilGzWrite(gzFile, gbSgbBorderChar, 32*256); utilGzWrite(gzFile, gbSgbBorderChar, 32 * 256);
utilGzWrite(gzFile, gbSgbPacket, 16*7); utilGzWrite(gzFile, gbSgbPacket, 16 * 7);
utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
utilGzWrite(gzFile, gbSgbATF, 20 * 18); utilGzWrite(gzFile, gbSgbATF, 20 * 18);
@ -887,19 +876,19 @@ void gbSgbSaveGame(gzFile gzFile)
void gbSgbReadGame(gzFile gzFile, int version) void gbSgbReadGame(gzFile gzFile, int version)
{ {
if(version >= 3) if (version >= 3)
utilReadData(gzFile, gbSgbSaveStructV3); utilReadData(gzFile, gbSgbSaveStructV3);
else { else {
utilReadData(gzFile, gbSgbSaveStruct); utilReadData(gzFile, gbSgbSaveStruct);
gbSgbFourPlayers = 0; gbSgbFourPlayers = 0;
} }
if(version >= 8) { if (version >= 8) {
utilGzRead(gzFile, gbSgbBorder, 2048); utilGzRead(gzFile, gbSgbBorder, 2048);
utilGzRead(gzFile, gbSgbBorderChar, 32*256); utilGzRead(gzFile, gbSgbBorderChar, 32 * 256);
} }
utilGzRead(gzFile, gbSgbPacket, 16*7); utilGzRead(gzFile, gbSgbPacket, 16 * 7);
utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
utilGzRead(gzFile, gbSgbATF, 20 * 18); utilGzRead(gzFile, gbSgbATF, 20 * 18);

View File

@ -1,13 +1,13 @@
#include <string.h> #include <string.h>
#include "../gba/Sound.h"
#include "../Util.h" #include "../Util.h"
#include "../gba/Sound.h"
#include "gb.h"
#include "gbGlobals.h" #include "gbGlobals.h"
#include "gbSound.h" #include "gbSound.h"
#include "gb.h"
#include "../apu/Gb_Apu.h"
#include "../apu/Effects_Buffer.h" #include "../apu/Effects_Buffer.h"
#include "../apu/Gb_Apu.h"
extern long soundSampleRate; // current sound quality extern long soundSampleRate; // current sound quality
@ -29,10 +29,10 @@ static inline blip_time_t blip_time()
return (SOUND_CLOCK_TICKS - soundTicks) * ticks_to_time; return (SOUND_CLOCK_TICKS - soundTicks) * ticks_to_time;
} }
u8 gbSoundRead( u16 address ) u8 gbSoundRead(u16 address)
{ {
if ( gb_apu && address >= NR10 && address <= 0xFF3F ) if (gb_apu && address >= NR10 && address <= 0xFF3F)
return gb_apu->read_register( blip_time(), address ); return gb_apu->read_register(blip_time(), address);
return gbMemory[address]; return gbMemory[address];
} }
@ -41,14 +41,14 @@ void gbSoundEvent(register u16 address, register int data)
{ {
gbMemory[address] = data; gbMemory[address] = data;
if ( gb_apu && address >= NR10 && address <= 0xFF3F ) if (gb_apu && address >= NR10 && address <= 0xFF3F)
gb_apu->write_register( blip_time(), address, data ); gb_apu->write_register(blip_time(), address, data);
} }
static void end_frame( blip_time_t time ) static void end_frame(blip_time_t time)
{ {
gb_apu ->end_frame( time ); gb_apu->end_frame(time);
stereo_buffer->end_frame( time ); stereo_buffer->end_frame(time);
} }
static void apply_effects() static void apply_effects()
@ -62,16 +62,15 @@ static void apply_effects()
stereo_buffer->config().surround = gb_effects_config_current.surround; stereo_buffer->config().surround = gb_effects_config_current.surround;
stereo_buffer->apply_config(); stereo_buffer->apply_config();
for ( int i = 0; i < chan_count; i++ ) for (int i = 0; i < chan_count; i++) {
{
Multi_Buffer::channel_t ch = { 0, 0, 0 }; Multi_Buffer::channel_t ch = { 0, 0, 0 };
if ( prevSoundEnable >> i & 1 ) if (prevSoundEnable >> i & 1)
ch = stereo_buffer->channel( i ); ch = stereo_buffer->channel(i);
gb_apu->set_output( ch.center, ch.left, ch.right, i ); gb_apu->set_output(ch.center, ch.left, ch.right, i);
} }
} }
void gbSoundConfigEffects( gb_effects_config_t const& c ) void gbSoundConfigEffects(gb_effects_config_t const& c)
{ {
gb_effects_config = c; gb_effects_config = c;
} }
@ -80,25 +79,25 @@ static void apply_volume()
{ {
soundVolume_ = soundGetVolume(); soundVolume_ = soundGetVolume();
if ( gb_apu ) if (gb_apu)
gb_apu->volume( soundVolume_ ); gb_apu->volume(soundVolume_);
} }
void gbSoundTick() void gbSoundTick()
{ {
if ( gb_apu && stereo_buffer ) if (gb_apu && stereo_buffer) {
{
// Run sound hardware to present // Run sound hardware to present
end_frame( SOUND_CLOCK_TICKS * ticks_to_time ); end_frame(SOUND_CLOCK_TICKS * ticks_to_time);
flush_samples(stereo_buffer); flush_samples(stereo_buffer);
// Update effects config if it was changed // Update effects config if it was changed
if ( memcmp( &gb_effects_config_current, &gb_effects_config, if (memcmp(&gb_effects_config_current, &gb_effects_config,
sizeof gb_effects_config ) || soundGetEnable() != prevSoundEnable ) sizeof gb_effects_config)
|| soundGetEnable() != prevSoundEnable)
apply_effects(); apply_effects();
if ( soundVolume_ != soundGetVolume() ) if (soundVolume_ != soundGetVolume())
apply_volume(); apply_volume();
} }
} }
@ -106,14 +105,14 @@ void gbSoundTick()
static void reset_apu() static void reset_apu()
{ {
Gb_Apu::mode_t mode = Gb_Apu::mode_dmg; Gb_Apu::mode_t mode = Gb_Apu::mode_dmg;
if ( gbHardware & 2 ) if (gbHardware & 2)
mode = Gb_Apu::mode_cgb; mode = Gb_Apu::mode_cgb;
if ( gbHardware & 8 || declicking ) if (gbHardware & 8 || declicking)
mode = Gb_Apu::mode_agb; mode = Gb_Apu::mode_agb;
gb_apu->reset( mode ); gb_apu->reset(mode);
gb_apu->reduce_clicks( declicking ); gb_apu->reduce_clicks(declicking);
if ( stereo_buffer ) if (stereo_buffer)
stereo_buffer->clear(); stereo_buffer->clear();
soundTicks = SOUND_CLOCK_TICKS; soundTicks = SOUND_CLOCK_TICKS;
@ -122,8 +121,7 @@ static void reset_apu()
static void remake_stereo_buffer() static void remake_stereo_buffer()
{ {
// APU // APU
if ( !gb_apu ) if (!gb_apu) {
{
gb_apu = new Gb_Apu; // TODO: handle errors gb_apu = new Gb_Apu; // TODO: handle errors
reset_apu(); reset_apu();
} }
@ -133,34 +131,35 @@ static void remake_stereo_buffer()
stereo_buffer = 0; stereo_buffer = 0;
stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory
if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory if (stereo_buffer->set_sample_rate(soundSampleRate)) {
stereo_buffer->clock_rate( gb_apu->clock_rate ); } // TODO: handle out of memory
stereo_buffer->clock_rate(gb_apu->clock_rate);
// Multi_Buffer // Multi_Buffer
static int const chan_types [chan_count] = { static int const chan_types[chan_count] = {
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2, Multi_Buffer::wave_type + 1, Multi_Buffer::wave_type + 2,
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1 Multi_Buffer::wave_type + 3, Multi_Buffer::mixed_type + 1
}; };
if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors if (stereo_buffer->set_channel_count(chan_count, chan_types)) {
} // TODO: handle errors
// Volume Level // Volume Level
apply_effects(); apply_effects();
apply_volume(); apply_volume();
} }
void gbSoundSetDeclicking( bool enable ) void gbSoundSetDeclicking(bool enable)
{ {
if ( declicking != enable ) if (declicking != enable) {
{
declicking = enable; declicking = enable;
if ( gb_apu ) if (gb_apu) {
{
// Can't change sound hardware mode without resetting APU, so save/load // Can't change sound hardware mode without resetting APU, so save/load
// state around mode change // state around mode change
gb_apu_state_t state; gb_apu_state_t state;
gb_apu->save_state( &state ); gb_apu->save_state(&state);
reset_apu(); reset_apu();
if ( gb_apu->load_state( state ) ) { } // ignore error if (gb_apu->load_state(state)) {
} // ignore error
} }
} }
} }
@ -212,24 +211,20 @@ void gbSoundReset()
int addr = 0xff30; int addr = 0xff30;
while(addr < 0xff40) { while (addr < 0xff40) {
gbMemory[addr++] = 0x00; gbMemory[addr++] = 0x00;
gbMemory[addr++] = 0xff; gbMemory[addr++] = 0xff;
} }
} }
void gbSoundSetSampleRate( long sampleRate ) void gbSoundSetSampleRate(long sampleRate)
{ {
if ( soundSampleRate != sampleRate ) if (soundSampleRate != sampleRate) {
{ if (systemCanChangeSoundQuality()) {
if ( systemCanChangeSoundQuality() )
{
soundShutdown(); soundShutdown();
soundSampleRate = sampleRate; soundSampleRate = sampleRate;
soundInit(); soundInit();
} } else {
else
{
soundSampleRate = sampleRate; soundSampleRate = sampleRate;
} }
@ -242,202 +237,220 @@ static struct {
gb_apu_state_t apu; gb_apu_state_t apu;
} state; } state;
static char dummy_state [735 * 2]; static char dummy_state[735 * 2];
#define SKIP( type, name ) { dummy_state, sizeof (type) } #define SKIP(type, name) \
{ \
dummy_state, sizeof(type) \
}
#define LOAD( type, name ) { &name, sizeof (type) } #define LOAD(type, name) \
{ \
&name, sizeof(type) \
}
// Old save state support // Old save state support
static variable_desc gbsound_format [] = static variable_desc gbsound_format[] = {
{ SKIP(int, soundPaused),
SKIP( int, soundPaused ), SKIP(int, soundPlay),
SKIP( int, soundPlay ), SKIP(int, soundTicks),
SKIP( int, soundTicks ), SKIP(int, SOUND_CLOCK_TICKS),
SKIP( int, SOUND_CLOCK_TICKS ), SKIP(int, soundLevel1),
SKIP( int, soundLevel1 ), SKIP(int, soundLevel2),
SKIP( int, soundLevel2 ), SKIP(int, soundBalance),
SKIP( int, soundBalance ), SKIP(int, soundMasterOn),
SKIP( int, soundMasterOn ), SKIP(int, soundIndex),
SKIP( int, soundIndex ), SKIP(int, soundVIN),
SKIP( int, soundVIN ), SKIP(int, soundOn[0]),
SKIP( int, soundOn [0] ), SKIP(int, soundATL[0]),
SKIP( int, soundATL [0] ), SKIP(int, sound1Skip),
SKIP( int, sound1Skip ), SKIP(int, soundIndex[0]),
SKIP( int, soundIndex [0] ), SKIP(int, sound1Continue),
SKIP( int, sound1Continue ), SKIP(int, soundEnvelopeVolume[0]),
SKIP( int, soundEnvelopeVolume [0] ), SKIP(int, soundEnvelopeATL[0]),
SKIP( int, soundEnvelopeATL [0] ), SKIP(int, sound1EnvelopeATLReload),
SKIP( int, sound1EnvelopeATLReload ), SKIP(int, sound1EnvelopeUpDown),
SKIP( int, sound1EnvelopeUpDown ), SKIP(int, sound1SweepATL),
SKIP( int, sound1SweepATL ), SKIP(int, sound1SweepATLReload),
SKIP( int, sound1SweepATLReload ), SKIP(int, sound1SweepSteps),
SKIP( int, sound1SweepSteps ), SKIP(int, sound1SweepUpDown),
SKIP( int, sound1SweepUpDown ), SKIP(int, sound1SweepStep),
SKIP( int, sound1SweepStep ), SKIP(int, soundOn[1]),
SKIP( int, soundOn [1] ), SKIP(int, soundATL[1]),
SKIP( int, soundATL [1] ), SKIP(int, sound2Skip),
SKIP( int, sound2Skip ), SKIP(int, soundIndex[1]),
SKIP( int, soundIndex [1] ), SKIP(int, sound2Continue),
SKIP( int, sound2Continue ), SKIP(int, soundEnvelopeVolume[1]),
SKIP( int, soundEnvelopeVolume [1] ), SKIP(int, soundEnvelopeATL[1]),
SKIP( int, soundEnvelopeATL [1] ), SKIP(int, sound2EnvelopeATLReload),
SKIP( int, sound2EnvelopeATLReload ), SKIP(int, sound2EnvelopeUpDown),
SKIP( int, sound2EnvelopeUpDown ), SKIP(int, soundOn[2]),
SKIP( int, soundOn [2] ), SKIP(int, soundATL[2]),
SKIP( int, soundATL [2] ), SKIP(int, sound3Skip),
SKIP( int, sound3Skip ), SKIP(int, soundIndex[2]),
SKIP( int, soundIndex [2] ), SKIP(int, sound3Continue),
SKIP( int, sound3Continue ), SKIP(int, sound3OutputLevel),
SKIP( int, sound3OutputLevel ), SKIP(int, soundOn[3]),
SKIP( int, soundOn [3] ), SKIP(int, soundATL[3]),
SKIP( int, soundATL [3] ), SKIP(int, sound4Skip),
SKIP( int, sound4Skip ), SKIP(int, soundIndex[3]),
SKIP( int, soundIndex [3] ), SKIP(int, sound4Clock),
SKIP( int, sound4Clock ), SKIP(int, sound4ShiftRight),
SKIP( int, sound4ShiftRight ), SKIP(int, sound4ShiftSkip),
SKIP( int, sound4ShiftSkip ), SKIP(int, sound4ShiftIndex),
SKIP( int, sound4ShiftIndex ), SKIP(int, sound4NSteps),
SKIP( int, sound4NSteps ), SKIP(int, sound4CountDown),
SKIP( int, sound4CountDown ), SKIP(int, sound4Continue),
SKIP( int, sound4Continue ), SKIP(int, soundEnvelopeVolume[2]),
SKIP( int, soundEnvelopeVolume [2] ), SKIP(int, soundEnvelopeATL[2]),
SKIP( int, soundEnvelopeATL [2] ), SKIP(int, sound4EnvelopeATLReload),
SKIP( int, sound4EnvelopeATLReload ), SKIP(int, sound4EnvelopeUpDown),
SKIP( int, sound4EnvelopeUpDown ), SKIP(int, soundEnableFlag),
SKIP( int, soundEnableFlag ),
{ NULL, 0 } { NULL, 0 }
}; };
static variable_desc gbsound_format2 [] = static variable_desc gbsound_format2[] = {
{ SKIP(int, sound1ATLreload),
SKIP( int, sound1ATLreload ), SKIP(int, freq1low),
SKIP( int, freq1low ), SKIP(int, freq1high),
SKIP( int, freq1high ), SKIP(int, sound2ATLreload),
SKIP( int, sound2ATLreload ), SKIP(int, freq2low),
SKIP( int, freq2low ), SKIP(int, freq2high),
SKIP( int, freq2high ), SKIP(int, sound3ATLreload),
SKIP( int, sound3ATLreload ), SKIP(int, freq3low),
SKIP( int, freq3low ), SKIP(int, freq3high),
SKIP( int, freq3high ), SKIP(int, sound4ATLreload),
SKIP( int, sound4ATLreload ), SKIP(int, freq4),
SKIP( int, freq4 ),
{ NULL, 0 } { NULL, 0 }
}; };
static variable_desc gbsound_format3 [] = static variable_desc gbsound_format3[] = {
{ SKIP(u8[2 * 735], soundBuffer),
SKIP( u8[2*735], soundBuffer ), SKIP(u8[2 * 735], soundBuffer),
SKIP( u8[2*735], soundBuffer ), SKIP(u16[735], soundFinalWave),
SKIP( u16[735], soundFinalWave ),
{ NULL, 0 } { NULL, 0 }
}; };
enum { enum {
nr10 = 0, nr10 = 0,
nr11, nr12, nr13, nr14, nr11,
nr20, nr21, nr22, nr23, nr24, nr12,
nr30, nr31, nr32, nr33, nr34, nr13,
nr40, nr41, nr42, nr43, nr44, nr14,
nr50, nr51, nr52 nr20,
nr21,
nr22,
nr23,
nr24,
nr30,
nr31,
nr32,
nr33,
nr34,
nr40,
nr41,
nr42,
nr43,
nr44,
nr50,
nr51,
nr52
}; };
static void gbSoundReadGameOld(int version,gzFile gzFile) static void gbSoundReadGameOld(int version, gzFile gzFile)
{ {
if ( version == 11 ) if (version == 11) {
{
// Version 11 didn't save any state // Version 11 didn't save any state
// TODO: same for version 10? // TODO: same for version 10?
state.apu.regs [nr50] = 0x77; // volume at max state.apu.regs[nr50] = 0x77; // volume at max
state.apu.regs [nr51] = 0xFF; // channels enabled state.apu.regs[nr51] = 0xFF; // channels enabled
state.apu.regs [nr52] = 0x80; // power on state.apu.regs[nr52] = 0x80; // power on
return; return;
} }
// Load state // Load state
utilReadData( gzFile, gbsound_format ); utilReadData(gzFile, gbsound_format);
if ( version >= 11 ) // TODO: never executed; remove? if (version >= 11) // TODO: never executed; remove?
utilReadData( gzFile, gbsound_format2 ); utilReadData(gzFile, gbsound_format2);
utilReadData( gzFile, gbsound_format3 ); utilReadData(gzFile, gbsound_format3);
int quality = 1; int quality = 1;
if ( version >= 7 ) if (version >= 7)
quality = utilReadInt( gzFile ); quality = utilReadInt(gzFile);
gbSoundSetSampleRate( 44100 / quality ); gbSoundSetSampleRate(44100 / quality);
// Convert to format Gb_Apu uses // Convert to format Gb_Apu uses
gb_apu_state_t& s = state.apu; gb_apu_state_t& s = state.apu;
// Only some registers are properly preserved // Only some registers are properly preserved
static int const regs_to_copy [] = { static int const regs_to_copy[] = {
nr10, nr11, nr12, nr21, nr22, nr30, nr32, nr42, nr43, nr50, nr51, nr52, -1 nr10, nr11, nr12, nr21, nr22, nr30, nr32, nr42, nr43, nr50, nr51, nr52, -1
}; };
for ( int i = 0; regs_to_copy [i] >= 0; i++ ) for (int i = 0; regs_to_copy[i] >= 0; i++)
s.regs [regs_to_copy [i]] = gbMemory [0xFF10 + regs_to_copy [i]]; s.regs[regs_to_copy[i]] = gbMemory[0xFF10 + regs_to_copy[i]];
memcpy( &s.regs [0x20], &gbMemory [0xFF30], 0x10 ); // wave memcpy(&s.regs[0x20], &gbMemory[0xFF30], 0x10); // wave
} }
// New state format // New state format
static variable_desc gb_state [] = static variable_desc gb_state[] = {
{ LOAD(int, state.version), // room_for_expansion will be used by later versions
LOAD( int, state.version ), // room_for_expansion will be used by later versions
// APU // APU
LOAD( u8 [0x40], state.apu.regs ), // last values written to registers and wave RAM (both banks) LOAD(u8[0x40], state.apu.regs), // last values written to registers and wave RAM (both banks)
LOAD( int, state.apu.frame_time ), // clocks until next frame sequencer action LOAD(int, state.apu.frame_time), // clocks until next frame sequencer action
LOAD( int, state.apu.frame_phase ), // next step frame sequencer will run LOAD(int, state.apu.frame_phase), // next step frame sequencer will run
LOAD( int, state.apu.sweep_freq ), // sweep's internal frequency register LOAD(int, state.apu.sweep_freq), // sweep's internal frequency register
LOAD( int, state.apu.sweep_delay ), // clocks until next sweep action LOAD(int, state.apu.sweep_delay), // clocks until next sweep action
LOAD( int, state.apu.sweep_enabled ), LOAD(int, state.apu.sweep_enabled),
LOAD( int, state.apu.sweep_neg ), // obscure internal flag LOAD(int, state.apu.sweep_neg), // obscure internal flag
LOAD( int, state.apu.noise_divider ), LOAD(int, state.apu.noise_divider),
LOAD( int, state.apu.wave_buf ), // last read byte of wave RAM LOAD(int, state.apu.wave_buf), // last read byte of wave RAM
LOAD( int [4], state.apu.delay ), // clocks until next channel action LOAD(int[4], state.apu.delay), // clocks until next channel action
LOAD( int [4], state.apu.length_ctr ), LOAD(int[4], state.apu.length_ctr),
LOAD( int [4], state.apu.phase ), // square/wave phase, noise LFSR LOAD(int[4], state.apu.phase), // square/wave phase, noise LFSR
LOAD( int [4], state.apu.enabled ), // internal enabled flag LOAD(int[4], state.apu.enabled), // internal enabled flag
LOAD( int [3], state.apu.env_delay ), // clocks until next envelope action LOAD(int[3], state.apu.env_delay), // clocks until next envelope action
LOAD( int [3], state.apu.env_volume ), LOAD(int[3], state.apu.env_volume),
LOAD( int [3], state.apu.env_enabled ), LOAD(int[3], state.apu.env_enabled),
SKIP( int [13], room_for_expansion ), SKIP(int[13], room_for_expansion),
// Emulator // Emulator
SKIP( int [16], room_for_expansion ), SKIP(int[16], room_for_expansion),
{ NULL, 0 } { NULL, 0 }
}; };
void gbSoundSaveGame( gzFile out ) void gbSoundSaveGame(gzFile out)
{ {
gb_apu->save_state( &state.apu ); gb_apu->save_state(&state.apu);
// Be sure areas for expansion get written as zero // Be sure areas for expansion get written as zero
memset( dummy_state, 0, sizeof dummy_state ); memset(dummy_state, 0, sizeof dummy_state);
state.version = 1; state.version = 1;
utilWriteData( out, gb_state ); utilWriteData(out, gb_state);
} }
void gbSoundReadGame( int version, gzFile in ) void gbSoundReadGame(int version, gzFile in)
{ {
// Prepare APU and default state // Prepare APU and default state
reset_apu(); reset_apu();
gb_apu->save_state( &state.apu ); gb_apu->save_state(&state.apu);
if ( version > 11 ) if (version > 11)
utilReadData( in, gb_state ); utilReadData(in, gb_state);
else else
gbSoundReadGameOld( version, in ); gbSoundReadGameOld(version, in);
gb_apu->load_state( state.apu ); gb_apu->load_state(state.apu);
} }

View File

@ -24,7 +24,7 @@ struct gb_effects_config_t {
}; };
// Changes effects configuration // Changes effects configuration
void gbSoundConfigEffects(gb_effects_config_t const &); void gbSoundConfigEffects(gb_effects_config_t const&);
extern gb_effects_config_t gb_effects_config; // current configuration extern gb_effects_config_t gb_effects_config; // current configuration
//// GB sound emulation //// GB sound emulation