src/main.c

changeset 41
75887b42d7e5
parent 40
239bc48590ba
child 42
1d55c8c7c1ac
     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;