some more formating things etc
This commit is contained in:
parent
a49edee427
commit
48086ba62f
9573
src/gb/GB.cpp
9573
src/gb/GB.cpp
File diff suppressed because it is too large
Load Diff
38
src/gb/gb.h
38
src/gb/gb.h
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
365
src/gb/gbCodes.h
365
src/gb/gbCodes.h
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
384
src/gb/gbDis.cpp
384
src/gb/gbDis.cpp
|
@ -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;
|
||||
}
|
||||
|
|
997
src/gb/gbGfx.cpp
997
src/gb/gbGfx.cpp
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
2714
src/gb/gbMemory.cpp
2714
src/gb/gbMemory.cpp
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
1335
src/gb/gbSGB.cpp
1335
src/gb/gbSGB.cpp
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue