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

@ -7,41 +7,41 @@
#define Z_FLAG 0x80
typedef union {
struct {
struct {
#ifdef WORDS_BIGENDIAN
uint8_t B1, B0;
uint8_t B1, B0;
#else
uint8_t B0, B1;
uint8_t B0, B1;
#endif
} B;
uint16_t W;
} B;
uint16_t W;
} gbRegister;
extern gbRegister AF, BC, DE, HL, SP, PC;
extern uint16_t IFF;
int gbDis(char *, u16);
int gbDis(char*, u16);
bool gbLoadRom(const char *);
bool gbLoadRom(const char*);
bool gbUpdateSizes();
void gbEmulate(int);
void gbWriteMemory(register uint16_t, register uint8_t);
void gbDrawLine();
bool gbIsGameboyRom(const char *);
bool gbIsGameboyRom(const char*);
void gbGetHardwareType();
void gbReset();
void gbCleanUp();
void gbCPUInit(const char *, bool);
bool gbWriteBatteryFile(const char *);
bool gbWriteBatteryFile(const char *, bool);
bool gbReadBatteryFile(const char *);
bool gbWriteSaveState(const char *);
bool gbWriteMemSaveState(char *, int, long &);
bool gbReadSaveState(const char *);
bool gbReadMemSaveState(char *, int);
void gbCPUInit(const char*, bool);
bool gbWriteBatteryFile(const char*);
bool gbWriteBatteryFile(const char*, bool);
bool gbReadBatteryFile(const char*);
bool gbWriteSaveState(const char*);
bool gbWriteMemSaveState(char*, int, long&);
bool gbReadSaveState(const char*);
bool gbReadMemSaveState(char*, int);
void gbSgbRenderBorder();
bool gbWritePNGFile(const char *);
bool gbWriteBMPFile(const char *);
bool gbReadGSASnapshot(const char *);
bool gbWritePNGFile(const char*);
bool gbWriteBMPFile(const char*);
bool gbReadGSASnapshot(const char*);
extern int gbHardware;

View File

