mirror of https://github.com/mlaux/gb6.git
fix push and pop, add more extended instructions
This commit is contained in:
parent
ed785440fc
commit
b6966cb605
81
src/cpu.c
81
src/cpu.c
|
@ -137,24 +137,41 @@ static void dec_with_carry(struct cpu *regs, u8 *reg)
|
|||
set_flag(regs, FLAG_ZERO);
|
||||
}
|
||||
|
||||
static void rotate_left(struct cpu *regs, u8 *reg)
|
||||
static u8 rotate_left(struct cpu *regs, u8 reg)
|
||||
{
|
||||
// copy old leftmost bit to carry flag
|
||||
regs->f = (*reg & 0x80) >> 3 | (regs->f & ~FLAG_CARRY);
|
||||
regs->f = (reg & 0x80) >> 3 | (regs->f & ~FLAG_CARRY);
|
||||
// rotate
|
||||
*reg <<= 1;
|
||||
int result = reg << 1;
|
||||
// restore leftmost (now rightmost) bit
|
||||
*reg |= (regs->f & FLAG_CARRY) >> 4;
|
||||
result |= (regs->f & FLAG_CARRY) >> 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void rotate_right(struct cpu *regs, u8 *reg)
|
||||
static u8 rotate_right(struct cpu *regs, u8 reg)
|
||||
{
|
||||
// copy old rightmost bit to carry flag
|
||||
regs->f = (*reg & 0x01) << 4 | (regs->f & ~FLAG_CARRY);
|
||||
regs->f = (reg & 0x01) << 4 | (regs->f & ~FLAG_CARRY);
|
||||
// rotate
|
||||
*reg >>= 1;
|
||||
int result = reg >> 1;
|
||||
// restore rightmost bit to left
|
||||
*reg |= (regs->f & FLAG_CARRY) << 3;
|
||||
result |= (regs->f & FLAG_CARRY) << 3;
|
||||
return result;
|
||||
}
|
||||
|
||||
static u8 shift_left(struct cpu *cpu, u8 value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 shift_right(struct cpu *cpu, u8 value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 swap(struct cpu *cpu, u8 value)
|
||||
{
|
||||
return ((value & 0xf0) >> 4) | ((value & 0x0f) << 4);
|
||||
}
|
||||
|
||||
static void xor(struct cpu *regs, u8 value)
|
||||
|
@ -223,15 +240,21 @@ static void subtract(struct cpu *cpu, u8 value, int with_carry, int just_compare
|
|||
|
||||
static void push(struct cpu *cpu, u16 value)
|
||||
{
|
||||
write16(cpu, cpu->sp - 2, value & 0xff);
|
||||
write16(cpu, cpu->sp - 1, value >> 8);
|
||||
printf("sp=%04x\n", cpu->sp);
|
||||
printf("memory[sp-2] = %02x\n", value & 0xff);
|
||||
printf("memory[sp-1] = %02x\n", value >> 8);
|
||||
write8(cpu, cpu->sp - 2, value & 0xff);
|
||||
write8(cpu, cpu->sp - 1, value >> 8);
|
||||
cpu->sp -= 2;
|
||||
}
|
||||
|
||||
static u16 pop(struct cpu *cpu)
|
||||
{
|
||||
cpu->sp += 2;
|
||||
return read16(cpu, cpu->sp - 1) << 8 | read16(cpu, cpu->sp - 2);
|
||||
printf("sp=%04x\n", cpu->sp);
|
||||
printf("read memory[sp-2] = %02x\n", read8(cpu, cpu->sp - 2));
|
||||
printf("read memory[sp-1] = %02x\n", read8(cpu, cpu->sp - 1));
|
||||
return read8(cpu, cpu->sp - 1) << 8 | read8(cpu, cpu->sp - 2);
|
||||
}
|
||||
|
||||
static void add16(struct cpu *cpu, u16 src)
|
||||
|
@ -290,8 +313,20 @@ static void extended_insn(struct cpu *cpu, u8 insn)
|
|||
int bit = (insn >> 3) & 0x7;
|
||||
int reg = insn & 0x7;
|
||||
|
||||
u8 (*funcs[8])(struct cpu *, u8) = {
|
||||
rotate_left,
|
||||
rotate_right,
|
||||
rotate_left, // TODO non-carry version
|
||||
rotate_right,
|
||||
shift_left,
|
||||
shift_right,
|
||||
swap,
|
||||
shift_right // TODO SRL
|
||||
};
|
||||
|
||||
switch (op) {
|
||||
case 0:
|
||||
write_reg(cpu, reg, funcs[bit](cpu, read_reg(cpu, reg)));
|
||||
break;
|
||||
case 1: // BIT
|
||||
temp = read_reg(cpu, reg);
|
||||
|
@ -332,7 +367,7 @@ void cpu_step(struct cpu *cpu)
|
|||
cpu->pc += 2;
|
||||
break;
|
||||
case 0x07: // RLCA
|
||||
rotate_left(cpu, &cpu->a);
|
||||
cpu->a = rotate_left(cpu, cpu->a);
|
||||
break;
|
||||
case 0x08: // LD (a16),SP
|
||||
write16(cpu, read16(cpu, cpu->pc), cpu->sp);
|
||||
|
@ -341,8 +376,11 @@ void cpu_step(struct cpu *cpu)
|
|||
case 0x19: // ADD HL,DE
|
||||
add16(cpu, read_de(cpu));
|
||||
break;
|
||||
case 0x17: // RLA
|
||||
cpu->a = rotate_left(cpu, cpu->a);
|
||||
break;
|
||||
case 0x1f: // RRA
|
||||
rotate_right(cpu, &cpu->a);
|
||||
cpu->a = rotate_right(cpu, cpu->a);
|
||||
break;
|
||||
|
||||
// incs and decs
|
||||
|
@ -481,7 +519,7 @@ void cpu_step(struct cpu *cpu)
|
|||
case 0x20: // JR NZ,r8
|
||||
temp = read8(cpu, cpu->pc);
|
||||
if (!flag_isset(cpu, FLAG_ZERO)) {
|
||||
cpu->pc += *((signed char *) &temp);
|
||||
cpu->pc += *((signed char *) &temp) + 1;
|
||||
} else {
|
||||
cpu->pc++;
|
||||
}
|
||||
|
@ -500,6 +538,10 @@ void cpu_step(struct cpu *cpu)
|
|||
cpu->sp = read16(cpu, cpu->pc);
|
||||
cpu->pc += 2;
|
||||
break;
|
||||
case 0x22: // LD (HL+), A
|
||||
write8(cpu, read_hl(cpu), cpu->a);
|
||||
write_hl(cpu, read_hl(cpu) + 1);
|
||||
break;
|
||||
case 0x32: // LD (HL-), A
|
||||
write8(cpu, read_hl(cpu), cpu->a);
|
||||
write_hl(cpu, read_hl(cpu) - 1);
|
||||
|
@ -613,6 +655,12 @@ void cpu_step(struct cpu *cpu)
|
|||
case 0xf7: push(cpu, cpu->pc); cpu->pc = 0x30; break;
|
||||
case 0xff: push(cpu, cpu->pc); cpu->pc = 0x38; break;
|
||||
|
||||
case 0xc1: // POP BC
|
||||
write_bc(cpu, pop(cpu));
|
||||
break;
|
||||
case 0xc5: // PUSH BC
|
||||
push(cpu, read_bc(cpu));
|
||||
break;
|
||||
case 0xcb:
|
||||
extended_insn(cpu, read8(cpu, cpu->pc));
|
||||
cpu->pc++;
|
||||
|
@ -626,7 +674,7 @@ void cpu_step(struct cpu *cpu)
|
|||
cpu->pc++;
|
||||
break;
|
||||
case 0xe2: // LD (C),A
|
||||
write8(cpu, cpu->c, cpu->a);
|
||||
write8(cpu, 0xff00 + cpu->c, cpu->a);
|
||||
break;
|
||||
case 0xea: // LD (a16),A
|
||||
write16(cpu, read16(cpu, cpu->pc), cpu->a);
|
||||
|
@ -641,6 +689,9 @@ void cpu_step(struct cpu *cpu)
|
|||
}
|
||||
cpu->pc++;
|
||||
break;
|
||||
case 0xf2: // LD A,(C)
|
||||
cpu->a = read8(cpu, 0xff00 + cpu->c);
|
||||
break;
|
||||
case 0xf3: // DI
|
||||
break;
|
||||
case 0xfb: // EI
|
||||
|
|
|
@ -15,6 +15,9 @@ void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom)
|
|||
u8 dmg_read(void *_dmg, u16 address)
|
||||
{
|
||||
struct dmg *dmg = (struct dmg *) _dmg;
|
||||
if (address < 0x100) {
|
||||
return dmg_boot_rom[address];
|
||||
}
|
||||
if (address < 0x4000) {
|
||||
return dmg->rom->data[address];
|
||||
} else if (address < 0x8000) {
|
||||
|
@ -27,6 +30,8 @@ u8 dmg_read(void *_dmg, u16 address)
|
|||
return 0;
|
||||
} else if (address < 0xe000) {
|
||||
return dmg->main_ram[address - 0xc000];
|
||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||
return dmg->zero_page[address - 0xff80];
|
||||
} else {
|
||||
// not sure about any of this yet
|
||||
return 0;
|
||||
|
@ -49,6 +54,8 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
|||
// TODO switchable ram bank
|
||||
} else if (address < 0xe000) {
|
||||
dmg->main_ram[address - 0xc000] = data;
|
||||
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||
dmg->zero_page[address - 0xff80] = data;
|
||||
} else {
|
||||
// not sure about any of this yet
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
struct dmg {
|
||||
struct cpu *cpu;
|
||||
struct rom *rom;
|
||||
struct lcd *lcd;
|
||||
u8 main_ram[0x2000];
|
||||
u8 video_ram[0x2000];
|
||||
u8 zero_page[0x80];
|
||||
};
|
||||
|
||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "lcd.h"
|
||||
|
||||
void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value)
|
||||
{
|
||||
if (x >= LCD_WIDTH || y >= LCD_HEIGHT) {
|
||||
printf("warning: trying to write to (%d, %d) outside of lcd bounds\n", x, y);
|
||||
return;
|
||||
}
|
||||
lcd->pixels[y * LCD_WIDTH + x] = value;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _LCD_H
|
||||
#define _LCD_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define LCD_WIDTH 160
|
||||
#define LCD_HEIGHT 144
|
||||
|
||||
struct lcd {
|
||||
u8 *pixels;
|
||||
};
|
||||
|
||||
void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value);
|
||||
|
||||
#endif
|
|
@ -9,6 +9,7 @@ int main(int argc, char *argv[])
|
|||
struct cpu cpu;
|
||||
struct rom rom;
|
||||
struct dmg dmg;
|
||||
int executed = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("no rom specified\n");
|
||||
|
@ -26,9 +27,9 @@ int main(int argc, char *argv[])
|
|||
dmg_new(&dmg, &cpu, &rom);
|
||||
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
||||
|
||||
cpu.pc = 0x100;
|
||||
cpu.pc = 0;
|
||||
|
||||
while (1) {
|
||||
for (; executed < 100000; executed++) {
|
||||
cpu_step(&cpu);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue