Esempio n. 1
0
void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
	struct GBMemory* memory = &gb->memory;
	int bank = value & 0xF;
	switch (address >> 13) {
	case 0x0:
		switch (value) {
		case 0:
			memory->sramAccess = false;
			break;
		case 0xA:
			memory->sramAccess = true;
			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
			break;
		default:
			// TODO
			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
			break;
		}
		break;
	case 0x1:
		if (!bank) {
			++bank;
		}
		GBMBCSwitchBank(gb, bank);
		break;
	default:
		// TODO
		mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
		break;
	}}
Esempio n. 2
0
bool GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) {
	if (!SOCKET_FAILED(stub->socket)) {
		GDBStubShutdown(stub);
	}
	stub->socket = SocketOpenTCP(port, bindAddress);
	if (SOCKET_FAILED(stub->socket)) {
		mLOG(DEBUGGER, ERROR, "Couldn't open socket");
		return false;
	}
	if (!SocketSetBlocking(stub->socket, false)) {
		goto cleanup;
	}
	int err = SocketListen(stub->socket, 1);
	if (err) {
		goto cleanup;
	}

	return true;

cleanup:
	mLOG(DEBUGGER, ERROR, "Couldn't listen on port");
	SocketClose(stub->socket);
	stub->socket = INVALID_SOCKET;
	return false;
}
Esempio n. 3
0
File: core.c Progetto: Bizcocho/mgba
void mCoreTakeScreenshot(struct mCore* core) {
#ifdef USE_PNG
	size_t stride;
	color_t* pixels = 0;
	unsigned width, height;
	core->desiredVideoDimensions(core, &width, &height);
	struct VFile* vf = VDirFindNextAvailable(core->dirs.screenshot, core->dirs.baseName, "-", ".png", O_CREAT | O_TRUNC | O_WRONLY);
	bool success = false;
	if (vf) {
		core->getVideoBuffer(core, &pixels, &stride);
		png_structp png = PNGWriteOpen(vf);
		png_infop info = PNGWriteHeader(png, width, height);
		success = PNGWritePixels(png, width, height, stride, pixels);
		PNGWriteClose(png, info);
		vf->close(vf);
	}
	if (success) {
		mLOG(STATUS, INFO, "Screenshot saved");
		return;
	}
#else
	UNUSED(core);
#endif
	mLOG(STATUS, WARN, "Failed to take screenshot");
}
Esempio n. 4
0
void GDBStubUpdate(struct GDBStub* stub) {
	if (stub->socket == INVALID_SOCKET) {
		if (stub->d.state == DEBUGGER_PAUSED) {
			stub->d.state = DEBUGGER_RUNNING;
		}
		return;
	}
	if (stub->connection == INVALID_SOCKET) {
		if (stub->shouldBlock) {
			Socket reads = stub->socket;
			SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
		}
		stub->connection = SocketAccept(stub->socket, 0);
		if (!SOCKET_FAILED(stub->connection)) {
			if (!SocketSetBlocking(stub->connection, false)) {
				goto connectionLost;
			}
			mDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0);
		} else if (SocketWouldBlock()) {
			return;
		} else {
			goto connectionLost;
		}
	}
	while (true) {
		if (stub->shouldBlock) {
			Socket reads = stub->connection;
			SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
		}
		ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
		if (messageLen == 0) {
			goto connectionLost;
		}
		if (messageLen == -1) {
			if (SocketWouldBlock()) {
				return;
			}
			goto connectionLost;
		}
		stub->line[messageLen] = '\0';
		mLOG(DEBUGGER, DEBUG, "< %s", stub->line);
		ssize_t position = 0;
		while (position < messageLen) {
			position += _parseGDBMessage(stub, &stub->line[position]);
		}
	}

connectionLost:
	mLOG(DEBUGGER, WARN, "Connection lost");
	GDBStubHangup(stub);
}
Esempio n. 5
0
bool mSDLInitAudio(struct mSDLAudio* context, struct mCoreThread* threadContext) {
	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
		mLOG(SDL_AUDIO, ERROR, "Could not initialize SDL sound system: %s", SDL_GetError());
		return false;
	}

	context->desiredSpec.freq = context->sampleRate;
	context->desiredSpec.format = AUDIO_S16SYS;
	context->desiredSpec.channels = 2;
	context->desiredSpec.samples = context->samples;
	context->desiredSpec.callback = _mSDLAudioCallback;
	context->desiredSpec.userdata = context;

