#include "display_screen.h"
#include <algorithm>
#include "SoundSDL.hxx"
#ifdef __USE_SDL
namespace ale {
DisplayScreen::DisplayScreen(MediaSource* mediaSource, Sound* sound,
ColourPalette& palette)
: manual_control_active(false), media_source(mediaSource), my_sound(sound),
colour_palette(palette), delay_msec(17) {
screen_height = media_source->height();
screen_width = media_source->width();
assert(window_height >= screen_height);
assert(window_width >= screen_width);
yratio = window_height / (float)screen_height;
xratio = window_width / (float)screen_width;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Could not initialize SDL: %s\n", SDL_GetError());
exit(1);
}
screen = SDL_SetVideoMode(window_width, window_height, 8, SDL_HWPALETTE);
if (screen == NULL) {
fprintf(stderr, "Couldn't Initialize Screen: %s\n", SDL_GetError());
exit(1);
}
SDL_WM_SetCaption("ALE Viz", NULL);
fprintf(stderr,
"Screen Display Active. [Manual Control Mode] 'm' "
"[Slowdown] 'a' [Speedup] 's' [VolumeDown] '[' [VolumeUp] ']'.\n");
last_frame_time = SDL_GetTicks();
}
DisplayScreen::~DisplayScreen() { SDL_Quit(); }
void DisplayScreen::display_screen() {
if (SDL_MUSTLOCK(screen)) {
if (SDL_LockSurface(screen) < 0) {
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return;
}
}
int xciel = int(xratio) + 1;
int yciel = int(yratio) + 1;
uInt8* pi_curr_frame_buffer = media_source->currentFrameBuffer();
int y, x, r, g, b;
SDL_Rect rect;
for (int i = 0; i < screen_width * screen_height; i++) {
y = i / screen_width;
x = i - (y * screen_width);
colour_palette.getRGB(pi_curr_frame_buffer[i], r, g, b);
rect.x = (int)(x * xratio);
rect.y = (int)(y * yratio);
rect.w = xciel;
rect.h = yciel;
SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b));
}
if (SDL_MUSTLOCK(screen)) {
SDL_UnlockSurface(screen);
}
SDL_UpdateRect(screen, 0, 0, 0, 0);
poll();
Uint32 newTime = SDL_GetTicks();
Uint32 delta = newTime - std::min(last_frame_time, newTime);
if (delta < delay_msec) {
SDL_Delay(delay_msec - delta);
} else {
last_frame_time = SDL_GetTicks() + delta - delay_msec;
}
}
void DisplayScreen::poll() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
handleSDLEvent(event);
}
};
void DisplayScreen::handleSDLEvent(const SDL_Event& event) {
switch (event.type) {
case SDL_QUIT:
exit(0);
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_m:
manual_control_active = !manual_control_active;
if (manual_control_active) {
fprintf(stderr, "Manual Control Enabled: [Move] "
"Arrow keys [Fire] Space [NO-OP] Return.\n");
} else {
fprintf(stderr, "Manual Control Disabled\n");
}
break;
case SDLK_s:
delay_msec = delay_msec > 5 ? delay_msec - 5 : 0;
fprintf(stderr, "[Speedup] %d msec delay\n", delay_msec);
break;
case SDLK_a:
delay_msec = delay_msec + 5;
fprintf(stderr, "[Slowdown] %d msec delay\n", delay_msec);
break;
#ifdef SOUND_SUPPORT
case SDLK_LEFTBRACKET:
fprintf(stderr, "[VolumeDown]\n");
for (int i = 0; i < 5; ++i) {
((SoundSDL*)my_sound)->adjustVolume(-1);
}
break;
case SDLK_RIGHTBRACKET:
fprintf(stderr, "[VolumeUp]\n");
for (int i = 0; i < 5; ++i) {
((SoundSDL*)my_sound)->adjustVolume(1);
}
break;
#endif default:
break;
}
break;
default:
break;
}
};
Action DisplayScreen::getUserAction() {
if (!manual_control_active) {
return UNDEFINED;
}
Action a = PLAYER_A_NOOP;
poll();
SDL_PumpEvents();
Uint8* keymap = SDL_GetKeyState(NULL);
if (keymap[SDLK_p]) {
return PLAYER_A_NOOP;
} else if (keymap[SDLK_UP] && keymap[SDLK_RIGHT] && keymap[SDLK_SPACE]) {
a = PLAYER_A_UPRIGHTFIRE;
} else if (keymap[SDLK_UP] && keymap[SDLK_LEFT] && keymap[SDLK_SPACE]) {
a = PLAYER_A_UPLEFTFIRE;
} else if (keymap[SDLK_DOWN] && keymap[SDLK_RIGHT] && keymap[SDLK_SPACE]) {
a = PLAYER_A_DOWNRIGHTFIRE;
} else if (keymap[SDLK_DOWN] && keymap[SDLK_LEFT] && keymap[SDLK_SPACE]) {
a = PLAYER_A_DOWNLEFTFIRE;
} else if (keymap[SDLK_UP] && keymap[SDLK_LEFT]) {
a = PLAYER_A_UPLEFT;
} else if (keymap[SDLK_UP] && keymap[SDLK_RIGHT]) {
a = PLAYER_A_UPRIGHT;
} else if (keymap[SDLK_DOWN] && keymap[SDLK_LEFT]) {
a = PLAYER_A_DOWNLEFT;
} else if (keymap[SDLK_DOWN] && keymap[SDLK_RIGHT]) {
a = PLAYER_A_DOWNRIGHT;
} else if (keymap[SDLK_UP] && keymap[SDLK_SPACE]) {
a = PLAYER_A_UPFIRE;
} else if (keymap[SDLK_DOWN] && keymap[SDLK_SPACE]) {
a = PLAYER_A_DOWNFIRE;
} else if (keymap[SDLK_LEFT] && keymap[SDLK_SPACE]) {
a = PLAYER_A_LEFTFIRE;
} else if (keymap[SDLK_RIGHT] && keymap[SDLK_SPACE]) {
a = PLAYER_A_RIGHTFIRE;
} else if (keymap[SDLK_SPACE]) {
a = PLAYER_A_FIRE;
} else if (keymap[SDLK_RETURN]) {
a = PLAYER_A_NOOP;
} else if (keymap[SDLK_LEFT]) {
a = PLAYER_A_LEFT;
} else if (keymap[SDLK_RIGHT]) {
a = PLAYER_A_RIGHT;
} else if (keymap[SDLK_UP]) {
a = PLAYER_A_UP;
} else if (keymap[SDLK_DOWN]) {
a = PLAYER_A_DOWN;
}
return a;
}
}
#endif