add gbcolor code from froggestspirit
https://github.com/deltabeard/Peanut-GB/issues/50 https://github.com/deltabeard/Peanut-GB/tree/cgb
This commit is contained in:
+471
-9
@@ -105,6 +105,10 @@
|
|||||||
# define PEANUT_GB_USE_INTRINSICS 1
|
# define PEANUT_GB_USE_INTRINSICS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PEANUT_FULL_GBC_SUPPORT
|
||||||
|
# define PEANUT_FULL_GBC_SUPPORT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Only include function prototypes. At least one file must *not* have this
|
/* Only include function prototypes. At least one file must *not* have this
|
||||||
* defined. */
|
* defined. */
|
||||||
// #define PEANUT_GB_HEADER_ONLY
|
// #define PEANUT_GB_HEADER_ONLY
|
||||||
@@ -119,8 +123,13 @@
|
|||||||
#define ANY_INTR 0x1F
|
#define ANY_INTR 0x1F
|
||||||
|
|
||||||
/* Memory section sizes for DMG */
|
/* Memory section sizes for DMG */
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
#define WRAM_SIZE 0x8000
|
||||||
|
#define VRAM_SIZE 0x4000
|
||||||
|
#else
|
||||||
#define WRAM_SIZE 0x2000
|
#define WRAM_SIZE 0x2000
|
||||||
#define VRAM_SIZE 0x2000
|
#define VRAM_SIZE 0x2000
|
||||||
|
#endif
|
||||||
#define HRAM_IO_SIZE 0x0100
|
#define HRAM_IO_SIZE 0x0100
|
||||||
#define OAM_SIZE 0x00A0
|
#define OAM_SIZE 0x00A0
|
||||||
|
|
||||||
@@ -151,6 +160,10 @@
|
|||||||
/* Serial clock locked to 8192Hz on DMG.
|
/* Serial clock locked to 8192Hz on DMG.
|
||||||
* 4194304 / (8192 / 8) = 4096 clock cycles for sending 1 byte. */
|
* 4194304 / (8192 / 8) = 4096 clock cycles for sending 1 byte. */
|
||||||
#define SERIAL_CYCLES 4096
|
#define SERIAL_CYCLES 4096
|
||||||
|
#define SERIAL_CYCLES_1KB (SERIAL_CYCLES/1ul)
|
||||||
|
#define SERIAL_CYCLES_2KB (SERIAL_CYCLES/2ul)
|
||||||
|
#define SERIAL_CYCLES_32KB (SERIAL_CYCLES/32ul)
|
||||||
|
#define SERIAL_CYCLES_64KB (SERIAL_CYCLES/64ul)
|
||||||
|
|
||||||
/* Calculating VSYNC. */
|
/* Calculating VSYNC. */
|
||||||
#define DMG_CLOCK_FREQ 4194304.0
|
#define DMG_CLOCK_FREQ 4194304.0
|
||||||
@@ -236,6 +249,10 @@
|
|||||||
#define OBJ_FLIP_Y 0x40
|
#define OBJ_FLIP_Y 0x40
|
||||||
#define OBJ_FLIP_X 0x20
|
#define OBJ_FLIP_X 0x20
|
||||||
#define OBJ_PALETTE 0x10
|
#define OBJ_PALETTE 0x10
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
#define OBJ_BANK 0x08
|
||||||
|
#define OBJ_CGB_PALETTE 0x07
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Joypad buttons */
|
/* Joypad buttons */
|
||||||
#define JOYPAD_A 0x01
|
#define JOYPAD_A 0x01
|
||||||
@@ -699,6 +716,31 @@ struct gb_s
|
|||||||
bool interlace_count : 1;
|
bool interlace_count : 1;
|
||||||
} display;
|
} display;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
/* Game Boy Color Mode*/
|
||||||
|
struct {
|
||||||
|
uint8_t cgbMode;
|
||||||
|
uint8_t doubleSpeed;
|
||||||
|
uint8_t doubleSpeedPrep;
|
||||||
|
uint8_t wramBank;
|
||||||
|
uint16_t wramBankOffset;
|
||||||
|
uint8_t vramBank;
|
||||||
|
uint16_t vramBankOffset;
|
||||||
|
uint16_t fixPalette[0x40]; //BG then OAM palettes fixed for the screen
|
||||||
|
uint8_t OAMPalette[0x40];
|
||||||
|
uint8_t BGPalette[0x40];
|
||||||
|
uint8_t OAMPaletteID;
|
||||||
|
uint8_t BGPaletteID;
|
||||||
|
uint8_t OAMPaletteInc;
|
||||||
|
uint8_t BGPaletteInc;
|
||||||
|
uint8_t dmaActive;
|
||||||
|
uint8_t dmaMode;
|
||||||
|
uint8_t dmaSize;
|
||||||
|
uint16_t dmaSource;
|
||||||
|
uint16_t dmaDest;
|
||||||
|
} cgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variables that may be modified directly by the front-end.
|
* Variables that may be modified directly by the front-end.
|
||||||
* This method seems to be easier and possibly less overhead than
|
* This method seems to be easier and possibly less overhead than
|
||||||
@@ -808,8 +850,11 @@ uint8_t __gb_read(struct gb_s *gb, uint16_t addr)
|
|||||||
|
|
||||||
case 0x8:
|
case 0x8:
|
||||||
case 0x9:
|
case 0x9:
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
return gb->vram[addr - gb->cgb.vramBankOffset];
|
||||||
|
#else
|
||||||
return gb->vram[addr - VRAM_ADDR];
|
return gb->vram[addr - VRAM_ADDR];
|
||||||
|
#endif
|
||||||
case 0xA:
|
case 0xA:
|
||||||
case 0xB:
|
case 0xB:
|
||||||
if(gb->mbc == 3 && gb->cart_ram_bank >= 0x08)
|
if(gb->mbc == 3 && gb->cart_ram_bank >= 0x08)
|
||||||
@@ -838,6 +883,10 @@ uint8_t __gb_read(struct gb_s *gb, uint16_t addr)
|
|||||||
|
|
||||||
case 0xC:
|
case 0xC:
|
||||||
case 0xD:
|
case 0xD:
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode && addr >= WRAM_1_ADDR)
|
||||||
|
return gb->wram[addr - gb->cgb.wramBankOffset];
|
||||||
|
#endif
|
||||||
return gb->wram[addr - WRAM_0_ADDR];
|
return gb->wram[addr - WRAM_0_ADDR];
|
||||||
|
|
||||||
case 0xE:
|
case 0xE:
|
||||||
@@ -845,7 +894,11 @@ uint8_t __gb_read(struct gb_s *gb, uint16_t addr)
|
|||||||
|
|
||||||
case 0xF:
|
case 0xF:
|
||||||
if(addr < OAM_ADDR)
|
if(addr < OAM_ADDR)
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
return gb->wram[(addr - 0x2000) - gb->cgb.wramBankOffset];
|
||||||
|
#else
|
||||||
return gb->wram[addr - ECHO_ADDR];
|
return gb->wram[addr - ECHO_ADDR];
|
||||||
|
#endif
|
||||||
|
|
||||||
if(addr < UNUSED_ADDR)
|
if(addr < UNUSED_ADDR)
|
||||||
return gb->oam[addr - OAM_ADDR];
|
return gb->oam[addr - OAM_ADDR];
|
||||||
@@ -874,9 +927,53 @@ uint8_t __gb_read(struct gb_s *gb, uint16_t addr)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
/* IO and Interrupts. */
|
||||||
|
switch (addr & 0xFF)
|
||||||
|
{
|
||||||
|
/* Speed Switch*/
|
||||||
|
case 0x4D:
|
||||||
|
return (gb->cgb.doubleSpeed << 7) + gb->cgb.doubleSpeedPrep;
|
||||||
|
/* CGB VRAM Bank*/
|
||||||
|
case 0x4F:
|
||||||
|
return gb->cgb.vramBank | 0xFE;
|
||||||
|
/* CGB DMA*/
|
||||||
|
case 0x51:
|
||||||
|
return (gb->cgb.dmaSource >> 8);
|
||||||
|
case 0x52:
|
||||||
|
return (gb->cgb.dmaSource & 0xF0);
|
||||||
|
case 0x53:
|
||||||
|
return (gb->cgb.dmaDest >> 8);
|
||||||
|
case 0x54:
|
||||||
|
return (gb->cgb.dmaDest & 0xF0);
|
||||||
|
case 0x55:
|
||||||
|
return (gb->cgb.dmaActive << 7) | (gb->cgb.dmaSize - 1);
|
||||||
|
/* IR Register*/
|
||||||
|
case 0x56:
|
||||||
|
return gb->hram_io[0x56];
|
||||||
|
/* CGB BG Palette Index*/
|
||||||
|
case 0x68:
|
||||||
|
return (gb->cgb.BGPaletteID & 0x3F) + (gb->cgb.BGPaletteInc << 7);
|
||||||
|
/* CGB BG Palette*/
|
||||||
|
case 0x69:
|
||||||
|
return gb->cgb.BGPalette[(gb->cgb.BGPaletteID & 0x3F)];
|
||||||
|
/* CGB OAM Palette Index*/
|
||||||
|
case 0x6A:
|
||||||
|
return (gb->cgb.OAMPaletteID & 0x3F) + (gb->cgb.OAMPaletteInc << 7);
|
||||||
|
/* CGB OAM Palette*/
|
||||||
|
case 0x6B:
|
||||||
|
return gb->cgb.OAMPalette[(gb->cgb.OAMPaletteID & 0x3F)];
|
||||||
|
/* CGB WRAM Bank*/
|
||||||
|
case 0x70:
|
||||||
|
return gb->cgb.wramBank;
|
||||||
|
default:
|
||||||
|
#endif
|
||||||
/* HRAM */
|
/* HRAM */
|
||||||
if(addr >= IO_ADDR)
|
if(addr >= IO_ADDR)
|
||||||
return gb->hram_io[addr - IO_ADDR];
|
return gb->hram_io[addr - IO_ADDR];
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -978,7 +1075,11 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val)
|
|||||||
|
|
||||||
case 0x8:
|
case 0x8:
|
||||||
case 0x9:
|
case 0x9:
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
gb->vram[addr - gb->cgb.vramBankOffset] = val;
|
||||||
|
#else
|
||||||
gb->vram[addr - VRAM_ADDR] = val;
|
gb->vram[addr - VRAM_ADDR] = val;
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xA:
|
case 0xA:
|
||||||
@@ -1026,7 +1127,11 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xD:
|
case 0xD:
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
gb->wram[addr - gb->cgb.wramBankOffset] = val;
|
||||||
|
#else
|
||||||
gb->wram[addr - WRAM_1_ADDR + WRAM_BANK_SIZE] = val;
|
gb->wram[addr - WRAM_1_ADDR + WRAM_BANK_SIZE] = val;
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xE:
|
case 0xE:
|
||||||
@@ -1036,7 +1141,11 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val)
|
|||||||
case 0xF:
|
case 0xF:
|
||||||
if(addr < OAM_ADDR)
|
if(addr < OAM_ADDR)
|
||||||
{
|
{
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
gb->wram[(addr - 0x2000) - gb->cgb.wramBankOffset] = val;
|
||||||
|
#else
|
||||||
gb->wram[addr - ECHO_ADDR] = val;
|
gb->wram[addr - ECHO_ADDR] = val;
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,7 +1174,9 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val)
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
uint16_t fixPaletteTemp;
|
||||||
|
#endif
|
||||||
/* IO and Interrupts. */
|
/* IO and Interrupts. */
|
||||||
switch(PEANUT_GB_GET_LSB16(addr))
|
switch(PEANUT_GB_GET_LSB16(addr))
|
||||||
{
|
{
|
||||||
@@ -1176,10 +1287,13 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val)
|
|||||||
{
|
{
|
||||||
uint16_t dma_addr;
|
uint16_t dma_addr;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
dma_addr = (uint_fast16_t)(val % 0xF1) << 8;
|
||||||
|
gb->hram_io[IO_DMA] = (val % 0xF1);
|
||||||
|
#else
|
||||||
dma_addr = (uint_fast16_t)val << 8;
|
dma_addr = (uint_fast16_t)val << 8;
|
||||||
gb->hram_io[IO_DMA] = val;
|
gb->hram_io[IO_DMA] = val;
|
||||||
|
#endif
|
||||||
for(i = 0; i < OAM_SIZE; i++)
|
for(i = 0; i < OAM_SIZE; i++)
|
||||||
{
|
{
|
||||||
gb->oam[i] = __gb_read(gb, dma_addr + i);
|
gb->oam[i] = __gb_read(gb, dma_addr + i);
|
||||||
@@ -1222,10 +1336,98 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val)
|
|||||||
gb->hram_io[IO_WX] = val;
|
gb->hram_io[IO_WX] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
/* Prepare Speed Switch*/
|
||||||
|
case 0x4D:
|
||||||
|
gb->cgb.doubleSpeedPrep = val & 1;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CGB VRAM Bank*/
|
||||||
|
case 0x4F:
|
||||||
|
gb->cgb.vramBank = val & 0x01;
|
||||||
|
if(gb->cgb.cgbMode) gb->cgb.vramBankOffset = VRAM_ADDR - (gb->cgb.vramBank << 13);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
/* Turn off boot ROM */
|
/* Turn off boot ROM */
|
||||||
case 0x50:
|
case 0x50:
|
||||||
gb->hram_io[IO_BOOT] = 0x01;
|
gb->hram_io[IO_BOOT] = 0x01;
|
||||||
return;
|
return;
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
/* DMA Register */
|
||||||
|
case 0x51:
|
||||||
|
gb->cgb.dmaSource = (gb->cgb.dmaSource & 0xFF) + (val << 8);
|
||||||
|
return;
|
||||||
|
case 0x52:
|
||||||
|
gb->cgb.dmaSource = (gb->cgb.dmaSource & 0xFF00) + val;
|
||||||
|
return;
|
||||||
|
case 0x53:
|
||||||
|
gb->cgb.dmaDest = (gb->cgb.dmaDest & 0xFF) + (val << 8);
|
||||||
|
return;
|
||||||
|
case 0x54:
|
||||||
|
gb->cgb.dmaDest = (gb->cgb.dmaDest & 0xFF00) + val;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* DMA Register*/
|
||||||
|
case 0x55:
|
||||||
|
gb->cgb.dmaSize = (val & 0x7F) + 1;
|
||||||
|
gb->cgb.dmaMode = val >> 7;
|
||||||
|
//DMA GBC
|
||||||
|
if(gb->cgb.dmaActive)
|
||||||
|
{ // Only transfer if dma is not active (=1) otherwise treat it as a termination
|
||||||
|
if(gb->cgb.cgbMode && (!gb->cgb.dmaMode))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (gb->cgb.dmaSize << 4); i++)
|
||||||
|
{
|
||||||
|
__gb_write(gb, ((gb->cgb.dmaDest & 0x1FF0) | 0x8000) + i, __gb_read(gb, (gb->cgb.dmaSource & 0xFFF0) + i));
|
||||||
|
}
|
||||||
|
gb->cgb.dmaSource += (gb->cgb.dmaSize << 4);
|
||||||
|
gb->cgb.dmaDest += (gb->cgb.dmaSize << 4);
|
||||||
|
gb->cgb.dmaSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gb->cgb.dmaActive = gb->cgb.dmaMode ^ 1; // set active if it's an HBlank DMA
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* IR Register*/
|
||||||
|
case 0x56:
|
||||||
|
gb->hram_io[0x56] = val;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CGB BG Palette Index*/
|
||||||
|
case 0x68:
|
||||||
|
gb->cgb.BGPaletteID = val & 0x3F;
|
||||||
|
gb->cgb.BGPaletteInc = val >> 7;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CGB BG Palette*/
|
||||||
|
case 0x69:
|
||||||
|
gb->cgb.BGPalette[(gb->cgb.BGPaletteID & 0x3F)] = val;
|
||||||
|
fixPaletteTemp = (gb->cgb.BGPalette[(gb->cgb.BGPaletteID & 0x3E) + 1] << 8) + (gb->cgb.BGPalette[(gb->cgb.BGPaletteID & 0x3E)]);
|
||||||
|
gb->cgb.fixPalette[((gb->cgb.BGPaletteID & 0x3E) >> 1)] = ((fixPaletteTemp & 0x7C00) >> 10) | (fixPaletteTemp & 0x03E0) | ((fixPaletteTemp & 0x001F) << 10); // swap Red and Blue
|
||||||
|
if(gb->cgb.BGPaletteInc) gb->cgb.BGPaletteID = (++gb->cgb.BGPaletteID) & 0x3F;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CGB OAM Palette Index*/
|
||||||
|
case 0x6A:
|
||||||
|
gb->cgb.OAMPaletteID = val & 0x3F;
|
||||||
|
gb->cgb.OAMPaletteInc = val >> 7;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CGB OAM Palette*/
|
||||||
|
case 0x6B:
|
||||||
|
gb->cgb.OAMPalette[(gb->cgb.OAMPaletteID & 0x3F)] = val;
|
||||||
|
fixPaletteTemp = (gb->cgb.OAMPalette[(gb->cgb.OAMPaletteID & 0x3E) + 1] << 8) + (gb->cgb.OAMPalette[(gb->cgb.OAMPaletteID & 0x3E)]);
|
||||||
|
gb->cgb.fixPalette[0x20 + ((gb->cgb.OAMPaletteID & 0x3E) >> 1)] = ((fixPaletteTemp & 0x7C00) >> 10) | (fixPaletteTemp & 0x03E0) | ((fixPaletteTemp & 0x001F) << 10); // swap Red and Blue
|
||||||
|
if(gb->cgb.OAMPaletteInc) gb->cgb.OAMPaletteID = (++gb->cgb.OAMPaletteID) & 0x3F;
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CGB WRAM Bank*/
|
||||||
|
case 0x70:
|
||||||
|
gb->cgb.wramBank = val;
|
||||||
|
gb->cgb.wramBankOffset = WRAM_1_ADDR - (1 << 12);
|
||||||
|
if(gb->cgb.cgbMode && (gb->cgb.wramBank & 7) > 0) gb->cgb.wramBankOffset = WRAM_1_ADDR - ((gb->cgb.wramBank & 7) << 12);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Interrupt Enable Register */
|
/* Interrupt Enable Register */
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
@@ -1458,6 +1660,9 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
if(gb->direct.frame_skip && !gb->display.frame_skip_count)
|
if(gb->direct.frame_skip && !gb->display.frame_skip_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
uint8_t pixelsPrio[160] = {0}; //do these pixels have priority over OAM?
|
||||||
|
#endif
|
||||||
/* If interlaced mode is activated, check if we need to draw the current
|
/* If interlaced mode is activated, check if we need to draw the current
|
||||||
* line. */
|
* line. */
|
||||||
if(gb->direct.interlace)
|
if(gb->direct.interlace)
|
||||||
@@ -1478,7 +1683,11 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If background is enabled, draw it. */
|
/* If background is enabled, draw it. */
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode || gb->hram_io[IO_LCDC] & LCDC_BG_ENABLE)
|
||||||
|
#else
|
||||||
if(gb->hram_io[IO_LCDC] & LCDC_BG_ENABLE)
|
if(gb->hram_io[IO_LCDC] & LCDC_BG_ENABLE)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t bg_y, disp_x, bg_x, idx, py, px, t1, t2;
|
uint8_t bg_y, disp_x, bg_x, idx, py, px, t1, t2;
|
||||||
uint16_t bg_map, tile;
|
uint16_t bg_map, tile;
|
||||||
@@ -1506,6 +1715,9 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
|
|
||||||
/* Get tile index for current background tile. */
|
/* Get tile index for current background tile. */
|
||||||
idx = gb->vram[bg_map + (bg_x >> 3)];
|
idx = gb->vram[bg_map + (bg_x >> 3)];
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
uint8_t idxAtt = gb->vram[bg_map + (bg_x >> 3) + 0x2000];
|
||||||
|
#endif
|
||||||
/* Y coordinate of tile pixel to draw. */
|
/* Y coordinate of tile pixel to draw. */
|
||||||
py = (bg_y & 0x07);
|
py = (bg_y & 0x07);
|
||||||
/* X coordinate of tile pixel to draw. */
|
/* X coordinate of tile pixel to draw. */
|
||||||
@@ -1517,12 +1729,35 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
else
|
else
|
||||||
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
if(idxAtt & 0x08) tile += 0x2000; //VRAM bank 2
|
||||||
|
if(idxAtt & 0x40) tile += 2 * (7 - py);
|
||||||
|
}
|
||||||
|
if(!(idxAtt & 0x40))
|
||||||
|
{
|
||||||
|
tile += 2 * py;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fetch first tile */
|
||||||
|
if(gb->cgb.cgbMode && (idxAtt & 0x20))
|
||||||
|
{ //Horizantal Flip
|
||||||
|
t1 = gb->vram[tile] << px;
|
||||||
|
t2 = gb->vram[tile + 1] << px;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t1 = gb->vram[tile] >> px;
|
||||||
|
t2 = gb->vram[tile + 1] >> px;
|
||||||
|
}
|
||||||
|
#else
|
||||||
tile += 2 * py;
|
tile += 2 * py;
|
||||||
|
|
||||||
/* fetch first tile */
|
/* fetch first tile */
|
||||||
t1 = gb->vram[tile] >> px;
|
t1 = gb->vram[tile] >> px;
|
||||||
t2 = gb->vram[tile + 1] >> px;
|
t2 = gb->vram[tile + 1] >> px;
|
||||||
|
#endif
|
||||||
for(; disp_x != 0xFF; disp_x--)
|
for(; disp_x != 0xFF; disp_x--)
|
||||||
{
|
{
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
@@ -1533,18 +1768,60 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
px = 0;
|
px = 0;
|
||||||
bg_x = disp_x + gb->hram_io[IO_SCX];
|
bg_x = disp_x + gb->hram_io[IO_SCX];
|
||||||
idx = gb->vram[bg_map + (bg_x >> 3)];
|
idx = gb->vram[bg_map + (bg_x >> 3)];
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
idxAtt = gb->vram[bg_map + (bg_x >> 3) + 0x2000];
|
||||||
|
#endif
|
||||||
if(gb->hram_io[IO_LCDC] & LCDC_TILE_SELECT)
|
if(gb->hram_io[IO_LCDC] & LCDC_TILE_SELECT)
|
||||||
tile = VRAM_TILES_1 + idx * 0x10;
|
tile = VRAM_TILES_1 + idx * 0x10;
|
||||||
else
|
else
|
||||||
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
if(idxAtt & 0x08) tile += 0x2000; //VRAM bank 2
|
||||||
|
if(idxAtt & 0x40) tile += 2 * (7 - py);
|
||||||
|
}
|
||||||
|
if(!(idxAtt & 0x40))
|
||||||
|
{
|
||||||
tile += 2 * py;
|
tile += 2 * py;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
tile += 2 * py;
|
||||||
|
#endif
|
||||||
t1 = gb->vram[tile];
|
t1 = gb->vram[tile];
|
||||||
t2 = gb->vram[tile + 1];
|
t2 = gb->vram[tile + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy background */
|
/* copy background */
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode && (idxAtt & 0x20))
|
||||||
|
{ //Horizantal Flip
|
||||||
|
c = (((t1 & 0x80) >> 1) | (t2 & 0x80)) >> 6;
|
||||||
|
pixels[disp_x] = ((idxAtt & 0x07) << 2) + c;
|
||||||
|
pixelsPrio[disp_x] = (idxAtt >> 7);
|
||||||
|
t1 = t1 << 1;
|
||||||
|
t2 = t2 << 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
pixels[disp_x] = ((idxAtt & 0x07) << 2) + c;
|
||||||
|
pixelsPrio[disp_x] = (idxAtt >> 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixels[disp_x] = gb->display.bg_palette[c];
|
||||||
|
#if PEANUT_GB_12_COLOUR
|
||||||
|
pixels[disp_x] |= LCD_PALETTE_BG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
t1 = t1 >> 1;
|
||||||
|
t2 = t2 >> 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
||||||
pixels[disp_x] = gb->display.bg_palette[c];
|
pixels[disp_x] = gb->display.bg_palette[c];
|
||||||
#if PEANUT_GB_12_COLOUR
|
#if PEANUT_GB_12_COLOUR
|
||||||
@@ -1552,6 +1829,7 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
#endif
|
#endif
|
||||||
t1 = t1 >> 1;
|
t1 = t1 >> 1;
|
||||||
t2 = t2 >> 1;
|
t2 = t2 >> 1;
|
||||||
|
#endif
|
||||||
px++;
|
px++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1576,18 +1854,44 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
py = gb->display.window_clear & 0x07;
|
py = gb->display.window_clear & 0x07;
|
||||||
px = 7 - (win_x & 0x07);
|
px = 7 - (win_x & 0x07);
|
||||||
idx = gb->vram[win_line + (win_x >> 3)];
|
idx = gb->vram[win_line + (win_x >> 3)];
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
uint8_t idxAtt = gb->vram[win_line + (win_x >> 3) + 0x2000];
|
||||||
|
#endif
|
||||||
|
|
||||||
if(gb->hram_io[IO_LCDC] & LCDC_TILE_SELECT)
|
if(gb->hram_io[IO_LCDC] & LCDC_TILE_SELECT)
|
||||||
tile = VRAM_TILES_1 + idx * 0x10;
|
tile = VRAM_TILES_1 + idx * 0x10;
|
||||||
else
|
else
|
||||||
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
if(idxAtt & 0x08) tile += 0x2000; //VRAM bank 2
|
||||||
|
if(idxAtt & 0x40) tile += 2 * (7 - py);
|
||||||
|
}
|
||||||
|
if(!(idxAtt & 0x40))
|
||||||
|
{
|
||||||
|
tile += 2 * py;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch first tile
|
||||||
|
if(gb->cgb.cgbMode && (idxAtt & 0x20))
|
||||||
|
{ //Horizantal Flip
|
||||||
|
t1 = gb->vram[tile] << px;
|
||||||
|
t2 = gb->vram[tile + 1] << px;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t1 = gb->vram[tile] >> px;
|
||||||
|
t2 = gb->vram[tile + 1] >> px;
|
||||||
|
}
|
||||||
|
#else
|
||||||
tile += 2 * py;
|
tile += 2 * py;
|
||||||
|
|
||||||
// fetch first tile
|
// fetch first tile
|
||||||
t1 = gb->vram[tile] >> px;
|
t1 = gb->vram[tile] >> px;
|
||||||
t2 = gb->vram[tile + 1] >> px;
|
t2 = gb->vram[tile + 1] >> px;
|
||||||
|
#endif
|
||||||
// loop & copy window
|
// loop & copy window
|
||||||
end = (gb->hram_io[IO_WX] < 7 ? 0 : gb->hram_io[IO_WX] - 7) - 1;
|
end = (gb->hram_io[IO_WX] < 7 ? 0 : gb->hram_io[IO_WX] - 7) - 1;
|
||||||
|
|
||||||
@@ -1601,18 +1905,61 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
px = 0;
|
px = 0;
|
||||||
win_x = disp_x - gb->hram_io[IO_WX] + 7;
|
win_x = disp_x - gb->hram_io[IO_WX] + 7;
|
||||||
idx = gb->vram[win_line + (win_x >> 3)];
|
idx = gb->vram[win_line + (win_x >> 3)];
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
idxAtt = gb->vram[win_line + (win_x >> 3) + 0x2000];
|
||||||
|
#endif
|
||||||
|
|
||||||
if(gb->hram_io[IO_LCDC] & LCDC_TILE_SELECT)
|
if(gb->hram_io[IO_LCDC] & LCDC_TILE_SELECT)
|
||||||
tile = VRAM_TILES_1 + idx * 0x10;
|
tile = VRAM_TILES_1 + idx * 0x10;
|
||||||
else
|
else
|
||||||
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
tile = VRAM_TILES_2 + ((idx + 0x80) % 0x100) * 0x10;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
if(idxAtt & 0x08) tile += 0x2000; //VRAM bank 2
|
||||||
|
if(idxAtt & 0x40) tile += 2 * (7 - py);
|
||||||
|
}
|
||||||
|
if(!(idxAtt & 0x40))
|
||||||
|
{
|
||||||
tile += 2 * py;
|
tile += 2 * py;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
tile += 2 * py;
|
||||||
|
#endif
|
||||||
t1 = gb->vram[tile];
|
t1 = gb->vram[tile];
|
||||||
t2 = gb->vram[tile + 1];
|
t2 = gb->vram[tile + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy window
|
// copy window
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(idxAtt & 0x20)
|
||||||
|
{ //Horizantal Flip
|
||||||
|
c = (((t1 & 0x80) >> 1) | (t2 & 0x80)) >> 6;
|
||||||
|
pixels[disp_x] = ((idxAtt & 0x07) << 2) + c;
|
||||||
|
pixelsPrio[disp_x] = (idxAtt >> 7);
|
||||||
|
t1 = t1 << 1;
|
||||||
|
t2 = t2 << 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
pixels[disp_x] = ((idxAtt & 0x07) << 2) + c;
|
||||||
|
pixelsPrio[disp_x] = (idxAtt >> 7);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixels[disp_x] = gb->display.bg_palette[c];
|
||||||
|
#if PEANUT_GB_12_COLOUR
|
||||||
|
pixels[disp_x] |= LCD_PALETTE_BG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
t1 = t1 >> 1;
|
||||||
|
t2 = t2 >> 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
||||||
pixels[disp_x] = gb->display.bg_palette[c];
|
pixels[disp_x] = gb->display.bg_palette[c];
|
||||||
#if PEANUT_GB_12_COLOUR
|
#if PEANUT_GB_12_COLOUR
|
||||||
@@ -1620,6 +1967,7 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
#endif
|
#endif
|
||||||
t1 = t1 >> 1;
|
t1 = t1 >> 1;
|
||||||
t2 = t2 >> 1;
|
t2 = t2 >> 1;
|
||||||
|
#endif
|
||||||
px++;
|
px++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,11 +2006,17 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
sprites_to_render[number_of_sprites].x = OX;
|
sprites_to_render[number_of_sprites].x = OX;
|
||||||
number_of_sprites++;
|
number_of_sprites++;
|
||||||
}
|
}
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(!gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
/* If maximum number of sprites reached, prioritise X
|
/* If maximum number of sprites reached, prioritise X
|
||||||
* coordinate and object location in OAM. */
|
* coordinate and object location in OAM. */
|
||||||
qsort(&sprites_to_render[0], number_of_sprites,
|
qsort(&sprites_to_render[0], number_of_sprites,
|
||||||
sizeof(sprites_to_render[0]), compare_sprites);
|
sizeof(sprites_to_render[0]), compare_sprites);
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(number_of_sprites > MAX_SPRITES_LINE)
|
if(number_of_sprites > MAX_SPRITES_LINE)
|
||||||
number_of_sprites = MAX_SPRITES_LINE;
|
number_of_sprites = MAX_SPRITES_LINE;
|
||||||
#endif
|
#endif
|
||||||
@@ -1712,8 +2066,18 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
py = (gb->hram_io[IO_LCDC] & LCDC_OBJ_SIZE ? 15 : 7) - py;
|
py = (gb->hram_io[IO_LCDC] & LCDC_OBJ_SIZE ? 15 : 7) - py;
|
||||||
|
|
||||||
// fetch the tile
|
// fetch the tile
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
t1 = gb->vram[((OF & OBJ_BANK) << 10) + VRAM_TILES_1 + OT * 0x10 + 2 * py];
|
||||||
|
t2 = gb->vram[((OF & OBJ_BANK) << 10) + VRAM_TILES_1 + OT * 0x10 + 2 * py + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
t1 = gb->vram[VRAM_TILES_1 + OT * 0x10 + 2 * py];
|
t1 = gb->vram[VRAM_TILES_1 + OT * 0x10 + 2 * py];
|
||||||
t2 = gb->vram[VRAM_TILES_1 + OT * 0x10 + 2 * py + 1];
|
t2 = gb->vram[VRAM_TILES_1 + OT * 0x10 + 2 * py + 1];
|
||||||
|
}
|
||||||
|
|
||||||
// handle x flip
|
// handle x flip
|
||||||
if(OF & OBJ_FLIP_X)
|
if(OF & OBJ_FLIP_X)
|
||||||
@@ -1742,7 +2106,22 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
{
|
{
|
||||||
uint8_t c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
uint8_t c = (t1 & 0x1) | ((t2 & 0x1) << 1);
|
||||||
// check transparency / sprite overlap / background overlap
|
// check transparency / sprite overlap / background overlap
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
uint8_t isBackgroundDisabled = c && !(gb->hram_io[IO_LCDC] & LCDC_BG_ENABLE);
|
||||||
|
uint8_t isPixelPriorityNonConflicting = c &&
|
||||||
|
!(pixelsPrio[disp_x] && (pixels[disp_x] & 0x3)) &&
|
||||||
|
!((OF & OBJ_PRIORITY) && (pixels[disp_x] & 0x3));
|
||||||
|
|
||||||
|
if(isBackgroundDisabled || isPixelPriorityNonConflicting)
|
||||||
|
{
|
||||||
|
/* Set pixel colour. */
|
||||||
|
pixels[disp_x] = ((OF & OBJ_CGB_PALETTE) << 2) + c + 0x20; // add 0x20 to differentiate from BG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if(c && !(OF & OBJ_PRIORITY && !((pixels[disp_x] & 0x3) == gb->display.bg_palette[0])))
|
if(c && !(OF & OBJ_PRIORITY && !((pixels[disp_x] & 0x3) == gb->display.bg_palette[0])))
|
||||||
{
|
{
|
||||||
/* Set pixel colour. */
|
/* Set pixel colour. */
|
||||||
@@ -1752,6 +2131,10 @@ void __gb_draw_line(struct gb_s *gb)
|
|||||||
#if PEANUT_GB_12_COLOUR
|
#if PEANUT_GB_12_COLOUR
|
||||||
/* Set pixel palette (OBJ0 or OBJ1). */
|
/* Set pixel palette (OBJ0 or OBJ1). */
|
||||||
pixels[disp_x] |= (OF & OBJ_PALETTE);
|
pixels[disp_x] |= (OF & OBJ_PALETTE);
|
||||||
|
#endif
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
/* Deselect BG palette. */
|
||||||
|
pixels[disp_x] &= ~LCD_PALETTE_BG;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1937,6 +2320,13 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
|
|
||||||
case 0x10: /* STOP */
|
case 0x10: /* STOP */
|
||||||
//gb->gb_halt = true;
|
//gb->gb_halt = true;
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode & gb->cgb.doubleSpeedPrep)
|
||||||
|
{
|
||||||
|
gb->cgb.doubleSpeedPrep = 0;
|
||||||
|
gb->cgb.doubleSpeed ^= 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x11: /* LD DE, imm */
|
case 0x11: /* LD DE, imm */
|
||||||
@@ -3313,15 +3703,22 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
/* Check serial transmission. */
|
/* Check serial transmission. */
|
||||||
if(gb->hram_io[IO_SC] & SERIAL_SC_TX_START)
|
if(gb->hram_io[IO_SC] & SERIAL_SC_TX_START)
|
||||||
{
|
{
|
||||||
|
unsigned int serial_cycles = SERIAL_CYCLES_1KB;
|
||||||
|
|
||||||
/* If new transfer, call TX function. */
|
/* If new transfer, call TX function. */
|
||||||
if(gb->counter.serial_count == 0 &&
|
if(gb->counter.serial_count == 0 &&
|
||||||
gb->gb_serial_tx != NULL)
|
gb->gb_serial_tx != NULL)
|
||||||
(gb->gb_serial_tx)(gb, gb->hram_io[IO_SB]);
|
(gb->gb_serial_tx)(gb, gb->hram_io[IO_SB]);
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->hram_io[IO_SC] & 0x3)
|
||||||
|
serial_cycles = SERIAL_CYCLES_32KB;
|
||||||
|
#endif
|
||||||
|
|
||||||
gb->counter.serial_count += inst_cycles;
|
gb->counter.serial_count += inst_cycles;
|
||||||
|
|
||||||
/* If it's time to receive byte, call RX function. */
|
/* If it's time to receive byte, call RX function. */
|
||||||
if(gb->counter.serial_count >= SERIAL_CYCLES)
|
if(gb->counter.serial_count >= serial_cycles)
|
||||||
{
|
{
|
||||||
/* If RX can be done, do it. */
|
/* If RX can be done, do it. */
|
||||||
/* If RX failed, do not change SB if using external
|
/* If RX failed, do not change SB if using external
|
||||||
@@ -3396,6 +3793,11 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* LCD Timing */
|
/* LCD Timing */
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if (inst_cycles > 1)
|
||||||
|
gb->counter.lcd_count += (inst_cycles >> gb->cgb.doubleSpeed);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
gb->counter.lcd_count += inst_cycles;
|
gb->counter.lcd_count += inst_cycles;
|
||||||
|
|
||||||
/* New Scanline. HBlank -> VBlank or OAM Scan */
|
/* New Scanline. HBlank -> VBlank or OAM Scan */
|
||||||
@@ -3467,6 +3869,20 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
gb->hram_io[IO_STAT] = (gb->hram_io[IO_STAT] & ~STAT_MODE) | IO_STAT_MODE_OAM_SCAN;
|
gb->hram_io[IO_STAT] = (gb->hram_io[IO_STAT] & ~STAT_MODE) | IO_STAT_MODE_OAM_SCAN;
|
||||||
gb->counter.lcd_count = 0;
|
gb->counter.lcd_count = 0;
|
||||||
|
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
//DMA GBC
|
||||||
|
if(gb->cgb.cgbMode && !gb->cgb.dmaActive && gb->cgb.dmaMode)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < 0x10; i++)
|
||||||
|
{
|
||||||
|
__gb_write(gb, ((gb->cgb.dmaDest & 0x1FF0) | 0x8000) + i,
|
||||||
|
__gb_read(gb, (gb->cgb.dmaSource & 0xFFF0) + i));
|
||||||
|
}
|
||||||
|
gb->cgb.dmaSource += 0x10;
|
||||||
|
gb->cgb.dmaDest += 0x10;
|
||||||
|
if(!(--gb->cgb.dmaSize)) gb->cgb.dmaActive = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(gb->hram_io[IO_STAT] & STAT_MODE_2_INTR)
|
if(gb->hram_io[IO_STAT] & STAT_MODE_2_INTR)
|
||||||
gb->hram_io[IO_IF] |= LCDC_INTR;
|
gb->hram_io[IO_IF] |= LCDC_INTR;
|
||||||
|
|
||||||
@@ -3592,6 +4008,20 @@ void gb_reset(struct gb_s *gb)
|
|||||||
gb->hram_io[IO_LCDC] = 0x91;
|
gb->hram_io[IO_LCDC] = 0x91;
|
||||||
gb->hram_io[IO_STAT] = 0x85;
|
gb->hram_io[IO_STAT] = 0x85;
|
||||||
gb->hram_io[IO_BOOT] = 0x01;
|
gb->hram_io[IO_BOOT] = 0x01;
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode)
|
||||||
|
{
|
||||||
|
gb->cpu_reg.a = 0x11;
|
||||||
|
gb->cpu_reg.f.f_bits.z = 1;
|
||||||
|
gb->cpu_reg.f.f_bits.n = 0;
|
||||||
|
gb->cpu_reg.f.f_bits.h = hdr_chk;
|
||||||
|
gb->cpu_reg.f.f_bits.c = hdr_chk;
|
||||||
|
gb->cpu_reg.bc.reg = 0x0000;
|
||||||
|
gb->cpu_reg.de.reg = 0x0008;
|
||||||
|
gb->cpu_reg.hl.reg = 0x007C;
|
||||||
|
gb->hram_io[IO_DIV] = 0xFF;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
__gb_write(gb, 0xFF26, 0xF1);
|
__gb_write(gb, 0xFF26, 0xF1);
|
||||||
|
|
||||||
@@ -3619,6 +4049,9 @@ void gb_reset(struct gb_s *gb)
|
|||||||
gb->hram_io[IO_JOYP] = 0xCF;
|
gb->hram_io[IO_JOYP] = 0xCF;
|
||||||
gb->hram_io[IO_SB ] = 0x00;
|
gb->hram_io[IO_SB ] = 0x00;
|
||||||
gb->hram_io[IO_SC ] = 0x7E;
|
gb->hram_io[IO_SC ] = 0x7E;
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
if(gb->cgb.cgbMode) gb->hram_io[IO_SC] = 0x7F;
|
||||||
|
#endif
|
||||||
/* DIV */
|
/* DIV */
|
||||||
gb->hram_io[IO_TIMA] = 0x00;
|
gb->hram_io[IO_TIMA] = 0x00;
|
||||||
gb->hram_io[IO_TMA ] = 0x00;
|
gb->hram_io[IO_TMA ] = 0x00;
|
||||||
@@ -3638,6 +4071,29 @@ void gb_reset(struct gb_s *gb)
|
|||||||
gb->hram_io[IO_WX] = 0x00;
|
gb->hram_io[IO_WX] = 0x00;
|
||||||
gb->hram_io[IO_IE] = 0x00;
|
gb->hram_io[IO_IE] = 0x00;
|
||||||
gb->hram_io[IO_IF] = 0xE1;
|
gb->hram_io[IO_IF] = 0xE1;
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
/* Initialize some CGB registers */
|
||||||
|
gb->cgb.doubleSpeed = 0;
|
||||||
|
gb->cgb.doubleSpeedPrep = 0;
|
||||||
|
gb->cgb.wramBank = 1;
|
||||||
|
gb->cgb.wramBankOffset = WRAM_0_ADDR;
|
||||||
|
gb->cgb.vramBank = 0;
|
||||||
|
gb->cgb.vramBankOffset = VRAM_ADDR;
|
||||||
|
for (int i = 0; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
gb->cgb.OAMPalette[(i << 1)] = gb->cgb.BGPalette[(i << 1)] = 0x7F;
|
||||||
|
gb->cgb.OAMPalette[(i << 1) + 1] = gb->cgb.BGPalette[(i << 1) + 1] = 0xFF;
|
||||||
|
}
|
||||||
|
gb->cgb.OAMPaletteID = 0;
|
||||||
|
gb->cgb.BGPaletteID = 0;
|
||||||
|
gb->cgb.OAMPaletteInc = 0;
|
||||||
|
gb->cgb.BGPaletteInc = 0;
|
||||||
|
gb->cgb.dmaActive = 1; // Not active
|
||||||
|
gb->cgb.dmaMode = 0;
|
||||||
|
gb->cgb.dmaSize = 0;
|
||||||
|
gb->cgb.dmaSource = 0;
|
||||||
|
gb->cgb.dmaDest = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
enum gb_init_error_e gb_init(struct gb_s *gb,
|
enum gb_init_error_e gb_init(struct gb_s *gb,
|
||||||
@@ -3647,6 +4103,9 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
|
|||||||
void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t),
|
void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t),
|
||||||
void *priv)
|
void *priv)
|
||||||
{
|
{
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
const uint16_t cgb_flag = 0x0143;
|
||||||
|
#endif
|
||||||
const uint16_t mbc_location = 0x0147;
|
const uint16_t mbc_location = 0x0147;
|
||||||
const uint16_t bank_count_location = 0x0148;
|
const uint16_t bank_count_location = 0x0148;
|
||||||
const uint16_t ram_size_location = 0x0149;
|
const uint16_t ram_size_location = 0x0149;
|
||||||
@@ -3708,6 +4167,9 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
|
|||||||
|
|
||||||
/* Check if cartridge type is supported, and set MBC type. */
|
/* Check if cartridge type is supported, and set MBC type. */
|
||||||
{
|
{
|
||||||
|
#if PEANUT_FULL_GBC_SUPPORT
|
||||||
|
gb->cgb.cgbMode = (gb->gb_rom_read(gb, cgb_flag) & 0x80) >> 7;
|
||||||
|
#endif
|
||||||
const uint8_t mbc_value = gb->gb_rom_read(gb, mbc_location);
|
const uint8_t mbc_value = gb->gb_rom_read(gb, mbc_location);
|
||||||
|
|
||||||
if(mbc_value > sizeof(cart_mbc) - 1 ||
|
if(mbc_value > sizeof(cart_mbc) - 1 ||
|
||||||
|
|||||||
Reference in New Issue
Block a user