- [NEW] Sprites funcionant

- [NEW] OAM DMA copy funcionant
This commit is contained in:
2025-01-24 14:52:36 +01:00
parent 771136e712
commit 8c8afa220f
5 changed files with 99 additions and 8 deletions

View File

@@ -169,29 +169,69 @@ namespace gbscreen
struct oam_entry_t struct oam_entry_t
{ {
uint8_t y, tile, attr; uint8_t y, x, tile, attr;
}; };
oam_entry_t *oam = nullptr;
void fill_line_buffer_obj(uint8_t LY) void fill_line_buffer_obj(uint8_t LY)
{ {
const uint8_t LCDC = mem::readMem(0xff40); const uint8_t LCDC = mem::readMem(0xff40);
if ((LCDC & 0x2) == 0) return; if ((LCDC & 0x2) == 0) return;
oam = (oam_entry_t*)mem::rawPtr(0xfe00);
const uint8_t height = (LCDC & 0x4) ? 16 : 8; const uint8_t height = (LCDC & 0x4) ? 16 : 8;
uint8_t obj_list[10] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; uint8_t obj_list[10] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
int num_obj_found=0; int num_obj_found=0;
int obj=0; int obj=0;
while (obj<40 && num_obj_found<10) // Revisem els 40 posibles sprites o fins a trobar 10...
{ while (obj<40 && num_obj_found<10) {
const uint8_t y = mem::readMem(0xff00+(obj*4)); // Si el sprite està tocant la linea actual l'afegim a la llista
if ( (LY>=y) && (LY<y+height) ) { if ( (LY+16 >= (oam[obj].y)) && (LY+16 < (oam[obj].y+height)) ) {
obj_list[num_obj_found]=obj; obj_list[num_obj_found]=obj;
uint8_t i = num_obj_found;
while( (i>0) && (obj_list[i-1]) )
num_obj_found++; num_obj_found++;
} }
obj++; obj++;
} }
// Pintem els sprites en el buffer de sprites
uint8_t pixels[160];
uint8_t x_pos[160];
for (int i=0;i<160;++i) { pixels[i] = 0; x_pos[i] = 255; }
obj=0;
while (obj_list[obj] != 255) {
oam_entry_t *o = &oam[obj_list[obj]];
const uint8_t ly = uint8_t(LY-o->y) & 0x7;
uint16_t tile = height==8 ? o->tile : o->tile & 0xFE; // si es dos tiles de alt, el primer sempre comença en numero parell
uint8_t yflip = o->attr&0x40 ? 8-ly : ly; // està invertit verticalment?
uint16_t tile_address = 0x8000 + (tile<<4) + (yflip*2);
uint8_t a = mem::readMem(tile_address);
uint8_t b = mem::readMem(tile_address+1);
for (int i=0; i<8; ++i) { // Per a cada pixel de la linea del tile...
if (o->x+i>=168) break; // Si ja estem fora de la pantalla per la dreta, eixim del bucle
if (o->x+i>=8) { // Si està dins de la pantalla...
if (x_pos[o->x+i-8]>o->x) { // Si te una x menor que la que tenía
//uint8_t xflip = o->attr&0x20 ? 8 : 0; // està invertit horitzontalment?
uint8_t ppos = 1 << ( o->attr&0x20 ? i : 7-i);
uint8_t val = (a&ppos ? 1 : 0) + (b&ppos ? 2 : 0 ); // agafem el pixel que toca
if (val) { // Si el pixel no es transparent...
pixels[o->x+i-8] = val | o->attr&0x80; // el pintem al buffer, amb el flag de prioritat respecte al BKG
x_pos[o->x+i-8] = o->x; // I apuntem la seua x per a comparar després
}
}
}
}
obj++;
}
// Per últim, volquem els pixels que toque al buffer de linea
for (int i=0; i<160; ++i) {
if (pixels[i]>0) { // si el pixel no es transparent...
if ( !(pixels[i]&0x80) || (line_buffer[i]==0) ) { // Si te prioritat o el color de fondo es 0...
line_buffer[i] = pixels[i]&0x03; // pintem el pixel (llevant el flag de prioritat)
}
}
}
} }
void refresh(const uint32_t dt, const bool full) void refresh(const uint32_t dt, const bool full)
@@ -244,6 +284,7 @@ namespace gbscreen
STAT = (STAT & 0xFC) | 0x02; // Set mode 2 STAT = (STAT & 0xFC) | 0x02; // Set mode 2
if (STAT&0x20) stat_interrupt = true; if (STAT&0x20) stat_interrupt = true;
fill_line_buffer_bkg(LY); fill_line_buffer_bkg(LY);
fill_line_buffer_obj(LY);
} }
else if (LY==154) else if (LY==154)
{ {

View File

@@ -71,6 +71,7 @@ namespace mbc_none
} else { } else {
if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room
if ( (address==0xFF00) ) { value = value & 0x30; } if ( (address==0xFF00) ) { value = value & 0x30; }
if ( (address==0xFF46) ) mem::init_dma_transfer(value);
hram[address - 0xFE00] = value; hram[address - 0xFE00] = value;
} }
} }
@@ -95,6 +96,24 @@ namespace mbc_none
} }
uint8_t* rawPtr(uint16_t address)
{
if (address < 0x8000) {
if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return &bootrom[address];
return &rom[address];
} else if (address < 0xA000) {
return &vram[address - 0x8000];
} else if (address < 0xC000) {
return &exram[address - 0xA000];
} else if (address < 0xE000) {
return &wram[address - 0xC000];
} else if (address < 0xFE00) {
return &wram[address - 0xE000];
} else {
return &hram[address - 0XFE00];
}
}
void reset() void reset()
{ {
FILE *f = fopen("dmg_boot.bin", "rb"); FILE *f = fopen("dmg_boot.bin", "rb");
@@ -121,6 +140,7 @@ namespace mbc_none
mem::saveState = mbc_none::saveState; mem::saveState = mbc_none::saveState;
mem::loadState = mbc_none::loadState; mem::loadState = mbc_none::loadState;
mem::reset = mbc_none::reset; mem::reset = mbc_none::reset;
mem::rawPtr = mbc_none::rawPtr;
mbc_none::rom = rom; mbc_none::rom = rom;

26
mem.cpp
View File

@@ -12,9 +12,14 @@ namespace mem
void (*setTag)(uint16_t, uint8_t); void (*setTag)(uint16_t, uint8_t);
void (*saveState)(FILE*); void (*saveState)(FILE*);
void (*loadState)(FILE*); void (*loadState)(FILE*);
uint8_t*(*rawPtr)(uint16_t);
char *title = nullptr; char *title = nullptr;
uint16_t dma_address = 0;
uint8_t dma_pos = 160;
uint16_t dma_dots = 0;
void init(uint8_t* rom, const int size) void init(uint8_t* rom, const int size)
{ {
//if (memory) free(memory); //if (memory) free(memory);
@@ -33,4 +38,23 @@ namespace mem
}; };
} }
void init_dma_transfer(uint8_t source)
{
dma_address = source << 8;
dma_pos = 0;
dma_dots = 0;
}
void update_mapped(const uint32_t dt)
{
if (dma_pos<160) {
dma_dots += dt;
while (dma_dots >= 4 && dma_pos<160) {
dma_dots -= 4;
mem::writeMem(0xfe00|dma_pos, mem::readMem(dma_address|dma_pos));
dma_pos++;
}
}
}
} }

5
mem.h
View File

@@ -35,4 +35,9 @@ namespace mem
extern void (*saveState)(FILE*); extern void (*saveState)(FILE*);
extern void (*loadState)(FILE*); extern void (*loadState)(FILE*);
extern uint8_t*(*rawPtr)(uint16_t);
void init_dma_transfer(uint8_t source);
void update_mapped(const uint32_t dt);
} }

View File

@@ -1009,6 +1009,7 @@ namespace sm83
debug::setcursor(rPC); debug::setcursor(rPC);
debug::history::store(); debug::history::store();
mem::update_mapped(t);
return t; return t;
} }