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