Search
lxdream.org :: lxdream :: r295:6637664291a8
lxdream 0.9.1
released Jun 29
Download Now
changeset295:6637664291a8
parent294:a5beff9b2b85
child296:1aa1c5ba59fd
authornkeynes
dateTue Jan 16 10:34:46 2007 +0000 (17 years ago)
Bug 24: Initial implementation of "save scene" function
src/Makefile.am
src/Makefile.in
src/dreamcast.c
src/dreamcast.h
src/pvr2/pvr2.c
src/pvr2/pvr2.h
src/pvr2/rendsave.c
1.1 --- a/src/Makefile.am Tue Jan 16 09:18:32 2007 +0000
1.2 +++ b/src/Makefile.am Tue Jan 16 10:34:46 2007 +0000
1.3 @@ -23,7 +23,7 @@
1.4 aica/aica.c aica/aica.h aica/audio.c aica/audio.h \
1.5 pvr2/pvr2.c pvr2/pvr2.h pvr2/pvr2mem.c \
1.6 pvr2/tacore.c pvr2/render.c pvr2/rendcore.c pvr2/rendbkg.c pvr2/rendsort.c \
1.7 - pvr2/texcache.c pvr2/yuv.c \
1.8 + pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c \
1.9 maple/maple.c maple/maple.h \
1.10 maple/controller.c maple/controller.h \
1.11 gui/support.c gui/support.h \
2.1 --- a/src/Makefile.in Tue Jan 16 09:18:32 2007 +0000
2.2 +++ b/src/Makefile.in Tue Jan 16 10:34:46 2007 +0000
2.3 @@ -157,7 +157,7 @@
2.4 aica/aica.c aica/aica.h aica/audio.c aica/audio.h \
2.5 pvr2/pvr2.c pvr2/pvr2.h pvr2/pvr2mem.c \
2.6 pvr2/tacore.c pvr2/render.c pvr2/rendcore.c pvr2/rendbkg.c pvr2/rendsort.c \
2.7 - pvr2/texcache.c pvr2/yuv.c \
2.8 + pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c \
2.9 maple/maple.c maple/maple.h \
2.10 maple/controller.c maple/controller.h \
2.11 gui/support.c gui/support.h \
2.12 @@ -195,13 +195,13 @@
2.13 aica.$(OBJEXT) audio.$(OBJEXT) pvr2.$(OBJEXT) pvr2mem.$(OBJEXT) \
2.14 tacore.$(OBJEXT) render.$(OBJEXT) rendcore.$(OBJEXT) \
2.15 rendbkg.$(OBJEXT) rendsort.$(OBJEXT) texcache.$(OBJEXT) \
2.16 - yuv.$(OBJEXT) maple.$(OBJEXT) controller.$(OBJEXT) \
2.17 - support.$(OBJEXT) interface.$(OBJEXT) callbacks.$(OBJEXT) \
2.18 - gui.$(OBJEXT) mmr_win.$(OBJEXT) debug_win.$(OBJEXT) \
2.19 - dump_win.$(OBJEXT) loader.$(OBJEXT) bootstrap.$(OBJEXT) \
2.20 - util.$(OBJEXT) display.$(OBJEXT) audio_null.$(OBJEXT) \
2.21 - audio_esd.$(OBJEXT) video_null.$(OBJEXT) video_gtk.$(OBJEXT) \
2.22 - video_x11.$(OBJEXT) video_gl.$(OBJEXT)
2.23 + yuv.$(OBJEXT) rendsave.$(OBJEXT) maple.$(OBJEXT) \
2.24 + controller.$(OBJEXT) support.$(OBJEXT) interface.$(OBJEXT) \
2.25 + callbacks.$(OBJEXT) gui.$(OBJEXT) mmr_win.$(OBJEXT) \
2.26 + debug_win.$(OBJEXT) dump_win.$(OBJEXT) loader.$(OBJEXT) \
2.27 + bootstrap.$(OBJEXT) util.$(OBJEXT) display.$(OBJEXT) \
2.28 + audio_null.$(OBJEXT) audio_esd.$(OBJEXT) video_null.$(OBJEXT) \
2.29 + video_gtk.$(OBJEXT) video_x11.$(OBJEXT) video_gl.$(OBJEXT)
2.30 lxdream_OBJECTS = $(am_lxdream_OBJECTS)
2.31 lxdream_DEPENDENCIES =
2.32 lxdream_LDFLAGS =
2.33 @@ -227,16 +227,16 @@
2.34 @AMDEP_TRUE@ ./$(DEPDIR)/mmr_win.Po ./$(DEPDIR)/nrg.Po \
2.35 @AMDEP_TRUE@ ./$(DEPDIR)/pvr2.Po ./$(DEPDIR)/pvr2mem.Po \
2.36 @AMDEP_TRUE@ ./$(DEPDIR)/rendbkg.Po ./$(DEPDIR)/rendcore.Po \
2.37 -@AMDEP_TRUE@ ./$(DEPDIR)/render.Po ./$(DEPDIR)/rendsort.Po \
2.38 -@AMDEP_TRUE@ ./$(DEPDIR)/scif.Po ./$(DEPDIR)/sh4core.Po \
2.39 -@AMDEP_TRUE@ ./$(DEPDIR)/sh4dasm.Po ./$(DEPDIR)/sh4mem.Po \
2.40 -@AMDEP_TRUE@ ./$(DEPDIR)/sh4mmio.Po ./$(DEPDIR)/support.Po \
2.41 -@AMDEP_TRUE@ ./$(DEPDIR)/syscall.Po ./$(DEPDIR)/tacore.Po \
2.42 -@AMDEP_TRUE@ ./$(DEPDIR)/texcache.Po ./$(DEPDIR)/timer.Po \
2.43 -@AMDEP_TRUE@ ./$(DEPDIR)/util.Po ./$(DEPDIR)/video_gl.Po \
2.44 -@AMDEP_TRUE@ ./$(DEPDIR)/video_gtk.Po ./$(DEPDIR)/video_null.Po \
2.45 -@AMDEP_TRUE@ ./$(DEPDIR)/video_x11.Po ./$(DEPDIR)/watch.Po \
2.46 -@AMDEP_TRUE@ ./$(DEPDIR)/yuv.Po
2.47 +@AMDEP_TRUE@ ./$(DEPDIR)/render.Po ./$(DEPDIR)/rendsave.Po \
2.48 +@AMDEP_TRUE@ ./$(DEPDIR)/rendsort.Po ./$(DEPDIR)/scif.Po \
2.49 +@AMDEP_TRUE@ ./$(DEPDIR)/sh4core.Po ./$(DEPDIR)/sh4dasm.Po \
2.50 +@AMDEP_TRUE@ ./$(DEPDIR)/sh4mem.Po ./$(DEPDIR)/sh4mmio.Po \
2.51 +@AMDEP_TRUE@ ./$(DEPDIR)/support.Po ./$(DEPDIR)/syscall.Po \
2.52 +@AMDEP_TRUE@ ./$(DEPDIR)/tacore.Po ./$(DEPDIR)/texcache.Po \
2.53 +@AMDEP_TRUE@ ./$(DEPDIR)/timer.Po ./$(DEPDIR)/util.Po \
2.54 +@AMDEP_TRUE@ ./$(DEPDIR)/video_gl.Po ./$(DEPDIR)/video_gtk.Po \
2.55 +@AMDEP_TRUE@ ./$(DEPDIR)/video_null.Po ./$(DEPDIR)/video_x11.Po \
2.56 +@AMDEP_TRUE@ ./$(DEPDIR)/watch.Po ./$(DEPDIR)/yuv.Po
2.57 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
2.58 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
2.59 CCLD = $(CC)
2.60 @@ -325,6 +325,7 @@
2.61 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rendbkg.Po@am__quote@
2.62 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rendcore.Po@am__quote@
2.63 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@
2.64 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rendsave.Po@am__quote@
2.65 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rendsort.Po@am__quote@
2.66 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scif.Po@am__quote@
2.67 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sh4core.Po@am__quote@
2.68 @@ -960,6 +961,28 @@
2.69 @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.70 @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o yuv.obj `if test -f 'pvr2/yuv.c'; then $(CYGPATH_W) 'pvr2/yuv.c'; else $(CYGPATH_W) '$(srcdir)/pvr2/yuv.c'; fi`
2.71
2.72 +rendsave.o: pvr2/rendsave.c
2.73 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rendsave.o -MD -MP -MF "$(DEPDIR)/rendsave.Tpo" \
2.74 +@am__fastdepCC_TRUE@ -c -o rendsave.o `test -f 'pvr2/rendsave.c' || echo '$(srcdir)/'`pvr2/rendsave.c; \
2.75 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/rendsave.Tpo" "$(DEPDIR)/rendsave.Po"; \
2.76 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/rendsave.Tpo"; exit 1; \
2.77 +@am__fastdepCC_TRUE@ fi
2.78 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pvr2/rendsave.c' object='rendsave.o' libtool=no @AMDEPBACKSLASH@
2.79 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/rendsave.Po' tmpdepfile='$(DEPDIR)/rendsave.TPo' @AMDEPBACKSLASH@
2.80 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.81 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rendsave.o `test -f 'pvr2/rendsave.c' || echo '$(srcdir)/'`pvr2/rendsave.c
2.82 +
2.83 +rendsave.obj: pvr2/rendsave.c
2.84 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rendsave.obj -MD -MP -MF "$(DEPDIR)/rendsave.Tpo" \
2.85 +@am__fastdepCC_TRUE@ -c -o rendsave.obj `if test -f 'pvr2/rendsave.c'; then $(CYGPATH_W) 'pvr2/rendsave.c'; else $(CYGPATH_W) '$(srcdir)/pvr2/rendsave.c'; fi`; \
2.86 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/rendsave.Tpo" "$(DEPDIR)/rendsave.Po"; \
2.87 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/rendsave.Tpo"; exit 1; \
2.88 +@am__fastdepCC_TRUE@ fi
2.89 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pvr2/rendsave.c' object='rendsave.obj' libtool=no @AMDEPBACKSLASH@
2.90 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/rendsave.Po' tmpdepfile='$(DEPDIR)/rendsave.TPo' @AMDEPBACKSLASH@
2.91 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.92 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rendsave.obj `if test -f 'pvr2/rendsave.c'; then $(CYGPATH_W) 'pvr2/rendsave.c'; else $(CYGPATH_W) '$(srcdir)/pvr2/rendsave.c'; fi`
2.93 +
2.94 maple.o: maple/maple.c
2.95 @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maple.o -MD -MP -MF "$(DEPDIR)/maple.Tpo" \
2.96 @am__fastdepCC_TRUE@ -c -o maple.o `test -f 'maple/maple.c' || echo '$(srcdir)/'`maple/maple.c; \
3.1 --- a/src/dreamcast.c Tue Jan 16 09:18:32 2007 +0000
3.2 +++ b/src/dreamcast.c Tue Jan 16 10:34:46 2007 +0000
3.3 @@ -1,5 +1,5 @@
3.4 /**
3.5 - * $Id: dreamcast.c,v 1.20 2007-01-12 10:16:02 nkeynes Exp $
3.6 + * $Id: dreamcast.c,v 1.21 2007-01-16 10:34:46 nkeynes Exp $
3.7 * Central switchboard for the system. This pulls all the individual modules
3.8 * together into some kind of coherent structure. This is also where you'd
3.9 * add Naomi support, if I ever get a board to play with...
3.10 @@ -371,9 +371,6 @@
3.11
3.12 /********************************* Save States *****************************/
3.13
3.14 -#define DREAMCAST_SAVE_MAGIC "%!-lxDream!Save\0"
3.15 -#define DREAMCAST_SAVE_VERSION 0x00010000
3.16 -
3.17 struct save_state_header {
3.18 char magic[16];
3.19 uint32_t version;
4.1 --- a/src/dreamcast.h Tue Jan 16 09:18:32 2007 +0000
4.2 +++ b/src/dreamcast.h Tue Jan 16 10:34:46 2007 +0000
4.3 @@ -1,5 +1,5 @@
4.4 /**
4.5 - * $Id: dreamcast.h,v 1.11 2006-07-02 04:59:00 nkeynes Exp $
4.6 + * $Id: dreamcast.h,v 1.12 2007-01-16 10:34:46 nkeynes Exp $
4.7 *
4.8 * Public interface for dreamcast.c -
4.9 * Central switchboard for the system. This pulls all the individual modules
4.10 @@ -58,9 +58,15 @@
4.11 gboolean dreamcast_load_config( const gchar *filename );
4.12 gboolean dreamcast_save_config( const gchar *filename );
4.13
4.14 +#define DREAMCAST_SAVE_MAGIC "%!-lxDream!Save\0"
4.15 +#define DREAMCAST_SAVE_VERSION 0x00010000
4.16 +
4.17 int dreamcast_save_state( const gchar *filename );
4.18 int dreamcast_load_state( const gchar *filename );
4.19
4.20 +#define SCENE_SAVE_MAGIC "%!-lxDream!Scene"
4.21 +#define SCENE_SAVE_VERSION 0x00010000
4.22 +
4.23 extern struct dreamcast_config_group dreamcast_config_root[];
4.24
4.25 /* Global config values */
5.1 --- a/src/pvr2/pvr2.c Tue Jan 16 09:18:32 2007 +0000
5.2 +++ b/src/pvr2/pvr2.c Tue Jan 16 10:34:46 2007 +0000
5.3 @@ -1,5 +1,5 @@
5.4 /**
5.5 - * $Id: pvr2.c,v 1.39 2007-01-15 08:32:09 nkeynes Exp $
5.6 + * $Id: pvr2.c,v 1.40 2007-01-16 10:34:46 nkeynes Exp $
5.7 *
5.8 * PVR2 (Video) Core module implementation and MMIO registers.
5.9 *
5.10 @@ -69,7 +69,7 @@
5.11 uint32_t irq_vpos1;
5.12 uint32_t irq_vpos2;
5.13 uint32_t odd_even_field; /* 1 = odd, 0 = even */
5.14 -
5.15 + gchar *save_next_render_filename;
5.16 /* timing */
5.17 uint32_t dot_clock;
5.18 uint32_t total_lines;
5.19 @@ -123,6 +123,7 @@
5.20 texcache_init();
5.21 pvr2_reset();
5.22 pvr2_ta_reset();
5.23 + pvr2_state.save_next_render_filename = NULL;
5.24 }
5.25
5.26 static void pvr2_reset( void )
5.27 @@ -150,13 +151,17 @@
5.28 {
5.29 fwrite( &pvr2_state, sizeof(pvr2_state), 1, f );
5.30 pvr2_ta_save_state( f );
5.31 + pvr2_yuv_save_state( f );
5.32 }
5.33
5.34 static int pvr2_load_state( FILE *f )
5.35 {
5.36 if( fread( &pvr2_state, sizeof(pvr2_state), 1, f ) != 1 )
5.37 return 1;
5.38 - return pvr2_ta_load_state(f);
5.39 + if( pvr2_ta_load_state(f) ) {
5.40 + return 1;
5.41 + }
5.42 + return pvr2_yuv_load_state(f);
5.43 }
5.44
5.45 /**
5.46 @@ -202,6 +207,17 @@
5.47 return pvr2_state.frame_count;
5.48 }
5.49
5.50 +gboolean pvr2_save_next_scene( const gchar *filename )
5.51 +{
5.52 + if( pvr2_state.save_next_render_filename != NULL ) {
5.53 + g_free( pvr2_state.save_next_render_filename );
5.54 + }
5.55 + pvr2_state.save_next_render_filename = g_strdup(filename);
5.56 + return TRUE;
5.57 +}
5.58 +
5.59 +
5.60 +
5.61 /**
5.62 * Display the next frame, copying the current contents of video ram to
5.63 * the window. If the video configuration has changed, first recompute the
5.64 @@ -288,9 +304,15 @@
5.65 val &= 0x00000007; /* Do stuff? */
5.66 MMIO_WRITE( PVR2, reg, val );
5.67 break;
5.68 - case RENDER_START:
5.69 - if( val == 0xFFFFFFFF || val == 0x00000001 )
5.70 - pvr2_render_scene();
5.71 + case RENDER_START: /* Don't really care what value */
5.72 + if( pvr2_state.save_next_render_filename != NULL ) {
5.73 + if( pvr2_render_save_scene(pvr2_state.save_next_render_filename) == 0 ) {
5.74 + INFO( "Saved scene to %s", pvr2_state.save_next_render_filename);
5.75 + }
5.76 + g_free( pvr2_state.save_next_render_filename );
5.77 + pvr2_state.save_next_render_filename = NULL;
5.78 + }
5.79 + pvr2_render_scene();
5.80 break;
5.81 case RENDER_POLYBASE:
5.82 MMIO_WRITE( PVR2, reg, val&0x00F00000 );
6.1 --- a/src/pvr2/pvr2.h Tue Jan 16 09:18:32 2007 +0000
6.2 +++ b/src/pvr2/pvr2.h Tue Jan 16 10:34:46 2007 +0000
6.3 @@ -1,5 +1,5 @@
6.4 /**
6.5 - * $Id: pvr2.h,v 1.21 2007-01-15 12:58:05 nkeynes Exp $
6.6 + * $Id: pvr2.h,v 1.22 2007-01-16 10:34:46 nkeynes Exp $
6.7 *
6.8 * PVR2 (video chip) functions and macros.
6.9 *
6.10 @@ -64,6 +64,7 @@
6.11 void pvr2_next_frame( void );
6.12 void pvr2_set_base_address( uint32_t );
6.13 int pvr2_get_frame_count( void );
6.14 +gboolean pvr2_save_next_scene( const gchar *filename );
6.15
6.16 #define PVR2_CMD_END_OF_LIST 0x00
6.17 #define PVR2_CMD_USER_CLIP 0x20
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/src/pvr2/rendsave.c Tue Jan 16 10:34:46 2007 +0000
7.3 @@ -0,0 +1,97 @@
7.4 +/**
7.5 + * $Id: rendsave.c,v 1.1 2007-01-16 10:34:46 nkeynes Exp $
7.6 + *
7.7 + * Scene-save support. This is mainly for test/debug purposes.
7.8 + *
7.9 + * Copyright (c) 2005 Nathan Keynes.
7.10 + *
7.11 + * This program is free software; you can redistribute it and/or modify
7.12 + * it under the terms of the GNU General Public License as published by
7.13 + * the Free Software Foundation; either version 2 of the License, or
7.14 + * (at your option) any later version.
7.15 + *
7.16 + * This program is distributed in the hope that it will be useful,
7.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.19 + * GNU General Public License for more details.
7.20 + */
7.21 +
7.22 +#include <stdio.h>
7.23 +#include <errno.h>
7.24 +#include <time.h>
7.25 +#include "pvr2/pvr2.h"
7.26 +#include "dreamcast.h"
7.27 +
7.28 +/**
7.29 + * Size of pages for the purposes of saving - this has nothing to do with the
7.30 + * actual page size, of course.
7.31 + */
7.32 +#define SAVE_PAGE_SIZE 1024
7.33 +#define SAVE_PAGE_COUNT 8192
7.34 +
7.35 +extern char *video_base;
7.36 +
7.37 +/* Determine pages of memory to save. Start walking from the render tilemap
7.38 + * data and build up a page list
7.39 + */
7.40 +static void pvr2_find_referenced_pages( char *pages )
7.41 +{
7.42 + /* Dummy implementation - save everything */
7.43 + memset( pages, 1, SAVE_PAGE_COUNT );
7.44 +}
7.45 +
7.46 +/**
7.47 + * Save the current rendering data to a file for later analysis.
7.48 + * @return 0 on success, non-zero on failure.
7.49 + */
7.50 +int pvr2_render_save_scene( const gchar *filename )
7.51 +{
7.52 + struct header {
7.53 + char magic[16];
7.54 + uint32_t version;
7.55 + uint32_t timestamp;
7.56 + uint32_t frame_count;
7.57 + } scene_header;
7.58 +
7.59 + char page_map[SAVE_PAGE_COUNT];
7.60 + int i,j;
7.61 + pvr2_find_referenced_pages(page_map);
7.62 +
7.63 + FILE *f = fopen( filename, "wo" );
7.64 + if( f == NULL ) {
7.65 + ERROR( "Unable to open file '%s' to write scene data: %s", filename, strerror(errno) );
7.66 + return -1;
7.67 + }
7.68 +
7.69 + /* Header */
7.70 + memcpy( scene_header.magic, SCENE_SAVE_MAGIC, 16 );
7.71 + scene_header.version = SCENE_SAVE_VERSION;
7.72 + scene_header.timestamp = time(NULL);
7.73 + scene_header.frame_count = pvr2_get_frame_count();
7.74 + fwrite( &scene_header, sizeof(scene_header), 1, f );
7.75 +
7.76 + /* PVR2 registers - could probably be more specific, but doesn't
7.77 + * really use a lot of space. Loader is assumed to know which
7.78 + * registers actually need to be set.
7.79 + */
7.80 + fwrite( mmio_region_PVR2.mem, 0x1000, 1, f );
7.81 + fwrite( mmio_region_PVR2PAL.mem, 0x1000, 1, f );
7.82 +
7.83 + /* Write out the VRAM pages we care about */
7.84 + for( i=0; i<SAVE_PAGE_COUNT; i++ ) {
7.85 + if( page_map[i] != 0 ) {
7.86 + for( j=i+1; j<SAVE_PAGE_COUNT && page_map[j] != 0; j++ );
7.87 + /* Write region from i..j-1 */
7.88 + uint32_t start = i * SAVE_PAGE_SIZE;
7.89 + uint32_t length = (j-i) * SAVE_PAGE_SIZE;
7.90 + fwrite( &start, sizeof(uint32_t), 1, f );
7.91 + fwrite( &length, sizeof(uint32_t), 1, f );
7.92 + fwrite( video_base + start, 1, length, f );
7.93 + i = j-1;
7.94 + }
7.95 + }
7.96 + /* Write out the EOF marker */
7.97 + uint32_t eof = 0xFFFFFFFF;
7.98 + fwrite( &eof, sizeof(uint32_t), 1, f );
7.99 + fclose( f );
7.100 +}
.