asm compatibility re-fixed, nsf for asm fixed, msg displ
[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 #ifdef GP2X
34 #include <unistd.h>
35 #endif
36
37 #include "types.h"
38 #include "video.h"
39 #include "fce.h"
40 #include "svga.h"
41 #include "version.h"
42 #include "general.h"
43 #include "memory.h"
44
45 uint8 *XBuf=NULL;
46
47 int InitVirtualVideo(void)
48 {
49  if(!XBuf)              /* Some driver code may allocate XBuf externally. */
50   if(!(XBuf = (uint8*) (FCEU_malloc(320 * 240))))
51    return 0;
52 /*
53  if(sizeof(uint8*)==4)
54  {
55   m=(uint32) XBuf;
56   m+=8;m&=0xFFFFFFF8;
57   XBuf=(uint8 *)m;
58  }
59 */
60  memset(XBuf,128,320*240);
61  return 1;
62 }
63
64 #ifndef ZLIB
65 static uint8 pcxheader[128] =
66 {
67  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,
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,1,0,1,0,0,0,0,0,0,0,
69  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,
70  0,0,0,0,0,0,0,0,0,0,0,0,0,0,
71 };
72
73 int SaveSnapshot(void)
74 {
75  char *fn=0;
76  uint8 *tmp;
77  int x,u,y;
78  FILE *pp=NULL;
79
80  for(u=0;u<999;u++)
81  {
82   pp=fopen((fn=FCEU_MakeFName(FCEUMKF_SNAP,u,"pcx")),"rb");
83   if(pp==NULL) break;
84   fclose(pp);
85  }
86
87  if(!(pp=fopen(fn,"wb")))
88   return 0;
89
90  {
91   int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
92
93   tmp=XBuf+8+FSettings.FirstSLine*272;
94
95   pcxheader[10]=totallines;
96   fwrite(pcxheader,1,128,pp);
97   for(y=0;y<totallines;y++)
98   {
99    for(x=0;x<256;x++)
100    {
101     if(*tmp>=0xc0) fputc(0xC1,pp);
102      fputc(*tmp,pp);
103     tmp++;
104    }
105    tmp+=16;
106   }
107  }
108
109  fputc(0xC,pp);
110  for(x=0;x<256;x++)
111  {
112   uint8 r,g,b;
113
114   FCEUD_GetPalette(x,&r,&g,&b);
115   fputc(r,pp);
116   fputc(g,pp);
117   fputc(b,pp);
118  }
119  fclose(pp);
120
121  return u+1;
122 }
123
124 #else
125
126 #include <zlib.h>
127 #include "crc32.h"
128
129 static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
130 {
131  uint32 crc;
132
133  uint8 tempo[4];
134
135  tempo[0]=size>>24;
136  tempo[1]=size>>16;
137  tempo[2]=size>>8;
138  tempo[3]=size;
139
140  if(fwrite(tempo,4,1,fp)!=1)
141   return 0;
142  if(fwrite(type,4,1,fp)!=1)
143   return 0;
144
145  if(size)
146   if(fwrite(data,1,size,fp)!=size)
147    return 0;
148
149  crc=CalcCRC32(0,(uint8 *)type,4);
150  if(size)
151   crc=CalcCRC32(crc,data,size);
152
153  tempo[0]=crc>>24;
154  tempo[1]=crc>>16;
155  tempo[2]=crc>>8;
156  tempo[3]=crc;
157
158  if(fwrite(tempo,4,1,fp)!=1)
159   return 0;
160  return 1;
161 }
162
163 int SaveSnapshot(void)
164 {
165  char *fn=0;
166  int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
167  int x,u,y;
168  FILE *pp=NULL;
169  uint8 *compmem=NULL;
170  unsigned long compmemsize=totallines*263+12;
171
172  if(!(compmem=FCEU_malloc(compmemsize)))
173   return 0;
174
175  for(u=0;u<999;u++)
176  {
177   pp=fopen((fn=FCEU_MakeFName(FCEUMKF_SNAP,u,"png")),"rb");
178   if(pp==NULL) break;
179   fclose(pp);
180  }
181
182  if(!(pp=fopen(fn,"wb")))
183   return 0;
184  {
185   static uint8 header[8]={137,80,78,71,13,10,26,10};
186   if(fwrite(header,8,1,pp)!=1)
187    goto PNGerr;
188  }
189
190  {
191   uint8 chunko[13];
192
193   chunko[0]=chunko[1]=chunko[3]=0;
194   chunko[2]=0x1;                        // Width of 256
195
196   chunko[4]=chunko[5]=chunko[6]=0;
197   chunko[7]=totallines;                 // Height
198
199   chunko[8]=8;                          // bit depth
200   chunko[9]=3;                          // Color type; indexed 8-bit
201   chunko[10]=0;                         // compression: deflate
202   chunko[11]=0;                         // Basic adapative filter set(though none are used).
203   chunko[12]=0;                         // No interlace.
204
205   if(!WritePNGChunk(pp,13,"IHDR",chunko))
206    goto PNGerr;
207  }
208
209  {
210   char pdata[256*3];
211
212   //void FCEUD_GetPalette(uint8 i,uint8 *r, unsigned char *g, unsigned char *b);
213   for(x=0;x<256;x++)
214    FCEUD_GetPalette(x,(uint8*)(pdata+x*3),(unsigned char*)(pdata+x*3+1),(unsigned char*)(pdata+x*3+2));
215    // static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
216   if(!WritePNGChunk(pp,256*3,"PLTE",(uint8 *)pdata))
217    goto PNGerr;
218  }
219
220  {
221   uint8 *tmp=XBuf+FSettings.FirstSLine*272+8;
222   uint8 *dest,*mal,*mork;
223
224   /* If memory couldn't be allocated, just use XBuf(screen contents
225      will be corrupted for one frame, though.
226   */
227   if(!(mal=mork=dest=malloc((totallines<<8)+totallines)))
228    mork=dest=XBuf;
229
230   for(y=0;y<totallines;y++)
231   {
232    *dest=0;                     // No filter.
233    dest++;
234    for(x=256;x;x--,tmp++,dest++)
235     *dest=*tmp;
236    tmp+=16;
237   }
238
239   if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK)
240   {
241    if(mal) free(mal);
242    goto PNGerr;
243   }
244   if(mal) free(mal);
245   if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
246    goto PNGerr;
247  }
248  if(!WritePNGChunk(pp,0,"IEND",0))
249   goto PNGerr;
250
251  free(compmem);
252  fclose(pp);
253 #ifdef GP2X
254  sync();
255 #endif
256
257  return u+1;
258
259
260  PNGerr:
261  if(compmem)
262   free(compmem);
263  if(pp)
264   fclose(pp);
265  return(0);
266 }
267
268 #endif