@ -1,532 +1,505 @@
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "../System.h"
#include "../NLS.h"
#include "../System.h"
#include "../Util.h"
#include "../common/ConfigManager.h"
#include "gb.h"
#include "gbCheats.h"
#include "gbGlobals.h"
#include "gb.h"
#include "../common/ConfigManager.h"
gbCheat gbCheatList[MAX_CHEATS];
int gbCheatNumber = 0;
int gbNextCheat = 0;
bool gbCheatMap[0x10000];
#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_IS_HEX(a) (((a) >= 'A' && (a) <= 'F') || ((a) >= '0' && (a) <= '9'))
#define GBCHEAT_HEX_VALUE(a) ((a) >= 'A' ? (a) - 'A' + 10 : (a) - '0')
void gbCheatUpdateMap()
{
memset(gbCheatMap, 0, 0x10000);
memset(gbCheatMap, 0, 0x10000);
for(int i = 0; i < gbCheatNumber; i++) {
if(gbCheatList[i].enabled)
gbCheatMap[gbCheatList[i].address] = true;
}
for (int i = 0; i < gbCheatNumber; i++) {
if (gbCheatList[i].enabled)
gbCheatMap[gbCheatList[i].address] = true;
}
}
void gbCheatsSaveGame(gzFile gzFile)
{
utilWriteInt(gzFile, gbCheatNumber);
if(gbCheatNumber>0)
utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber);
utilWriteInt(gzFile, gbCheatNumber);
if (gbCheatNumber > 0)
utilGzWrite(gzFile, &gbCheatList[0], sizeof(gbCheat) * gbCheatNumber);
}
void gbCheatsReadGame(gzFile gzFile, int version)
{
if(version <= 8) {
int gbGgOn = utilReadInt(gzFile);
if (version <= 8) {
int gbGgOn = utilReadInt(gzFile);
if(gbGgOn) {
int n = utilReadInt(gzFile);
gbXxCheat tmpCheat;
for(int i = 0; i < n; i++) {
utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat));
gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
}
if (gbGgOn) {
int n = utilReadInt(gzFile);
gbXxCheat tmpCheat;
for (int i = 0; i < n; i++) {
utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat));
gbAddGgCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
}
}
int gbGsOn = utilReadInt(gzFile);
if (gbGsOn) {
int n = utilReadInt(gzFile);
gbXxCheat tmpCheat;
for (int i = 0; i < n; i++) {
utilGzRead(gzFile, &tmpCheat, sizeof(gbXxCheat));
gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
}
}
} else {
gbCheatNumber = utilReadInt(gzFile);
if (gbCheatNumber > 0) {
utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat) * gbCheatNumber);
}
}
int gbGsOn = utilReadInt(gzFile);
if(gbGsOn) {
int n = utilReadInt(gzFile);
gbXxCheat tmpCheat;
for(int i = 0; i < n; i++) {
utilGzRead(gzFile,&tmpCheat, sizeof(gbXxCheat));
gbAddGsCheat(tmpCheat.cheatCode, tmpCheat.cheatDesc);
}
}
} else {
gbCheatNumber = utilReadInt(gzFile);
if(gbCheatNumber>0) {
utilGzRead(gzFile, &gbCheatList[0], sizeof(gbCheat)*gbCheatNumber);
}
}
gbCheatUpdateMap();
gbCheatUpdateMap();
}
void gbCheatsReadGameSkip(gzFile gzFile, int version)
{
if( version <= 8 ) {
int gbGgOn = utilReadInt( gzFile );
if( gbGgOn ) {
int n = utilReadInt( gzFile );
if( n > 0 ) {
utilGzSeek( gzFile, n * sizeof(gbXxCheat), SEEK_CUR );
}
}
if (version <= 8) {
int gbGgOn = utilReadInt(gzFile);
if (gbGgOn) {
int n = utilReadInt(gzFile);
if (n > 0) {
utilGzSeek(gzFile, n * sizeof(gbXxCheat), SEEK_CUR);
}
}
int gbGsOn = utilReadInt( gzFile );
if( gbGsOn ) {
int n = utilReadInt(gzFile);
if( n > 0 ) {
utilGzSeek( gzFile, n * sizeof(gbXxCheat), SEEK_CUR );
}
}
} else {
int n = utilReadInt( gzFile );
int gbGsOn = utilReadInt(gzFile);
if (gbGsOn) {
int n = utilReadInt(gzFile);
if (n > 0) {
utilGzSeek(gzFile, n * sizeof(gbXxCheat), SEEK_CUR);
}
}
} else {
int n = utilReadInt(gzFile);
if( n > 0 ) {
utilGzSeek( gzFile, n * sizeof(gbCheat), SEEK_CUR );
if (n > 0) {
utilGzSeek(gzFile, n * sizeof(gbCheat), SEEK_CUR);
}
}
}
}
void gbCheatsSaveCheatList(const char *file)
void gbCheatsSaveCheatList(const char* file)
{
if(gbCheatNumber == 0)
return;
FILE *f = fopen(file, "wb");
if(f == NULL)
return;
int version = 1;
fwrite(&version, 1, sizeof(version), f);
int type = 1;
fwrite(&type, 1, sizeof(type), f);
fwrite(&gbCheatNumber, 1, sizeof(gbCheatNumber), f);
fwrite(gbCheatList, 1, sizeof(gbCheat) * gbCheatNumber, f);
fclose(f);
if (gbCheatNumber == 0)
return;
FILE* f = fopen(file, "wb");
if (f == NULL)
return;
int version = 1;
fwrite(&version, 1, sizeof(version), f);
int type = 1;
fwrite(&type, 1, sizeof(type), f);
fwrite(&gbCheatNumber, 1, sizeof(gbCheatNumber), f);
fwrite(gbCheatList, 1, sizeof(gbCheat) * gbCheatNumber, f);
fclose(f);
}
bool gbCheatsLoadCheatList(const char *file)
bool gbCheatsLoadCheatList(const char* file)
{
gbCheatNumber = 0;
gbCheatNumber = 0;
gbCheatUpdateMap();
gbCheatUpdateMap();
int count = 0;
int count = 0;
FILE *f = fopen(file, "rb");
FILE* f = fopen(file, "rb");
if(f == NULL)
return false;
if (f == NULL)
return false;
int version = 0;
int version = 0;
if(fread(&version, 1, sizeof(version), f) != sizeof(version)) {
fclose(f);
return false;
}
if (fread(&version, 1, sizeof(version), f) != sizeof(version)) {
fclose(f);
return false;
}
if(version != 1) {
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
N_("Unsupported cheat list version %d"), version);
fclose(f);
return false;
}
if (version != 1) {
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_VERSION,
N_("Unsupported cheat list version %d"), version);
fclose(f);
return false;
}
int type = 0;
if(fread(&type, 1, sizeof(type), f) != sizeof(type)) {
fclose(f);
return false;
}
int type = 0;
if (fread(&type, 1, sizeof(type), f) != sizeof(type)) {
fclose(f);
return false;
}
if(type != 1) {
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
N_("Unsupported cheat list type %d"), type);
fclose(f);
return false;
}
if (type != 1) {
systemMessage(MSG_UNSUPPORTED_CHEAT_LIST_TYPE,
N_("Unsupported cheat list type %d"), type);
fclose(f);
return false;
}
if(fread(&count, 1, sizeof(count), f) != sizeof(count)) {
fclose(f);
return false;
}
if (fread(&count, 1, sizeof(count), f) != sizeof(count)) {
fclose(f);
return false;
}
if(fread(gbCheatList, 1, sizeof(gbCheatList), f) > sizeof(gbCheatList)) {
fclose(f);
return false;
}
if (fread(gbCheatList, 1, sizeof(gbCheatList), f) > sizeof(gbCheatList)) {
fclose(f);
return false;
}
gbCheatNumber = count;
gbCheatUpdateMap();
gbCheatNumber = count;
gbCheatUpdateMap();
return true;
}
bool gbVerifyGsCode(const char *code)
{
size_t len = strlen(code);
if(len == 0)
return true;
}
if(len != 8)
return false;
bool gbVerifyGsCode(const char* code)
{
size_t len = strlen(code);
for(int i = 0; i < 8; i++)
if(!GBCHEAT_IS_HEX(code[i]))
return false;
if (len == 0)
return true;
/* int address = GBCHEAT_HEX_VALUE(code[6]) << 12 |
if (len != 8)
return false;
for (int i = 0; i < 8; i++)
if (!GBCHEAT_IS_HEX(code[i]))
return false;
/* int address = GBCHEAT_HEX_VALUE(code[6]) << 12 |
GBCHEAT_HEX_VALUE(code[7]) << 8 |
GBCHEAT_HEX_VALUE(code[4]) << 4 |
GBCHEAT_HEX_VALUE(code[5]);*/
return true;
}
bool gbAddGsCheat(const char *code, const char *desc)
{
if(gbCheatNumber > (MAX_CHEATS - 1)) {
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached."));
return false;
}
if(!gbVerifyGsCode(code)) {
systemMessage(MSG_INVALID_GAMESHARK_CODE,
N_("Invalid GameShark code: %s"), code);
return false;
}
int i = gbCheatNumber;
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 |
GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 |
GBCHEAT_HEX_VALUE(code[3]);
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]);
gbCheatList[i].compare = 0;
gbCheatList[i].enabled = true;
int gsCode = gbCheatList[i].code;
if ((gsCode !=1) && ((gsCode & 0xF0) !=0x80) && ((gsCode & 0xF0) !=0x90) &&
((gsCode & 0xF0) !=0xA0) && ((gsCode) !=0xF0) && ((gsCode) !=0xF1))
systemMessage(MSG_WRONG_GAMESHARK_CODE,
N_("Wrong GameShark code type : %s"), code);
else if (((gsCode & 0xF0) ==0xA0) || ((gsCode) ==0xF0) || ((gsCode) ==0xF1))
systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE,
N_("Unsupported GameShark code type : %s"), code);
gbCheatNumber++;
return true;
}
bool gbVerifyGgCode(const char *code)
{
size_t len = strlen(code);
if(len != 11 &&
len != 7 &&
len != 6 &&
len != 0)
return false;
if(len == 0)
return true;
}
if(!GBCHEAT_IS_HEX(code[0]))
return false;
if(!GBCHEAT_IS_HEX(code[1]))
return false;
if(!GBCHEAT_IS_HEX(code[2]))
return false;
if(code[3] != '-')
return false;
if(!GBCHEAT_IS_HEX(code[4]))
return false;
if(!GBCHEAT_IS_HEX(code[5]))
return false;
if(!GBCHEAT_IS_HEX(code[6]))
return false;
if(code[7] != 0) {
if(code[7] != '-')
return false;
if(code[8] != 0) {
if(!GBCHEAT_IS_HEX(code[8]))
return false;
if(!GBCHEAT_IS_HEX(code[9]))
return false;
if(!GBCHEAT_IS_HEX(code[10]))
bool gbAddGsCheat(const char* code, const char* desc)
{
if (gbCheatNumber > (MAX_CHEATS - 1)) {
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached."));
return false;
}
}
// int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
// GBCHEAT_HEX_VALUE(code[1]);
if (!gbVerifyGsCode(code)) {
systemMessage(MSG_INVALID_GAMESHARK_CODE,
N_("Invalid GameShark code: %s"), code);
return false;
}
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);
int i = gbCheatNumber;
if(address >= 0x8000 && address <= 0x9fff)
return false;
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
if(address >= 0xc000)
return false;
gbCheatList[i].code = GBCHEAT_HEX_VALUE(code[0]) << 4 | GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].value = GBCHEAT_HEX_VALUE(code[2]) << 4 | GBCHEAT_HEX_VALUE(code[3]);
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]);
gbCheatList[i].compare = 0;
gbCheatList[i].enabled = true;
int gsCode = gbCheatList[i].code;
if ((gsCode != 1) && ((gsCode & 0xF0) != 0x80) && ((gsCode & 0xF0) != 0x90) && ((gsCode & 0xF0) != 0xA0) && ((gsCode) != 0xF0) && ((gsCode) != 0xF1))
systemMessage(MSG_WRONG_GAMESHARK_CODE,
N_("Wrong GameShark code type : %s"), code);
else if (((gsCode & 0xF0) == 0xA0) || ((gsCode) == 0xF0) || ((gsCode) == 0xF1))
systemMessage(MSG_UNSUPPORTED_GAMESHARK_CODE,
N_("Unsupported GameShark code type : %s"), code);
gbCheatNumber++;
if(code[7] == 0 || code[8] == '0')
return true;
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) +
(GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff;
compare = (compare >> 2) | ( (compare << 6) & 0xc0);
compare ^= 0x45;
int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9]));
if(cloak >=1 && cloak <= 7)
return false;
return true;
}
bool gbAddGgCheat(const char *code, const char *desc)
bool gbVerifyGgCode(const char* code)
{
if(gbCheatNumber > (MAX_CHEATS - 1)) {
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached."));
return false;
}
size_t len = strlen(code);
if(!gbVerifyGgCode(code)) {
systemMessage(MSG_INVALID_GAMEGENIE_CODE,
N_("Invalid GameGenie code: %s"), code);
return false;
}
if (len != 11 && len != 7 && len != 6 && len != 0)
return false;
int i = gbCheatNumber;
if (len == 0)
return true;
size_t len = strlen(code);
if (!GBCHEAT_IS_HEX(code[0]))
return false;
if (!GBCHEAT_IS_HEX(code[1]))
return false;
if (!GBCHEAT_IS_HEX(code[2]))
return false;
if (code[3] != '-')
return false;
if (!GBCHEAT_IS_HEX(code[4]))
return false;
if (!GBCHEAT_IS_HEX(code[5]))
return false;
if (!GBCHEAT_IS_HEX(code[6]))
return false;
if (code[7] != 0) {
if (code[7] != '-')
return false;
if (code[8] != 0) {
if (!GBCHEAT_IS_HEX(code[8]))
return false;
if (!GBCHEAT_IS_HEX(code[9]))
return false;
if (!GBCHEAT_IS_HEX(code[10]))
return false;
}
}
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
// int replace = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
// GBCHEAT_HEX_VALUE(code[1]);
gbCheatList[i].code = 0x101;
gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) +
GBCHEAT_HEX_VALUE(code[1]);
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);
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);
if (address >= 0x8000 && address <= 0x9fff)
return false;
gbCheatList[i].compare = 0;
if (address >= 0xc000)
return false;
if(len != 7 && len != 8) {
if (code[7] == 0 || code[8] == '0')
return true;
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) +
(GBCHEAT_HEX_VALUE(code[10]));
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + (GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff;
compare = (compare >> 2) | ( (compare << 6) & 0xc0);
compare = (compare >> 2) | ((compare << 6) & 0xc0);
compare ^= 0x45;
gbCheatList[i].compare = compare;
//gbCheatList[i].code = 0;
gbCheatList[i].code = 0x100; // fix for compare value
int cloak = (GBCHEAT_HEX_VALUE(code[8])) ^ (GBCHEAT_HEX_VALUE(code[9]));
}
if (cloak >= 1 && cloak <= 7)
return false;
return true;
}
gbCheatList[i].enabled = true;
bool gbAddGgCheat(const char* code, const char* desc)
{
if (gbCheatNumber > (MAX_CHEATS - 1)) {
systemMessage(MSG_MAXIMUM_NUMBER_OF_CHEATS,
N_("Maximum number of cheats reached."));
return false;
}
gbCheatMap[gbCheatList[i].address] = true;
if (!gbVerifyGgCode(code)) {
systemMessage(MSG_INVALID_GAMEGENIE_CODE,
N_("Invalid GameGenie code: %s"), code);
return false;
}
gbCheatNumber++;
int i = gbCheatNumber;
return true;
size_t len = strlen(code);
strcpy(gbCheatList[i].cheatCode, code);
strcpy(gbCheatList[i].cheatDesc, desc);
gbCheatList[i].code = 0x101;
gbCheatList[i].value = (GBCHEAT_HEX_VALUE(code[0]) << 4) + GBCHEAT_HEX_VALUE(code[1]);
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);
gbCheatList[i].compare = 0;
if (len != 7 && len != 8) {
int compare = (GBCHEAT_HEX_VALUE(code[8]) << 4) + (GBCHEAT_HEX_VALUE(code[10]));
compare = compare ^ 0xff;
compare = (compare >> 2) | ((compare << 6) & 0xc0);
compare ^= 0x45;
gbCheatList[i].compare = compare;
//gbCheatList[i].code = 0;
gbCheatList[i].code = 0x100; // fix for compare value
}
gbCheatList[i].enabled = true;
gbCheatMap[gbCheatList[i].address] = true;
gbCheatNumber++;
return true;
}
void gbCheatRemove(int i)
{
if(i < 0 || i >= gbCheatNumber) {
systemMessage(MSG_INVALID_CHEAT_TO_REMOVE,
N_("Invalid cheat to remove %d"), i);
return;
}
if (i < 0 || i >= gbCheatNumber) {
systemMessage(MSG_INVALID_CHEAT_TO_REMOVE,
N_("Invalid cheat to remove %d"), i);
return;
}
if((i+1) < gbCheatNumber) {
memcpy(&gbCheatList[i], &gbCheatList[i+1], sizeof(gbCheat)*
(gbCheatNumber-i-1));
}
if ((i + 1) < gbCheatNumber) {
memcpy(&gbCheatList[i], &gbCheatList[i + 1], sizeof(gbCheat) * (gbCheatNumber - i - 1));
}
gbCheatNumber--;
gbCheatNumber--;
gbCheatUpdateMap();
gbCheatUpdateMap();
}
void gbCheatRemoveAll()
{
gbCheatNumber = 0;
gbCheatUpdateMap();
gbCheatNumber = 0;
gbCheatUpdateMap();
}
void gbCheatEnable(int i)
{
if(i >=0 && i < gbCheatNumber) {
if(!gbCheatList[i].enabled) {
gbCheatList[i].enabled = true;
gbCheatUpdateMap();
if (i >= 0 && i < gbCheatNumber) {
if (!gbCheatList[i].enabled) {
gbCheatList[i].enabled = true;
gbCheatUpdateMap();
}
}
}
}
void gbCheatDisable(int i)
{
if(i >=0 && i < gbCheatNumber) {
if(gbCheatList[i].enabled) {
gbCheatList[i].enabled = false;
gbCheatUpdateMap();
if (i >= 0 && i < gbCheatNumber) {
if (gbCheatList[i].enabled) {
gbCheatList[i].enabled = false;
gbCheatUpdateMap();
}
}
}
}
bool gbCheatReadGSCodeFile(const char *fileName)
bool gbCheatReadGSCodeFile(const char* fileName)
{
FILE *file = fopen(fileName, "rb");
FILE* file = fopen(fileName, "rb");
if(!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
return false;
}
if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
return false;
}
fseek(file, 0x18, SEEK_SET);
int count = 0;
fread(&count, 1, 2, file);
int dummy = 0;
gbCheatRemoveAll();
char desc[13];
char code[9];
int i;
for(i = 0; i < count; i++) {
fread(&dummy, 1, 2, file);
fread(desc, 1, 12, file);
desc[12] = 0;
fread(code, 1, 8, file);
code[8] = 0;
gbAddGsCheat(code, desc);
}
fseek(file, 0x18, SEEK_SET);
int count = 0;
fread(&count, 1, 2, file);
int dummy = 0;
gbCheatRemoveAll();
char desc[13];
char code[9];
int i;
for (i = 0; i < count; i++) {
fread(&dummy, 1, 2, file);
fread(desc, 1, 12, file);
desc[12] = 0;
fread(code, 1, 8, file);
code[8] = 0;
gbAddGsCheat(code, desc);
}
for(i = 0; i < gbCheatNumber; i++)
gbCheatDisable(i);
for (i = 0; i < gbCheatNumber; i++)
gbCheatDisable(i);
fclose(file);
return true;
fclose(file);
return true;
}
// Used to emulated GG codes
u8 gbCheatRead(u16 address)
uint8_t gbCheatRead(uint16_t address)
{
if(!cheatsEnabled)
return gbMemoryMap[address>>12][address & 0xFFF];
if (!cheatsEnabled)
return gbMemoryMap[address >> 12][address & 0xFFF];
for(int i = 0; i < gbCheatNumber; i++) {
if(gbCheatList[i].enabled && gbCheatList[i].address == address) {
switch(gbCheatList[i].code) {
case 0x100: // GameGenie support
if(gbMemoryMap[address>>12][address&0xFFF] == gbCheatList[i].compare)
return gbCheatList[i].value;
break;
case 0x101: // GameGenie 6 digits code support
return gbCheatList[i].value;
break;
}
for (int i = 0; i < gbCheatNumber; i++) {
if (gbCheatList[i].enabled && gbCheatList[i].address == address) {
switch (gbCheatList[i].code) {
case 0x100: // GameGenie support
if (gbMemoryMap[address >> 12][address & 0xFFF] == gbCheatList[i].compare)
return gbCheatList[i].value;
break;
case 0x101: // GameGenie 6 digits code support
return gbCheatList[i].value;
break;
}
}
}
}
return gbMemoryMap[address>>12][address&0xFFF];
return gbMemoryMap[address >> 12][address & 0xFFF];
}
// Used to emulate GS codes.
void gbCheatWrite(bool reboot)
{
if(cheatsEnabled)
{
u16 address = 0;
if (cheatsEnabled) {
u16 address = 0;
if (gbNextCheat >= gbCheatNumber)
gbNextCheat = 0;
if (gbNextCheat >= gbCheatNumber)
gbNextCheat = 0;
for(int i = gbNextCheat; i < gbCheatNumber; i++) {
if(gbCheatList[i].enabled) {
address = gbCheatList[i].address;
if ((!reboot) && (address >= 0x8000) && !((address>=0xA000) && (address<0xC000)))
{ // These codes are executed one per one, at each Vblank
switch(gbCheatList[i].code) {
case 0x01:
gbWriteMemory(address, gbCheatList[i].value);
gbNextCheat = i+1;
return;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9A:
case 0x9B:
case 0x9C:
case 0x9D:
case 0x9E:
case 0x9F:
int oldbank = gbMemory[0xff70];
gbWriteMemory(0xff70, gbCheatList[i].code & 0xf);
gbWriteMemory(address, gbCheatList[i].value);
gbWriteMemory(0xff70, oldbank);
gbNextCheat = i+1;
return;
}
for (int i = gbNextCheat; i < gbCheatNumber; i++) {
if (gbCheatList[i].enabled) {
address = gbCheatList[i].address;
if ((!reboot) && (address >= 0x8000) && !((address >= 0xA000) && (address < 0xC000))) { // These codes are executed one per one, at each Vblank
switch (gbCheatList[i].code) {
case 0x01:
gbWriteMemory(address, gbCheatList[i].value);
gbNextCheat = i + 1;
return;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9A:
case 0x9B:
case 0x9C:
case 0x9D:
case 0x9E:
case 0x9F:
int oldbank = gbMemory[0xff70];
gbWriteMemory(0xff70, gbCheatList[i].code & 0xf);
gbWriteMemory(address, gbCheatList[i].value);
gbWriteMemory(0xff70, oldbank);
gbNextCheat = i + 1;
return;
}
} else // These codes are only executed when the game is booted
{
switch (gbCheatList[i].code & 0xF0) {
case 0x80:
gbWriteMemory(0x0000, 0x0A);
gbWriteMemory(0x4000, gbCheatList[i].value & 0xF);
gbWriteMemory(address, gbCheatList[i].value);
gbNextCheat = i + 1;
return;
}
}
}
}
else // These codes are only executed when the game is booted
{
switch(gbCheatList[i].code & 0xF0) {
case 0x80:
gbWriteMemory(0x0000, 0x0A);
gbWriteMemory(0x4000, gbCheatList[i].value & 0xF);
gbWriteMemory(address, gbCheatList[i].value);
gbNextCheat = i+1;
return;
}
}
}
}
}
}

View File

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

View File

@ -22,8 +22,7 @@ break;
case 0x05:
// DEC B
BC.B.B1--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B1] | ((BC.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B1] | ((BC.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x06:
// LD B, NN
@ -45,8 +44,7 @@ break;
case 0x09:
// ADD HL,BC
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) |
(((long)HL.W + (long)BC.W) & 0x10000 ? C_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);
HL.W = tempRegister.W;
break;
case 0x0a:
@ -65,8 +63,7 @@ break;
case 0x0d:
// DEC C
BC.B.B0--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B0] | ((BC.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[BC.B.B0] | ((BC.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x0e:
// LD C, NN
@ -82,15 +79,15 @@ case 0x10:
// STOP
opcode = gbReadOpcode(PC.W++);
if (gbCgbMode) {
if (gbMemory[0xff4d] & 1) {
gbSpeedSwitch();
// clockTicks += 228*144-(gbSpeed ? 62 : 63);
if (gbMemory[0xff4d] & 1) {
gbSpeedSwitch();
// clockTicks += 228*144-(gbSpeed ? 62 : 63);
if (gbSpeed == 0)
gbMemory[0xff4d] = 0x00;
else
gbMemory[0xff4d] = 0x80;
}
if (gbSpeed == 0)
gbMemory[0xff4d] = 0x00;
else
gbMemory[0xff4d] = 0x80;
}
}
break;
case 0x11:
@ -114,8 +111,7 @@ break;
case 0x15:
// DEC D
DE.B.B1--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B1] | ((DE.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B1] | ((DE.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x16:
// LD D,NN
@ -134,8 +130,7 @@ break;
case 0x19:
// ADD HL,DE
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) |
(((long)HL.W + (long)DE.W) & 0x10000 ? C_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);
HL.W = tempRegister.W;
break;
case 0x1a:
@ -154,8 +149,7 @@ break;
case 0x1d:
// DEC E
DE.B.B0--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B0] | ((DE.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[DE.B.B0] | ((DE.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x1e:
// LD E,NN
@ -170,10 +164,10 @@ break;
case 0x20:
// JR NZ,NN
if (AF.B.B0 & Z_FLAG)
PC.W++;
PC.W++;
else {
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
}
break;
case 0x21:
@ -197,8 +191,7 @@ break;
case 0x25:
// DEC H
HL.B.B1--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B1] | ((HL.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B1] | ((HL.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x26:
// LD H,NN
@ -213,16 +206,15 @@ break;
case 0x28:
// JR Z,NN
if (AF.B.B0 & Z_FLAG) {
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
} else
PC.W++;
PC.W++;
break;
case 0x29:
// ADD HL,HL
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) |
(((long)HL.W + (long)HL.W) & 0x10000 ? C_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);
HL.W = tempRegister.W;
break;
case 0x2a:
@ -241,8 +233,7 @@ break;
case 0x2d:
// DEC L
HL.B.B0--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B0] | ((HL.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[HL.B.B0] | ((HL.B.B0 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x2e:
// LD L,NN
@ -256,10 +247,10 @@ break;
case 0x30:
// JR NC,NN
if (AF.B.B0 & C_FLAG)
PC.W++;
PC.W++;
else {
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
}
break;
case 0x31:
@ -284,8 +275,7 @@ break;
case 0x35:
// DEC (HL)
tempValue = gbReadMemory(HL.W) - 1;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[tempValue] | ((tempValue & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[tempValue] | ((tempValue & 0x0F) == 0x0F ? H_FLAG : 0);
gbWriteMemory(HL.W, tempValue);
break;
case 0x36:
@ -299,16 +289,15 @@ break;
case 0x38:
// JR C,NN
if (AF.B.B0 & C_FLAG) {
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
PC.W += (s8)gbReadOpcode(PC.W) + 1;
clockTicks++;
} else
PC.W++;
PC.W++;
break;
case 0x39:
// ADD HL,SP
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) |
(((long)HL.W + (long)SP.W) & 0x10000 ? C_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);
HL.W = tempRegister.W;
break;
case 0x3a:
@ -327,8 +316,7 @@ break;
case 0x3d:
// DEC A
AF.B.B1--;
AF.B.B0 =
N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[AF.B.B1] | ((AF.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
AF.B.B0 = N_FLAG | (AF.B.B0 & C_FLAG) | ZeroTable[AF.B.B1] | ((AF.B.B1 & 0x0F) == 0x0F ? H_FLAG : 0);
break;
case 0x3e:
// LD A,NN
@ -560,16 +548,16 @@ case 0x76:
// If an EI is pending, the interrupts are triggered before Halt state !!
// Fix Torpedo Range's intro.
if (IFF & 0x40) {
IFF &= ~0x70;
IFF |= 1;
PC.W--;
IFF &= ~0x70;
IFF |= 1;
PC.W--;
} else {
// if (IE & IF) and interrupts are disabeld,
// Halt is cancelled.
if ((register_IE & register_IF & 0x1f) && !(IFF & 1)) {
IFF |= 2;
} else
IFF |= 0x80;
// if (IE & IF) and interrupts are disabeld,
// Halt is cancelled.
if ((register_IE & register_IF & 0x1f) && !(IFF & 1)) {
IFF |= 2;
} else
IFF |= 0x80;
}
break;
case 0x77:
@ -611,165 +599,142 @@ break;
case 0x80:
// ADD B
tempRegister.W = AF.B.B1 + BC.B.B1;
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.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 = tempRegister.B.B0;
break;
case 0x81:
// ADD C
tempRegister.W = AF.B.B1 + BC.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.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 = tempRegister.B.B0;
break;
case 0x82:
// ADD D
tempRegister.W = AF.B.B1 + DE.B.B1;
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.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 = tempRegister.B.B0;
break;
case 0x83:
// ADD E
tempRegister.W = AF.B.B1 + DE.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.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 = tempRegister.B.B0;
break;
case 0x84:
// ADD H
tempRegister.W = AF.B.B1 + HL.B.B1;
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.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 = tempRegister.B.B0;
break;
case 0x85:
// ADD L
tempRegister.W = AF.B.B1 + HL.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.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 = tempRegister.B.B0;
break;
case 0x86:
// ADD (HL)
tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 + tempValue;
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.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 = tempRegister.B.B0;
break;
case 0x87:
// ADD A
tempRegister.W = AF.B.B1 + AF.B.B1;
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.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 = tempRegister.B.B0;
break;
case 0x88:
// ADC B:
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.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x89:
// ADC C
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.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x8a:
// ADC D
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.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x8b:
// ADC E
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.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x8c:
// ADC H
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.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x8d:
// ADC L
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.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x8e:
// ADC (HL)
tempValue = gbReadMemory(HL.W);
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.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x8f:
// ADC A
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.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x90:
// SUB B
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.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x91:
// SUB C
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.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x92:
// SUB D
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.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x93:
// SUB E
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.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x94:
// SUB H
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.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x95:
// SUB L
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.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x96:
// SUB (HL)
tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 - tempValue;
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.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 = tempRegister.B.B0;
break;
case 0x97:
@ -780,58 +745,50 @@ break;
case 0x98:
// SBC B
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.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x99:
// SBC C
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.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x9a:
// SBC D
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.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x9b:
// SBC E
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.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x9c:
// SBC H
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.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x9d:
// SBC L
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.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x9e:
// SBC (HL)
tempValue = gbReadMemory(HL.W);
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.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0x9f:
// SBC A
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.B1 ^ AF.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0xa0:
@ -960,45 +917,38 @@ break;
case 0xb8:
// CP B:
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.B1 ^ BC.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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);
break;
case 0xb9:
// CP C
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.B1 ^ BC.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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);
break;
case 0xba:
// CP D
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.B1 ^ DE.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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);
break;
case 0xbb:
// CP E
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.B1 ^ DE.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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);
break;
case 0xbc:
// CP H
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.B1 ^ HL.B.B1 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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);
break;
case 0xbd:
// CP L
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.B1 ^ HL.B.B0 ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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);
break;
case 0xbe:
// CP (HL)
tempValue = gbReadMemory(HL.W);
tempRegister.W = AF.B.B1 - tempValue;
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.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break;
case 0xbf:
// CP A
@ -1007,9 +957,9 @@ break;
case 0xc0:
// RET NZ
if (!(AF.B.B0 & Z_FLAG)) {
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
}
break;
case 0xc1:
@ -1020,12 +970,12 @@ break;
case 0xc2:
// JP NZ,NNNN
if (AF.B.B0 & Z_FLAG)
PC.W += 2;
PC.W += 2;
else {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
}
break;
case 0xc3:
@ -1037,14 +987,14 @@ break;
case 0xc4:
// CALL NZ,NNNN
if (AF.B.B0 & Z_FLAG)
PC.W += 2;
PC.W += 2;
else {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
}
break;
case 0xc5:
@ -1056,8 +1006,7 @@ case 0xc6:
// ADD NN
tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 + tempValue;
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.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 = tempRegister.B.B0;
break;
case 0xc7:
@ -1069,9 +1018,9 @@ break;
case 0xc8:
// RET Z
if (AF.B.B0 & Z_FLAG) {
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
}
break;
case 0xc9:
@ -1082,25 +1031,25 @@ break;
case 0xca:
// JP Z,NNNN
if (AF.B.B0 & Z_FLAG) {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
} else
PC.W += 2;
PC.W += 2;
break;
// CB done outside
case 0xcc:
// CALL Z,NNNN
if (AF.B.B0 & Z_FLAG) {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
} else
PC.W += 2;
PC.W += 2;
break;
case 0xcd:
// CALL NNNN
@ -1114,8 +1063,7 @@ case 0xce:
// ADC NN
tempValue = gbReadOpcode(PC.W++);
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.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0xcf:
@ -1127,9 +1075,9 @@ break;
case 0xd0:
// RET NC
if (!(AF.B.B0 & C_FLAG)) {
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
}
break;
case 0xd1:
@ -1140,12 +1088,12 @@ break;
case 0xd2:
// JP NC,NNNN
if (AF.B.B0 & C_FLAG)
PC.W += 2;
PC.W += 2;
else {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
}
break;
// D3 illegal
@ -1156,14 +1104,14 @@ break;
case 0xd4:
// CALL NC,NNNN
if (AF.B.B0 & C_FLAG)
PC.W += 2;
PC.W += 2;
else {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
}
break;
case 0xd5:
@ -1175,8 +1123,7 @@ case 0xd6:
// SUB NN
tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 - tempValue;
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.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 = tempRegister.B.B0;
break;
case 0xd7:
@ -1188,9 +1135,9 @@ break;
case 0xd8:
// RET C
if (AF.B.B0 & C_FLAG) {
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
PC.B.B0 = gbReadMemory(SP.W++);
PC.B.B1 = gbReadMemory(SP.W++);
clockTicks += 3;
}
break;
case 0xd9:
@ -1202,12 +1149,12 @@ break;
case 0xda:
// JP C,NNNN
if (AF.B.B0 & C_FLAG) {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W);
PC.W = tempRegister.W;
clockTicks++;
} else
PC.W += 2;
PC.W += 2;
break;
// DB illegal
case 0xdb:
@ -1217,14 +1164,14 @@ break;
case 0xdc:
// CALL C,NNNN
if (AF.B.B0 & C_FLAG) {
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
tempRegister.B.B0 = gbReadOpcode(PC.W++);
tempRegister.B.B1 = gbReadOpcode(PC.W++);
gbWriteMemory(--SP.W, PC.B.B1);
gbWriteMemory(--SP.W, PC.B.B0);
PC.W = tempRegister.W;
clockTicks += 3;
} else
PC.W += 2;
PC.W += 2;
break;
// DD illegal
case 0xdd:
@ -1235,8 +1182,7 @@ case 0xde:
// SBC NN
tempValue = gbReadOpcode(PC.W++);
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.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
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 = tempRegister.B.B0;
break;
case 0xdf:
@ -1286,8 +1232,7 @@ case 0xe8:
// ADD SP,NN
offset = (s8)gbReadOpcode(PC.W++);
tempRegister.W = SP.W + offset;
AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) |
((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_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 = tempRegister.W;
break;
case 0xe9:
@ -1365,8 +1310,7 @@ case 0xf8:
// LD HL,SP+NN
offset = (s8)gbReadOpcode(PC.W++);
tempRegister.W = SP.W + offset;
AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) |
((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_FLAG : 0);
AF.B.B0 = ((SP.W ^ offset ^ tempRegister.W) & 0x100 ? C_FLAG : 0) | ((SP.W ^ offset ^ tempRegister.W) & 0x10 ? H_FLAG : 0);
HL.W = tempRegister.W;
break;
case 0xf9:
@ -1382,12 +1326,12 @@ break;
case 0xfb:
// EI
if (!(IFF & 0x30))
// If an EI is executed right before HALT,
// the interrupts are triggered before the Halt state !!
// Fix Torpedo Range Intro.
// IFF |= 0x10 : 1 ticks before the EI enables the interrupts
// IFF |= 0x40 : marks that an EI is being executed.
IFF |= 0x50;
// If an EI is executed right before HALT,
// the interrupts are triggered before the Halt state !!
// Fix Torpedo Range Intro.
// IFF |= 0x10 : 1 ticks before the EI enables the interrupts
// IFF |= 0x40 : marks that an EI is being executed.
IFF |= 0x50;
break;
// FC illegal (FC = breakpoint)
case 0xfc:
@ -1402,8 +1346,7 @@ case 0xfe:
// CP NN
tempValue = gbReadOpcode(PC.W++);
tempRegister.W = AF.B.B1 - tempValue;
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.B0 = N_FLAG | (tempRegister.B.B1 ? C_FLAG : 0) | ZeroTable[tempRegister.B.B0] | ((AF.B.B1 ^ tempValue ^ tempRegister.B.B0) & 0x10 ? H_FLAG : 0);
break;
case 0xff:
// RST 38
@ -1413,7 +1356,7 @@ PC.W = 0x0038;
break;
default:
if (gbSystemMessage == false) {
systemMessage(0, N_("Unknown opcode %02x at %04x"), gbReadOpcode(PC.W - 1), PC.W - 1);
gbSystemMessage = true;
systemMessage(0, N_("Unknown opcode %02x at %04x"), gbReadOpcode(PC.W - 1), PC.W - 1);
gbSystemMessage = true;
}
return;

View File

@ -101,165 +101,165 @@ break;
case 0x10:
// RL B
if (BC.B.B1 & 0x80) {
BC.B.B1 = (BC.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B1] | C_FLAG;
BC.B.B1 = (BC.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B1] | C_FLAG;
} else {
BC.B.B1 = (BC.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B1];
BC.B.B1 = (BC.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B1];
}
break;
case 0x11:
// RL C
if (BC.B.B0 & 0x80) {
BC.B.B0 = (BC.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B0] | C_FLAG;
BC.B.B0 = (BC.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B0] | C_FLAG;
} else {
BC.B.B0 = (BC.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B0];
BC.B.B0 = (BC.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[BC.B.B0];
}
break;
case 0x12:
// RL D
if (DE.B.B1 & 0x80) {
DE.B.B1 = (DE.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B1] | C_FLAG;
DE.B.B1 = (DE.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B1] | C_FLAG;
} else {
DE.B.B1 = (DE.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B1];
DE.B.B1 = (DE.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B1];
}
break;
case 0x13:
// RL E
if (DE.B.B0 & 0x80) {
DE.B.B0 = (DE.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B0] | C_FLAG;
DE.B.B0 = (DE.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B0] | C_FLAG;
} else {
DE.B.B0 = (DE.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B0];
DE.B.B0 = (DE.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[DE.B.B0];
}
break;
case 0x14:
// RL H
if (HL.B.B1 & 0x80) {
HL.B.B1 = (HL.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B1] | C_FLAG;
HL.B.B1 = (HL.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B1] | C_FLAG;
} else {
HL.B.B1 = (HL.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B1];
HL.B.B1 = (HL.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B1];
}
break;
case 0x15:
// RL L
if (HL.B.B0 & 0x80) {
HL.B.B0 = (HL.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B0] | C_FLAG;
HL.B.B0 = (HL.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B0] | C_FLAG;
} else {
HL.B.B0 = (HL.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B0];
HL.B.B0 = (HL.B.B0 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[HL.B.B0];
}
break;
case 0x16:
// RL (HL)
tempValue = gbReadMemory(HL.W);
if (tempValue & 0x80) {
tempValue = (tempValue << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[tempValue] | C_FLAG;
tempValue = (tempValue << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[tempValue] | C_FLAG;
} else {
tempValue = (tempValue << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[tempValue];
tempValue = (tempValue << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[tempValue];
}
gbWriteMemory(HL.W, tempValue);
break;
case 0x17:
// RL A
if (AF.B.B1 & 0x80) {
AF.B.B1 = (AF.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[AF.B.B1] | C_FLAG;
AF.B.B1 = (AF.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[AF.B.B1] | C_FLAG;
} else {
AF.B.B1 = (AF.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[AF.B.B1];
AF.B.B1 = (AF.B.B1 << 1) | (AF.B.B0 & C_FLAG ? 1 : 0);
AF.B.B0 = ZeroTable[AF.B.B1];
}
break;
case 0x18:
// RR B
if (BC.B.B1 & 0x01) {
BC.B.B1 = (BC.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B1] | C_FLAG;
BC.B.B1 = (BC.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B1] | C_FLAG;
} else {
BC.B.B1 = (BC.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B1];
BC.B.B1 = (BC.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B1];
}
break;
case 0x19:
// RR C
if (BC.B.B0 & 0x01) {
BC.B.B0 = (BC.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B0] | C_FLAG;
BC.B.B0 = (BC.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B0] | C_FLAG;
} else {
BC.B.B0 = (BC.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B0];
BC.B.B0 = (BC.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[BC.B.B0];
}
break;
case 0x1a:
// RR D
if (DE.B.B1 & 0x01) {
DE.B.B1 = (DE.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B1] | C_FLAG;
DE.B.B1 = (DE.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B1] | C_FLAG;
} else {
DE.B.B1 = (DE.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B1];
DE.B.B1 = (DE.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B1];
}
break;
case 0x1b:
// RR E
if (DE.B.B0 & 0x01) {
DE.B.B0 = (DE.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B0] | C_FLAG;
DE.B.B0 = (DE.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B0] | C_FLAG;
} else {
DE.B.B0 = (DE.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B0];
DE.B.B0 = (DE.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[DE.B.B0];
}
break;
case 0x1c:
// RR H
if (HL.B.B1 & 0x01) {
HL.B.B1 = (HL.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B1] | C_FLAG;
HL.B.B1 = (HL.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B1] | C_FLAG;
} else {
HL.B.B1 = (HL.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B1];
HL.B.B1 = (HL.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B1];
}
break;
case 0x1d:
// RR L
if (HL.B.B0 & 0x01) {
HL.B.B0 = (HL.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B0] | C_FLAG;
HL.B.B0 = (HL.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B0] | C_FLAG;
} else {
HL.B.B0 = (HL.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B0];
HL.B.B0 = (HL.B.B0 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[HL.B.B0];
}
break;
case 0x1e:
// RR (HL)
tempValue = gbReadMemory(HL.W);
if (tempValue & 0x01) {
tempValue = (tempValue >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[tempValue] | C_FLAG;
tempValue = (tempValue >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[tempValue] | C_FLAG;
} else {
tempValue = (tempValue >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[tempValue];
tempValue = (tempValue >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[tempValue];
}
gbWriteMemory(HL.W, tempValue);
break;
case 0x1f:
// RR A
if (AF.B.B1 & 0x01) {
AF.B.B1 = (AF.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[AF.B.B1] | C_FLAG;
AF.B.B1 = (AF.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[AF.B.B1] | C_FLAG;
} else {
AF.B.B1 = (AF.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[AF.B.B1];
AF.B.B1 = (AF.B.B1 >> 1) | (AF.B.B0 & C_FLAG ? 0x80 : 0);
AF.B.B0 = ZeroTable[AF.B.B1];
}
break;
case 0x20:
@ -1264,7 +1264,7 @@ AF.B.B1 |= 1 << 7;
break;
default:
if (gbSystemMessage == false) {
systemMessage(0, N_("Unknown opcode %02x at %04x"), gbReadOpcode(PC.W - 1), PC.W - 1);
gbSystemMessage = true;
systemMessage(0, N_("Unknown opcode %02x at %04x"), gbReadOpcode(PC.W - 1), PC.W - 1);
gbSystemMessage = true;
}
return;

View File

@ -5,227 +5,225 @@
#include "gbGlobals.h"
typedef struct {
u8 mask;
u8 value;
const char *mnen;
uint8_t mask;
uint8_t value;
const char* mnen;
} GBOPCODE;
#define GB_READ(x) gbMemoryMap[(x)>>12][(x)&0xfff]
#define GB_READ(x) gbMemoryMap[(x) >> 12][(x)&0xfff]
static const char *registers[] =
{ "B", "C", "D", "E", "H", "L", "(HL)", "A" };
static const char* registers[] = { "B", "C", "D", "E", "H", "L", "(HL)", "A" };
static const char *registers16[] =
{ "BC", "DE", "HL", "SP", // for some operations
static const char* registers16[] = { "BC", "DE", "HL", "SP", // for some operations
"BC", "DE", "HL", "AF" }; // for push/pop
static const char *cond[] =
{ "NZ", "Z", "NC", "C" };
static const char* cond[] = { "NZ", "Z", "NC", "C" };
static char hexDigits[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
static GBOPCODE opcodes[] = {
{ 0xff, 0x00, "NOP" },
{ 0xcf, 0x01, "LD %R4,%W" },
{ 0xff, 0x02, "LD (BC),A" },
{ 0xcf, 0x03, "INC %R4" },
{ 0xc7, 0x04, "INC %r3" },
{ 0xc7, 0x05, "DEC %r3" },
{ 0xc7, 0x06, "LD %r3,%B" },
{ 0xff, 0x07, "RLCA" },
{ 0xff, 0x08, "LD (%W),SP" },
{ 0xcf, 0x09, "ADD HL,%R4" },
{ 0xff, 0x0a, "LD A,(BC)" },
{ 0xcf, 0x0b, "DEC %R4" },
{ 0xff, 0x0f, "RRCA" },
{ 0xff, 0x10, "STOP" },
{ 0xff, 0x12, "LD (DE),A" },
{ 0xff, 0x17, "RLA" },
{ 0xff, 0x18, "JR %d" },
{ 0xff, 0x1a, "LD A,(DE)" },
{ 0xff, 0x1f, "RRA" },
{ 0xe7, 0x20, "JR %c3,%d" },
{ 0xff, 0x22, "LDI (HL),A" },
{ 0xff, 0x27, "DAA" },
{ 0xff, 0x2a, "LDI A,(HL)" },
{ 0xff, 0x2f, "CPL" },
{ 0xff, 0x32, "LDD (HL),A" },
{ 0xff, 0x37, "SCF" },
{ 0xff, 0x3a, "LDD A,(HL)" },
{ 0xff, 0x3f, "CCF" },
{ 0xff, 0x76, "HALT" },
{ 0xc0, 0x40, "LD %r3,%r0" },
{ 0xf8, 0x80, "ADD A,%r0" },
{ 0xf8, 0x88, "ADC A,%r0" },
{ 0xf8, 0x90, "SUB %r0" },
{ 0xf8, 0x98, "SBC A,%r0" },
{ 0xf8, 0xa0, "AND %r0" },
{ 0xf8, 0xa8, "XOR %r0" },
{ 0xf8, 0xb0, "OR %r0" },
{ 0xf8, 0xb8, "CP %r0" },
{ 0xe7, 0xc0, "RET %c3" },
{ 0xcf, 0xc1, "POP %t4" },
{ 0xe7, 0xc2, "JP %c3,%W" },
{ 0xff, 0xc3, "JP %W" },
{ 0xe7, 0xc4, "CALL %c3,%W" },
{ 0xcf, 0xc5, "PUSH %t4" },
{ 0xff, 0xc6, "ADD A,%B" },
{ 0xc7, 0xc7, "RST %P" },
{ 0xff, 0xc9, "RET" },
{ 0xff, 0xcd, "CALL %W" },
{ 0xff, 0xce, "ADC %B" },
{ 0xff, 0xd6, "SUB %B" },
{ 0xff, 0xd9, "RETI" },
{ 0xff, 0xde, "SBC %B" },
{ 0xff, 0xe0, "LD (FF%B),A" },
{ 0xff, 0xe2, "LD (FF00h+C),A" },
{ 0xff, 0xe6, "AND %B" },
{ 0xff, 0xe8, "ADD SP,%D" },
{ 0xff, 0xe9, "LD PC,HL" },
{ 0xff, 0xea, "LD (%W),A" },
{ 0xff, 0xee, "XOR %B" },
{ 0xff, 0xf0, "LD A,(FF%B)" },
{ 0xff, 0xf2, "LD A,(FF00h+C)" },
{ 0xff, 0xf3, "DI" },
{ 0xff, 0xf6, "OR %B" },
{ 0xff, 0xf8, "LD HL,SP%D" },
{ 0xff, 0xf9, "LD SP,HL" },
{ 0xff, 0xfa, "LD A,(%W)" },
{ 0xff, 0xfb, "EI" },
{ 0xff, 0xfe, "CP %B" },
{ 0x00, 0x00, "DB %B" }
{ 0xff, 0x00, "NOP" },
{ 0xcf, 0x01, "LD %R4,%W" },
{ 0xff, 0x02, "LD (BC),A" },
{ 0xcf, 0x03, "INC %R4" },
{ 0xc7, 0x04, "INC %r3" },
{ 0xc7, 0x05, "DEC %r3" },
{ 0xc7, 0x06, "LD %r3,%B" },
{ 0xff, 0x07, "RLCA" },
{ 0xff, 0x08, "LD (%W),SP" },
{ 0xcf, 0x09, "ADD HL,%R4" },
{ 0xff, 0x0a, "LD A,(BC)" },
{ 0xcf, 0x0b, "DEC %R4" },
{ 0xff, 0x0f, "RRCA" },
{ 0xff, 0x10, "STOP" },
{ 0xff, 0x12, "LD (DE),A" },
{ 0xff, 0x17, "RLA" },
{ 0xff, 0x18, "JR %d" },
{ 0xff, 0x1a, "LD A,(DE)" },
{ 0xff, 0x1f, "RRA" },
{ 0xe7, 0x20, "JR %c3,%d" },
{ 0xff, 0x22, "LDI (HL),A" },
{ 0xff, 0x27, "DAA" },
{ 0xff, 0x2a, "LDI A,(HL)" },
{ 0xff, 0x2f, "CPL" },
{ 0xff, 0x32, "LDD (HL),A" },
{ 0xff, 0x37, "SCF" },
{ 0xff, 0x3a, "LDD A,(HL)" },
{ 0xff, 0x3f, "CCF" },
{ 0xff, 0x76, "HALT" },
{ 0xc0, 0x40, "LD %r3,%r0" },
{ 0xf8, 0x80, "ADD A,%r0" },
{ 0xf8, 0x88, "ADC A,%r0" },
{ 0xf8, 0x90, "SUB %r0" },
{ 0xf8, 0x98, "SBC A,%r0" },
{ 0xf8, 0xa0, "AND %r0" },
{ 0xf8, 0xa8, "XOR %r0" },
{ 0xf8, 0xb0, "OR %r0" },
{ 0xf8, 0xb8, "CP %r0" },
{ 0xe7, 0xc0, "RET %c3" },
{ 0xcf, 0xc1, "POP %t4" },
{ 0xe7, 0xc2, "JP %c3,%W" },
{ 0xff, 0xc3, "JP %W" },
{ 0xe7, 0xc4, "CALL %c3,%W" },
{ 0xcf, 0xc5, "PUSH %t4" },
{ 0xff, 0xc6, "ADD A,%B" },
{ 0xc7, 0xc7, "RST %P" },
{ 0xff, 0xc9, "RET" },
{ 0xff, 0xcd, "CALL %W" },
{ 0xff, 0xce, "ADC %B" },
{ 0xff, 0xd6, "SUB %B" },
{ 0xff, 0xd9, "RETI" },
{ 0xff, 0xde, "SBC %B" },
{ 0xff, 0xe0, "LD (FF%B),A" },
{ 0xff, 0xe2, "LD (FF00h+C),A" },
{ 0xff, 0xe6, "AND %B" },
{ 0xff, 0xe8, "ADD SP,%D" },
{ 0xff, 0xe9, "LD PC,HL" },
{ 0xff, 0xea, "LD (%W),A" },
{ 0xff, 0xee, "XOR %B" },
{ 0xff, 0xf0, "LD A,(FF%B)" },
{ 0xff, 0xf2, "LD A,(FF00h+C)" },
{ 0xff, 0xf3, "DI" },
{ 0xff, 0xf6, "OR %B" },
{ 0xff, 0xf8, "LD HL,SP%D" },
{ 0xff, 0xf9, "LD SP,HL" },
{ 0xff, 0xfa, "LD A,(%W)" },
{ 0xff, 0xfb, "EI" },
{ 0xff, 0xfe, "CP %B" },
{ 0x00, 0x00, "DB %B" }
};
static GBOPCODE cbOpcodes[] = {
{ 0xf8, 0x00, "RLC %r0" },
{ 0xf8, 0x08, "RRC %r0" },
{ 0xf8, 0x10, "RL %r0" },
{ 0xf8, 0x18, "RR %r0" },
{ 0xf8, 0x20, "SLA %r0" },
{ 0xf8, 0x28, "SRA %r0" },
{ 0xf8, 0x30, "SWAP %r0" },
{ 0xf8, 0x38, "SRL %r0" },
{ 0xc0, 0x40, "BIT %b,%r0" },
{ 0xc0, 0x80, "RES %b,%r0" },
{ 0xc0, 0xc0, "SET %b,%r0" },
{ 0x00, 0x00, "DB CBh,%B" }
{ 0xf8, 0x00, "RLC %r0" },
{ 0xf8, 0x08, "RRC %r0" },
{ 0xf8, 0x10, "RL %r0" },
{ 0xf8, 0x18, "RR %r0" },
{ 0xf8, 0x20, "SLA %r0" },
{ 0xf8, 0x28, "SRA %r0" },
{ 0xf8, 0x30, "SWAP %r0" },
{ 0xf8, 0x38, "SRL %r0" },
{ 0xc0, 0x40, "BIT %b,%r0" },
{ 0xc0, 0x80, "RES %b,%r0" },
{ 0xc0, 0xc0, "SET %b,%r0" },
{ 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 & 15];
return p;
*p++ = hexDigits[value >> 4];
*p++ = hexDigits[value & 15];
return p;
}
static char *addHex16(char *p, u16 value)
static char* addHex16(char* p, uint16_t value)
{
p = addHex(p, value>>8);
return addHex(p, value & 255);
p = addHex(p, value >> 8);
return addHex(p, value & 255);
}
static char *addStr(char *p, const char *s)
static char* addStr(char* p, const char* s)
{
while(*s) {
*p++ = *s++;
}
return p;
while (*s) {
*p++ = *s++;
}
return p;
}
int gbDis(char *buffer, u16 address)
int gbDis(char* buffer, uint16_t address)
{
char *p = buffer;
int instr = 1;
u16 addr = address;
sprintf(p, "%04x ", address);
p += 12;
char* p = buffer;
int instr = 1;
uint16_t addr = address;
sprintf(p, "%04x ", address);
p += 12;
u8 opcode = GB_READ(address);
address++;
const char *mnen;
GBOPCODE *op;
if(opcode == 0xcb) {
opcode = GB_READ(address);
uint8_t opcode = GB_READ(address);
address++;
instr++;
op = cbOpcodes;
} else {
op = opcodes;
}
while(op->value != (opcode & op->mask)) op++;
mnen = op->mnen;
const char* mnen;
GBOPCODE* op;
if (opcode == 0xcb) {
opcode = GB_READ(address);
address++;
instr++;
op = cbOpcodes;
} else {
op = opcodes;
}
while (op->value != (opcode & op->mask))
op++;
mnen = op->mnen;
u8 b0, b1;
s8 disp;
int shift;
uint8_t b0, b1;
int8_t disp;
int shift;
while(*mnen) {
if(*mnen == '%') {
mnen++;
switch(*mnen++) {
case 'W':
b0 = GB_READ(address);
address++;
b1 = GB_READ(address);
address++;
p = addHex16(p, b0|b1<<8);
instr += 2;
*p++ = 'h';
break;
case 'B':
p = addHex(p, GB_READ(address));
*p++ = 'h';
address++;
instr++;
break;
case 'D':
disp = GB_READ(address);
if(disp >= 0)
*p++ = '+';
p += sprintf(p, "%d", disp);
instr++;
break;
case 'd':
disp = GB_READ(address);
address++;
p = addHex16(p, address+disp);
*p++ = 'h';
instr++;
break;
case 'b':
// kind of a hack, but it works :-)
*p++ = hexDigits[(opcode >> 3) & 7];
break;
case 'r':
shift = *mnen++ - '0';
p = addStr(p, registers[(opcode >> shift) & 7]);
break;
case 'R':
shift = *mnen++ - '0';
p = addStr(p, registers16[(opcode >> shift) & 3]);
break;
case 't':
shift = *mnen++ - '0';
p = addStr(p, registers16[4+((opcode >> shift) & 3)]);
break;
case 'P':
p = addHex(p, ((opcode >> 3) & 7) * 8);
break;
case 'c':
shift = *mnen++ - '0';
p = addStr(p, cond[(opcode >> shift) & 3]);
break;
}
} else
*p++ = *mnen++;
}
for(int i = 0; i < instr; i++) {
u16 a = addr + i;
addHex(buffer+5+i*2, GB_READ(a));
}
*p = 0;
return instr;
while (*mnen) {
if (*mnen == '%') {
mnen++;
switch (*mnen++) {
case 'W':
b0 = GB_READ(address);
address++;
b1 = GB_READ(address);
address++;
p = addHex16(p, b0 | b1 << 8);
instr += 2;
*p++ = 'h';
break;
case 'B':
p = addHex(p, GB_READ(address));
*p++ = 'h';
address++;
instr++;
break;
case 'D':
disp = GB_READ(address);
if (disp >= 0)
*p++ = '+';
p += sprintf(p, "%d", disp);
instr++;
break;
case 'd':
disp = GB_READ(address);
address++;
p = addHex16(p, address + disp);
*p++ = 'h';
instr++;
break;
case 'b':
// kind of a hack, but it works :-)
*p++ = hexDigits[(opcode >> 3) & 7];
break;
case 'r':
shift = *mnen++ - '0';
p = addStr(p, registers[(opcode >> shift) & 7]);
break;
case 'R':
shift = *mnen++ - '0';
p = addStr(p, registers16[(opcode >> shift) & 3]);
break;
case 't':
shift = *mnen++ - '0';
p = addStr(p, registers16[4 + ((opcode >> shift) & 3)]);
break;
case 'P':
p = addHex(p, ((opcode >> 3) & 7) * 8);
break;
case 'c':
shift = *mnen++ - '0';
p = addStr(p, cond[(opcode >> shift) & 3]);
break;
}
} else
*p++ = *mnen++;
}
for (int i = 0; i < instr; i++) {
uint16_t a = addr + i;
addHex(buffer + 5 + i * 2, GB_READ(a));
}
*p = 0;
return instr;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -4,134 +4,134 @@
#include <time.h>
struct mapperMBC1 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
int mapperRomBank0Remapping;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
int mapperRomBank0Remapping;
};
struct mapperMBC2 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMEnable;
int mapperROMBank;
};
struct mapperMBC3 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperClockLatch;
int mapperClockRegister;
int mapperSeconds;
int mapperMinutes;
int mapperHours;
int mapperDays;
int mapperControl;
int mapperLSeconds;
int mapperLMinutes;
int mapperLHours;
int mapperLDays;
int mapperLControl;
time_t mapperLastTime;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperClockLatch;
int mapperClockRegister;
int mapperSeconds;
int mapperMinutes;
int mapperHours;
int mapperDays;
int mapperControl;
int mapperLSeconds;
int mapperLMinutes;
int mapperLHours;
int mapperLDays;
int mapperLControl;
time_t mapperLastTime;
};
struct mapperMBC5 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperROMHighAddress;
int mapperRAMAddress;
int isRumbleCartridge;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperROMHighAddress;
int mapperRAMAddress;
int isRumbleCartridge;
};
struct mapperMBC7 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int cs;
int sk;
int state;
int buffer;
int idle;
int count;
int code;
int address;
int writeEnable;
int value;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int cs;
int sk;
int state;
int buffer;
int idle;
int count;
int code;
int address;
int writeEnable;
int value;
};
struct mapperHuC1 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
};
struct mapperHuC3 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperAddress;
int mapperRAMFlag;
int mapperRAMValue;
int mapperRegister1;
int mapperRegister2;
int mapperRegister3;
int mapperRegister4;
int mapperRegister5;
int mapperRegister6;
int mapperRegister7;
int mapperRegister8;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperAddress;
int mapperRAMFlag;
int mapperRAMValue;
int mapperRegister1;
int mapperRegister2;
int mapperRegister3;
int mapperRegister4;
int mapperRegister5;
int mapperRegister6;
int mapperRegister7;
int mapperRegister8;
};
struct mapperTAMA5 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperRamByteSelect;
int mapperCommandNumber;
int mapperLastCommandNumber;
int mapperCommands[0x10];
int mapperRegister;
int mapperClockLatch;
int mapperClockRegister;
int mapperSeconds;
int mapperMinutes;
int mapperHours;
int mapperDays;
int mapperMonths;
int mapperYears;
int mapperControl;
int mapperLSeconds;
int mapperLMinutes;
int mapperLHours;
int mapperLDays;
int mapperLMonths;
int mapperLYears;
int mapperLControl;
time_t mapperLastTime;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperRAMAddress;
int mapperRamByteSelect;
int mapperCommandNumber;
int mapperLastCommandNumber;
int mapperCommands[0x10];
int mapperRegister;
int mapperClockLatch;
int mapperClockRegister;
int mapperSeconds;
int mapperMinutes;
int mapperHours;
int mapperDays;
int mapperMonths;
int mapperYears;
int mapperControl;
int mapperLSeconds;
int mapperLMinutes;
int mapperLHours;
int mapperLDays;
int mapperLMonths;
int mapperLYears;
int mapperLControl;
time_t mapperLastTime;
};
struct mapperMMM01 {
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
int mapperRomBank0Remapping;
int mapperRAMEnable;
int mapperROMBank;
int mapperRAMBank;
int mapperMemoryModel;
int mapperROMHighAddress;
int mapperRAMAddress;
int mapperRomBank0Remapping;
};
struct mapperGS3 {
int mapperROMBank;
int mapperROMBank;
};
extern mapperMBC1 gbDataMBC1;

View File

@ -1,10 +1,10 @@
#include <stdio.h>
#include <memory.h>
#include "../System.h"
#include <memory.h>
#include <stdio.h>
u8 gbPrinterStatus = 0;
int gbPrinterState = 0;
u8 gbPrinterData[0x280*9];
u8 gbPrinterData[0x280 * 9];
u8 gbPrinterPacket[0x400];
int gbPrinterCount = 0;
int gbPrinterDataCount = 0;
@ -13,37 +13,36 @@ int gbPrinterResult = 0;
bool gbPrinterCheckCRC()
{
u16 crc = 0;
u16 crc = 0;
for(int i = 2; i < (6+gbPrinterDataSize); i++) {
crc += gbPrinterPacket[i];
}
for (int i = 2; i < (6 + gbPrinterDataSize); i++) {
crc += gbPrinterPacket[i];
}
int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] +
(gbPrinterPacket[7+gbPrinterDataSize]<<8);
int msgCrc = gbPrinterPacket[6 + gbPrinterDataSize] + (gbPrinterPacket[7 + gbPrinterDataSize] << 8);
return msgCrc == crc;
return msgCrc == crc;
}
void gbPrinterReset()
{
gbPrinterState = 0;
gbPrinterDataSize = 0;
gbPrinterDataCount = 0;
gbPrinterCount = 0;
gbPrinterStatus = 0;
gbPrinterResult = 0;
gbPrinterState = 0;
gbPrinterDataSize = 0;
gbPrinterDataCount = 0;
gbPrinterCount = 0;
gbPrinterStatus = 0;
gbPrinterResult = 0;
}
void gbPrinterShowData()
{
systemGbPrint(gbPrinterData,
gbPrinterDataCount,
gbPrinterPacket[6],
gbPrinterPacket[7],
gbPrinterPacket[8],
gbPrinterPacket[9]);
/*
systemGbPrint(gbPrinterData,
gbPrinterDataCount,
gbPrinterPacket[6],
gbPrinterPacket[7],
gbPrinterPacket[8],
gbPrinterPacket[9]);
/*
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT, 160, 144, 0, 0);
@ -89,126 +88,126 @@ void gbPrinterShowData()
void gbPrinterReceiveData()
{
int i = gbPrinterDataCount;
if(gbPrinterPacket[3]) { // compressed
u8 *data = &gbPrinterPacket[6];
u8 *dest = &gbPrinterData[gbPrinterDataCount];
int len = 0;
while(len < gbPrinterDataSize) {
u8 control = *data++;
if(control & 0x80) { // repeated data
control &= 0x7f;
control += 2;
memset(dest, *data++, control);
len += 2;
dest += control;
} else { // raw data
control++;
memcpy(dest, data, control);
dest += control;
data += control;
len += control + 1;
}
if (gbPrinterPacket[3]) { // compressed
u8* data = &gbPrinterPacket[6];
u8* dest = &gbPrinterData[gbPrinterDataCount];
int len = 0;
while (len < gbPrinterDataSize) {
u8 control = *data++;
if (control & 0x80) { // repeated data
control &= 0x7f;
control += 2;
memset(dest, *data++, control);
len += 2;
dest += control;
} else { // raw data
control++;
memcpy(dest, data, control);
dest += control;
data += control;
len += control + 1;
}
}
gbPrinterDataCount = (int)(dest - gbPrinterData);
} else {
memcpy(&gbPrinterData[gbPrinterDataCount],
&gbPrinterPacket[6],
gbPrinterDataSize);
gbPrinterDataCount += gbPrinterDataSize;
}
gbPrinterDataCount = (int)(dest - gbPrinterData);
} else {
memcpy(&gbPrinterData[gbPrinterDataCount],
&gbPrinterPacket[6],
gbPrinterDataSize);
gbPrinterDataCount += gbPrinterDataSize;
}
}
void gbPrinterCommand()
{
switch(gbPrinterPacket[2]) {
case 0x01:
// reset/initialize packet
gbPrinterDataCount = 0;
gbPrinterStatus = 0;
break;
case 0x02:
// print packet
gbPrinterShowData();
break;
case 0x04:
// data packet
gbPrinterReceiveData();
break;
case 0x0f:
// NUL packet
break;
}
switch (gbPrinterPacket[2]) {
case 0x01:
// reset/initialize packet
gbPrinterDataCount = 0;
gbPrinterStatus = 0;
break;
case 0x02:
// print packet
gbPrinterShowData();
break;
case 0x04:
// data packet
gbPrinterReceiveData();
break;
case 0x0f:
// NUL packet
break;
}
}
u8 gbPrinterSend(u8 b)
{
switch(gbPrinterState) {
case 0:
gbPrinterCount = 0;
// receiving preamble
if(b == 0x88) {
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
} else {
// todo: handle failure
gbPrinterReset();
}
break;
case 1:
// receiving preamble
if(b == 0x33) {
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
} else {
// todo: handle failure
gbPrinterReset();
}
break;
case 2:
// receiving header
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == 6) {
gbPrinterState++;
gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8);
}
break;
case 3:
// receiving data
if(gbPrinterDataSize) {
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == (6+gbPrinterDataSize)) {
switch (gbPrinterState) {
case 0:
gbPrinterCount = 0;
// receiving preamble
if (b == 0x88) {
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
} else {
// todo: handle failure
gbPrinterReset();
}
break;
case 1:
// receiving preamble
if (b == 0x33) {
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
} else {
// todo: handle failure
gbPrinterReset();
}
break;
case 2:
// receiving header
gbPrinterPacket[gbPrinterCount++] = b;
if (gbPrinterCount == 6) {
gbPrinterState++;
gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5] << 8);
}
break;
case 3:
// receiving data
if (gbPrinterDataSize) {
gbPrinterPacket[gbPrinterCount++] = b;
if (gbPrinterCount == (6 + gbPrinterDataSize)) {
gbPrinterState++;
}
break;
}
gbPrinterState++;
}
break;
}
gbPrinterState++;
// intentionally move to next if no data to receive
case 4:
// receiving CRC
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
break;
case 5:
// receiving CRC-2
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCheckCRC()) {
gbPrinterCommand();
case 4:
// receiving CRC
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
break;
case 5:
// receiving CRC-2
gbPrinterPacket[gbPrinterCount++] = b;
if (gbPrinterCheckCRC()) {
gbPrinterCommand();
}
gbPrinterState++;
break;
case 6:
// receiving dummy 1
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = 0x81;
gbPrinterState++;
break;
case 7:
// receiving dummy 2
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = gbPrinterStatus;
gbPrinterState = 0;
gbPrinterCount = 0;
break;
}
gbPrinterState++;
break;
case 6:
// receiving dummy 1
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = 0x81;
gbPrinterState++;
break;
case 7:
// receiving dummy 2
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = gbPrinterStatus;
gbPrinterState = 0;
gbPrinterCount = 0;
break;
}
return gbPrinterResult;
return gbPrinterResult;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,443 +1,456 @@
#include <string.h>
#include "../gba/Sound.h"
#include "../Util.h"
#include "../gba/Sound.h"
#include "gb.h"
#include "gbGlobals.h"
#include "gbSound.h"
#include "gb.h"
#include "../apu/Gb_Apu.h"
#include "../apu/Effects_Buffer.h"
#include "../apu/Gb_Apu.h"
extern long soundSampleRate; // current sound quality
gb_effects_config_t gb_effects_config = { false, 0.20f, 0.15f, false };
static gb_effects_config_t gb_effects_config_current;
static gb_effects_config_t gb_effects_config_current;
static Simple_Effects_Buffer* stereo_buffer;
static Gb_Apu* gb_apu;
static Gb_Apu* gb_apu;
static float soundVolume_ = -1;
static float soundVolume_ = -1;
static int prevSoundEnable = -1;
static bool declicking = false;
static bool declicking = false;
int const chan_count = 4;
int const ticks_to_time = 2 * GB_APU_OVERCLOCK;
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 )
return gb_apu->read_register( blip_time(), address );
if (gb_apu && address >= NR10 && address <= 0xFF3F)
return gb_apu->read_register(blip_time(), address);
return gbMemory[address];
return gbMemory[address];
}
void gbSoundEvent(register u16 address, register int data)
{
gbMemory[address] = data;
gbMemory[address] = data;
if ( gb_apu && address >= NR10 && address <= 0xFF3F )
gb_apu->write_register( blip_time(), address, data );
if (gb_apu && address >= NR10 && address <= 0xFF3F)
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 );
stereo_buffer->end_frame( time );
gb_apu->end_frame(time);
stereo_buffer->end_frame(time);
}
static void apply_effects()
{
prevSoundEnable = soundGetEnable();
gb_effects_config_current = gb_effects_config;
prevSoundEnable = soundGetEnable();
gb_effects_config_current = gb_effects_config;
stereo_buffer->config().enabled = gb_effects_config_current.enabled;
stereo_buffer->config().echo = gb_effects_config_current.echo;
stereo_buffer->config().stereo = gb_effects_config_current.stereo;
stereo_buffer->config().surround = gb_effects_config_current.surround;
stereo_buffer->apply_config();
stereo_buffer->config().enabled = gb_effects_config_current.enabled;
stereo_buffer->config().echo = gb_effects_config_current.echo;
stereo_buffer->config().stereo = gb_effects_config_current.stereo;
stereo_buffer->config().surround = gb_effects_config_current.surround;
stereo_buffer->apply_config();
for ( int i = 0; i < chan_count; i++ )
{
Multi_Buffer::channel_t ch = { 0, 0, 0 };
if ( prevSoundEnable >> i & 1 )
ch = stereo_buffer->channel( i );
gb_apu->set_output( ch.center, ch.left, ch.right, i );
}
for (int i = 0; i < chan_count; i++) {
Multi_Buffer::channel_t ch = { 0, 0, 0 };
if (prevSoundEnable >> i & 1)
ch = stereo_buffer->channel(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;
}
static void apply_volume()
{
soundVolume_ = soundGetVolume();
soundVolume_ = soundGetVolume();
if ( gb_apu )
gb_apu->volume( soundVolume_ );
if (gb_apu)
gb_apu->volume(soundVolume_);
}
void gbSoundTick()
{
if ( gb_apu && stereo_buffer )
{
// Run sound hardware to present
end_frame( SOUND_CLOCK_TICKS * ticks_to_time );
if (gb_apu && stereo_buffer) {
// Run sound hardware to present
end_frame(SOUND_CLOCK_TICKS * ticks_to_time);
flush_samples(stereo_buffer);
flush_samples(stereo_buffer);
// Update effects config if it was changed
if ( memcmp( &gb_effects_config_current, &gb_effects_config,
sizeof gb_effects_config ) || soundGetEnable() != prevSoundEnable )
apply_effects();
// Update effects config if it was changed
if (memcmp(&gb_effects_config_current, &gb_effects_config,
sizeof gb_effects_config)
|| soundGetEnable() != prevSoundEnable)
apply_effects();
if ( soundVolume_ != soundGetVolume() )
apply_volume();
}
if (soundVolume_ != soundGetVolume())
apply_volume();
}
}
static void reset_apu()
{
Gb_Apu::mode_t mode = Gb_Apu::mode_dmg;
if ( gbHardware & 2 )
mode = Gb_Apu::mode_cgb;
if ( gbHardware & 8 || declicking )
mode = Gb_Apu::mode_agb;
gb_apu->reset( mode );
gb_apu->reduce_clicks( declicking );
Gb_Apu::mode_t mode = Gb_Apu::mode_dmg;
if (gbHardware & 2)
mode = Gb_Apu::mode_cgb;
if (gbHardware & 8 || declicking)
mode = Gb_Apu::mode_agb;
gb_apu->reset(mode);
gb_apu->reduce_clicks(declicking);
if ( stereo_buffer )
stereo_buffer->clear();
if (stereo_buffer)
stereo_buffer->clear();
soundTicks = SOUND_CLOCK_TICKS;
soundTicks = SOUND_CLOCK_TICKS;
}
static void remake_stereo_buffer()
{
// APU
if ( !gb_apu )
{
gb_apu = new Gb_Apu; // TODO: handle errors
reset_apu();
}
// APU
if (!gb_apu) {
gb_apu = new Gb_Apu; // TODO: handle errors
reset_apu();
}
// Stereo_Buffer
delete stereo_buffer;
stereo_buffer = 0;
// Stereo_Buffer
delete stereo_buffer;
stereo_buffer = 0;
stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory
if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory
stereo_buffer->clock_rate( gb_apu->clock_rate );
// Multi_Buffer
static int const chan_types [chan_count] = {
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2,
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1
};
if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors
stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory
if (stereo_buffer->set_sample_rate(soundSampleRate)) {
} // TODO: handle out of memory
stereo_buffer->clock_rate(gb_apu->clock_rate);
// Volume Level
apply_effects();
apply_volume();
// Multi_Buffer
static int const chan_types[chan_count] = {
Multi_Buffer::wave_type + 1, Multi_Buffer::wave_type + 2,
Multi_Buffer::wave_type + 3, Multi_Buffer::mixed_type + 1
};
if (stereo_buffer->set_channel_count(chan_count, chan_types)) {
} // TODO: handle errors
// Volume Level
apply_effects();
apply_volume();
}
void gbSoundSetDeclicking( bool enable )
void gbSoundSetDeclicking(bool enable)
{
if ( declicking != enable )
{
declicking = enable;
if ( gb_apu )
{
// Can't change sound hardware mode without resetting APU, so save/load
// state around mode change
gb_apu_state_t state;
gb_apu->save_state( &state );
reset_apu();
if ( gb_apu->load_state( state ) ) { } // ignore error
}
}
if (declicking != enable) {
declicking = enable;
if (gb_apu) {
// Can't change sound hardware mode without resetting APU, so save/load
// state around mode change
gb_apu_state_t state;
gb_apu->save_state(&state);
reset_apu();
if (gb_apu->load_state(state)) {
} // ignore error
}
}
}
bool gbSoundGetDeclicking()
{
return declicking;
return declicking;
}
void gbSoundReset()
{
SOUND_CLOCK_TICKS = 20000; // 1/100 second
SOUND_CLOCK_TICKS = 20000; // 1/100 second
remake_stereo_buffer();
reset_apu();
remake_stereo_buffer();
reset_apu();
soundPaused = 1;
soundPaused = 1;
gbSoundEvent(0xff10, 0x80);
gbSoundEvent(0xff11, 0xbf);
gbSoundEvent(0xff12, 0xf3);
gbSoundEvent(0xff14, 0xbf);
gbSoundEvent(0xff16, 0x3f);
gbSoundEvent(0xff17, 0x00);
gbSoundEvent(0xff19, 0xbf);
gbSoundEvent(0xff10, 0x80);
gbSoundEvent(0xff11, 0xbf);
gbSoundEvent(0xff12, 0xf3);
gbSoundEvent(0xff14, 0xbf);
gbSoundEvent(0xff16, 0x3f);
gbSoundEvent(0xff17, 0x00);
gbSoundEvent(0xff19, 0xbf);
gbSoundEvent(0xff1a, 0x7f);
gbSoundEvent(0xff1b, 0xff);
gbSoundEvent(0xff1c, 0xbf);
gbSoundEvent(0xff1e, 0xbf);
gbSoundEvent(0xff1a, 0x7f);
gbSoundEvent(0xff1b, 0xff);
gbSoundEvent(0xff1c, 0xbf);
gbSoundEvent(0xff1e, 0xbf);
gbSoundEvent(0xff20, 0xff);
gbSoundEvent(0xff21, 0x00);
gbSoundEvent(0xff22, 0x00);
gbSoundEvent(0xff23, 0xbf);
gbSoundEvent(0xff24, 0x77);
gbSoundEvent(0xff25, 0xf3);
gbSoundEvent(0xff20, 0xff);
gbSoundEvent(0xff21, 0x00);
gbSoundEvent(0xff22, 0x00);
gbSoundEvent(0xff23, 0xbf);
gbSoundEvent(0xff24, 0x77);
gbSoundEvent(0xff25, 0xf3);
if (gbHardware & 0x4)
gbSoundEvent(0xff26, 0xf0);
else
gbSoundEvent(0xff26, 0xf1);
if (gbHardware & 0x4)
gbSoundEvent(0xff26, 0xf0);
else
gbSoundEvent(0xff26, 0xf1);
/* workaround for game Beetlejuice */
if (gbHardware & 0x1) {
gbSoundEvent(0xff24, 0x77);
gbSoundEvent(0xff25, 0xf3);
}
/* workaround for game Beetlejuice */
if (gbHardware & 0x1) {
gbSoundEvent(0xff24, 0x77);
gbSoundEvent(0xff25, 0xf3);
}
int addr = 0xff30;
int addr = 0xff30;
while(addr < 0xff40) {
gbMemory[addr++] = 0x00;
gbMemory[addr++] = 0xff;
}
while (addr < 0xff40) {
gbMemory[addr++] = 0x00;
gbMemory[addr++] = 0xff;
}
}
void gbSoundSetSampleRate( long sampleRate )
void gbSoundSetSampleRate(long sampleRate)
{
if ( soundSampleRate != sampleRate )
{
if ( systemCanChangeSoundQuality() )
{
soundShutdown();
soundSampleRate = sampleRate;
soundInit();
}
else
{
soundSampleRate = sampleRate;
}
if (soundSampleRate != sampleRate) {
if (systemCanChangeSoundQuality()) {
soundShutdown();
soundSampleRate = sampleRate;
soundInit();
} else {
soundSampleRate = sampleRate;
}
remake_stereo_buffer();
}
remake_stereo_buffer();
}
}
static struct {
int version;
gb_apu_state_t apu;
int version;
gb_apu_state_t apu;
} 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
static variable_desc gbsound_format [] =
{
SKIP( int, soundPaused ),
SKIP( int, soundPlay ),
SKIP( int, soundTicks ),
SKIP( int, SOUND_CLOCK_TICKS ),
SKIP( int, soundLevel1 ),
SKIP( int, soundLevel2 ),
SKIP( int, soundBalance ),
SKIP( int, soundMasterOn ),
SKIP( int, soundIndex ),
SKIP( int, soundVIN ),
SKIP( int, soundOn [0] ),
SKIP( int, soundATL [0] ),
SKIP( int, sound1Skip ),
SKIP( int, soundIndex [0] ),
SKIP( int, sound1Continue ),
SKIP( int, soundEnvelopeVolume [0] ),
SKIP( int, soundEnvelopeATL [0] ),
SKIP( int, sound1EnvelopeATLReload ),
SKIP( int, sound1EnvelopeUpDown ),
SKIP( int, sound1SweepATL ),
SKIP( int, sound1SweepATLReload ),
SKIP( int, sound1SweepSteps ),
SKIP( int, sound1SweepUpDown ),
SKIP( int, sound1SweepStep ),
SKIP( int, soundOn [1] ),
SKIP( int, soundATL [1] ),
SKIP( int, sound2Skip ),
SKIP( int, soundIndex [1] ),
SKIP( int, sound2Continue ),
SKIP( int, soundEnvelopeVolume [1] ),
SKIP( int, soundEnvelopeATL [1] ),
SKIP( int, sound2EnvelopeATLReload ),
SKIP( int, sound2EnvelopeUpDown ),
SKIP( int, soundOn [2] ),
SKIP( int, soundATL [2] ),
SKIP( int, sound3Skip ),
SKIP( int, soundIndex [2] ),
SKIP( int, sound3Continue ),
SKIP( int, sound3OutputLevel ),
SKIP( int, soundOn [3] ),
SKIP( int, soundATL [3] ),
SKIP( int, sound4Skip ),
SKIP( int, soundIndex [3] ),
SKIP( int, sound4Clock ),
SKIP( int, sound4ShiftRight ),
SKIP( int, sound4ShiftSkip ),
SKIP( int, sound4ShiftIndex ),
SKIP( int, sound4NSteps ),
SKIP( int, sound4CountDown ),
SKIP( int, sound4Continue ),
SKIP( int, soundEnvelopeVolume [2] ),
SKIP( int, soundEnvelopeATL [2] ),
SKIP( int, sound4EnvelopeATLReload ),
SKIP( int, sound4EnvelopeUpDown ),
SKIP( int, soundEnableFlag ),
{ NULL, 0 }
static variable_desc gbsound_format[] = {
SKIP(int, soundPaused),
SKIP(int, soundPlay),
SKIP(int, soundTicks),
SKIP(int, SOUND_CLOCK_TICKS),
SKIP(int, soundLevel1),
SKIP(int, soundLevel2),
SKIP(int, soundBalance),
SKIP(int, soundMasterOn),
SKIP(int, soundIndex),
SKIP(int, soundVIN),
SKIP(int, soundOn[0]),
SKIP(int, soundATL[0]),
SKIP(int, sound1Skip),
SKIP(int, soundIndex[0]),
SKIP(int, sound1Continue),
SKIP(int, soundEnvelopeVolume[0]),
SKIP(int, soundEnvelopeATL[0]),
SKIP(int, sound1EnvelopeATLReload),
SKIP(int, sound1EnvelopeUpDown),
SKIP(int, sound1SweepATL),
SKIP(int, sound1SweepATLReload),
SKIP(int, sound1SweepSteps),
SKIP(int, sound1SweepUpDown),
SKIP(int, sound1SweepStep),
SKIP(int, soundOn[1]),
SKIP(int, soundATL[1]),
SKIP(int, sound2Skip),
SKIP(int, soundIndex[1]),
SKIP(int, sound2Continue),
SKIP(int, soundEnvelopeVolume[1]),
SKIP(int, soundEnvelopeATL[1]),
SKIP(int, sound2EnvelopeATLReload),
SKIP(int, sound2EnvelopeUpDown),
SKIP(int, soundOn[2]),
SKIP(int, soundATL[2]),
SKIP(int, sound3Skip),
SKIP(int, soundIndex[2]),
SKIP(int, sound3Continue),
SKIP(int, sound3OutputLevel),
SKIP(int, soundOn[3]),
SKIP(int, soundATL[3]),
SKIP(int, sound4Skip),
SKIP(int, soundIndex[3]),
SKIP(int, sound4Clock),
SKIP(int, sound4ShiftRight),
SKIP(int, sound4ShiftSkip),
SKIP(int, sound4ShiftIndex),
SKIP(int, sound4NSteps),
SKIP(int, sound4CountDown),
SKIP(int, sound4Continue),
SKIP(int, soundEnvelopeVolume[2]),
SKIP(int, soundEnvelopeATL[2]),
SKIP(int, sound4EnvelopeATLReload),
SKIP(int, sound4EnvelopeUpDown),
SKIP(int, soundEnableFlag),
{ NULL, 0 }
};
static variable_desc gbsound_format2 [] =
{
SKIP( int, sound1ATLreload ),
SKIP( int, freq1low ),
SKIP( int, freq1high ),
SKIP( int, sound2ATLreload ),
SKIP( int, freq2low ),
SKIP( int, freq2high ),
SKIP( int, sound3ATLreload ),
SKIP( int, freq3low ),
SKIP( int, freq3high ),
SKIP( int, sound4ATLreload ),
SKIP( int, freq4 ),
{ NULL, 0 }
static variable_desc gbsound_format2[] = {
SKIP(int, sound1ATLreload),
SKIP(int, freq1low),
SKIP(int, freq1high),
SKIP(int, sound2ATLreload),
SKIP(int, freq2low),
SKIP(int, freq2high),
SKIP(int, sound3ATLreload),
SKIP(int, freq3low),
SKIP(int, freq3high),
SKIP(int, sound4ATLreload),
SKIP(int, freq4),
{ NULL, 0 }
};
static variable_desc gbsound_format3 [] =
{
SKIP( u8[2*735], soundBuffer ),
SKIP( u8[2*735], soundBuffer ),
SKIP( u16[735], soundFinalWave ),
{ NULL, 0 }
static variable_desc gbsound_format3[] = {
SKIP(u8[2 * 735], soundBuffer),
SKIP(u8[2 * 735], soundBuffer),
SKIP(u16[735], soundFinalWave),
{ NULL, 0 }
};
enum {
nr10 = 0,
nr11, nr12, nr13, nr14,
nr20, nr21, nr22, nr23, nr24,
nr30, nr31, nr32, nr33, nr34,
nr40, nr41, nr42, nr43, nr44,
nr50, nr51, nr52
nr10 = 0,
nr11,
nr12,
nr13,
nr14,
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 )
{
// Version 11 didn't save any state
// TODO: same for version 10?
state.apu.regs [nr50] = 0x77; // volume at max
state.apu.regs [nr51] = 0xFF; // channels enabled
state.apu.regs [nr52] = 0x80; // power on
return;
}
if (version == 11) {
// Version 11 didn't save any state
// TODO: same for version 10?
state.apu.regs[nr50] = 0x77; // volume at max
state.apu.regs[nr51] = 0xFF; // channels enabled
state.apu.regs[nr52] = 0x80; // power on
return;
}
// Load state
utilReadData( gzFile, gbsound_format );
// Load state
utilReadData(gzFile, gbsound_format);
if ( version >= 11 ) // TODO: never executed; remove?
utilReadData( gzFile, gbsound_format2 );
if (version >= 11) // TODO: never executed; remove?
utilReadData(gzFile, gbsound_format2);
utilReadData( gzFile, gbsound_format3 );
utilReadData(gzFile, gbsound_format3);
int quality = 1;
if ( version >= 7 )
quality = utilReadInt( gzFile );
int quality = 1;
if (version >= 7)
quality = utilReadInt(gzFile);
gbSoundSetSampleRate( 44100 / quality );
gbSoundSetSampleRate(44100 / quality);
// Convert to format Gb_Apu uses
gb_apu_state_t& s = state.apu;
// Convert to format Gb_Apu uses
gb_apu_state_t& s = state.apu;
// Only some registers are properly preserved
static int const regs_to_copy [] = {
nr10, nr11, nr12, nr21, nr22, nr30, nr32, nr42, nr43, nr50, nr51, nr52, -1
};
for ( int i = 0; regs_to_copy [i] >= 0; i++ )
s.regs [regs_to_copy [i]] = gbMemory [0xFF10 + regs_to_copy [i]];
// Only some registers are properly preserved
static int const regs_to_copy[] = {
nr10, nr11, nr12, nr21, nr22, nr30, nr32, nr42, nr43, nr50, nr51, nr52, -1
};
for (int i = 0; regs_to_copy[i] >= 0; 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
static variable_desc gb_state [] =
{
LOAD( int, state.version ), // room_for_expansion will be used by later versions
static variable_desc gb_state[] = {
LOAD(int, state.version), // room_for_expansion will be used by later versions
// APU
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_phase ), // next step frame sequencer will run
// APU
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_phase), // next step frame sequencer will run
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_enabled ),
LOAD( int, state.apu.sweep_neg ), // obscure internal flag
LOAD( int, state.apu.noise_divider ),
LOAD( int, state.apu.wave_buf ), // last read byte of wave RAM
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_enabled),
LOAD(int, state.apu.sweep_neg), // obscure internal flag
LOAD(int, state.apu.noise_divider),
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.length_ctr ),
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.delay), // clocks until next channel action
LOAD(int[4], state.apu.length_ctr),
LOAD(int[4], state.apu.phase), // square/wave phase, noise LFSR
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_volume ),
LOAD( int [3], state.apu.env_enabled ),
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_enabled),
SKIP( int [13], room_for_expansion ),
SKIP(int[13], room_for_expansion),
// Emulator
SKIP( int [16], room_for_expansion ),
// Emulator
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
memset( dummy_state, 0, sizeof dummy_state );
// Be sure areas for expansion get written as zero
memset(dummy_state, 0, sizeof dummy_state);
state.version = 1;
utilWriteData( out, gb_state );
state.version = 1;
utilWriteData(out, gb_state);
}
void gbSoundReadGame( int version, gzFile in )
void gbSoundReadGame(int version, gzFile in)
{
// Prepare APU and default state
reset_apu();
gb_apu->save_state( &state.apu );
// Prepare APU and default state
reset_apu();
gb_apu->save_state(&state.apu);
if ( version > 11 )
utilReadData( in, gb_state );
else
gbSoundReadGameOld( version, in );
if (version > 11)
utilReadData(in, gb_state);
else
gbSoundReadGameOld(version, in);
gb_apu->load_state( state.apu );
gb_apu->load_state(state.apu);
}

View File

@ -16,15 +16,15 @@ bool gbSoundGetDeclicking();
// Effects configuration
struct gb_effects_config_t {
bool enabled; // false = disable all effects
bool enabled; // false = disable all effects
float echo; // 0.0 = none, 1.0 = lots
float stereo; // 0.0 = channels in center, 1.0 = channels on left/right
bool surround; // true = put some channels in back
float echo; // 0.0 = none, 1.0 = lots
float stereo; // 0.0 = channels in center, 1.0 = channels on left/right
bool surround; // true = put some channels in back
};
// 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
//// GB sound emulation
@ -65,7 +65,7 @@ u8 gbSoundRead(u16 address);
// Notifies emulator that SOUND_CLOCK_TICKS clocks have passed
void gbSoundTick();
extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to gbSoundTick()
extern int soundTicks; // Number of 16.8 MHz clocks until gbSoundTick() will be called
extern int soundTicks; // Number of 16.8 MHz clocks until gbSoundTick() will be called
// Saves/loads emulator state
void gbSoundSaveGame(gzFile out);