Skip to content

Commit

Permalink
Merge pull request #24 from shadyjesse/sdl2-migration
Browse files Browse the repository at this point in the history
SDL 2 migration, grabbing mouse now works much better
  • Loading branch information
philpem authored Oct 24, 2020
2 parents 6c33b9f + c50461d commit 5d369b9
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 37 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ endif
# SDL support
####
ifeq ($(ENABLE_SDL),yes)
LIBLNK += $(shell sdl-config --libs)
CFLAGS += $(shell sdl-config --cflags)
LIBLNK += $(shell sdl2-config --libs)
CFLAGS += $(shell sdl2-config --cflags)
endif


Expand Down
26 changes: 13 additions & 13 deletions src/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@
* Key map -- a mapping from SDLK_xxx constants to scancodes and vice versa.
*/
struct {
SDLKey key; ///< SDLK_xxx key code constant
SDL_Keycode key; ///< SDLK_xxx key code constant
int extended; ///< 1 if this is an extended keycode
unsigned char scancode; ///< Keyboard scan code
} keymap[] = {
{ SDLK_UP, 0, 0x01 }, // ROLL/Up [UpArrow]
{ SDLK_KP2, 0, 0x01 }, // ROLL/Up [Keypad 2]
{ SDLK_KP_2, 0, 0x01 }, // ROLL/Up [Keypad 2]
// { SDLK_, 1, 0x02 }, // Clear Line
// { SDLK_, 1, 0x03 }, // Rstrt / Ref
{ SDLK_ESCAPE, 1, 0x04 }, // Exit
{ SDLK_KP1, 0, 0x05 }, // PREV [Keypad 1]
{ SDLK_KP_1, 0, 0x05 }, // PREV [Keypad 1]
// { SDLK_, 1, 0x06 }, // Msg
{ SDLK_BACKSPACE, 1, 0x07 }, // Cancl
{ SDLK_BACKSPACE, 0, 0x08 }, // Backspace
{ SDLK_TAB, 0, 0x09 }, // Tab
{ SDLK_RETURN, 1, 0x0a }, // ENTER
{ SDLK_DOWN, 0, 0x0b }, // ROLL/Down [DownArrow]
{ SDLK_KP0, 0, 0x0b }, // ROLL/Down [Keypad 0]
{ SDLK_KP3, 0, 0x0c }, // NEXT [Keypad 3]
{ SDLK_KP_0, 0, 0x0b }, // ROLL/Down [Keypad 0]
{ SDLK_KP_3, 0, 0x0c }, // NEXT [Keypad 3]
{ SDLK_RETURN, 0, 0x0d }, // RETURN [Return]
{ SDLK_LEFT, 0, 0x0e }, // <-- [LeftArrow]
{ SDLK_KP_MINUS, 0, 0x0e }, // <-- [Keypad -]
Expand All @@ -54,7 +54,7 @@ struct {
// { SDLK_, 1, 0x22 }, // Redo
// { SDLK_, 1, 0x23 }, // FIND
// { SDLK_, 1, 0x24 }, // RPLAC
{ SDLK_BREAK, 0, 0x25 }, // RESET/BREAK [Pause/Break]
{ SDLK_PAUSE, 0, 0x25 }, // RESET/BREAK [Pause/Break]
// { SDLK_, 1, 0x26 }, // DleteChar
{ SDLK_QUOTE, 0, 0x27 }, // ' (single-quote)
// { SDLK_, 1, 0x28 }, // SLCT/MARK
Expand Down Expand Up @@ -82,17 +82,17 @@ struct {
// Keycodes 3E, 3F, 40 not used
// { SDLK_, 1, 0x41 }, // CMD
// { SDLK_, 1, 0x42 }, // CLOSE/OPEN
{ SDLK_KP7, 0, 0x43 }, // PRINT
{ SDLK_KP8, 0, 0x44 }, // CLEAR/RFRSH
{ SDLK_KP_7, 0, 0x43 }, // PRINT
{ SDLK_KP_8, 0, 0x44 }, // CLEAR/RFRSH
{ SDLK_CAPSLOCK, 0, 0x45 }, // Caps Lock
{ SDLK_KP9, 0, 0x46 }, // PAGE
{ SDLK_KP4, 0, 0x47 }, // BEG
{ SDLK_KP_9, 0, 0x46 }, // PAGE
{ SDLK_KP_4, 0, 0x47 }, // BEG
{ SDLK_LSHIFT, 0, 0x48 }, // Left Shift
{ SDLK_RSHIFT, 0, 0x49 }, // Right Shift
{ SDLK_HOME, 0, 0x4a }, // Home
{ SDLK_KP5, 0, 0x4a }, // Home [Keypad 5]
{ SDLK_KP_5, 0, 0x4a }, // Home [Keypad 5]
{ SDLK_END, 0, 0x4b }, // End
{ SDLK_KP6, 0, 0x4b }, // End [Keypad 6]
{ SDLK_KP_6, 0, 0x4b }, // End [Keypad 6]
{ SDLK_LCTRL, 0, 0x4c }, // Left Ctrl? \___ not sure which is left and which is right...
{ SDLK_RCTRL, 0, 0x4d }, // Right Ctrl? /
// Keycodes 4E thru 5A not used
Expand Down Expand Up @@ -128,7 +128,7 @@ struct {
{ SDLK_y, 0, 0x79 }, // Y
{ SDLK_z, 0, 0x7a }, // Z
// Keycodes 7B, 7C, 7D not used
{ SDLK_NUMLOCK, 0, 0x7e }, // Numlock
{ SDLK_NUMLOCKCLEAR, 0, 0x7e }, // Numlock
{ SDLK_DELETE, 0, 0x7f } // Dlete
};

Expand Down
58 changes: 58 additions & 0 deletions src/lightbar.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

104 changes: 86 additions & 18 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "state.h"
#include "memory.h"

#include "lightbar.c"

extern int cpu_log_enabled;

void FAIL(char *err)
Expand Down Expand Up @@ -105,8 +107,10 @@ void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
/**
* @brief Refresh the screen.
* @param surface SDL surface upon which to draw.
* @param renderer SDL renderer.
* @param texture SDL texture to copy surface to.
*/
void refreshScreen(SDL_Surface *s)
void refreshScreen(SDL_Surface *s, SDL_Renderer *r, SDL_Texture *t)
{
// Lock the screen surface (if necessary)
if (SDL_MUSTLOCK(s)) {
Expand Down Expand Up @@ -140,22 +144,41 @@ void refreshScreen(SDL_Surface *s)
}
}

// TODO: blit LEDs and status info

// Unlock the screen surface
if (SDL_MUSTLOCK(s)) {
SDL_UnlockSurface(s);
}

// Trigger a refresh -- TODO: partial refresh depending on whether we
// refreshed the screen area, status area, both, or none. Use SDL_UpdateRect() for this.
SDL_Flip(s);
// Update framebuffer texture
SDL_UpdateTexture(t, NULL, s->pixels, s->pitch);
SDL_RenderCopy(r, t, NULL, NULL);
}

#define LED_SIZE 8

void refreshStatusBar(SDL_Renderer *r, SDL_Texture *lightbar_tex)
{
SDL_Rect red_led = { 0, 0, LED_SIZE, LED_SIZE };
SDL_Rect green_led = { LED_SIZE, 0, LED_SIZE, LED_SIZE };
SDL_Rect yellow_led = { LED_SIZE*2, 0, LED_SIZE, LED_SIZE };
SDL_Rect inactive_led = { LED_SIZE*3, 0, LED_SIZE, LED_SIZE };
SDL_Rect dstrect = { 720-LED_SIZE*4, 348-LED_SIZE, LED_SIZE, LED_SIZE };

// LED bit values are inverse of documentation (leftmost LED is LSB)
// Red user LED (leftmost LED) can be turned on using "syslocal(SYSL_LED, 1)" from sys/syslocal.h
SDL_RenderCopy(r, lightbar_tex, (state.leds & 1) ? &red_led : &inactive_led, &dstrect);
dstrect.x += LED_SIZE;
SDL_RenderCopy(r, lightbar_tex, (state.leds & 2) ? &green_led : &inactive_led, &dstrect);
dstrect.x += LED_SIZE;
SDL_RenderCopy(r, lightbar_tex, (state.leds & 4) ? &yellow_led : &inactive_led, &dstrect);
dstrect.x += LED_SIZE;
SDL_RenderCopy(r, lightbar_tex, (state.leds & 8) ? &red_led : &inactive_led, &dstrect);
}

/**
* @brief Handle events posted by SDL.
*/
bool HandleSDLEvents(SDL_Surface *screen)
bool HandleSDLEvents(SDL_Window *window)
{
SDL_Event event;
static int mouse_grabbed = 0, mouse_buttons = 0;
Expand All @@ -175,12 +198,10 @@ bool HandleSDLEvents(SDL_Surface *screen)
switch (event.key.keysym.sym) {
case SDLK_F10:
if (mouse_grabbed){
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_SetRelativeMouseMode(SDL_FALSE);
mouse_grabbed = 0;
}else{
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
SDL_SetRelativeMouseMode(SDL_TRUE);
mouse_grabbed = 1;
}
break;
Expand Down Expand Up @@ -274,13 +295,43 @@ int main(int argc, char *argv[])
atexit(SDL_Quit);

// Set up the video display
SDL_Surface *screen = NULL;
if ((screen = SDL_SetVideoMode(720, 348, 8, SDL_SWSURFACE | SDL_ANYFORMAT)) == NULL) {
fprintf(stderr, "Could not find a suitable video mode: %s.\n", SDL_GetError());
SDL_Window *window;
if ((window = SDL_CreateWindow("FreeBee 3B1 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
720, 348, 0)) == NULL) {
fprintf(stderr, "Error creating SDL window: %s.\n", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer){
fprintf(stderr, "Error creating SDL renderer: %s.\n", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_Texture *fbTexture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGB888,
SDL_TEXTUREACCESS_STREAMING,
720, 348);
if (!fbTexture){
fprintf(stderr, "Error creating SDL FB texture: %s.\n", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_Surface *screen = SDL_CreateRGBSurface(0, 720, 348, 32, 0, 0, 0, 0);
if (!screen){
fprintf(stderr, "Error creating SDL FB surface: %s.\n", SDL_GetError());
exit(EXIT_FAILURE);
}
// Load in status LED sprites
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom((void*)lightbar.pixel_data, lightbar.width, lightbar.height,
lightbar.bytes_per_pixel*8, lightbar.bytes_per_pixel*lightbar.width,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
#else
0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
#endif
);
SDL_Texture *lightbarTexture = SDL_CreateTextureFromSurface(renderer, surf);
SDL_FreeSurface(surf);

printf("Set %dx%d at %d bits-per-pixel mode\n\n", screen->w, screen->h, screen->format->BitsPerPixel);
SDL_WM_SetCaption("FreeBee 3B1 emulator", "FreeBee");

// Load a disc image
load_fd();
Expand All @@ -299,6 +350,7 @@ int main(int argc, char *argv[])
uint32_t next_timeslot = SDL_GetTicks() + MILLISECS_PER_TIMESLOT;
uint32_t clock_cycles = 0, tmp;
bool exitEmu = false;
uint8_t last_leds = 255;

/*bool lastirq_fdc = false;*/
for (;;) {
Expand Down Expand Up @@ -418,8 +470,17 @@ int main(int argc, char *argv[])
}
// Is it time to run the 60Hz periodic interrupt yet?
if (clock_cycles > CLOCKS_PER_60HZ) {
// Refresh the screen
refreshScreen(screen);
// Refresh the screen if VRAM has been changed
if (state.vram_updated){
refreshScreen(screen, renderer, fbTexture);
}
if (state.vram_updated || last_leds != state.leds){
refreshStatusBar(renderer, lightbarTexture);
last_leds = state.leds;
}
state.vram_updated = false;
SDL_RenderPresent(renderer);

if (state.timer_enabled){
m68k_set_irq(6);
state.timer_asserted = true;
Expand All @@ -431,7 +492,7 @@ int main(int argc, char *argv[])
}

// handle SDL events -- returns true if we need to exit
if (HandleSDLEvents(screen))
if (HandleSDLEvents(window))
exitEmu = true;

// make sure frame rate is equal to real time
Expand Down Expand Up @@ -459,5 +520,12 @@ int main(int argc, char *argv[])
fclose(state.fdc_disc);
}

// Clean up SDL
SDL_DestroyTexture(lightbarTexture);
SDL_FreeSurface(screen);
SDL_DestroyTexture(fbTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

return 0;
}
3 changes: 3 additions & 0 deletions src/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,7 @@ void m68k_write_memory_32(uint32_t address, uint32_t value)/*{{{*/
case 0x020000: // Video RAM
if (address > 0x427FFF) fprintf(stderr, "NOTE: WR32 to VideoRAM mirror, addr=0x%08X\n", address);
WR32(state.vram, address, 0x7FFF, value);
state.vram_updated = true;
break;
default:
IoWrite(address, value, 32);
Expand Down Expand Up @@ -1052,6 +1053,7 @@ void m68k_write_memory_16(uint32_t address, uint32_t value)/*{{{*/
case 0x020000: // Video RAM
if (address > 0x427FFF) fprintf(stderr, "NOTE: WR16 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
WR16(state.vram, address, 0x7FFF, value);
state.vram_updated = true;
break;
default:
IoWrite(address, value, 16);
Expand Down Expand Up @@ -1099,6 +1101,7 @@ void m68k_write_memory_8(uint32_t address, uint32_t value)/*{{{*/
case 0x020000: // Video RAM
if (address > 0x427FFF) fprintf(stderr, "NOTE: WR8 to VideoRAM mirror, addr=0x%08X, data=0x%04X\n", address, value);
WR8(state.vram, address, 0x7FFF, value);
state.vram_updated = true;
break;
default:
IoWrite(address, value, 8);
Expand Down
3 changes: 3 additions & 0 deletions src/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ typedef struct {

/// VIDPAL mod (allows user writing to VRAM)
bool vidpal;

/// Update screen only when VRAM has been changed
bool vram_updated;
} S_state;

// Global emulator state. Yes, I know global variables are evil, please don't
Expand Down
8 changes: 4 additions & 4 deletions src/wd2010.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val)
case CMD_RESTORE:
// Restore. Set track to 0 and throw an IRQ.
ctx->track = 0;
SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_NewTimerCallback)seek_complete, ctx);
SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_TimerCallback)seek_complete, ctx);
break;
case CMD_SCAN_ID:
ctx->cylinder_high_reg = (ctx->track >> 8) & CYLH_MASK;
Expand Down Expand Up @@ -351,7 +351,7 @@ void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val)
ctx->formatting = cmd == CMD_WRITE_FORMAT;
switch (cmd){
case CMD_SEEK:
SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_NewTimerCallback)seek_complete, ctx);
SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_TimerCallback)seek_complete, ctx);
break;
case CMD_READ_SECTOR:
/*XXX: does a separate function to set the head have to be added?*/
Expand Down Expand Up @@ -401,7 +401,7 @@ void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val)

ctx->status = 0;
ctx->status |= (ctx->data_pos < ctx->data_len) ? SR_DRQ | SR_COMMAND_IN_PROGRESS | SR_BUSY : 0x00;
/*SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_NewTimerCallback)transfer_seek_complete, ctx);*/
/*SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_TimerCallback)transfer_seek_complete, ctx);*/
ctx->drq = true;

break;
Expand Down Expand Up @@ -444,7 +444,7 @@ void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val)

ctx->status = 0;
ctx->status |= (ctx->data_pos < ctx->data_len) ? SR_DRQ | SR_COMMAND_IN_PROGRESS | SR_BUSY : 0x00;
/*SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_NewTimerCallback)transfer_seek_complete, ctx);*/
/*SDL_AddTimer(WD2010_SEEK_DELAY, (SDL_TimerCallback)transfer_seek_complete, ctx);*/
ctx->drq = true;

break;
Expand Down

0 comments on commit 5d369b9

Please sign in to comment.