Browse Source

Flesh out system ports; clean up IO; stubs.

master
Ben Kurtovic 8 years ago
parent
commit
26dcf57f1b
9 changed files with 91 additions and 127 deletions
  1. +0
    -3
      src/gamegear.c
  2. +67
    -43
      src/io.c
  3. +1
    -2
      src/io.h
  4. +10
    -0
      src/psg.c
  5. +1
    -0
      src/psg.h
  6. +0
    -39
      src/vdp.c
  7. +0
    -31
      src/z80.c
  8. +0
    -1
      src/z80.h
  9. +12
    -8
      src/z80_ops.inc.c

+ 0
- 3
src/gamegear.c View File

@@ -207,9 +207,6 @@ const char* gamegear_get_exception(GameGear *gg)
case Z80_EXC_UNIMPLEMENTED_OPCODE:
SET_EXC("unimplemented opcode: 0x%02X", gg->cpu.exc_data)
break;
case Z80_EXC_IO_ERROR:
SET_EXC("I/O error on port 0x%02X", gg->cpu.exc_data)
break;
default:
SET_EXC("unknown exception")
break;


+ 67
- 43
src/io.c View File

@@ -2,6 +2,7 @@
Released under the terms of the MIT License. See LICENSE for details. */

#include "io.h"
#include "logging.h"

/*
Initialize an IO object.
@@ -17,7 +18,12 @@ void io_init(IO *io, VDP *vdp, PSG *psg)
*/
void io_power(IO *io)
{
io->except = false;
io->ports[0x00] = 0xC0; // Overseas mode, NTSC
io->ports[0x01] = 0x7F;
io->ports[0x02] = 0xFF;
io->ports[0x03] = 0x00;
io->ports[0x04] = 0xFF;
io->ports[0x05] = 0x00;
}

/*
@@ -29,37 +35,67 @@ bool io_check_irq(IO *io)
}

/*
Read from one of the system ports, which are numbered from 0x00 to 0x06.
*/
static uint8_t read_system_port(IO *io, uint8_t port)
{
switch (port) {
case 0x00:
// TODO: MSB is state of START button
return (io->ports[port] & 0x7F) | (0 << 7);
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
return io->ports[port];
}
return 0xFF;
}

/*
Write to one of the system ports, which are numbered from 0x00 to 0x06.
*/
static void write_system_port(IO *io, uint8_t port, uint8_t value)
{
switch (port) {
case 0x01:
case 0x02:
case 0x03:
io->ports[port] = value;
break;
case 0x05:
io->ports[port] = value & 0xF8;
break;
case 0x06:
psg_stereo(io->psg, value);
break;
}
}

/*
Read and return a byte from the given port.
*/
uint8_t io_port_read(IO *io, uint8_t port)
{
if (port <= 0x06) {
if (port == 0x00)
return 0xC0;
// TODO: GG specific registers; initial state: C0 7F FF 00 FF 00 FF
} else if (port <= 0x3F) {
if (port <= 0x06)
return read_system_port(io, port);
else if (port <= 0x3F)
return 0xFF;
} else if (port <= 0x7F && !(port % 2)) {
else if (port <= 0x7F && !(port % 2))
return io->vdp->v_counter;
} else if (port <= 0x7F) {
else if (port <= 0x7F)
return io->vdp->h_counter;
} else if (port <= 0xBF && !(port % 2)) {
else if (port <= 0xBF && !(port % 2))
return vdp_read_data(io->vdp);
} else if (port <= 0xBF) {
else if (port <= 0xBF)
return vdp_read_control(io->vdp);
} else if (port == 0xCD || port == 0xDC) {
// TODO: Return the I/O port A/B register
return 0xFF;
} else if (port == 0xC1 || port == 0xDD) {
// TODO: Return the I/O port B/misc. register
else if (port == 0xCD || port == 0xDC)
return 0xFF; // TODO: Return the I/O port A/B register
else if (port == 0xC1 || port == 0xDD)
return 0xFF; // TODO: Return the I/O port B/misc. register
else
return 0xFF;
} else {
return 0xFF;
}

io->except = true;
io->exc_port = port;
return 0;
}

