mirror of https://github.com/mlaux/gb6.git
interrupt system, vblank, key input, don't know if any of it works
This commit is contained in:
parent
1b5f02ef7a
commit
5735d65470
|
@ -103,6 +103,54 @@ void fill_memory_editor(struct dmg *dmg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct key_input {
|
||||||
|
int scancode;
|
||||||
|
int button;
|
||||||
|
int field;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct key_input key_inputs[] = {
|
||||||
|
{ SDL_SCANCODE_D, BUTTON_RIGHT, FIELD_JOY },
|
||||||
|
{ SDL_SCANCODE_A, BUTTON_LEFT, FIELD_JOY },
|
||||||
|
{ SDL_SCANCODE_W, BUTTON_UP, FIELD_JOY },
|
||||||
|
{ SDL_SCANCODE_S, BUTTON_DOWN, FIELD_JOY },
|
||||||
|
{ SDL_SCANCODE_L, BUTTON_A, FIELD_ACTION },
|
||||||
|
{ SDL_SCANCODE_K, BUTTON_B, FIELD_ACTION },
|
||||||
|
{ SDL_SCANCODE_N, BUTTON_SELECT, FIELD_ACTION },
|
||||||
|
{ SDL_SCANCODE_M, BUTTON_START, FIELD_ACTION },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
int scancode_to_joy[] = {
|
||||||
|
SDL_SCANCODE_D,
|
||||||
|
SDL_SCANCODE_A,
|
||||||
|
SDL_SCANCODE_W,
|
||||||
|
SDL_SCANCODE_S,
|
||||||
|
SDL_SCANCODE_L,
|
||||||
|
SDL_SCANCODE_K,
|
||||||
|
SDL_SCANCODE_N,
|
||||||
|
SDL_SCANCODE_M
|
||||||
|
};
|
||||||
|
int scancode_buttons[] = {
|
||||||
|
BUTTON_RIGHT,
|
||||||
|
BUTTON_LEFT,
|
||||||
|
BUTTON_UP,
|
||||||
|
BUTTON_DOWN,
|
||||||
|
BUTTON_A,
|
||||||
|
BUTTON_B,
|
||||||
|
BUTTON_SELECT,
|
||||||
|
BUTTON_START,
|
||||||
|
};
|
||||||
|
int scancode_fields[] = {
|
||||||
|
FIELD_JOY,
|
||||||
|
FIELD_JOY,
|
||||||
|
FIELD_JOY,
|
||||||
|
FIELD_JOY,
|
||||||
|
FIELD_ACTION,
|
||||||
|
FIELD_ACTION,
|
||||||
|
FIELD_ACTION,
|
||||||
|
FIELD_ACTION,
|
||||||
|
};
|
||||||
|
|
||||||
// Main code
|
// Main code
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -112,6 +160,8 @@ int main(int argc, char *argv[])
|
||||||
struct lcd lcd = { 0 };
|
struct lcd lcd = { 0 };
|
||||||
|
|
||||||
int executed;
|
int executed;
|
||||||
|
int paused = 0;
|
||||||
|
int pause_next = 0;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("no rom specified\n");
|
printf("no rom specified\n");
|
||||||
|
@ -206,7 +256,12 @@ int main(int argc, char *argv[])
|
||||||
unsigned int lastDrawTime = 0, currentTime;
|
unsigned int lastDrawTime = 0, currentTime;
|
||||||
while (!done)
|
while (!done)
|
||||||
{
|
{
|
||||||
dmg_step(&dmg);
|
if (!paused) {
|
||||||
|
dmg_step(&dmg);
|
||||||
|
}
|
||||||
|
if (pause_next) {
|
||||||
|
paused = 1;
|
||||||
|
}
|
||||||
|
|
||||||
currentTime = SDL_GetTicks();
|
currentTime = SDL_GetTicks();
|
||||||
if (currentTime >= lastDrawTime + 16) {
|
if (currentTime >= lastDrawTime + 16) {
|
||||||
|
@ -219,10 +274,25 @@ int main(int argc, char *argv[])
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event))
|
||||||
{
|
{
|
||||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||||
if (event.type == SDL_QUIT)
|
if (event.type == SDL_QUIT) {
|
||||||
done = true;
|
done = true;
|
||||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
|
}
|
||||||
|
|
||||||
|
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE
|
||||||
|
&& event.window.windowID == SDL_GetWindowID(window)) {
|
||||||
done = true;
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
|
||||||
|
struct key_input *key = key_inputs;
|
||||||
|
while (key->scancode) {
|
||||||
|
if (key->scancode == event.key.keysym.scancode) {
|
||||||
|
dmg_set_button(&dmg, key->field, key->button, event.type == SDL_KEYDOWN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
key++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the Dear ImGui frame
|
// Start the Dear ImGui frame
|
||||||
|
@ -261,6 +331,20 @@ int main(int argc, char *argv[])
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("C", &c_flag);
|
ImGui::Checkbox("C", &c_flag);
|
||||||
|
|
||||||
|
if (ImGui::Button("Run")) {
|
||||||
|
paused = 0;
|
||||||
|
pause_next = 0;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Stop")) {
|
||||||
|
paused = 1;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Step")) {
|
||||||
|
paused = 0;
|
||||||
|
pause_next = 1;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
@ -271,7 +355,7 @@ int main(int argc, char *argv[])
|
||||||
convert_output(dmg.lcd);
|
convert_output(dmg.lcd);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, output_image);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, output_image);
|
||||||
ImGui::Image((void*)(intptr_t) texture, ImVec2(256, 256));
|
ImGui::Image((void*)(intptr_t) texture, ImVec2(512, 512));
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
@ -290,6 +374,7 @@ int main(int argc, char *argv[])
|
||||||
fill_memory_editor(&dmg);
|
fill_memory_editor(&dmg);
|
||||||
|
|
||||||
editor.DrawWindow("Memory", full_address_space, 0x10000, 0x0000);
|
editor.DrawWindow("Memory", full_address_space, 0x10000, 0x0000);
|
||||||
|
editor.DrawWindow("ROM", dmg.rom->data, 0x8000, 0);
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
76
src/cpu.c
76
src/cpu.c
|
@ -91,6 +91,7 @@ static void inc_with_carry(struct cpu *regs, u8 *reg)
|
||||||
clear_flag(regs, FLAG_SIGN);
|
clear_flag(regs, FLAG_SIGN);
|
||||||
if(*reg == 0xff || *reg == 0x0f)
|
if(*reg == 0xff || *reg == 0x0f)
|
||||||
set_flag(regs, FLAG_HALF_CARRY);
|
set_flag(regs, FLAG_HALF_CARRY);
|
||||||
|
else clear_flag(regs, FLAG_HALF_CARRY);
|
||||||
(*reg)++;
|
(*reg)++;
|
||||||
if(*reg == 0)
|
if(*reg == 0)
|
||||||
set_flag(regs, FLAG_ZERO);
|
set_flag(regs, FLAG_ZERO);
|
||||||
|
@ -102,6 +103,7 @@ static void dec_with_carry(struct cpu *regs, u8 *reg)
|
||||||
set_flag(regs, FLAG_SIGN);
|
set_flag(regs, FLAG_SIGN);
|
||||||
if(*reg == 0x00 || *reg == 0x10)
|
if(*reg == 0x00 || *reg == 0x10)
|
||||||
set_flag(regs, FLAG_HALF_CARRY);
|
set_flag(regs, FLAG_HALF_CARRY);
|
||||||
|
else clear_flag(regs, FLAG_HALF_CARRY);
|
||||||
(*reg)--;
|
(*reg)--;
|
||||||
if(*reg == 0)
|
if(*reg == 0)
|
||||||
set_flag(regs, FLAG_ZERO);
|
set_flag(regs, FLAG_ZERO);
|
||||||
|
@ -218,10 +220,22 @@ static void add(struct cpu *cpu, u8 value, int with_carry)
|
||||||
sum_full++;
|
sum_full++;
|
||||||
}
|
}
|
||||||
sum_trunc = (u8) sum_full;
|
sum_trunc = (u8) sum_full;
|
||||||
set_flag(cpu, sum_trunc == 0 ? FLAG_ZERO : 0);
|
if (sum_trunc == 0) {
|
||||||
|
set_flag(cpu, FLAG_ZERO);
|
||||||
|
} else {
|
||||||
|
clear_flag(cpu, FLAG_ZERO);
|
||||||
|
}
|
||||||
clear_flag(cpu, FLAG_SIGN);
|
clear_flag(cpu, FLAG_SIGN);
|
||||||
set_flag(cpu, sum_full > sum_trunc ? FLAG_CARRY : 0);
|
if (sum_full > sum_trunc) {
|
||||||
// TODO H
|
set_flag(cpu, FLAG_CARRY);
|
||||||
|
} else {
|
||||||
|
clear_flag(cpu, FLAG_CARRY);
|
||||||
|
}
|
||||||
|
if (((cpu->a & 0xf) + (value & 0xf)) & 0x10) {
|
||||||
|
set_flag(cpu, FLAG_HALF_CARRY);
|
||||||
|
} else {
|
||||||
|
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||||
|
}
|
||||||
cpu->a = sum_trunc;
|
cpu->a = sum_trunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,12 +253,16 @@ static void subtract(struct cpu *cpu, u8 value, int with_carry, int just_compare
|
||||||
clear_flag(cpu, FLAG_ZERO);
|
clear_flag(cpu, FLAG_ZERO);
|
||||||
}
|
}
|
||||||
set_flag(cpu, FLAG_SIGN);
|
set_flag(cpu, FLAG_SIGN);
|
||||||
if (sum_full < sum_trunc) {
|
if (value > cpu->a) {
|
||||||
set_flag(cpu, FLAG_CARRY);
|
set_flag(cpu, FLAG_CARRY);
|
||||||
} else {
|
} else {
|
||||||
clear_flag(cpu, FLAG_CARRY);
|
clear_flag(cpu, FLAG_CARRY);
|
||||||
}
|
}
|
||||||
// TODO H
|
if (((cpu->a & 0xf) - (value & 0xf)) & 0x10) {
|
||||||
|
set_flag(cpu, FLAG_HALF_CARRY);
|
||||||
|
} else {
|
||||||
|
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||||
|
}
|
||||||
|
|
||||||
if (!just_compare) {
|
if (!just_compare) {
|
||||||
cpu->a = sum_trunc;
|
cpu->a = sum_trunc;
|
||||||
|
@ -382,14 +400,50 @@ static void conditional_jump(struct cpu *cpu, u8 opc, u8 neg_op, int flag) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u16 handlers[] = { 0x40, 0x48, 0x50, 0x58, 0x60 };
|
||||||
|
|
||||||
|
static u16 check_interrupts(struct cpu *cpu)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if (!cpu->interrupt_enable) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 enabled = cpu->mem_read(cpu->mem_model, 0xffff);
|
||||||
|
u16 requested = cpu->mem_read(cpu->mem_model, 0xff0f);
|
||||||
|
|
||||||
|
for (k = 0; k < NUM_INTERRUPTS; k++) {
|
||||||
|
int check = 1 << k;
|
||||||
|
if ((enabled & check) && (requested & check)) {
|
||||||
|
// clear request flag for this interrupt and disable all further
|
||||||
|
// interrupts until service routine executes EI or RETI
|
||||||
|
cpu->mem_write(cpu->mem_model, 0xff0f, requested & ~check);
|
||||||
|
cpu->interrupt_enable = 0;
|
||||||
|
return handlers[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void cpu_step(struct cpu *cpu)
|
void cpu_step(struct cpu *cpu)
|
||||||
{
|
{
|
||||||
u8 temp;
|
u8 temp;
|
||||||
u16 temp16;
|
u16 temp16, intr_dest;
|
||||||
|
|
||||||
|
intr_dest = check_interrupts(cpu);
|
||||||
|
if (intr_dest) {
|
||||||
|
push(cpu, cpu->pc);
|
||||||
|
cpu->pc = intr_dest;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
u8 opc = cpu->mem_read(cpu->mem_model, cpu->pc);
|
u8 opc = cpu->mem_read(cpu->mem_model, cpu->pc);
|
||||||
#ifdef GB6_DEBUG
|
#ifdef GB6_DEBUG
|
||||||
printf("0x%04x %s\n", cpu->pc, instructions[opc].format);
|
printf("0x%04x %s\n", cpu->pc, instructions[opc].format);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
cpu->cycle_count += instructions[opc].cycles;
|
cpu->cycle_count += instructions[opc].cycles;
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
|
@ -727,8 +781,10 @@ void cpu_step(struct cpu *cpu)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xca: // JP Z, u16
|
case 0xca: // JP Z, u16
|
||||||
|
temp16 = read16(cpu, cpu->pc);
|
||||||
|
cpu->pc += 2;
|
||||||
if (flag_isset(cpu, FLAG_ZERO)) {
|
if (flag_isset(cpu, FLAG_ZERO)) {
|
||||||
cpu->pc = read16(cpu, cpu->pc);
|
cpu->pc = temp16;
|
||||||
cpu->cycle_count += instructions[opc].cycles_branch - instructions[opc].cycles;
|
cpu->cycle_count += instructions[opc].cycles_branch - instructions[opc].cycles;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -742,6 +798,10 @@ void cpu_step(struct cpu *cpu)
|
||||||
case 0xd5: // PUSH DE
|
case 0xd5: // PUSH DE
|
||||||
push(cpu, read_de(cpu));
|
push(cpu, read_de(cpu));
|
||||||
break;
|
break;
|
||||||
|
case 0xd9: // RETI
|
||||||
|
cpu->pc = pop(cpu);
|
||||||
|
cpu->interrupt_enable = 1;
|
||||||
|
break;
|
||||||
case 0xe0: // LD (a8),A
|
case 0xe0: // LD (a8),A
|
||||||
write8(cpu, 0xff00 + read8(cpu, cpu->pc), cpu->a);
|
write8(cpu, 0xff00 + read8(cpu, cpu->pc), cpu->a);
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
|
@ -773,6 +833,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
cpu->a = read8(cpu, 0xff00 + cpu->c);
|
cpu->a = read8(cpu, 0xff00 + cpu->c);
|
||||||
break;
|
break;
|
||||||
case 0xf3: // DI
|
case 0xf3: // DI
|
||||||
|
cpu->interrupt_enable = 0;
|
||||||
break;
|
break;
|
||||||
case 0xf5: // PUSH AF
|
case 0xf5: // PUSH AF
|
||||||
push(cpu, read_af(cpu));
|
push(cpu, read_af(cpu));
|
||||||
|
@ -782,6 +843,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
cpu->pc += 2;
|
cpu->pc += 2;
|
||||||
break;
|
break;
|
||||||
case 0xfb: // EI
|
case 0xfb: // EI
|
||||||
|
cpu->interrupt_enable = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unknown opcode 0x%02x %s\n", opc, instructions[opc].format);
|
printf("unknown opcode 0x%02x %s\n", opc, instructions[opc].format);
|
||||||
|
|
|
@ -16,6 +16,7 @@ struct cpu
|
||||||
u16 sp;
|
u16 sp;
|
||||||
u16 pc;
|
u16 pc;
|
||||||
u32 cycle_count;
|
u32 cycle_count;
|
||||||
|
u8 interrupt_enable;
|
||||||
|
|
||||||
u8 (*mem_read)(void *, u16);
|
u8 (*mem_read)(void *, u16);
|
||||||
void (*mem_write)(void *, u16, u8);
|
void (*mem_write)(void *, u16, u8);
|
||||||
|
@ -37,4 +38,11 @@ int flag_isset(struct cpu *cpu, int flag);
|
||||||
#define FLAG_HALF_CARRY 0x20
|
#define FLAG_HALF_CARRY 0x20
|
||||||
#define FLAG_CARRY 0x10
|
#define FLAG_CARRY 0x10
|
||||||
|
|
||||||
|
#define INT_VBLANK (1 << 0)
|
||||||
|
#define INT_LCDSTAT (1 << 1)
|
||||||
|
#define INT_TIMER (1 << 2)
|
||||||
|
#define INT_SERIAL (1 << 3)
|
||||||
|
#define INT_JOYPAD (1 << 4)
|
||||||
|
#define NUM_INTERRUPTS 5
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
48
src/dmg.c
48
src/dmg.c
|
@ -13,6 +13,33 @@ void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom, struct lcd *lcd)
|
||||||
dmg->cpu = cpu;
|
dmg->cpu = cpu;
|
||||||
dmg->rom = rom;
|
dmg->rom = rom;
|
||||||
dmg->lcd = lcd;
|
dmg->lcd = lcd;
|
||||||
|
|
||||||
|
dmg->joypad = 0xf; // nothing pressed
|
||||||
|
dmg->action_buttons = 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dmg_set_button(struct dmg *dmg, int field, int button, int pressed)
|
||||||
|
{
|
||||||
|
u8 *mod;
|
||||||
|
if (field == FIELD_JOY) {
|
||||||
|
mod = &dmg->joypad;
|
||||||
|
} else if (field == FIELD_ACTION) {
|
||||||
|
mod = &dmg->action_buttons;
|
||||||
|
} else {
|
||||||
|
printf("setting invalid button state\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pressed) {
|
||||||
|
*mod &= ~button;
|
||||||
|
} else {
|
||||||
|
*mod |= button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 get_button_state(struct dmg *dmg)
|
||||||
|
{
|
||||||
|
return dmg->action_selected ? dmg->action_buttons : dmg->joypad;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 dmg_read(void *_dmg, u16 address)
|
u8 dmg_read(void *_dmg, u16 address)
|
||||||
|
@ -37,6 +64,12 @@ u8 dmg_read(void *_dmg, u16 address)
|
||||||
return lcd_read(dmg->lcd, address);
|
return lcd_read(dmg->lcd, address);
|
||||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
return dmg->zero_page[address - 0xff80];
|
return dmg->zero_page[address - 0xff80];
|
||||||
|
} else if (address == 0xff00) {
|
||||||
|
return get_button_state(dmg);
|
||||||
|
} else if (address == 0xff0f) {
|
||||||
|
return dmg->interrupt_requested;
|
||||||
|
} else if (address == 0xffff) {
|
||||||
|
return dmg->interrupt_enabled;
|
||||||
} else {
|
} else {
|
||||||
// not sure about any of this yet
|
// not sure about any of this yet
|
||||||
// commented out bc of memory view window
|
// commented out bc of memory view window
|
||||||
|
@ -65,11 +98,21 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
||||||
lcd_write(dmg->lcd, address, data);
|
lcd_write(dmg->lcd, address, data);
|
||||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
dmg->zero_page[address - 0xff80] = data;
|
dmg->zero_page[address - 0xff80] = data;
|
||||||
|
} else if (address == 0xff00) {
|
||||||
|
dmg->action_selected = data & (1 << 5);
|
||||||
|
} else if (address == 0xff0f) {
|
||||||
|
dmg->interrupt_requested = data;
|
||||||
|
} else if (address == 0xffff) {
|
||||||
|
dmg->interrupt_enabled = data;
|
||||||
} else {
|
} else {
|
||||||
// not sure about any of this yet
|
// not sure about any of this yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void exit(int);
|
|
||||||
|
void dmg_request_interrupt(struct dmg *dmg, int nr)
|
||||||
|
{
|
||||||
|
dmg->interrupt_requested |= nr;
|
||||||
|
}
|
||||||
|
|
||||||
void dmg_step(void *_dmg)
|
void dmg_step(void *_dmg)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +128,7 @@ void dmg_step(void *_dmg)
|
||||||
int next_scanline = lcd_step(dmg->lcd);
|
int next_scanline = lcd_step(dmg->lcd);
|
||||||
if (next_scanline == 144) {
|
if (next_scanline == 144) {
|
||||||
// vblank has started, draw all the stuff from ram into the lcd
|
// vblank has started, draw all the stuff from ram into the lcd
|
||||||
|
dmg_request_interrupt(dmg, INT_VBLANK);
|
||||||
|
|
||||||
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
|
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
|
||||||
int bg_base = (lcdc & LCDC_BG_TILE_MAP) ? 0x9c00 : 0x9800;
|
int bg_base = (lcdc & LCDC_BG_TILE_MAP) ? 0x9c00 : 0x9800;
|
||||||
|
@ -92,8 +136,6 @@ void dmg_step(void *_dmg)
|
||||||
int use_unsigned = lcdc & LCDC_BG_TILE_DATA;
|
int use_unsigned = lcdc & LCDC_BG_TILE_DATA;
|
||||||
int tilebase = use_unsigned ? 0x8000 : 0x9000;
|
int tilebase = use_unsigned ? 0x8000 : 0x9000;
|
||||||
|
|
||||||
printf("tile map: %04x, tile data: %04x\n", bg_base, tilebase);
|
|
||||||
|
|
||||||
int k = 0, off = 0;
|
int k = 0, off = 0;
|
||||||
int tile_y = 0, tile_x = 0;
|
int tile_y = 0, tile_x = 0;
|
||||||
for (tile_y = 0; tile_y < 32; tile_y++) {
|
for (tile_y = 0; tile_y < 32; tile_y++) {
|
||||||
|
|
19
src/dmg.h
19
src/dmg.h
|
@ -5,6 +5,18 @@
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
|
||||||
|
#define FIELD_JOY 1
|
||||||
|
#define FIELD_ACTION 2
|
||||||
|
|
||||||
|
#define BUTTON_RIGHT (1 << 0)
|
||||||
|
#define BUTTON_LEFT (1 << 1)
|
||||||
|
#define BUTTON_UP (1 << 2)
|
||||||
|
#define BUTTON_DOWN (1 << 3)
|
||||||
|
#define BUTTON_A (1 << 0)
|
||||||
|
#define BUTTON_B (1 << 1)
|
||||||
|
#define BUTTON_SELECT (1 << 2)
|
||||||
|
#define BUTTON_START (1 << 3)
|
||||||
|
|
||||||
struct dmg {
|
struct dmg {
|
||||||
struct cpu *cpu;
|
struct cpu *cpu;
|
||||||
struct rom *rom;
|
struct rom *rom;
|
||||||
|
@ -13,9 +25,16 @@ struct dmg {
|
||||||
u8 video_ram[0x2000];
|
u8 video_ram[0x2000];
|
||||||
u8 zero_page[0x80];
|
u8 zero_page[0x80];
|
||||||
u32 last_lcd_update;
|
u32 last_lcd_update;
|
||||||
|
int action_selected; // non-0 if A/B/start/select selected, 0 for directions
|
||||||
|
u8 interrupt_enabled;
|
||||||
|
u8 interrupt_requested;
|
||||||
|
|
||||||
|
u8 joypad;
|
||||||
|
u8 action_buttons;
|
||||||
};
|
};
|
||||||
|
|
||||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom, struct lcd *lcd);
|
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom, struct lcd *lcd);
|
||||||
|
void dmg_set_button(struct dmg *dmg, int field, int button, int pressed);
|
||||||
|
|
||||||
// why did i make these void *
|
// why did i make these void *
|
||||||
u8 dmg_read(void *dmg, u16 address);
|
u8 dmg_read(void *dmg, u16 address);
|
||||||
|
|
Loading…
Reference in New Issue