1.1 diff -r 239bc48590ba -r 75887b42d7e5 src/main.c 1.2 --- a/src/main.c Thu Dec 02 23:03:13 2010 +0000 1.3 +++ b/src/main.c Thu Dec 02 23:30:13 2010 +0000 1.4 @@ -19,6 +19,99 @@ 1.5 exit(EXIT_FAILURE); 1.6 } 1.7 1.8 +/** 1.9 + * @brief Set the pixel at (x, y) to the given value 1.10 + * @note The surface must be locked before calling this! 1.11 + * @param surface SDL surface upon which to draw 1.12 + * @param x X co-ordinate 1.13 + * @param y Y co-ordinate 1.14 + * @param pixel Pixel value (from SDL_MapRGB) 1.15 + */ 1.16 +void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) 1.17 +{ 1.18 + int bpp = surface->format->BytesPerPixel; 1.19 + /* Here p is the address to the pixel we want to set */ 1.20 + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; 1.21 + 1.22 + switch (bpp) { 1.23 + case 1: 1.24 + *p = pixel; 1.25 + break; 1.26 + 1.27 + case 2: 1.28 + *(Uint16 *)p = pixel; 1.29 + break; 1.30 + 1.31 + case 3: 1.32 + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 1.33 + p[0] = (pixel >> 16) & 0xff; 1.34 + p[1] = (pixel >> 8) & 0xff; 1.35 + p[2] = pixel & 0xff; 1.36 + } 1.37 + else { 1.38 + p[0] = pixel & 0xff; 1.39 + p[1] = (pixel >> 8) & 0xff; 1.40 + p[2] = (pixel >> 16) & 0xff; 1.41 + } 1.42 + break; 1.43 + 1.44 + case 4: 1.45 + *(Uint32 *)p = pixel; 1.46 + break; 1.47 + 1.48 + default: 1.49 + break; /* shouldn't happen, but avoids warnings */ 1.50 + } // switch 1.51 +} 1.52 + 1.53 + 1.54 +/** 1.55 + * @brief Refresh the screen. 1.56 + * @param surface SDL surface upon which to draw. 1.57 + */ 1.58 +void refreshScreen(SDL_Surface *s) 1.59 +{ 1.60 + // Lock the screen surface (if necessary) 1.61 + if (SDL_MUSTLOCK(s)) { 1.62 + if (SDL_LockSurface(s) < 0) { 1.63 + fprintf(stderr, "ERROR: Unable to lock screen!\n"); 1.64 + exit(EXIT_FAILURE); 1.65 + } 1.66 + } 1.67 + 1.68 + // Map the foreground and background colours 1.69 + Uint32 fg = SDL_MapRGB(s->format, 0, 255, 0); // green foreground 1.70 + Uint32 bg = SDL_MapRGB(s->format, 0, 0, 0); // black background 1.71 + 1.72 + // Refresh the 3B1 screen area first. TODO: only do this if VRAM has actually changed! 1.73 + uint32_t vram_address = 0; 1.74 + for (int y=0; y<348; y++) { 1.75 + for (int x=0; x<720; x+=16) { // 720 pixels, monochrome, packed into 16bit words 1.76 + // Get the pixel 1.77 + uint16_t val = RD16(state.vram, vram_address, sizeof(state.vram)-1); 1.78 + vram_address += 2; 1.79 + // Now copy it to the video buffer 1.80 + for (int px=0; px<16; px++) { 1.81 + if (val & 1) 1.82 + putpixel(s, x+px, y, fg); 1.83 + else 1.84 + putpixel(s, x+px, y, bg); 1.85 + } 1.86 + } 1.87 + } 1.88 + 1.89 + // TODO: blit LEDs and status info 1.90 + 1.91 + // Unlock the screen surface 1.92 + if (SDL_MUSTLOCK(s)) { 1.93 + SDL_UnlockSurface(s); 1.94 + } 1.95 + 1.96 + // Trigger a refresh -- TODO: partial refresh depending on whether we 1.97 + // refreshed the screen area, status area, both, or none. Use SDL_UpdateRect() for this. 1.98 + SDL_Flip(s); 1.99 +} 1.100 + 1.101 /**************************** 1.102 * blessed be thy main()... 1.103 ****************************/ 1.104 @@ -80,7 +173,8 @@ 1.105 1.106 // Is it time to run the 60Hz periodic interrupt yet? 1.107 if (clock_cycles > CLOCKS_PER_60HZ) { 1.108 - // TODO: refresh screen 1.109 + // Refresh the screen 1.110 + refreshScreen(screen); 1.111 // TODO: trigger periodic interrupt (if enabled) 1.112 // decrement clock cycle counter, we've handled the intr. 1.113 clock_cycles -= CLOCKS_PER_60HZ;