/*
@@ -67,28 +103,16 @@ uint8_t io_port_read(IO *io, uint8_t port)
*/
void io_port_write(IO *io, uint8_t port, uint8_t value)
{
if (port <= 0x06) {
// TODO: GG specific registers; initial state: C0 7F FF 00 FF 00 FF
goto except;
} else if (port <= 0x3F && !(port % 2)) {
// TODO: Write to memory control register
goto except;
} else if (port <= 0x3F) {
// TODO: Write to I/O control register
goto except;
} else if (port <= 0x7F) {
if (port <= 0x06)
write_system_port(io, port, value);
else if (port <= 0x3F && !(port % 2))
return; // TODO: Write to memory control register
else if (port <= 0x3F)
return; // TODO: Write to I/O control register
else if (port <= 0x7F)
psg_write(io->psg, value);
} else if (port <= 0xBF && !(port % 2)) {
else if (port <= 0xBF && !(port % 2))
vdp_write_data(io->vdp, value);
} else if (port <= 0xBF) {
else if (port <= 0xBF)
vdp_write_control(io->vdp, value);
} else {
return;
}

return;

except:
io->except = true;
io->exc_port = port;
}

+ 1
- 2
src/io.h View File

@@ -14,8 +14,7 @@
typedef struct {
VDP *vdp;
PSG *psg;
bool except;
uint8_t exc_port;
uint8_t ports[6];
} IO;

/* Functions */


+ 10
- 0
src/psg.c View File

@@ -41,3 +41,13 @@ void psg_write(PSG *psg, uint8_t byte)
(void) psg;
TRACE("PSG ignoring write: 0x%02X", byte)
}

/*
Send a byte to the PSG's stereo control.
*/
void psg_stereo(PSG *psg, uint8_t byte)
{
// TODO
(void) psg;
TRACE("PSG ignoring stereo: 0x%02X", byte)
}

+ 1
- 0
src/psg.h View File

@@ -19,3 +19,4 @@ void psg_init(PSG*);
void psg_free(PSG*);
void psg_power(PSG*);
void psg_write(PSG*, uint8_t);
void psg_stereo(PSG*, uint8_t);

+ 0
- 39
src/vdp.c View File

@@ -433,43 +433,4 @@ void vdp_dump_registers(const VDP *vdp)
DEBUG("- $08: 0x%02X (HS)", regs[0x08])
DEBUG("- $09: 0x%02X (VS)", regs[0x09])
DEBUG("- $0A: 0x%02X (LC)", regs[0x0A])

// TODO: remove me!
DEBUG("Dumping CRAM:")
for (uint8_t i = 0; i < 32; i += 8) {
uint16_t w[8];
for (uint8_t j = 0; j < 8; j++)
w[j] = get_color(vdp, (i + j) % 16, i & 16);

DEBUG("- %04X %04X %04X %04X %04X %04X %04X %04X",
w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7])
}

return;

DEBUG("Dumping PNT:")
for (uint16_t i = 0; i < 18; i++) {
uint16_t w[20];
for (uint8_t j = 0; j < 20; j++)
w[j] = get_background_tile(vdp, i + 3, j + 6);

DEBUG("- %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X"
" %03X %03X %03X %03X %03X %03X %03X %03X %03X %03X",
w[0x00], w[0x01], w[0x02], w[0x03], w[0x04], w[0x05], w[0x06],
w[0x07], w[0x08], w[0x09], w[0x0A], w[0x0B], w[0x0C], w[0x0D],
w[0x0E], w[0x0F], w[0x10], w[0x11], w[0x12], w[0x13])
}

DEBUG("Dumping PGT:")
for (uint16_t i = 0; i < /* 512 */ 32; i++) {
uint32_t w[8];
for (uint8_t j = 0; j < 8; j++)
w[j] = vdp->vram[32 * i + 4 * j] +
(vdp->vram[32 * i + 4 * j + 1] << 8) +
(vdp->vram[32 * i + 4 * j + 2] << 16) +
(vdp->vram[32 * i + 4 * j + 3] << 24);

DEBUG("- 0x%04X: %08X %08X %08X %08X %08X %08X %08X %08X", i,
w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7])
}
}

+ 0
- 31
src/z80.c View File

@@ -130,37 +130,6 @@ static inline uint16_t stack_pop(Z80 *z80)
}

/*
Check for errors after an I/O operation.
*/
static void handle_io_errors(Z80 *z80)
{
if (z80->io->except) {
z80->except = true;
z80->exc_code = Z80_EXC_IO_ERROR;
z80->exc_data = z80->io->exc_port;
}
}

