mirror of
https://github.com/mlaux/gb6.git
synced 2024-06-07 07:29:34 +00:00
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);
|
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
|
// 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
|
// rotate
|
||||||
*reg <<= 1;
|
int result = reg << 1;
|
||||||
// restore leftmost (now rightmost) bit
|
// 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
|
// 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
|
// rotate
|
||||||
*reg >>= 1;
|
int result = reg >> 1;
|
||||||
// restore rightmost bit to left
|
// 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)
|
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)
|
static void push(struct cpu *cpu, u16 value)
|
||||||
{
|
{
|
||||||
write16(cpu, cpu->sp - 2, value & 0xff);
|
printf("sp=%04x\n", cpu->sp);
|
||||||
write16(cpu, cpu->sp - 1, value >> 8);
|
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;
|
cpu->sp -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 pop(struct cpu *cpu)
|
static u16 pop(struct cpu *cpu)
|
||||||
{
|
{
|
||||||
cpu->sp += 2;
|
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)
|
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 bit = (insn >> 3) & 0x7;
|
||||||
int reg = insn & 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) {
|
switch (op) {
|
||||||
case 0:
|
case 0:
|
||||||
|
write_reg(cpu, reg, funcs[bit](cpu, read_reg(cpu, reg)));
|
||||||
break;
|
break;
|
||||||
case 1: // BIT
|
case 1: // BIT
|
||||||
temp = read_reg(cpu, reg);
|
temp = read_reg(cpu, reg);
|
||||||
|
@ -332,7 +367,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
cpu->pc += 2;
|
cpu->pc += 2;
|
||||||
break;
|
break;
|
||||||
case 0x07: // RLCA
|
case 0x07: // RLCA
|
||||||
rotate_left(cpu, &cpu->a);
|
cpu->a = rotate_left(cpu, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0x08: // LD (a16),SP
|
case 0x08: // LD (a16),SP
|
||||||
write16(cpu, read16(cpu, cpu->pc), cpu->sp);
|
write16(cpu, read16(cpu, cpu->pc), cpu->sp);
|
||||||
|
@ -341,8 +376,11 @@ void cpu_step(struct cpu *cpu)
|
||||||
case 0x19: // ADD HL,DE
|
case 0x19: // ADD HL,DE
|
||||||
add16(cpu, read_de(cpu));
|
add16(cpu, read_de(cpu));
|
||||||
break;
|
break;
|
||||||
|
case 0x17: // RLA
|
||||||
|
cpu->a = rotate_left(cpu, cpu->a);
|
||||||
|
break;
|
||||||
case 0x1f: // RRA
|
case 0x1f: // RRA
|
||||||
rotate_right(cpu, &cpu->a);
|
cpu->a = rotate_right(cpu, cpu->a);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// incs and decs
|
// incs and decs
|
||||||
|
@ -481,7 +519,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
case 0x20: // JR NZ,r8
|
case 0x20: // JR NZ,r8
|
||||||
temp = read8(cpu, cpu->pc);
|
temp = read8(cpu, cpu->pc);
|
||||||
if (!flag_isset(cpu, FLAG_ZERO)) {
|
if (!flag_isset(cpu, FLAG_ZERO)) {
|
||||||
cpu->pc += *((signed char *) &temp);
|
cpu->pc += *((signed char *) &temp) + 1;
|
||||||
} else {
|
} else {
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
}
|
}
|
||||||
|
@ -500,6 +538,10 @@ void cpu_step(struct cpu *cpu)
|
||||||
cpu->sp = read16(cpu, cpu->pc);
|
cpu->sp = read16(cpu, cpu->pc);
|
||||||
cpu->pc += 2;
|
cpu->pc += 2;
|
||||||
break;
|
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
|
case 0x32: // LD (HL-), A
|
||||||
write8(cpu, read_hl(cpu), cpu->a);
|
write8(cpu, read_hl(cpu), cpu->a);
|
||||||
write_hl(cpu, read_hl(cpu) - 1);
|
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 0xf7: push(cpu, cpu->pc); cpu->pc = 0x30; break;
|
||||||
case 0xff: push(cpu, cpu->pc); cpu->pc = 0x38; 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:
|
case 0xcb:
|
||||||
extended_insn(cpu, read8(cpu, cpu->pc));
|
extended_insn(cpu, read8(cpu, cpu->pc));
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
|
@ -626,7 +674,7 @@ void cpu_step(struct cpu *cpu)
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
break;
|
break;
|
||||||
case 0xe2: // LD (C),A
|
case 0xe2: // LD (C),A
|
||||||
write8(cpu, cpu->c, cpu->a);
|
write8(cpu, 0xff00 + cpu->c, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0xea: // LD (a16),A
|
case 0xea: // LD (a16),A
|
||||||
write16(cpu, read16(cpu, cpu->pc), cpu->a);
|
write16(cpu, read16(cpu, cpu->pc), cpu->a);
|
||||||
|
@ -641,6 +689,9 @@ void cpu_step(struct cpu *cpu)
|
||||||
}
|
}
|
||||||
cpu->pc++;
|
cpu->pc++;
|
||||||
break;
|
break;
|
||||||
|
case 0xf2: // LD A,(C)
|
||||||
|
cpu->a = read8(cpu, 0xff00 + cpu->c);
|
||||||
|
break;
|
||||||
case 0xf3: // DI
|
case 0xf3: // DI
|
||||||
break;
|
break;
|
||||||
case 0xfb: // EI
|
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)
|
u8 dmg_read(void *_dmg, u16 address)
|
||||||
{
|
{
|
||||||
struct dmg *dmg = (struct dmg *) _dmg;
|
struct dmg *dmg = (struct dmg *) _dmg;
|
||||||
|
if (address < 0x100) {
|
||||||
|
return dmg_boot_rom[address];
|
||||||
|
}
|
||||||
if (address < 0x4000) {
|
if (address < 0x4000) {
|
||||||
return dmg->rom->data[address];
|
return dmg->rom->data[address];
|
||||||
} else if (address < 0x8000) {
|
} else if (address < 0x8000) {
|
||||||
|
@ -27,6 +30,8 @@ u8 dmg_read(void *_dmg, u16 address)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (address < 0xe000) {
|
} else if (address < 0xe000) {
|
||||||
return dmg->main_ram[address - 0xc000];
|
return dmg->main_ram[address - 0xc000];
|
||||||
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
|
return dmg->zero_page[address - 0xff80];
|
||||||
} else {
|
} else {
|
||||||
// not sure about any of this yet
|
// not sure about any of this yet
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -49,6 +54,8 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
||||||
// TODO switchable ram bank
|
// TODO switchable ram bank
|
||||||
} else if (address < 0xe000) {
|
} else if (address < 0xe000) {
|
||||||
dmg->main_ram[address - 0xc000] = data;
|
dmg->main_ram[address - 0xc000] = data;
|
||||||
|
} else if (address >= 0xff80 && address <= 0xfffe) {
|
||||||
|
dmg->zero_page[address - 0xff80] = data;
|
||||||
} else {
|
} else {
|
||||||
// not sure about any of this yet
|
// not sure about any of this yet
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
struct dmg {
|
struct dmg {
|
||||||
struct cpu *cpu;
|
struct cpu *cpu;
|
||||||
struct rom *rom;
|
struct rom *rom;
|
||||||
|
struct lcd *lcd;
|
||||||
u8 main_ram[0x2000];
|
u8 main_ram[0x2000];
|
||||||
u8 video_ram[0x2000];
|
u8 video_ram[0x2000];
|
||||||
|
u8 zero_page[0x80];
|
||||||
};
|
};
|
||||||
|
|
||||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom);
|
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom);
|
||||||
|
|
13
src/lcd.c
Normal file
13
src/lcd.c
Normal file
|
@ -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;
|
||||||
|
}
|
15
src/lcd.h
Normal file
15
src/lcd.h
Normal file
|
@ -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 cpu cpu;
|
||||||
struct rom rom;
|
struct rom rom;
|
||||||
struct dmg dmg;
|
struct dmg dmg;
|
||||||
|
int executed = 0;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("no rom specified\n");
|
printf("no rom specified\n");
|
||||||
|
@ -26,9 +27,9 @@ int main(int argc, char *argv[])
|
||||||
dmg_new(&dmg, &cpu, &rom);
|
dmg_new(&dmg, &cpu, &rom);
|
||||||
cpu_bind_mem_model(&cpu, &dmg, dmg_read, dmg_write);
|
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);
|
cpu_step(&cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user