#if SDL_VERSION_ATLEAST(2, 0, 0)
	context->deviceId = SDL_OpenAudioDevice(0, 0, &context->desiredSpec, &context->obtainedSpec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
	if (context->deviceId == 0) {
#else
	if (SDL_OpenAudio(&context->desiredSpec, &context->obtainedSpec) < 0) {
#endif
		mLOG(SDL_AUDIO, ERROR, "Could not open SDL sound system");
		return false;
	}
	context->core = 0;

	if (threadContext) {
		context->core = threadContext->core;
		context->sync = &threadContext->impl->sync;

#if SDL_VERSION_ATLEAST(2, 0, 0)
		SDL_PauseAudioDevice(context->deviceId, 0);
#else
		SDL_PauseAudio(0);
#endif
	}

	return true;
}

void mSDLDeinitAudio(struct mSDLAudio* context) {
	UNUSED(context);
#if SDL_VERSION_ATLEAST(2, 0, 0)
	SDL_PauseAudioDevice(context->deviceId, 1);
	SDL_CloseAudioDevice(context->deviceId);
#else
	SDL_PauseAudio(1);
	SDL_CloseAudio();
#endif
	SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
Esempio n. 6
0
bool mCoreLoadState(struct mCore* core, int slot, int flags) {
	struct VFile* vf = mCoreGetState(core, slot, false);
	if (!vf) {
		return false;
	}
	bool success = mCoreLoadStateNamed(core, vf, flags);
	vf->close(vf);
	if (success) {
		mLOG(STATUS, INFO, "State %i loaded", slot);
	} else {
		mLOG(STATUS, INFO, "State %i failed to loaded", slot);
	}

	return success;
}
Esempio n. 7
0
static void _sendMessage(struct GDBStub* stub) {
	if (stub->lineAck != GDB_ACK_OFF) {
		stub->lineAck = GDB_ACK_PENDING;
	}
	uint8_t checksum = 0;
	int i = 1;
	char buffer = stub->outgoing[0];
	char swap;
	stub->outgoing[0] = '$';
	if (buffer) {
		for (; i < GDB_STUB_MAX_LINE - 5; ++i) {
			checksum += buffer;
			swap = stub->outgoing[i];
			stub->outgoing[i] = buffer;
			buffer = swap;
			if (!buffer) {
				++i;
				break;
			}
		}
	}
	stub->outgoing[i] = '#';
	_int2hex8(checksum, &stub->outgoing[i + 1]);
	stub->outgoing[i + 3] = 0;
	mLOG(DEBUGGER, DEBUG, "> %s", stub->outgoing);
	SocketSend(stub->connection, stub->outgoing, i + 3);
}
Esempio n. 8
0
void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
	switch (address) {
	case GPIO_REG_DATA:
		hw->pinState &= ~hw->direction;
		hw->pinState |= value;
		_readPins(hw);
		break;
	case GPIO_REG_DIRECTION:
		hw->direction = value;
		break;
	case GPIO_REG_CONTROL:
		hw->readWrite = value;
		break;
	default:
		mLOG(GBA_HW, WARN, "Invalid GPIO address");
	}
	if (hw->readWrite) {
		uint16_t old;
		LOAD_16(old, 0, hw->gpioBase);
		old &= ~hw->direction;
		old |= hw->pinState;
		STORE_16(old, 0, hw->gpioBase);
	} else {
		hw->gpioBase[0] = 0;
	}
}
Esempio n. 9
0
uint8_t GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
	gb->memory.hdmaSource = gb->memory.io[REG_HDMA1] << 8;
	gb->memory.hdmaSource |= gb->memory.io[REG_HDMA2];
	gb->memory.hdmaDest = gb->memory.io[REG_HDMA3] << 8;
	gb->memory.hdmaDest |= gb->memory.io[REG_HDMA4];
	gb->memory.hdmaSource &= 0xFFF0;
	if (gb->memory.hdmaSource >= 0x8000 && gb->memory.hdmaSource < 0xA000) {
		mLOG(GB_MEM, GAME_ERROR, "Invalid HDMA source: %04X", gb->memory.hdmaSource);
		return value | 0x80;
	}
	gb->memory.hdmaDest &= 0x1FF0;
	gb->memory.hdmaDest |= 0x8000;
	bool wasHdma = gb->memory.isHdma;
	gb->memory.isHdma = value & 0x80;
	if ((!wasHdma && !gb->memory.isHdma) || gb->video.mode == 0) {
		if (gb->memory.isHdma) {
			gb->memory.hdmaRemaining = 0x10;
		} else {
			gb->memory.hdmaRemaining = ((value & 0x7F) + 1) * 0x10;
		}
		gb->cpuBlocked = true;
		mTimingSchedule(&gb->timing, &gb->memory.hdmaEvent, 0);
	} else if (gb->memory.isHdma && !GBRegisterLCDCIsEnable(gb->memory.io[REG_LCDC])) {
		return 0x80 | ((value + 1) & 0x7F);
	}
	return value & 0x7F;
}
Esempio n. 10
0
File: mgm.c Progetto: Bizcocho/mgba
uint16_t GBAMGMQueryInput(struct GBARRContext* rr) {
	if (!rr->isPlaying(rr)) {
		return 0;
	}

	struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
	if (mgm->peekedTag == TAG_INPUT) {
		_readTag(mgm, mgm->movieStream);
	}
	mgm->inputThisFrame = true;
	if (mgm->currentInput == INVALID_INPUT) {
		mLOG(GBA_RR, WARN, "Stream did not specify input");
	}
	mLOG(GBA_RR, DEBUG, "Input replay: %03X", mgm->currentInput);
	return mgm->currentInput;
}
Esempio n. 11
0
void GBASavedataInitEEPROM(struct GBASavedata* savedata) {
	if (savedata->type == SAVEDATA_AUTODETECT) {
		savedata->type = SAVEDATA_EEPROM512;
	} else if (savedata->type != SAVEDATA_EEPROM512 && savedata->type != SAVEDATA_EEPROM) {
		mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
		return;
	}
	int32_t eepromSize = SIZE_CART_EEPROM512;
	if (savedata->type == SAVEDATA_EEPROM) {
		eepromSize = SIZE_CART_EEPROM;
	}
	off_t end;
	if (!savedata->vf) {
		end = 0;
		savedata->data = anonymousMemoryMap(SIZE_CART_EEPROM);
	} else {
		end = savedata->vf->size(savedata->vf);
		if (end < eepromSize) {
			savedata->vf->truncate(savedata->vf, eepromSize);
		} else if (end >= SIZE_CART_EEPROM) {
			eepromSize = SIZE_CART_EEPROM;
			savedata->type = SAVEDATA_EEPROM;
		}
		savedata->data = savedata->vf->map(savedata->vf, eepromSize, savedata->mapMode);
	}
	if (end < SIZE_CART_EEPROM512) {
		memset(&savedata->data[end], 0xFF, SIZE_CART_EEPROM512 - end);
	}
}
Esempio n. 12
0
File: mgm.c Progetto: Bizcocho/mgba
bool _loadStream(struct GBAMGMContext* mgm, uint32_t streamId) {
	if (mgm->movieStream && !mgm->movieStream->close(mgm->movieStream)) {
		return false;
	}
	mgm->movieStream = 0;
	mgm->streamId = streamId;
	mgm->currentInput = INVALID_INPUT;
	char buffer[14];
	snprintf(buffer, sizeof(buffer), "%u" BINARY_EXT, streamId);
	if (mgm->d.isRecording(&mgm->d)) {
		int flags = O_CREAT | O_RDWR;
		if (streamId > mgm->maxStreamId) {
			flags |= O_TRUNC;
		}
		mgm->movieStream = mgm->streamDir->openFile(mgm->streamDir, buffer, flags);
	} else if (mgm->d.isPlaying(&mgm->d)) {
		mgm->movieStream = mgm->streamDir->openFile(mgm->streamDir, buffer, O_RDONLY);
		mgm->peekedTag = TAG_INVALID;
		if (!mgm->movieStream || !_verifyMagic(mgm, mgm->movieStream) || !_seekTag(mgm, mgm->movieStream, TAG_BEGIN)) {
			mgm->d.stopPlaying(&mgm->d);
		}
	}
	mLOG(GBA_RR, DEBUG, "Loading segment: %u", streamId);
	mgm->d.frames = 0;
	mgm->d.lagFrames = 0;
	return true;
}
Esempio n. 13
0
void GBASavedataInitFlash(struct GBASavedata* savedata) {
	if (savedata->type == SAVEDATA_AUTODETECT) {
		savedata->type = SAVEDATA_FLASH512;
	}
	if (savedata->type != SAVEDATA_FLASH512 && savedata->type != SAVEDATA_FLASH1M) {
		mLOG(GBA_SAVE, WARN, "Can't re-initialize savedata");
		return;
	}
	int32_t flashSize = SIZE_CART_FLASH512;
	if (savedata->type == SAVEDATA_FLASH1M) {
		flashSize = SIZE_CART_FLASH1M;
	}
	off_t end;
	if (!savedata->vf) {
		end = 0;
		savedata->data = anonymousMemoryMap(SIZE_CART_FLASH1M);
	} else {
		end = savedata->vf->size(savedata->vf);
		if (end < flashSize) {
			savedata->vf->truncate(savedata->vf, flashSize);
		} else if (end >= SIZE_CART_FLASH1M) {
			flashSize = SIZE_CART_FLASH1M;
			savedata->type = SAVEDATA_FLASH1M;
		}
		savedata->data = savedata->vf->map(savedata->vf, flashSize, savedata->mapMode);
	}

	savedata->currentBank = savedata->data;
	if (end < SIZE_CART_FLASH512) {
		memset(&savedata->data[end], 0xFF, flashSize - end);
	}
}
Esempio n. 14
0
static void _GBMBCNone(struct GB* gb, uint16_t address, uint8_t value) {
	UNUSED(gb);
	UNUSED(address);
	UNUSED(value);

	mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
}
Esempio n. 15
0
void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
	struct GBMemory* memory = &gb->memory;
	int bank = value & 0x1F;
	switch (address >> 13) {
	case 0x0:
		switch (value) {
		case 0:
			memory->sramAccess = false;
			break;
		case 0xA:
			memory->sramAccess = true;
			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
			break;
		default:
			// TODO
			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
			break;
		}
		break;
	case 0x1:
		if (!bank) {
			++bank;
		}
		GBMBCSwitchBank(gb, bank | (memory->currentBank & 0x60));
		break;
	case 0x2:
		bank &= 3;
		if (!memory->mbcState.mbc1.mode) {
			GBMBCSwitchBank(gb, (bank << 5) | (memory->currentBank & 0x1F));
		} else {
			GBMBCSwitchSramBank(gb, bank);
		}
		break;
	case 0x3:
		memory->mbcState.mbc1.mode = value & 1;
		if (memory->mbcState.mbc1.mode) {
			GBMBCSwitchBank(gb, memory->currentBank & 0x1F);
		} else {
			GBMBCSwitchSramBank(gb, 0);
		}
		break;
	default:
		// TODO
		mLOG(GB_MBC, STUB, "MBC1 unknown address: %04X:%02X", address, value);
		break;
	}
}
Esempio n. 16
0
void GBResizeSram(struct GB* gb, size_t size) {
	if (gb->memory.sram && size <= gb->sramSize) {
		return;
	}
	mLOG(GB, INFO, "Resizing SRAM to %"PRIz"u bytes", size);
	struct VFile* vf = gb->sramVf;
	if (vf) {
		if (vf == gb->sramRealVf) {
			ssize_t vfSize = vf->size(vf);
			if (vfSize >= 0 && (size_t) vfSize < size) {
				uint8_t extdataBuffer[0x100];
				if (vfSize & 0xFF) {
					vf->seek(vf, -(vfSize & 0xFF), SEEK_END);
					vf->read(vf, extdataBuffer, vfSize & 0xFF);
				}
				if (gb->memory.sram) {
					vf->unmap(vf, gb->memory.sram, gb->sramSize);
				}
				vf->truncate(vf, size + (vfSize & 0xFF));
				if (vfSize & 0xFF) {
					vf->seek(vf, size, SEEK_SET);
					vf->write(vf, extdataBuffer, vfSize & 0xFF);
				}
				gb->memory.sram = vf->map(vf, size, MAP_WRITE);
				memset(&gb->memory.sram[gb->sramSize], 0xFF, size - gb->sramSize);
			} else if (size > gb->sramSize || !gb->memory.sram) {
				if (gb->memory.sram) {
					vf->unmap(vf, gb->memory.sram, gb->sramSize);
				}
				gb->memory.sram = vf->map(vf, size, MAP_WRITE);
			}
		} else {
			if (gb->memory.sram) {
				vf->unmap(vf, gb->memory.sram, gb->sramSize);
			}
			gb->memory.sram = vf->map(vf, size, MAP_READ);
		}
		if (gb->memory.sram == (void*) -1) {
			gb->memory.sram = NULL;
		}
	} else {
		uint8_t* newSram = anonymousMemoryMap(size);
		if (gb->memory.sram) {
			if (size > gb->sramSize) {
				memcpy(newSram, gb->memory.sram, gb->sramSize);
				memset(&newSram[gb->sramSize], 0xFF, size - gb->sramSize);
			} else {
				memcpy(newSram, gb->memory.sram, size);
			}
			mappedMemoryFree(gb->memory.sram, gb->sramSize);
		} else {
			memset(newSram, 0xFF, size);
		}
		gb->memory.sram = newSram;
	}
	if (gb->sramSize < size) {
		gb->sramSize = size;
	}
}
Esempio n. 17
0
uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
	struct GB* gb = (struct GB*) cpu->master;
	struct GBMemory* memory = &gb->memory;
	switch (address >> 12) {
	case GB_REGION_CART_BANK0:
	case GB_REGION_CART_BANK0 + 1:
	case GB_REGION_CART_BANK0 + 2:
	case GB_REGION_CART_BANK0 + 3:
		return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
	case GB_REGION_CART_BANK1:
	case GB_REGION_CART_BANK1 + 1:
	case GB_REGION_CART_BANK1 + 2:
	case GB_REGION_CART_BANK1 + 3:
		return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
	case GB_REGION_VRAM:
	case GB_REGION_VRAM + 1:
		return gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)];
	case GB_REGION_EXTERNAL_RAM:
	case GB_REGION_EXTERNAL_RAM + 1:
		if (memory->rtcAccess) {
			return memory->rtcRegs[memory->activeRtcReg];
		} else if (memory->sramAccess) {
			return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
		} else if (memory->mbcType == GB_MBC7) {
			return GBMBC7Read(memory, address);
		} else if (memory->mbcType == GB_HuC3) {
			return 0x01; // TODO: Is this supposed to be the current SRAM bank?
		}
		return 0xFF;
	case GB_REGION_WORKING_RAM_BANK0:
	case GB_REGION_WORKING_RAM_BANK0 + 2:
		return memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
	case GB_REGION_WORKING_RAM_BANK1:
		return memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
	default:
		if (address < GB_BASE_OAM) {
			return memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
		}
		if (address < GB_BASE_UNUSABLE) {
			if (gb->video.mode < 2) {
				return gb->video.oam.raw[address & 0xFF];
			}
			return 0xFF;
		}
		if (address < GB_BASE_IO) {
			mLOG(GB_MEM, GAME_ERROR, "Attempt to read from unusable memory: %04X", address);
			return 0xFF;
		}
		if (address < GB_BASE_HRAM) {
			return GBIORead(gb, address & (GB_SIZE_IO - 1));
		}
		if (address < GB_BASE_IE) {
			return memory->hram[address & GB_SIZE_HRAM];
		}
		return GBIORead(gb, REG_IE);
	}
}
Esempio n. 18
0
//============================================================================//
int
main()
{

    EC_OS       g_os;
    EC_WIDGET   g_wdgt;
    EC_RENDER   g_render;
    mLOG("Starting");
    g_wdgt.fOnInit(L"VSGE");
    g_wdgt.fRectSet(200, 200, 1024, 768);
    g_wdgt.fWdgtCreate(false);
    g_wdgt.fWdgtShow();
    EC_RENDER::INIT_STRUCT ini_str;

    ini_str.wdgt = g_wdgt.fHandlerGet();
    ini_str.bb_size.fClear();

    ES_DRAW_DATA draw_data;
    draw_data.fOnInitIndexedQuad( -1024/2,-768/2, 1024, 768, false, true, false);

    draw_data.fVertexColorSet(0,    ECOLOR_BLUE);
    draw_data.fVertexColorSet(1,    ECOLOR_BLUE);
    draw_data.fVertexColorSet(2,    ECOLOR_BLUE);
    draw_data.fVertexColorSet(3,    ECOLOR_BLUE);

    ES_DRAW_DATA    ano_data;
    ano_data.fOnInitIndexedQuad(0,0,2,2,false,false,false);

    ES_DRAW_OPTIONS draw_opt;
    draw_opt.fClear();
    draw_opt.fDiffuseSet(true);


    g_render.fOnInit(&ini_str);
    g_render.fEyeSet(0,0,1000,0,1,0,0,0,0);
    g_render.fProjectionPerspectiveSet(1024,768);

    static int clcl = 0;
    while(true)
    {//1
        g_os.fOnUpdate();

        g_render.fFrameClear(true, clcl,false,0,false ,0);
        if(EDONE == g_render.fFrameLock())
        {//1
            g_render.fDraw(&draw_data,  &draw_opt);
            g_render.fDraw(&ano_data,   &draw_opt);
            g_render.fFrameUnlock();
        }//1
        g_render.fFramePresent();
        clcl++;
    }//1



    return EAPPNOERROR;
}
Esempio n. 19
0
void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode) {
	struct GBASIODriver** driverLoc;
	switch (mode) {
	case SIO_NORMAL_8:
	case SIO_NORMAL_32:
		driverLoc = &sio->drivers.normal;
		break;
	case SIO_MULTI:
		driverLoc = &sio->drivers.multiplayer;
		break;
	case SIO_JOYBUS:
		driverLoc = &sio->drivers.joybus;
		break;
	default:
		mLOG(GBA_SIO, ERROR, "Setting an unsupported SIO driver: %x", mode);
		return;
	}
	if (*driverLoc) {
		if ((*driverLoc)->unload) {
			(*driverLoc)->unload(*driverLoc);
		}
		if ((*driverLoc)->deinit) {
			(*driverLoc)->deinit(*driverLoc);
		}
	}
	if (driver) {
		driver->p = sio;

		if (driver->init) {
			if (!driver->init(driver)) {
				driver->deinit(driver);
				mLOG(GBA_SIO, ERROR, "Could not initialize SIO driver");
				return;
			}
		}
		if (sio->mode == mode) {
			sio->activeDriver = driver;
			if (driver->load) {
				driver->load(driver);
			}
		}
	}
	*driverLoc = driver;
}
Esempio n. 20
0
void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
	struct GB* gb = (struct GB*) cpu->master;
	struct GBMemory* memory = &gb->memory;
	switch (address >> 12) {
	case GB_REGION_CART_BANK0:
	case GB_REGION_CART_BANK0 + 1:
	case GB_REGION_CART_BANK0 + 2:
	case GB_REGION_CART_BANK0 + 3:
	case GB_REGION_CART_BANK1:
	case GB_REGION_CART_BANK1 + 1:
	case GB_REGION_CART_BANK1 + 2:
	case GB_REGION_CART_BANK1 + 3:
		memory->mbc(gb, address, value);
		cpu->memory.setActiveRegion(cpu, cpu->pc);
		return;
	case GB_REGION_VRAM:
	case GB_REGION_VRAM + 1:
		gb->video.renderer->writeVRAM(gb->video.renderer, (address & (GB_SIZE_VRAM_BANK0 - 1)) | (GB_SIZE_VRAM_BANK0 * gb->video.vramCurrentBank));
		gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value;
		return;
	case GB_REGION_EXTERNAL_RAM:
	case GB_REGION_EXTERNAL_RAM + 1:
		if (memory->rtcAccess) {
			memory->rtcRegs[memory->activeRtcReg] = value;
		} else if (memory->sramAccess) {
			memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value;
		} else if (memory->mbcType == GB_MBC7) {
			GBMBC7Write(memory, address, value);
		}
		gb->sramDirty |= GB_SRAM_DIRT_NEW;
		return;
	case GB_REGION_WORKING_RAM_BANK0:
	case GB_REGION_WORKING_RAM_BANK0 + 2:
		memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
		return;
	case GB_REGION_WORKING_RAM_BANK1:
		memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
		return;
	default:
		if (address < GB_BASE_OAM) {
			memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
		} else if (address < GB_BASE_UNUSABLE) {
			if (gb->video.mode < 2) {
				gb->video.oam.raw[address & 0xFF] = value;
			}
		} else if (address < GB_BASE_IO) {
			mLOG(GB_MEM, GAME_ERROR, "Attempt to write to unusable memory: %04X:%02X", address, value);
		} else if (address < GB_BASE_HRAM) {
			GBIOWrite(gb, address & (GB_SIZE_IO - 1), value);
		} else if (address < GB_BASE_IE) {
			memory->hram[address & GB_SIZE_HRAM] = value;
		} else {
			GBIOWrite(gb, REG_IE, value);
		}
	}
}
Esempio n. 21
0
void mCoreTakeScreenshot(struct mCore* core) {
#ifdef USE_PNG
	size_t stride;
	const void* pixels = 0;
	unsigned width, height;
	core->desiredVideoDimensions(core, &width, &height);
	struct VFile* vf;
#ifndef PSP2
	vf = VDirFindNextAvailable(core->dirs.screenshot, core->dirs.baseName, "-", ".png", O_CREAT | O_TRUNC | O_WRONLY);
#else
	vf = VFileMemChunk(0, 0);
#endif
	bool success = false;
	if (vf) {
		core->getPixels(core, &pixels, &stride);
		png_structp png = PNGWriteOpen(vf);
		png_infop info = PNGWriteHeader(png, width, height);
		success = PNGWritePixels(png, width, height, stride, pixels);
		PNGWriteClose(png, info);
#ifdef PSP2
		void* data = vf->map(vf, 0, 0);
		PhotoExportParam param = {
			0,
			NULL,
			NULL,
			NULL,
			{ 0 }
		};
		scePhotoExportFromData(data, vf->size(vf), &param, NULL, NULL, NULL, NULL, 0);
#endif
		vf->close(vf);
	}
	if (success) {
		mLOG(STATUS, INFO, "Screenshot saved");
		return;
	}
#else
	UNUSED(core);
#endif
	mLOG(STATUS, WARN, "Failed to take screenshot");
}
Esempio n. 22
0
void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) {
	struct GBMemory* memory = &gb->memory;
	int bank;
	switch (address >> 12) {
	case 0x0:
	case 0x1:
		switch (value) {
		case 0:
			memory->sramAccess = false;
			break;
		case 0xA:
			memory->sramAccess = true;
			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
			break;
		default:
			// TODO
			mLOG(GB_MBC, STUB, "MBC5 unknown value %02X", value);
			break;
		}
		break;
	case 0x2:
		bank = (memory->currentBank & 0x100) | value;
		GBMBCSwitchBank(gb, bank);
		break;
	case 0x3:
		bank = (memory->currentBank & 0xFF) | ((value & 1) << 8);
		GBMBCSwitchBank(gb, bank);
		break;
	case 0x4:
	case 0x5:
		if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) {
			memory->rumble->setRumble(memory->rumble, (value >> 3) & 1);
			value &= ~8;
		}
		GBMBCSwitchSramBank(gb, value & 0xF);
		break;
	default:
		// TODO
		mLOG(GB_MBC, STUB, "MBC5 unknown address: %04X:%02X", address, value);
		break;
	}
