Browse Source

Add button input; fix background scrolling bug.

master
Ben Kurtovic 8 years ago
parent
commit
e48d7daa0d
6 changed files with 107 additions and 17 deletions
  1. +43
    -6
      src/emulator.c
  2. +14
    -0
      src/gamegear.c
  3. +12
    -1
      src/gamegear.h
  4. +22
    -4
      src/io.c
  5. +4
    -0
      src/io.h
  6. +12
    -6
      src/vdp.c

+ 43
- 6
src/emulator.c View File

@@ -86,17 +86,54 @@ static void draw_frame()
}

/*
Handle a keyboard press; translate it into a Game Gear button press.
*/
static void handle_keypress(GameGear *gg, SDL_Keycode key, bool state)
{
GGButton button;
switch (key) {
case SDLK_UP:
case SDLK_w:
button = BUTTON_UP; break;
case SDLK_DOWN:
case SDLK_s:
button = BUTTON_DOWN; break;
case SDLK_LEFT:
case SDLK_a:
button = BUTTON_LEFT; break;
case SDLK_RIGHT:
case SDLK_d:
button = BUTTON_RIGHT; break;
case SDLK_j:
button = BUTTON_TRIGGER_1; break;
case SDLK_k:
button = BUTTON_TRIGGER_2; break;
case SDLK_RETURN:
button = BUTTON_START; break;
default:
return;
}
gamegear_input(gg, button, state);
}

/*
Handle SDL events, mainly quit events and button presses.
*/
static void handle_events(GameGear *gg)
{
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
gamegear_power_off(gg);
return;
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
gamegear_power_off(gg);
return;
case SDL_KEYDOWN:
handle_keypress(gg, event.key.keysym.sym, true);
break;
case SDL_KEYUP:
handle_keypress(gg, event.key.keysym.sym, false);
break;
}
// TODO: buttons
}
}



+ 14
- 0
src/gamegear.c View File

@@ -68,6 +68,20 @@ void gamegear_load(GameGear *gg, const ROM *rom)
}

/*
Update the GameGear's button/joystick state.

'state' should be true when the button is pressed, and false when it is
released.
*/
void gamegear_input(GameGear *gg, GGButton button, bool state)
{
if (button == BUTTON_START)
io_set_start(&gg->io, state);
else
io_set_button(&gg->io, button, state);
}

/*
Power on the GameGear.

This clears the exception buffer and executes boot code (e.g. clearing


+ 12
- 1
src/gamegear.h View File

@@ -34,13 +34,24 @@ typedef struct GameGear {
char exc_buffer[GG_EXC_BUFF_SIZE];
} GameGear;

typedef enum {
BUTTON_UP = 0,
BUTTON_DOWN = 1,
BUTTON_LEFT = 2,
BUTTON_RIGHT = 3,
BUTTON_TRIGGER_1 = 4,
BUTTON_TRIGGER_2 = 5,
BUTTON_START
} GGButton;

/* Functions */

GameGear* gamegear_create();
void gamegear_destroy(GameGear*);
void gamegear_load(GameGear*, const ROM*);
void gamegear_simulate(GameGear*);
void gamegear_power_off(GameGear*); // TODO: generic "gamegear_input()" with a power-off option
void gamegear_input(GameGear*, GGButton, bool);
void gamegear_power_off(GameGear*);

void gamegear_attach_callback(GameGear*, GGFrameCallback);
void gamegear_attach_display(GameGear*, uint32_t*);


+ 22
- 4
src/io.c View File

@@ -24,6 +24,9 @@ void io_power(IO *io)
io->ports[0x03] = 0x00;
io->ports[0x04] = 0xFF;
io->ports[0x05] = 0x00;

io->buttons = 0xFF;
io->start = true;
}

/*
@@ -35,14 +38,29 @@ bool io_check_irq(IO *io)
}

/*
Set the state of the given joystick button.
*/
void io_set_button(IO *io, uint8_t button, bool state)
{
io->buttons = (io->buttons & ~(1 << button)) | ((!state) << button);
}

/*
Set the state of the start button.
*/
void io_set_start(IO *io, bool state)
{
io->start = !state;
}

/*
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);
return (io->ports[port] & 0x7F) | (io->start << 7);
case 0x01:
case 0x02:
case 0x03:
@@ -91,9 +109,9 @@ uint8_t io_port_read(IO *io, uint8_t port)
else if (port <= 0xBF)
return vdp_read_control(io->vdp);
else if (port == 0xCD || port == 0xDC)
return 0xFF; // TODO: Return the I/O port A/B register
return io->buttons;
else if (port == 0xC1 || port == 0xDD)
return 0xFF; // TODO: Return the I/O port B/misc. register
return 0xFF; // TODO
else
return 0xFF;
}


+ 4
- 0
src/io.h View File

@@ -15,6 +15,8 @@ typedef struct {
VDP *vdp;
PSG *psg;
uint8_t ports[6];
uint8_t buttons;
bool start;
} IO;

/* Functions */
@@ -22,5 +24,7 @@ typedef struct {
void io_init(IO*, VDP*, PSG*);
void io_power(IO*);
bool io_check_irq(IO*);
void io_set_button(IO*, uint8_t, bool);
void io_set_start(IO*, bool);
uint8_t io_port_read(IO*, uint8_t);
void io_port_write(IO*, uint8_t, uint8_t);

+ 12
- 6
src/vdp.c View File

@@ -207,7 +207,7 @@ static void draw_background(VDP *vdp)
uint8_t start_col = get_bg_hscroll(vdp) >> 3;
uint8_t fine_scroll = get_bg_hscroll(vdp) % 8;

for (col = 6; col < 20 + 6; col++) {
for (col = 5; col < 20 + 6; col++) {
hcell = (32 - start_col + col) % 32;
uint16_t tile = get_background_tile(vdp, vcell, hcell);
uint16_t pattern = tile & 0x01FF;
@@ -217,13 +217,16 @@ static void draw_background(VDP *vdp)
bool hflip = tile & 0x0200;

uint8_t vshift = vflip ? (7 - src_row % 8) : (src_row % 8), hshift;
uint8_t pixel, dst_col, index;
uint8_t pixel, index;
int16_t dst_col;
uint16_t color;

for (pixel = 0; pixel < 8; pixel++) {
dst_col = ((col - 6) << 3) + pixel + fine_scroll;
hshift = hflip ? (7 - pixel) : pixel;
if (dst_col < 0 || dst_col >= 160)
continue;

hshift = hflip ? (7 - pixel) : pixel;
index = read_pattern(vdp, pattern, vshift, hshift);
color = get_color(vdp, index, palette);
draw_pixel(vdp, dst_row, dst_col, color);
@@ -280,13 +283,16 @@ static void draw_sprites(VDP *vdp)
int16_t dst_col;

for (pixel = 0; pixel < 8; pixel++) {
dst_col = x + pixel - (6 << 3);
if (dst_col < 0 || dst_col >= 160)
continue;

index = read_pattern(vdp, pattern, vshift, pixel);
if (index == 0)
continue;

color = get_color(vdp, index, 1);
dst_col = x + pixel - (6 << 3);
if (dst_col >= 0 && dst_col < 160)
draw_pixel(vdp, dst_row, dst_col, color);
draw_pixel(vdp, dst_row, dst_col, color);
}
}
}


Loading…
Cancel
Save