NESEmulator/NES Emulator/mappers/mapper001.c
2021-10-31 02:02:31 +02:00

176 lines
4.3 KiB
C

#include "mapper001.h"
struct Mapper001* createMapper001(Byte prg_rom_size, Byte chr_rom_size, FILE* fp)
{
struct Mapper001* mapper = (struct Mapper001*)malloc(sizeof(struct Mapper001));
if (mapper == NULL)
{
fprintf(stderr, "Failed to create Mapper 000. Aborting\n");
exit(-1);
}
mapper->prg_rom_size = prg_rom_size;
mapper->prg_rom = (Byte*)calloc(prg_rom_size, 0x4000);
if (mapper->prg_rom == NULL)
{
fprintf(stderr, "Failed to allocate cartridge PRG ROM. Aborting\n");
exit(-1);
}
mapper->chr_rom_size = chr_rom_size;
mapper->chr_rom = (Byte*)calloc(chr_rom_size, 0x2000);
if (mapper->chr_rom == NULL)
{
fprintf(stderr, "Failed to allocate cartridge CHR ROM. Aborting\n");
exit(-1);
}
fread(mapper->prg_rom, 0x4000, prg_rom_size, fp);
fread(mapper->chr_rom, 0x2000, chr_rom_size, fp);
mapper->lowerChrBank = mapper->chr_rom;
mapper->upperChrBank = mapper->chr_rom + 0x1000;
mapper->lowerPrgBank = mapper->prg_rom;
mapper->upperPrgBank = mapper->prg_rom + 0x4000;
return mapper;
}
void destroyMapper001(struct Mapper001* mapper)
{
free(mapper->chr_rom);
free(mapper->prg_rom);
free(mapper);
}
Byte Mapper001_ReadCPU(void* mapper, Word address)
{
struct Mapper001* sMapper = (struct Mapper000*)mapper;
Byte val = 0x00;
if (address >= 0x6000 && address < 0x8000)
{
fprintf(stderr, "This Mapper 000 implementation doesnt support FamilyBasic PRG RAM\n");
exit(-1);
}
else if (address >= 0x8000 && address <= 0xBFFF)
{
val = sMapper->lowerPrgBank[address & 0x3FFF];
}
else if (address >= 0xC000 && address <= 0xFFFF)
{
val = sMapper->upperPrgBank[address & 0x3FFF];
}
else
{
fprintf(stderr, "Cartridge read access violation by the CPU at $%04X\n", address);
exit(-1);
}
return val;
}
Byte Mapper001_ReadPPU(void* mapper, Word address)
{
struct Mapper001* sMapper = (struct Mapper000*)mapper;
Byte val = 0x00;
if (address >= 0x2000)
{
fprintf(stderr, "Cartridge read access violation by the PPU at $%04X\n", address);
exit(-1);
}
else if (address < 0x1000 + 0x1000 * (1 - sMapper->control.chr_bank_mode))
{
val = sMapper->lowerChrBank[address];
}
else
{
val = sMapper->upperChrBank[address & 0x0FFF];
}
return val;
}
void Mapper001_WriteCPU(void* mapper, Word address, Byte value)
{
struct Mapper001* sMapper = (struct Mapper000*)mapper;
if ((value & 0x80) == 0x80)
{
sMapper->shiftRegister = 0x10;
sMapper->control.raw |= 0x0C;
return;
}
if ((sMapper->shiftRegister & 0x1) != 0x1)
{
sMapper->shiftRegister >>= 1;
sMapper->shiftRegister |= ((value & 0x1) << 4);
return;
}
Byte valueToBeWritten = (sMapper->shiftRegister >> 1) | ((value & 0x1) << 4);
if (address >= 0x8000 && address <= 0x9FFF)
{
sMapper->control.raw = valueToBeWritten;
}
else if (address >= 0xA000 && address <= 0xBFFF)
{
if (sMapper->control.chr_bank_mode == 0x00) // 8KB mode
valueToBeWritten &= ~(0x1); // clear last bit
sMapper->lowerChrBank = sMapper->chr_rom + (size_t)valueToBeWritten * 0x1000;
}
else if (address >= 0xC000 && address <= 0xDFFF)
{
if (sMapper->control.chr_bank_mode == 0x00) // 8KB mode
{
return; // ignore
}
sMapper->upperChrBank = sMapper->chr_rom + (size_t)valueToBeWritten * 0x1000;
}
else
{
switch (sMapper->control.prg_bank_mode)
{
case 0: // 32KB mode
case 1:
valueToBeWritten &= ~(0x1);
sMapper->lowerPrgBank = sMapper->prg_rom + ((size_t)valueToBeWritten & 0xE) * 0x8000;
sMapper->upperPrgBank = sMapper->lowerPrgBank + 0x4000;
break;
case 2: // fix first bank, switch second
sMapper->lowerPrgBank = sMapper->prg_rom;
sMapper->upperPrgBank = sMapper->prg_rom + ((size_t)valueToBeWritten & 0xE) * 0x4000;
break;
case 3: // fix last bank, switch first
sMapper->lowerPrgBank = sMapper->prg_rom + ((size_t)valueToBeWritten & 0xE) * 0x4000;
sMapper->upperPrgBank = sMapper->prg_rom + ((size_t)sMapper->prg_rom_size - 1) * 0x4000;
break;
}
}
}
void Mapper001_WritePPU(void* mapper, Word address, Byte value)
{
// nothing
}
void Mapper001_GetPatternTableTexture(void* mapper, SDL_Texture* texture, int index)
{
struct Mapper001* sMapper = (struct Mapper001*)mapper;
Byte* selectedBank = ((index == 0) ? sMapper->lowerChrBank : sMapper->upperChrBank);
int pitch;
void* pixels;
SDL_LockTexture(texture, NULL, &pixels, &pitch);
SDL_memcpy(pixels, selectedBank, 0x1000);
SDL_UnlockTexture(texture);
}