wannabe optimizations
[fceu.git] / video.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /****************************************/
22 /*              FCE Ultra               */
23 /*                                      */
24 /*              video.c                 */
25 /*                                      */
26 /*  Some generic high-level video       */
27 /*  related functions.                  */
28 /****************************************/
29
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include "types.h"
35 #include "video.h"
36 #include "fce.h"
37 #include "svga.h"
38 #include "version.h"
39 #include "general.h"
40 #include "memory.h"
41
42 uint8 *XBuf=NULL;
43
44 int InitVirtualVideo(void)
45 {
46  uint32 m;
47
48  if(!XBuf)              /* Some driver code may allocate XBuf externally. */
49   if(!(XBuf = (uint8*) (FCEU_malloc((256+16) * 240 + 8))))
50    return 0;
51
52  if(sizeof(uint8*)==4)
53  {
54   m=(uint32) XBuf;
55   m+=8;m&=0xFFFFFFF8;
56   XBuf=(uint8 *)m;
57  } 
58
59  memset(XBuf,128,272*240);
60  return 1;
61 }
62
63 #ifndef ZLIB
64 static uint8 pcxheader[128] =
65 {
66  10,5,1,8,1,0,1,0,0,1,240,0,2,1,234,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,
68  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
69  0,0,0,0,0,0,0,0,0,0,0,0,0,0,
70 };
71
72 int SaveSnapshot(void)
73 {
74  char *fn=0;
75  uint8 *tmp;
76  int x,u,y;
77  FILE *pp=NULL;
78
79  for(u=0;u<999;u++)
80  {
81   pp=fopen((fn=FCEU_MakeFName(FCEUMKF_SNAP,u,"pcx")),"rb");
82   if(pp==NULL) break;
83   fclose(pp);
84  }
85
86  if(!(pp=fopen(fn,"wb")))
87   return 0;
88
89  {
90   int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
91
92   tmp=XBuf+8+FSettings.FirstSLine*272;
93
94   pcxheader[10]=totallines;
95   fwrite(pcxheader,1,128,pp);
96   for(y=0;y<totallines;y++)
97   {
98    for(x=0;x<256;x++)
99    {
100     if(*tmp>=0xc0) fputc(0xC1,pp);
101      fputc(*tmp,pp);
102     tmp++;
103    }
104    tmp+=16;
105   }
106  }
107
108  fputc(0xC,pp);
109  for(x=0;x<256;x++)
110  {
111   uint8 r,g,b;
112
113   FCEUD_GetPalette(x,&r,&g,&b);
114   fputc(r,pp);
115   fputc(g,pp);
116   fputc(b,pp);
117  }
118  fclose(pp);
119  
120  return u+1;
121 }
122
123 #else
124
125 #include <zlib.h>
126 #include "crc32.h"
127
128 static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
129 {
130  uint32 crc;
131
132  uint8 tempo[4];
133
134  tempo[0]=size>>24;
135  tempo[1]=size>>16;
136  tempo[2]=size>>8;
137  tempo[3]=size;
138
139  if(fwrite(tempo,4,1,fp)!=1)
140   return 0;
141  if(fwrite(type,4,1,fp)!=1)
142   return 0;
143
144  if(size)
145   if(fwrite(data,1,size,fp)!=size)
146    return 0;
147
148  crc=CalcCRC32(0,(uint8 *)type,4);
149  if(size)
150   crc=CalcCRC32(crc,data,size);
151
152  tempo[0]=crc>>24;
153  tempo[1]=crc>>16;
154  tempo[2]=crc>>8;
155  tempo[3]=crc;
156
157  if(fwrite(tempo,4,1,fp)!=1)
158   return 0;
159  return 1;
160 }
161
162 int SaveSnapshot(void)
163 {
164  char *fn=0;
165  int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
166  int x,u,y;
167  FILE *pp=NULL;
168  uint8 *compmem=NULL;
169  uint32 compmemsize=totallines*263+12;
170
171  if(!(compmem=FCEU_malloc(compmemsize)))
172   return 0;
173
174  for(u=0;u<999;u++)
175  {
176   pp=fopen((fn=FCEU_MakeFName(FCEUMKF_SNAP,u,"png")),"rb");
177   if(pp==NULL) break;
178   fclose(pp);
179  }
180
181  if(!(pp=fopen(fn,"wb")))
182   return 0;
183  {
184   static uint8 header[8]={137,80,78,71,13,10,26,10};
185   if(fwrite(header,8,1,pp)!=1)
186    goto PNGerr;
187  }
188
189  {
190   uint8 chunko[13];
191
192   chunko[0]=chunko[1]=chunko[3]=0;
193   chunko[2]=0x1;                        // Width of 256
194
195   chunko[4]=chunko[5]=chunko[6]=0;
196   chunko[7]=totallines;                 // Height
197
198   chunko[8]=8;                          // bit depth
199   chunko[9]=3;                          // Color type; indexed 8-bit
200   chunko[10]=0;                         // compression: deflate
201   chunko[11]=0;                         // Basic adapative filter set(though none are used).
202   chunko[12]=0;                         // No interlace.
203
204   if(!WritePNGChunk(pp,13,"IHDR",chunko))
205    goto PNGerr;
206  }
207
208  {
209   char pdata[256*3];
210   
211   //void FCEUD_GetPalette(uint8 i,uint8 *r, unsigned char *g, unsigned char *b);
212   for(x=0;x<256;x++)
213    FCEUD_GetPalette(x,(uint8*)(pdata+x*3),(unsigned char*)(pdata+x*3+1),(unsigned char*)(pdata+x*3+2));
214    // static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
215   if(!WritePNGChunk(pp,256*3,"PLTE",(uint8 *)pdata))
216    goto PNGerr;
217  }
218
219  {
220   uint8 *tmp=XBuf+FSettings.FirstSLine*272+8;
221   uint8 *dest,*mal,*mork;
222
223   /* If memory couldn't be allocated, just use XBuf(screen contents
224      will be corrupted for one frame, though.
225   */
226   if(!(mal=mork=dest=malloc((totallines<<8)+totallines)))
227    mork=dest=XBuf;
228
229   for(y=0;y<totallines;y++)
230   {
231    *dest=0;                     // No filter.
232    dest++;
233    for(x=256;x;x--,tmp++,dest++)
234     *dest=*tmp;         
235    tmp+=16;
236   }
237
238   if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK)
239   {
240    if(mal) free(mal);
241    goto PNGerr;
242   }
243   if(mal) free(mal);
244   if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
245    goto PNGerr;
246  }
247  if(!WritePNGChunk(pp,0,"IEND",0))
248   goto PNGerr;
249
250  free(compmem);
251  fclose(pp);
252
253  return u+1;
254
255
256  PNGerr:
257  if(compmem)
258   free(compmem);
259  if(pp)
260   fclose(pp);
261  return(0);
262 }
263
264 #endif