Browse Source

Add Z80 INT support and VDP frame interrupts.

master
Ben Kurtovic 8 years ago
parent
commit
1b48fbe6a2
5 changed files with 53 additions and 1 deletions
  1. +11
    -0
      src/io.c
  2. +1
    -0
      src/io.h
  3. +18
    -1
      src/vdp.c
  4. +1
    -0
      src/vdp.h
  5. +22
    -0
      src/z80.c

+ 11
- 0
src/io.c View File

@@ -11,12 +11,23 @@ void io_init(IO *io, VDP *vdp)
io->vdp = vdp;
}

/*
"Power on" the IO object.
*/
void io_power(IO *io)
{
io->except = false;
}

/*
Return whether the IRQ line is currently active.
*/
bool io_check_irq(IO *io)
{
return vdp_assert_irq(io->vdp);
}

/*
Read and return a byte from the given port.
*/
uint8_t io_port_read(IO *io, uint8_t port)


+ 1
- 0
src/io.h View File

@@ -20,5 +20,6 @@ typedef struct {

void io_init(IO*, VDP*);
void io_power(IO*);
bool io_check_irq(IO*);
uint8_t io_port_read(IO*, uint8_t);
void io_port_write(IO*, uint8_t, uint8_t);

+ 18
- 1
src/vdp.c View File

@@ -60,6 +60,14 @@ void vdp_power(VDP *vdp)
}

/*
Return whether frame-completion interrupts are enabled.
*/
static bool should_frame_interrupt(const VDP *vdp)
{
return vdp->regs[0x01] & 0x20;
}

/*
Return the base address of the pattern name table.
*/
static uint16_t get_pnt_base(const VDP *vdp)
@@ -115,7 +123,8 @@ void vdp_simulate_line(VDP *vdp)
if (vdp->v_counter >= 0x18 && vdp->v_counter < 0xA8) {
// TODO: draw current line
}
// TODO: if (...) IRQ
if (vdp->v_counter == 0xC0)
vdp->stat_int = true;
advance_scanline(vdp);
}

@@ -225,6 +234,14 @@ void vdp_write_data(VDP *vdp, uint8_t byte)
}

/*
Return whether the VDP is currently asserting an interrupt.
*/
bool vdp_assert_irq(VDP *vdp)
{
return vdp->stat_int && should_frame_interrupt(vdp);
}

/*
@DEBUG_LEVEL
Print out all register values to stdout.
*/


+ 1
- 0
src/vdp.h View File

@@ -41,5 +41,6 @@ uint8_t vdp_read_control(VDP*);
uint8_t vdp_read_data(VDP*);
void vdp_write_control(VDP*, uint8_t);
void vdp_write_data(VDP*, uint8_t);
bool vdp_assert_irq(VDP*);

void vdp_dump_registers(const VDP*);

+ 22
- 0
src/z80.c View File

@@ -274,6 +274,24 @@ static inline uint8_t get_interrupt_mode(const Z80 *z80)
}

/*
Handle an active IRQ line. Return the number of cycles consumed.
*/
static inline uint8_t handle_interrupt(Z80 *z80)
{
z80->regfile.iff1 = z80->regfile.iff2 = 0;
stack_push(z80, z80->regfile.pc);

if (get_interrupt_mode(z80) < 2) {
z80->regfile.pc = 0x0038;
return 13;
} else {
uint16_t addr = (z80->regfile.i << 8) + 0xFF;
z80->regfile.pc = mmu_read_double(z80->mmu, addr);
return 19;
}
}

/*
Increment the refresh counter register, R.
*/
static inline void increment_refresh_counter(Z80 *z80)
@@ -324,6 +342,10 @@ bool z80_do_cycles(Z80 *z80, double cycles)
{
cycles += z80->pending_cycles;
while (cycles > 0 && !z80->except) {
if (io_check_irq(z80->io) && z80->regfile.iff1) {
cycles -= handle_interrupt(z80);
continue;
}
uint8_t opcode = mmu_read_byte(z80->mmu, z80->regfile.pc);
increment_refresh_counter(z80);
if (TRACE_LEVEL)


Loading…
Cancel
Save