/* * sdl_corruption.c * by Mike Melanson * * Be sure to have libSDL installed from: * http://www.libsdl.org/ * To compile with gcc on Unix: * gcc -Wall sdl_corruption.c -o sdl_corruption -lSDL * To run, be sure that the CGA_FONT.8X8 and 8088_COR.DAT in the same * directory as the program (case matters on Unix): * ./sdl_corruption */ #include #include #include /* CGA colors come from here: * http://en.wikipedia.org/wiki/Cga#The_CGA_color_palette */ static const unsigned int colors[] = { 0x000000, 0x0000AA, 0x00AA00, 0x00AAAA, 0xAA0000, 0xAA00AA, 0xAA5500, 0xAAAAAA, 0x555555, 0x5555FF, 0x55FF55, 0x55FFFF, 0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF }; #define CORRUPTION_DATA_FILE "8088_COR.DAT" #define VIDEO_FRAME_SIZE (40 * 25 * 2) #define AUDIO_FRAME_SIZE 735 #define TOTAL_FRAME_SIZE (VIDEO_FRAME_SIZE + AUDIO_FRAME_SIZE) #define VECTOR_FILE "CGA_FONT.8X8" #define VECTOR_TABLE_SIZE (256 * 8) void render_vector(unsigned int *pixels, unsigned char *vector, unsigned char vector_attributes, int stride) { int x, y; unsigned int color0, color1; unsigned char vector_byte; int mask; color0 = colors[vector_attributes >> 4]; color1 = colors[vector_attributes & 0x0F]; for (y = 0; y < 8; y++) { vector_byte = *vector++; mask = 0x80; for (x = 0; x < 8; x++) { if (vector_byte & mask) *pixels++ = color1; else *pixels++ = color0; mask >>= 1; } pixels += stride - 8; } } int main() { SDL_Surface *screen; SDL_Event event; unsigned int *pixels; unsigned char vector_table[VECTOR_TABLE_SIZE]; FILE *f; unsigned char video_frame[VIDEO_FRAME_SIZE]; int frame_index; unsigned char vector_attributes, vector_index; int x, y; int finished = 0; int paused = 0; int keypresseddown; off_t filesize; /* load the vector table (8x8 font) */ f = fopen(VECTOR_FILE, "rb"); if (!f) { perror(VECTOR_FILE); return 1; } if (fread(vector_table, VECTOR_TABLE_SIZE, 1, f) != 1) { perror(VECTOR_FILE); fclose(f); return 1; } fclose(f); /* open the corruption file and get the filesize */ f = fopen(CORRUPTION_DATA_FILE, "rb"); if (!f) { perror(CORRUPTION_DATA_FILE); return 1; } fseek(f, 0, SEEK_END); filesize = ftell(f); fseek(f, 0, SEEK_SET); if (filesize % TOTAL_FRAME_SIZE != 0) { printf ("corruption file corrupt (not divisible by %d)\n", TOTAL_FRAME_SIZE); return 1; } /* compute the number of frames */ filesize /= TOTAL_FRAME_SIZE; /* initialize the video mode */ if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) { printf ("could not initialize SDL: %s\n", SDL_GetError()); exit(1); } screen = SDL_SetVideoMode(320, 200, 32, SDL_SWSURFACE); if (screen == NULL) { printf("could not set video mode: %s\n", SDL_GetError()); exit(1); } SDL_WM_SetCaption("SDL Corruption", NULL); pixels = (unsigned int *)screen->pixels; printf("SDL Corruption contols:\n"); printf(" escape: exit\n"); printf(" space: pause\n"); printf(" 0..9: seek from beginning -> near-end\n"); while (!feof(f) && !finished) { SDL_PollEvent(&event); if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_ESCAPE) { finished = 1; continue; } else keypresseddown = event.key.keysym.sym; } else if (event.type == SDL_KEYUP) { if (keypresseddown == event.key.keysym.sym) { switch (event.key.keysym.sym) { case SDLK_SPACE: paused = !paused; break; case SDLK_0: case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5: case SDLK_6: case SDLK_7: case SDLK_8: case SDLK_9: fseek(f, (filesize * (event.key.keysym.sym - SDLK_0) / 10) * TOTAL_FRAME_SIZE, SEEK_SET); break; default: break; } keypresseddown = 0; } } SDL_Delay(1000/30); if (paused) continue; fread(video_frame, VIDEO_FRAME_SIZE, 1, f); frame_index = 0; fseek(f, AUDIO_FRAME_SIZE, SEEK_CUR); if (SDL_MUSTLOCK(screen)) { SDL_LockSurface(screen); } for (y = 0; y < 25; y++) { for (x = 0; x < 40; x++) { pixels = (unsigned int *)screen->pixels; pixels += (y * 40 * 8 * 8) + (x * 8); vector_index = video_frame[frame_index++]; vector_attributes = video_frame[frame_index++]; render_vector(pixels, vector_table + vector_index * 8, vector_attributes, 320); } } if (SDL_MUSTLOCK(screen)) { SDL_UnlockSurface(screen); } SDL_UpdateRect(screen, 0, 0, 0, 0); } fclose(f); atexit(SDL_Quit); return 0; }