/*
Read and return a byte from the given port, and check for errors.
*/
static inline uint8_t read_port(Z80 *z80, uint8_t port)
{
uint8_t value = io_port_read(z80->io, port);
handle_io_errors(z80);
return value;
}

/*
Write a byte to the given port, and check for errors.
*/
static inline void write_port(Z80 *z80, uint8_t port, uint8_t value)
{
io_port_write(z80->io, port, value);
handle_io_errors(z80);
}

/*
Extract an 8-bit register from the given opcode and return a pointer to it.
*/
static inline uint8_t* extract_reg(Z80 *z80, uint8_t opcode)


+ 0
- 1
src/z80.h View File

@@ -11,7 +11,6 @@

#define Z80_EXC_NOT_POWERED 0
#define Z80_EXC_UNIMPLEMENTED_OPCODE 1
#define Z80_EXC_IO_ERROR 2

/* Structs */



+ 12
- 8
src/z80_ops.inc.c View File

@@ -1969,7 +1969,7 @@ static uint8_t z80_inst_in_a_n(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t port = mmu_read_byte(z80->mmu, ++z80->regs.pc);
z80->regs.a = read_port(z80, port);
z80->regs.a = io_port_read(z80->io, port);
z80->regs.pc++;
return 11;
}
@@ -1980,7 +1980,7 @@ static uint8_t z80_inst_in_a_n(Z80 *z80, uint8_t opcode)
*/
static uint8_t z80_inst_in_r_c(Z80 *z80, uint8_t opcode)
{
uint8_t data = read_port(z80, z80->regs.c);
uint8_t data = io_port_read(z80->io, z80->regs.c);
if (opcode != 0x70)
*extract_reg(z80, opcode) = data;

@@ -1996,7 +1996,8 @@ static uint8_t z80_inst_in_r_c(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ini(Z80 *z80, uint8_t opcode)
{
(void) opcode;
mmu_write_byte(z80->mmu, z80->regs.hl, read_port(z80, z80->regs.c));
uint8_t data = io_port_read(z80->io, z80->regs.c);
mmu_write_byte(z80->mmu, z80->regs.hl, data);
set_flags_blockio(z80);

z80->regs.hl++;
@@ -2025,7 +2026,8 @@ static uint8_t z80_inst_inir(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ind(Z80 *z80, uint8_t opcode)
{
(void) opcode;
mmu_write_byte(z80->mmu, z80->regs.hl, read_port(z80, z80->regs.c));
uint8_t data = io_port_read(z80->io, z80->regs.c);
mmu_write_byte(z80->mmu, z80->regs.hl, data);
set_flags_blockio(z80);

z80->regs.hl--;
@@ -2055,7 +2057,7 @@ static uint8_t z80_inst_out_n_a(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t port = mmu_read_byte(z80->mmu, ++z80->regs.pc);
write_port(z80, port, z80->regs.a);
io_port_write(z80->io, port, z80->regs.a);
z80->regs.pc++;
return 11;
}
@@ -2068,7 +2070,7 @@ static uint8_t z80_inst_out_n_a(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_out_c_r(Z80 *z80, uint8_t opcode)
{
uint8_t value = opcode != 0x71 ? *extract_reg(z80, opcode) : 0;
write_port(z80, z80->regs.c, value);
io_port_write(z80->io, z80->regs.c, value);
z80->regs.pc++;
return 12;
}
@@ -2080,7 +2082,8 @@ static uint8_t z80_inst_out_c_r(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_outi(Z80 *z80, uint8_t opcode)
{
(void) opcode;
write_port(z80, z80->regs.c, mmu_read_byte(z80->mmu, z80->regs.hl));
uint8_t data = mmu_read_byte(z80->mmu, z80->regs.hl);
io_port_write(z80->io, z80->regs.c, data);
set_flags_blockio(z80);

z80->regs.hl++;
@@ -2109,7 +2112,8 @@ static uint8_t z80_inst_otir(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_outd(Z80 *z80, uint8_t opcode)
{
(void) opcode;
write_port(z80, z80->regs.c, mmu_read_byte(z80->mmu, z80->regs.hl));
uint8_t data = mmu_read_byte(z80->mmu, z80->regs.hl);
io_port_write(z80->io, z80->regs.c, data);
set_flags_blockio(z80);

z80->regs.hl--;


Loading…
Cancel
Save