Esempio n. 23
0
File: mgm.c Progetto: Bizcocho/mgba
void GBAMGMNextFrame(struct GBARRContext* rr) {
	if (!rr->isRecording(rr) && !rr->isPlaying(rr)) {
		return;
	}

	struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
	if (rr->isPlaying(rr)) {
		while (mgm->peekedTag == TAG_INPUT) {
			_readTag(mgm, mgm->movieStream);
			mLOG(GBA_RR, WARN, "Desync detected!");
		}
		if (mgm->peekedTag == TAG_LAG) {
			mLOG(GBA_RR, DEBUG, "Lag frame marked in stream");
			if (mgm->inputThisFrame) {
				mLOG(GBA_RR, WARN, "Lag frame in stream does not match movie");
			}
		}
	}

	++mgm->d.frames;
	mLOG(GBA_RR, DEBUG, "Frame: %u", mgm->d.frames);
	if (!mgm->inputThisFrame) {
		++mgm->d.lagFrames;
		mLOG(GBA_RR, DEBUG, "Lag frame: %u", mgm->d.lagFrames);
	}

	if (rr->isRecording(rr)) {
		if (!mgm->inputThisFrame) {
			_emitTag(mgm, mgm->movieStream, TAG_LAG);
		}
		_emitTag(mgm, mgm->movieStream, TAG_FRAME);
		mgm->inputThisFrame = false;
	} else {
		if (!_seekTag(mgm, mgm->movieStream, TAG_FRAME)) {
			_streamEndReached(mgm);
		}
	}
}
Esempio n. 24
0
void GBSramClean(struct GB* gb, uint32_t frameCount) {
	// TODO: Share with GBASavedataClean
	if (!gb->sramVf) {
		return;
	}
	if (gb->sramDirty & GB_SRAM_DIRT_NEW) {
		gb->sramDirtAge = frameCount;
		gb->sramDirty &= ~GB_SRAM_DIRT_NEW;
		if (!(gb->sramDirty & GB_SRAM_DIRT_SEEN)) {
			gb->sramDirty |= GB_SRAM_DIRT_SEEN;
		}
	} else if ((gb->sramDirty & GB_SRAM_DIRT_SEEN) && frameCount - gb->sramDirtAge > CLEANUP_THRESHOLD) {
		if (gb->memory.mbcType == GB_MBC3_RTC) {
			GBMBCRTCWrite(gb);
		}
		gb->sramDirty = 0;
		if (gb->memory.sram && gb->sramVf->sync(gb->sramVf, gb->memory.sram, gb->sramSize)) {
			mLOG(GB_MEM, INFO, "Savedata synced");
		} else {
			mLOG(GB_MEM, INFO, "Savedata failed to sync!");
		}
	}
}
Esempio n. 25
0
File: mgm.c Progetto: Bizcocho/mgba
void GBAMGMLogInput(struct GBARRContext* rr, uint16_t keys) {
	if (!rr->isRecording(rr)) {
		return;
	}

	struct GBAMGMContext* mgm = (struct GBAMGMContext*) rr;
	if (keys != mgm->currentInput) {
		_emitTag(mgm, mgm->movieStream, TAG_INPUT);
		mgm->movieStream->write(mgm->movieStream, &keys, sizeof(keys));
		mgm->currentInput = keys;
	}
	mLOG(GBA_RR, DEBUG, "Input log: %03X", mgm->currentInput);
	mgm->inputThisFrame = true;
}
Esempio n. 26
0
void GBMBCSwitchBank(struct GB* gb, int bank) {
	size_t bankStart = bank * GB_SIZE_CART_BANK0;
	if (bankStart + GB_SIZE_CART_BANK0 > gb->memory.romSize) {
		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
		bankStart &= (gb->memory.romSize - 1);
		bank = bankStart / GB_SIZE_CART_BANK0;
		if (!bank) {
			++bank;
		}
	}
	gb->memory.romBank = &gb->memory.rom[bankStart];
	gb->memory.currentBank = bank;
	if (gb->cpu->pc < GB_BASE_VRAM) {
		gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
	}
}
Esempio n. 27
0
bool GBSIOLockstepNodeInit(struct GBSIODriver* driver) {
	struct GBSIOLockstepNode* node = (struct GBSIOLockstepNode*) driver;
	mLOG(GB_SIO, DEBUG, "Lockstep %i: Node init", node->id);
	node->event.context = node;
	node->event.name = "GB SIO Lockstep";
	node->event.callback = _GBSIOLockstepNodeProcessEvents;
	node->event.priority = 0x80;

	node->nextEvent = 0;
	node->eventDiff = 0;
	mTimingSchedule(&driver->p->p->timing, &node->event, 0);
#ifndef NDEBUG
	node->phase = node->p->d.transferActive;
	node->transferId = node->p->d.transferId;
#endif
	return true;
}
Esempio n. 28
0
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
	struct GBMemory* memory = &gb->memory;
	int bank = value & 0x7F;
	switch (address >> 13) {
	case 0x0:
		switch (value) {
		case 0:
			memory->sramAccess = false;
			break;
		case 0xA:
			memory->sramAccess = true;
			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
			break;
		default:
			// TODO
			mLOG(GB_MBC, STUB, "MBC3 unknown value %02X", value);
			break;
		}
		break;
	case 0x1:
		if (!bank) {
			++bank;
		}
		GBMBCSwitchBank(gb, bank);
		break;
	case 0x2:
		if (value < 4) {
			GBMBCSwitchSramBank(gb, value);
			memory->rtcAccess = false;
		} else if (value >= 8 && value <= 0xC) {
			memory->activeRtcReg = value - 8;
			memory->rtcAccess = true;
		}
		break;
	case 0x3:
		if (memory->rtcLatched && value == 0) {
			memory->rtcLatched = false;
		} else if (!memory->rtcLatched && value == 1) {
			_latchRtc(gb->memory.rtc, gb->memory.rtcRegs, &gb->memory.rtcLastLatch);
			memory->rtcLatched = true;
		}
		break;
	}
}
Esempio n. 29
0
void GBVideoProcessDots(struct GBVideo* video) {
	if (video->mode != 3 || video->dotCounter < 0) {
		return;
	}
	int oldX = video->x;
	video->x = video->dotCounter + video->eventDiff + (video->p->cpu->cycles >> video->p->doubleSpeed);
	if (video->x > GB_VIDEO_HORIZONTAL_PIXELS) {
		video->x = GB_VIDEO_HORIZONTAL_PIXELS;
	} else if (video->x < 0) {
		mLOG(GB, FATAL, "Video dot clock went negative!");
		video->x = oldX;
	}
	if (video->x == GB_VIDEO_HORIZONTAL_PIXELS) {
		video->dotCounter = INT_MIN;
	}
	if (video->frameskipCounter <= 0) {
		video->renderer->drawRange(video->renderer, oldX, video->x, video->ly, video->objThisLine, video->objMax);
	}
}
Esempio n. 30
0
void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
	gb->memory.hdmaSource = gb->memory.io[REG_HDMA1] << 8;
	gb->memory.hdmaSource |= gb->memory.io[REG_HDMA2];
	gb->memory.hdmaDest = gb->memory.io[REG_HDMA3] << 8;
	gb->memory.hdmaDest |= gb->memory.io[REG_HDMA4];
	gb->memory.hdmaSource &= 0xFFF0;
	if (gb->memory.hdmaSource >= 0x8000 && gb->memory.hdmaSource < 0xA000) {
		mLOG(GB_MEM, GAME_ERROR, "Invalid HDMA source: %04X", gb->memory.hdmaSource);
		return;
	}
	gb->memory.hdmaDest &= 0x1FF0;
	gb->memory.hdmaDest |= 0x8000;
	bool wasHdma = gb->memory.isHdma;
	gb->memory.isHdma = value & 0x80;
	if (!wasHdma && !gb->memory.isHdma) {
		gb->memory.hdmaRemaining = ((value & 0x7F) + 1) * 0x10;
		gb->memory.hdmaNext = gb->cpu->cycles;
		gb->cpu->nextEvent = gb->cpu->cycles;
	}
}