1 
2 /*
3 
4    gameboy.c
5 
6    This file emulates the hardware (all around the Gameboy-CPU).
7 
8 */
9 
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 #ifdef UNIX
15 #include <unistd.h>
16 #endif
17 
18 #include <ctype.h>
19 #include <string.h>
20 
21 #include "globals.h"
22 #include "gameboy.h"
23 #include "sgb.h"
24 #include "z80.h"
25 
26 #define Z80OPC_GAMEBOYC_SKIP /* only M_RST needed from here */
27 #include "z80opc.h"
28 
29 #include "arplay.h"
30 
31 #include "sys.h"
32 
33 #ifdef SOUND
34 /*#define DEBUG_SOUND*/
35 #include "sound.h"
36 #endif
37 
38 rombank bank[GB_MAXROMBANKCOUNT];      /* rom                           */
39 rambank sram[GB_MAXRAMBANKCOUNT];      /* sram                          */
40 uchar *vram[2];                        /* vram                          */
41 uchar *iram[8];                        /* internal ram                  */
42                                        /* don't forget echoing !        */
43 uchar *oam;                            /* oam                           */
44 uchar *io;                             /* io                            */
45 
46 
47 char *lcdbuffer;                       /* gameboy screen buffer         */
48 unsigned int GB_BGPAL[8][4]=
49 {{0x7FFF,0x56B5,0x294A,0x0000},
50  {0x7FFF,0x56B5,0x294A,0x0000},
51  {0x7FFF,0x56B5,0x294A,0x0000},
52  {0x7FFF,0x56B5,0x294A,0x0000},
53  {0x7FFF,0x56B5,0x294A,0x0000},
54  {0x7FFF,0x56B5,0x294A,0x0000},
55  {0x7FFF,0x56B5,0x294A,0x0000},
56  {0x7FFF,0x56B5,0x294A,0x0000}};
57 unsigned int GB_OBJPAL[8][4]=
58 {{0x7FFF,0x56B5,0x294A,0x0000},
59  {0x7FFF,0x56B5,0x294A,0x0000},
60  {0x7FFF,0x56B5,0x294A,0x0000},
61  {0x7FFF,0x56B5,0x294A,0x0000},
62  {0x7FFF,0x56B5,0x294A,0x0000},
63  {0x7FFF,0x56B5,0x294A,0x0000},
64  {0x7FFF,0x56B5,0x294A,0x0000},
65  {0x7FFF,0x56B5,0x294A,0x0000}};
66 
67 ulong BGPAL[8][4],OBJPAL[8][4];
68 
69 uint  rombanknr,workbanknr;
70 uint  romselectmask;
71 uchar rambanknr;
72 int   rambankenabled;
73 uchar sramselectmask;
74 int   mbctype;
75 int   mbcmode;
76 uchar newjoypadstate,joypadstate,lcdphase;
77 int timerfreq,timerclks,dividerclks,lcdclks,joypadclks,
78     vblankdelay,sramsize,srambanksize,lastjoysel,serialioclks,
79     soundcounter,ABORT_EMULATION,vblankoccured,
80     hdmastarted,hdmasrc,hdmadst,soundclks,snd_updateclks,colormode,
81     siosendout;
82 
83 int serialclks[2][2]={{4096,2048},{128,64}};
84                                        /* [SC bit 1][cpuspeed] */
85 
86 char sramfile[256];
87 
88 void (*scanline)(void);     /* standard gameboy video output */
89 void gb_scanline8(void);
90 void gb_scanline16(void);
91 void gb_scanline32(void);
92 
93 void cgb_scanline16(void);  /* gameboy color video output */
94 void cgb_scanline32(void);
95 void cgb_scanline8(void);
96 
97 void switch2color(void);
98 
99 int GB_SRAMBANKSIZE[]=
100 {
101   0x2000,0x0800,0x2000,0x2000
102 };
103 uchar GB_SRAMSELECTMASK[]=
104 {
105   1,1,1,3
106 };
107 uchar GB_SRAMBANKCOUNT[]=
108 {
109   1,1,1,4
110 };
111 
112 uint GB_VCLKS[]=
113 {
114   80,172,208,560
115 };
116 /*uint GB_VCLKS[]=
117 {
118   80,172,208,460   * cycles 2,3,0,sigma *
119 };*/
120 /*uint GB_VCLKS[]=
121 {
122   80,172,204,456   * cycles 2,3,0,sigma (old, I made the refresh slower) *
123 };*/
124 
125 uint GB_TIMERFRQ[]=
126 {
127   1024,16,64,256
128 };
129 
130 uchar Area_0xFF00_init[]=
131 {
132   0xCF,0x00,0x7E,0xFF,0xAD,0x00,0x00,0xF8,
133   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,
134   0x80,0xBF,0xF3,0xFF,0x3F,0xFF,0x3F,0x00,
135   0xFF,0x3F,0x7F,0xFF,0x9F,0xFF,0x3F,0xFF,
136   0xFF,0x00,0x00,0x3F,0x77,0xF3,0xF1,0x00,
137   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140   0x91,0x80,0x00,0x00,0x05,0x00,0x00,0xFC,
141   0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00
142 };
143 
144 uchar Nintendo_Logo[]=
145 {
146   0xCE,0xED,0x66,0x66,0xCC,0x0D,0x00,0x0B,
147   0x03,0x73,0x00,0x83,0x00,0x0C,0x00,0x0D,
148   0x00,0x08,0x11,0x1F,0x88,0x89,0x00,0x0E,
149   0xDC,0xCC,0x6E,0xE6,0xDD,0xDD,0xD9,0x99,
150   0xBB,0xBB,0x67,0x63,0x6E,0x0E,0xEC,0xCC,
151   0xDD,0xDC,0x99,0x9F,0xBB,0xB9,0x33,0x3E
152 };
153 
154 uchar H_Flip[]=
155 {
156 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,
157 0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
158 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,
159 0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
160 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,
161 0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
162 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,
163 0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
164 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,
165 0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
166 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,
167 0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
168 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,
169 0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
170 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,
171 0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
172 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,
173 0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
174 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,
175 0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
176 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,
177 0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
178 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,
179 0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
180 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,
181 0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
182 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,
183 0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
184 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,
185 0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
186 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,
187 0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF,
188 };
189 
190 uchar IOIn(uint);
191 void IOOut(uint,uchar);
192 
193 
IOIn(uint addr)194 uchar IOIn(uint addr)
195 {
196     switch (addr) {
197     case 0x44:
198 	return LY<153 ? LY : 0;
199 
200     default:
201       return io[addr];
202     }
203 }
204 
GetByteAt(uint addr)205 uchar GetByteAt(uint addr)
206 {
207 #ifdef HARDDEBUG
208   if (addr>=0xFF10&&addr<=0xFF27) {
209     fprintf(OUTSTREAM,"IO read access: 0x%04X: %04X=>",Z80_REG.W.PC,addr);
210     if (addr>=0x4000) {
211       if (addr>=0x8000) {
212 	if (addr>=0xA000) {
213 	  if (addr>=0xC000) {
214 	    if (addr>=0xD000) {
215 	      if (addr>=0xE000) {
216 		if (addr>=0xF000) {
217 		  if (addr>=0xFE00) {
218 		    if (addr>=0xFF00) {
219 		      fprintf(OUTSTREAM,"%02X",IOIn(addr&0x00FF));
220 		    } else fprintf(OUTSTREAM,"%02X",oam[addr&0x00FF]);
221 		  } else fprintf(OUTSTREAM,"%02X",
222 				 iram[workbanknr][addr&0x0FFF]);
223 		} else fprintf(OUTSTREAM,"%02X",iram[0][addr&0x0FFF]);
224 	      } else fprintf(OUTSTREAM,"%02X",
225 			     iram[workbanknr][addr&0x0FFF]);
226 	    } else fprintf(OUTSTREAM,"%02X",iram[0][addr&0x0FFF]);
227 	  } else fprintf(OUTSTREAM,"%02X",sram[rambanknr][addr&0x1FFF]);
228 	} else fprintf(OUTSTREAM,"%02X",vram[VBK&1][addr&0x1FFF]);
229       } else fprintf(OUTSTREAM,"%02X",bank[rombanknr][addr&0x3FFF]);
230     } else fprintf(OUTSTREAM,"%02X",bank[0][addr]);
231     fprintf(OUTSTREAM,"\n");
232   }
233 #endif
234   if (addr<0x4000) return bank[0][addr];
235   if (addr<0x8000) return bank[rombanknr][addr & 0x3FFF];
236   if (addr<0xA000) return vram[VBK&1][addr & 0x1FFF];
237   if (addr<0xC000)
238     return /*(addr&0x1FFF)>=srambanksize ? 0 :*/
239       sram[rambanknr][addr & 0x1FFF];
240   if (addr<0xD000) return iram[0][addr&0x0FFF];
241   if (addr<0xE000) return iram[workbanknr][addr&0x0FFF];
242   if (addr<0xF000) return iram[0][addr&0x0FFF];
243   if (addr<0xFE00) return iram[workbanknr][addr&0x0FFF];
244   if (addr<0xFF00) return oam[addr & 0x00FF];
245   return IOIn(addr & 0x00FF);
246 
247   /*  switch (addr >> 13) {
248 
249       }*/
250 }
251 
GetWordAt(uint addr)252 uint GetWordAt(uint addr)
253 {
254   return ((uint)GetByteAt(addr+1)<<8)|GetByteAt(addr);
255 }
256 
IOOut(uint addr,uchar value)257 void IOOut(uint addr,uchar value)
258 {
259   int i;
260   uint u;
261 
262   value=ar_checkwrite(addr+0xFF00,value);
263   if (addr<0x4C) {
264     switch (addr) {
265     case 0x00: /* joypad info */
266       if (sgb_packagetransfer && !colormode) {
267 	switch ((value >> 4)& 0x03) {
268 	case 0:
269 #ifdef TDEBUG
270 	  fprintf(OUTSTREAM,"init\n");
271 	  sgb_dumppackagebuffer();
272 #endif
273 	  sgb_packagetransfer=1;
274 	  sgb_byte&=0xFFF0;
275 	  /* sgb_buffer[0]=0;*/
276 	  sgb_bitnr=0;
277 	  sgb_bit=-1;
278 	  break;
279 	case 1:sgb_bit=1;break;
280 	case 2:sgb_bit=0;break;
281 	case 3:
282 	  if (sgb_bit<0) break;
283 	  if ((sgb_pkgdone==0)&&(sgb_byte<SGB_BUFFERSIZE)) {
284 	    sgb_buffer[sgb_byte]|=(sgb_bit<<sgb_bitnr);
285 	    sgb_bitnr++;
286 	    if (sgb_bitnr>7) {
287 	      sgb_bitnr=0;
288 	      sgb_byte++;
289 	      sgb_buffer[sgb_byte]=0;
290 
291 	      /*      printf("(%d,%d)\n",sgb_byte,sgb_bitnr);*/
292 	      if (!(sgb_byte&0x0F)) {
293 		sgb_packagetransfer=0;
294 		sgb_pkgdone=1;
295 		sgb_processcmd();
296 	      }
297 	    }
298 	  } else {
299 	      /* package transfer successfully closed */
300 
301 	      sgb_closecmd();
302 	  }
303 	  break;
304 	}
305       }
306 
307       switch ((value >> 4)& 0x03) {
308       case 0:
309 #ifdef TDEBUG
310 	fprintf(OUTSTREAM,"init\n");
311 	sgb_dumppackagebuffer();
312 #endif
313 	sgb_packagetransfer=1;
314 	sgb_pkgdone=0;
315 	sgb_byte&=0xFFF0;
316 	sgb_bitnr=0;
317 	/* sgb_buffer[0]=0;*/
318 	sgb_bit=-1;
319 	break;
320       case 1:lastjoysel=0;break;
321       case 2:lastjoysel=1;break;
322       case 3:lastjoysel=2;sgb_packagetransfer=0;break;
323       }
324       switch (lastjoysel) {
325       case 0:
326 	P1=(joypadstate&0x0F)|0xD0;
327 	break;
328       case 1:
329 	P1=(joypadstate>>4)|0xE0;
330 	break;
331       case 2:
332 	/*if (!force_stdgameboy) P1=0x02;*/
333 	break;
334       }
335       /*printf("jps: (%02X,%02X,%d)->%02X\n",value,joypadstate,lastjoysel,P1);*/
336       break;
337     case 0x01: /* serial read/write byte */
338       siosendout=value;
339       break;
340     case 0x02: /* serial control */
341       if (colormode)
342 	serialioclks=serialclks[(SC&2)>>1][DBLSPEED];
343       else serialioclks=serialclks[0][0];
344 #ifdef DIALOGLINK
345       if ((value&0x81)==0x81) {
346 	dlglink_sndbyte(siosendout);
347 #ifdef HARDDEBUG
348 	printf("Master sio at PC:%04X (CTRL:%02X) =>%02X.\n",
349 	       Z80_REG.W.PC,value,siosendout);
350 #endif
351       }
352 #ifdef HARDDEBUG
353       if ((value&0x81)==0x80) {
354 	printf("Slave sio at PC:%04X (CTRL:%02X) =>%02X.\n",
355 	       Z80_REG.W.PC,value,siosendout);
356       }
357 #endif
358 #endif
359 
360       SC=value;
361 #ifndef DIALOGLINK
362       if (SC&0x01) IF|=0x08;
363       SC&=0x7F;SB=0xFF;
364 #endif
365       break;
366     case 0x04: /* reset divider reg */
367       DIV=0;dividerclks=GB_DIVLOAD;
368       break;
369     case 0x07:
370       TAC=value|0xF8;
371       timerclks=timerfreq=GB_TIMERFRQ[value&0x03];
372       break;
373     case 0x0F: /* interrupt flag */
374       IF=value|0xE0;
375       break;
376     case 0x40: /* lcd control */
377       if ((value & 0x80)==0) {
378 	LY=0;
379 	lcdphase=0;
380 	STAT=(STAT&0xFC)|2;
381 	lcdclks=GB_VCLKS[0];
382       }
383       LCDC=value;
384       break;
385     case 0x41:
386       STAT=(STAT&0x07)|0x80|(value&0x78);
387       break;
388     case 0x44:
389       /* should I reset ? */
390       break;
391     case 0x46:
392       for (i=0;i<0xA0;i++)
393 	/*	if ((i&3)==3)
394 		oam[i]=(oam[i]&0x0F)|(GetByteAt(((uint)value << 8)+i)&0xF0);
395 		else */
396 	    oam[i]=GetByteAt(((uint)value << 8)+i);
397       break;
398 
399       /* unsupported regs (unchanged) */
400     case 0x03:
401 
402     /* sound control regs */
403     case 0x15:
404       io[addr]=value;
405       break;
406     case 0x24: /* handled in sound module */
407     case 0x25:
408     case 0x26:
409       if (addr==0xFF26 && (value&0x80)>0) {
410 	soundcounter=4000000;
411 	io[0x26]=0x8F;
412       }
413 
414 #ifdef DEBUG_SOUND
415       printf("NR5%d<=%02X\n",(addr-4)&0x7,value);
416 #endif
417 
418       io[addr]=value;
419       break;
420 
421     case 0x10:
422       NR10=value;
423 #ifdef SOUND
424 #ifdef DEBUG_SOUND
425       if (value&7) printf("NR10<=%02X\n",value);
426 #endif
427       snd1_st=snd1_str=((NR10>>4)&7)<<1;
428 #endif
429       break;
430     case 0x11:
431       NR11=value;
432 #ifdef DEBUG_SOUND
433       if ((value&0xC0)!=0x80) printf("NR11<=%02X\n",value);
434 #endif
435       break;
436     case 0x12:
437       NR12=value;
438 #ifdef DEBUG_SOUND
439       printf("NR12<=%02X\n",value);
440 #endif
441 #ifdef SOUND
442       value=(value&7)<<2;
443       if (/*(NR12&8)==0 &&*/ value<snd_length1) snd_length1=value;
444 #endif
445       break;
446     case 0x13:
447       NR13=value;
448 #ifdef SOUND
449       /*      if (value==0xFF) snd_length1=0;*/
450       snd_reload1=gbfreq((((int)(NR14&7)<<8))|NR13);
451 #endif
452 #ifdef DEBUG_SOUND
453       printf("snd_reload1(low: %05i;%02X-%02X)\n",snd_reload1,NR13,NR12);
454 #endif
455       break;
456     case 0x14:
457       NR14=value;
458 #ifdef SOUND
459       snd_reload1=gbfreq((((int)(NR14&7)<<8))|NR13);
460       if (value&0x80) {
461 	if ((snd_init1=NR12&0xF7 ? 1 : 0))
462 	  snd_length1=value & 0x40 ? 65-(NR11&0x3F) : 0xFFFF;
463 #ifdef DEBUG_SOUND
464 	printf("%05i %09i (%02X%02X)\n",
465 	       ((int)(NR14&7)<<8)|NR13,snd_reload1,NR13,NR14);
466 #endif
467       }
468 #endif
469       break;
470 
471     case 0x16:
472 #ifdef DEBUG_SOUND
473       if ((value&0xC0)!=0x80) printf("NR21<=%02X\n",value);
474 #endif
475       NR21=value;
476       break;
477     case 0x17:
478       NR22=value;
479 #ifdef SOUND
480       value=(value&7)<<2;
481       if (/*(NR22&8)==0 &&*/ value<snd_length2) snd_length2=value;
482 #endif
483       break;
484     case 0x18:
485       NR23=value;
486 #ifdef SOUND
487       if (value==0xFF) snd_length2=0;
488       snd_reload2=gbfreq((((int)(NR24&7)<<8))|NR23);
489 #endif
490       break;
491     case 0x19:
492       NR24=value;
493 #ifdef SOUND
494       snd_reload2=gbfreq((((int)(NR24&7)<<8))|NR23);
495       if (value&0x80) {
496 	if ((snd_init2=NR22&0xF7 ? 1 : 0))
497 	  snd_length2=value & 0x40 ? 65-(NR21&0x3F) : 0xFFFF;
498       }
499 #endif
500       break;
501 
502     case 0x1A:
503       NR30=value;
504       break;
505     case 0x1B:
506       NR31=value;
507       break;
508     case 0x1C:
509       NR32=value;
510 #ifdef SOUND
511       switch ((value>>5)&3) {
512       case 0:snd_shr=4;break;
513       case 1:snd_shr=0;break;
514       case 2:snd_shr=1;break;
515       case 3:snd_shr=2;break;
516       }
517 #endif
518       break;
519     case 0x1D:
520       NR33=value;
521 #ifdef SOUND
522       if (value==0xFF) snd_length3=0;
523       snd_reload3=gbfreq((((int)(NR34&7)<<8))|NR33)>>1;
524 #endif
525       break;
526     case 0x1E:
527       NR34=value;
528 #ifdef SOUND
529       snd_reload3=gbfreq((((int)(NR34&7)<<8))|NR33)>>1;
530       if (value&0x80) {
531 	if ((snd_init3=(NR30>>7)))
532 	  snd_length3=value & 0x40 ? 257-NR31 : 0xFFFF;
533       }
534 #endif
535       break;
536 
537     case 0x20:
538 #ifdef DEBUG_SOUND
539       printf("NR41<=%02X\n",value);
540 #endif
541       NR41=value;
542       break;
543     case 0x21:
544 #ifdef DEBUG_SOUND
545       printf("NR42<=%02X\n",value);
546 #endif
547       NR42=value;
548 #ifdef SOUND
549       value=(value&7)<<2;
550       if (/*(NR42&8)==0 &&*/ value<snd_length4) snd_length4=value;
551       /*      if ((NR42&0xF7)==0) snd_init4=snd_length4=0;*/
552 #endif
553       break;
554     case 0x22:
555 #ifdef DEBUG_SOUND
556       printf("NR43<=%02X\n",value);
557 #endif
558       NR43=value;
559       break;
560     case 0x23:
561 #ifdef DEBUG_SOUND
562       printf("NR44<=%02X\n",value);
563 #endif
564       NR44=value;
565       /*
566 #ifdef SOUND
567       if (value&0x80) {
568 	snd_reload4=1;
569 	if ((snd_init4=NR42&0xF8 ? 1 : 0)) {
570 	  snd_length4=value & 0x40 ? 64-(NR41&0x3F) :
571 	    (NR42 & 0x07)<<4;
572 	  printf("snd_len4 %d\n",snd_length4);
573 	}
574       }
575 #endif
576       */
577 #ifdef SOUND
578       if (value&0x80) {
579 	snd_reload4=1;
580 	if ((snd_init4=NR42&0xF7 ? NR44>>7 : 0))
581 	  snd_length4=value & 0x40 ? 65-(NR41&0x3F) :
582 	    (NR42 & 0x07)<<4;
583       }
584 #endif
585       soundcounter=4000000;
586       break;
587 
588 
589 
590       /* unchanged writes */
591     case 0x05: /* timer counter          */
592     case 0x06: /* timer modulo           */
593     case 0x30: /* waveform sound data    */
594     case 0x31: /**/
595     case 0x32:
596     case 0x33:
597     case 0x34: /**/
598     case 0x35:
599     case 0x36:
600     case 0x37: /**/
601     case 0x38:
602     case 0x39:
603     case 0x3A:
604     case 0x3B:
605     case 0x3C: /**/
606     case 0x3D:
607     case 0x3E:
608     case 0x3F: /* --- waveform end       */
609     case 0x42: /* scroll y               */
610     case 0x43: /* scroll x               */
611     case 0x45: /* lcd y compare          */
612     case 0x47: /* BG palette             */
613     case 0x48: /* sprite palette 0       */
614     case 0x49: /* sprite palette 1       */
615     case 0x4A: /* window y               */
616     case 0x4B: /* window x               */
617       io[addr]=value;
618       break;
619     default:
620       return;
621     }
622   } else {
623     /* also 0xFFFF (=interrupt enable) *** unchanged *** */
624     if (addr>0x7F) io[addr]=value;
625 
626     /* CGB io handling */
627     switch (addr) {
628     case 0x4D: /* cpu speed switch */
629       if (!colormode) switch2color();
630       KEY1=(KEY1&0x80)|(value&1);
631       break;
632     case 0x4F: /* video bank selection */
633       if (!colormode) switch2color();
634       VBK=value&1;
635       break;
636     case 0x51: /* cgb DMA source hi */
637       if (!colormode) switch2color();
638       HDMA1=value;
639       hdmasrc=((unsigned int)HDMA1<<8)|(HDMA2&0xF0);
640       break;
641     case 0x52: /* cgb DMA source low */
642       if (!colormode) switch2color();
643       HDMA2=value&0xF0;
644       hdmasrc=((unsigned int)HDMA1<<8)|(HDMA2&0xF0);
645       break;
646     case 0x53: /* cgb DMA destination hi */
647       if (!colormode) switch2color();
648       HDMA3=value&0x1F;
649       hdmadst=((unsigned int)(HDMA3&0x1F)<<8)|(HDMA4&0xF0);
650       break;
651     case 0x54: /* cgb DMA destination low */
652       if (!colormode) switch2color();
653       HDMA4=value&0xF0;
654       hdmadst=((unsigned int)(HDMA3&0x1F)<<8)|(HDMA4&0xF0);
655       break;
656     case 0x55: /* cgb DMA start and counter */
657       if (!colormode) switch2color();
658       HDMA5=value;
659       hdmasrc=((unsigned int)HDMA1<<8)|(HDMA2&0xF0);
660       hdmadst=((unsigned int)(HDMA3&0x1F)<<8)|(HDMA4&0xF0);
661       switch (hdmastarted) {  /* general=>1; horizontal=>2 stoping=>-1*/
662       case 2:
663 	hdmastarted=value&0x80 ? 2 : -1;
664 	HDMA5&=0x7F;
665 	break;
666       default:
667 	hdmastarted=((HDMA5&0x80)>>7)+1;
668 	if (hdmastarted==2) {
669 	  HDMA5&=0x7F;
670 	  break;
671 	}
672 	for (i=((HDMA5&0x7F)+1)<<4;i>0;i--,hdmadst++,hdmasrc++)
673 	  vram[VBK&1][hdmadst&0x1FFF]=GetByteAt(hdmasrc);
674 	HDMA5=0x80;
675 	HDMA1=hdmasrc>>8;
676 	HDMA2=hdmasrc&0xF0;
677 	HDMA3=(hdmadst>>8)&0x1F;
678 	HDMA4=hdmadst&0xF0;
679 	hdmastarted=0;
680 	break;
681       }
682 
683 #ifdef DEBUG
684       printf("HDMA5<= %02X (%i) (%04X=>%04X) at 0x%04X\n",value,
685 	     hdmastarted,hdmasrc,hdmadst+0x8000,Z80_REG.W.PC);
686 #endif
687       /*      for (i=((HDMA5&0x7F)+1)<<4;i>0;i--,dma_d++,dma_s++)
688 	      vram[VBK&1][dma_d&0x1FFF]=GetByteAt(dma_s);*/
689       break;
690     case 0x56: /* infrared IO */
691       if (!colormode) switch2color();
692 #ifdef DEBUG
693       printf("Fixme: infrared access (%02X at %04X).\n",value,Z80_REG.W.PC);
694 #endif
695       break;
696     case 0x68: /* BG pal write specs */
697       if (!colormode) switch2color();
698       BCPS=value&0xBF;
699       u=GB_BGPAL[(value>>3)&7][(value>>1)&3];
700       BCPD=value&1 ? (u>>8)&0x7F : u&0xFF;
701       break;
702     case 0x69: /* BG pal write data */
703       if (!colormode) switch2color();
704       i=BCPS;
705       if (i&1) { /* high word */
706 	u=GB_BGPAL[(i>>3)&7][(i>>1)&3]=(GB_BGPAL[(i>>3)&7][(i>>1)&3]&0xFF)|
707 	  (value<<8);
708       } else { /* low word */
709 	u=GB_BGPAL[(i>>3)&7][(i>>1)&3]=(GB_BGPAL[(i>>3)&7][(i>>1)&3]&0xFF00)|
710 	  value;
711       }
712       BGPAL[(i>>3)&7][(i>>1)&3]=color_translate(u);
713       i=BCPS=i&0x80 ? (i&0x80)|((i+1)&0x3F) : i;
714       u=GB_BGPAL[(i>>3)&7][(i>>1)&3];
715       BCPD=i&1 ? u>>8 : u&0xFF;
716       break;
717     case 0x6A: /* OBJ pal write specs */
718       if (!colormode) switch2color();
719       OCPS=value&0xBF;
720       u=GB_OBJPAL[(value>>3)&7][(value>>1)&3];
721       OCPD=value&1 ? (u>>8)&0x7F : u&0xFF;
722       break;
723     case 0x6B: /* OBJ pal write data */
724       if (!colormode) switch2color();
725       i=OCPS;
726       if (i&1) { /* high word */
727 	u=GB_OBJPAL[(i>>3)&7][(i>>1)&3]=(GB_OBJPAL[(i>>3)&7][(i>>1)&3]&0xFF)|
728 	  (value<<8);
729       } else { /* low word */
730 	u=GB_OBJPAL[(i>>3)&7][(i>>1)&3]=(GB_OBJPAL[(i>>3)&7][(i>>1)&3]&0xFF00)|
731 	  value;
732       }
733       OBJPAL[(i>>3)&7][(i>>1)&3]=color_translate(u);
734       i=OCPS=i&0x80 ? (i&0x80)|((i+1)&0x3F) : i;
735       u=GB_OBJPAL[(i>>3)&7][(i>>1)&3];
736       OCPD=i&1 ? u>>8 : u&0xFF;
737       break;
738     case 0x70: /* work bank selection */
739       if (!colormode) switch2color();
740       SVBK=value&7;
741       workbanknr=value&7;
742       if (workbanknr==0) workbanknr++;
743 #ifdef HARDDEBUG
744       printf("WRAM bank %i selected.\n",workbanknr);
745 #endif
746       break;
747     }
748   }
749 }
750 
SetByteAt(uint addr,uchar value)751 void SetByteAt(uint addr, uchar value)
752 {
753 #ifdef DEBUG
754   if (addr==0xff59)
755     fprintf(OUTSTREAM,"%04X=>%02X accessed at PC: %04X\n",
756 	    addr,value,Z80_REG.W.PC);
757   /*      fprintf(OUTSTREAM,"%d%d ",(value>>5)&1,(value>>4)&1);*/
758 #endif
759 
760   switch (addr >> 8) {
761   case 0xFF:IOOut(addr & 0xFF,value);return;
762   default:
763     switch (addr >> 13) {
764     case 0:                                          /* RAM bank enable */
765       if (mbctype==0) {
766 	fprintf(OUTSTREAM,"Fixme: No MBC and using SRAM ?\n");
767 	fprintf(OUTSTREAM,"       (written %02X to %04X)\n",value,addr);
768 	return;
769       }
770       if ((mbctype==2)&&((addr & 0x0100)>0)) {
771 	fprintf(OUTSTREAM,"Fixme: Using MBC2 and writing 0x%02X to 0x%04X.\n",
772 	       value,addr);
773 	return;
774       }
775 
776       value&=0x0F;
777 #ifdef HARDDEBUG
778       if ((value!=10)&&(value!=0)) {
779 	fprintf(OUTSTREAM,"SRAM disable ? (0x%02X=>0x%04X)\n",value,addr);
780       }
781 #endif
782 
783       rambankenabled= value == 10 ? 1 : 0;
784       return;
785     case 1:                                          /* ROM bank select */
786       switch (mbctype) {
787       case 0:
788 	if (value!=1) {
789 	  fprintf(OUTSTREAM,"Fixme: No MBC and using ROM switching ?\n");
790 	  fprintf(OUTSTREAM,"       (written %02X to %04X)\n",value,addr);
791 	  return;
792 	}
793 	break;
794       case 1:
795 	if (mbcmode)
796 	  rombanknr=value; else
797 	    rombanknr=(rombanknr&0x60)|(value & 0x1F);
798 	if (rombanknr>=romselectmask) {
799 	  fprintf(OUTSTREAM,"Fixme: ROM bank %d selected.\n",rombanknr);
800 	  return;
801 	}
802 	break;
803       case 2:
804 	if ((addr & 0x0100)==0) {
805 	  fprintf(OUTSTREAM,
806 		  "Fixme: Using MBC2 and writing 0x%02X to 0x%04X.\n",
807 		  value,addr);
808 	  return;
809 	}
810 	if (mbcmode)
811 	  rombanknr=value; else
812 	    rombanknr=(rombanknr&0x60)|(value & 0x1F);
813 	if (rombanknr>=romselectmask) {
814 	  fprintf(OUTSTREAM,"Fixme: ROM bank %d selected.\n",value);
815 	  return;
816 	}
817 	break;
818       case 5:
819 	if (addr>=0x3000) break;
820 	if (value>=romselectmask) {
821 	  fprintf(OUTSTREAM,"Fixme: ROM bank %d selected (PC:%04X).\n",
822 		  value,Z80_REG.W.PC);
823 	  value&=romselectmask-1;
824 	}
825 	rombanknr=value&0x7F;
826 	break;
827       }
828 
829       if (rombanknr==0) rombanknr++;
830 #ifdef HARDDEBUG
831       fprintf(OUTSTREAM,"ROM select %d (PC:%04X).\n",rombanknr,Z80_REG.W.PC);
832 #endif
833       return;
834     case 2:                                        /* RAM/ROMHI bank select */
835       if ((value&0xF0)>0) return;
836       if (mbctype==2) {
837 	fprintf(OUTSTREAM,"Fixme: MBC2 and selecting RAM banks ?\n");
838 	fprintf(OUTSTREAM,"       (written %02X to %04X)\n",value,addr);
839 	return;
840       }
841       if ((mbcmode==0)&&(mbctype==1)) {                      /* ROM hi-addr */
842 	if (value>3) {
843 	  fprintf(OUTSTREAM,"Fixme: 16/8 mode, illegal hi address.\n");
844 	  fprintf(OUTSTREAM,"       (written %02X to %04X)\n",value,addr);
845 	  return;
846 	}
847 	rombanknr=(rombanknr & 0x1F)|((value&3)<<5);
848 	if (rombanknr>=romselectmask) {
849 	  fprintf(OUTSTREAM,"Fixme: ROM bank %d selected.\n",value);
850 	  return;
851 	}
852 #ifdef DEBUG
853 	fprintf(OUTSTREAM,"ROM bank %d selected (hi addr) PC:%04X.\n",
854 		rombanknr,Z80_REG.W.PC);
855 #endif
856 	return;
857       }
858       rambanknr=value&3;
859 
860       if (rambanknr>=sramselectmask) {
861 	fprintf(OUTSTREAM,"Fixme: RAM bank %d selected.\n",rambanknr);
862 	fprintf(OUTSTREAM,"       (written %02X to %04X)\n",value,addr);
863 	return;
864       }
865 #ifdef DEBUG
866       fprintf(OUTSTREAM,"RAM bank %d selected.\n",rambanknr);
867 #endif
868       return;
869     case 3:                                         /* MBC mode select */
870       if ((value&0xF0)>0) return;
871       if (mbctype==2) {
872 	fprintf(OUTSTREAM,"Fixme: MBC2 and selecting modes ?\n");
873 	fprintf(OUTSTREAM,"       (at PC: %04X written %02X to %04X)\n",
874 	       Z80_REG.W.PC,value,addr);
875 	return;
876       }
877       if (mbctype==5) {                          /* clock counter latch */
878 #ifdef DEBUG
879 	fprintf(OUTSTREAM,"Fixme: MBC5 clock funcs not implemented (%04X).\n",
880 		Z80_REG.W.PC);
881 #endif
882 	return;
883       }
884       mbcmode=value & 1;
885 #ifdef DEBUG
886       fprintf(OUTSTREAM,"MBC mode %s selected.\n",mbcmode == 0 ? "16/8" : "4/32");
887 #endif
888       return;
889     case 4:                                        /* VRAM access */
890       /* ************************************** */
891       /* *** NOT CHECKING IF ACCESSIBLE !!! *** */
892       /* ************************************** */
893       /*      fprintf(OUTSTREAM,"VRAM access: %04X at PC %04X\n",addr,Z80_REG.W.PC); */
894       vram[VBK&1][addr & 0x1FFF]=value;
895       return;
896     case 5:                                        /* SRAM access */
897       value=ar_checkwrite(addr,value);
898 
899       if (rambankenabled!=0)
900 	sram[rambanknr][addr & 0x1FFF]=value;
901       return;
902     case 6:                                        /* internal RAM and OAM */
903     case 7:                                        /* w/o IO (0xFF00-)     */
904       if (addr<0xFE00) {
905 	/* internal RAM with echoing ! */
906 
907 	value=ar_checkwrite((addr&0x1FFF)+0xC000,value);
908 	value=ar_checkwrite((addr&0x1FFF)+0xE000,value);
909 	switch (addr>>12) {
910 	case 0xC:
911 	case 0xE:
912 	  iram[0][addr & 0x0FFF]=value;
913 	  break;
914 	case 0xD:
915 	case 0xF:
916 	  iram[workbanknr][addr & 0x0FFF]=value;
917 	  break;
918 	}
919       } else {
920 	/* OAM access */
921 	/* ************************************** */
922 	/* *** NOT CHECKING IF ACCESSIBLE !!! *** */
923 	/* ***    THIS COULD BE FATAL !!!     *** */
924 	/* ************************************** */
925 	oam[addr & 0xFF]=value;
926       }
927       return;
928     }
929   }
930 }
931 
switch2color(void)932 void switch2color(void)
933 {
934   int k,l;
935   if (force_stdgameboy) return;
936 
937   switch (bitmapbits) {
938   case 8:
939     scanline=cgb_scanline8;
940     break;
941   case 16:
942     scanline=cgb_scanline16;
943     break;
944   case 32:
945     scanline=cgb_scanline32;
946     break;
947   default:
948     printf("Error: Cannot handle resolution %i, yet.\n",bitmapbits);
949     exit(1);
950   }
951   for (k=0;k<8;k++)
952     for (l=0;l<4;l++) {
953       BGPAL[k][l]= color_translate(GB_BGPAL[k][l] );
954       OBJPAL[k][l]=color_translate(GB_OBJPAL[k][l]);
955     }
956 
957 #ifndef DOS
958   fprintf(OUTSTREAM,"Gameboy COLOR rom detected.\n");
959 #endif
960   colormode=1;
961 }
962 
963 /* for games with battery: saving routine */
savestate(void)964 void savestate(void)
965 {
966   FILE *fp;
967   int j,zeros,b;
968 
969   fprintf(OUTSTREAM,"Saving state to %s ... ",sramfile);
970   fp=fopen(sramfile,"wb");
971   if (fp) {
972     zeros=0;j=0;
973     while (j<sramsize) {
974       b=sram[j / srambanksize][j % srambanksize];
975       if (b==0) zeros++;
976       else {
977 	while (zeros) { fputc(0,fp);zeros--;}
978 	fputc(b,fp);
979       }
980       j++;
981     }
982     fclose(fp);
983     if (zeros==sramsize) {
984       fprintf(OUTSTREAM,"(empty) ");
985       if (unlink(sramfile)) fprintf(OUTSTREAM,"erase FAILED, ");
986     }
987     fprintf(OUTSTREAM,"done.\n");
988   } else {
989     fprintf(OUTSTREAM,"ERROR\n");
990   }
991 }
992 
tidyup(void)993 void tidyup(void)
994 {
995   unsigned int i;
996 
997   donesys();
998 
999   fprintf(OUTSTREAM,"Freeing resources ... ");
1000   for (i=0;i<GB_WORKBANKCOUNT;i++) {
1001     if (iram[i]!=NULL) free(iram[i]);
1002   }
1003   if (oam!=NULL) free(oam);
1004   if (io!=NULL) free(io);
1005   if (vram[0]!=NULL) free(vram[0]);
1006   if (vram[1]!=NULL) free(vram[1]);
1007   out_ok;
1008 
1009   fprintf(OUTSTREAM,"Freeing ROM/RAM ...");
1010   for (i=0;i<sramselectmask;i++)
1011     if (sram[i]!=NULL) free(sram[i]);
1012   for (i=0;i<romselectmask;i++)
1013     if (bank[i]!=NULL) free(bank[i]);
1014   out_ok;
1015   return;
1016 }
1017 
initcart(char * cartfile)1018 int initcart(char *cartfile)
1019 {
1020   FILE *fp;
1021   unsigned int i,l;
1022   int j,k;
1023   char romname[17];
1024   char filename[512];
1025   uint cs=0,ccs=0;
1026 
1027 #ifdef UNIX
1028 #define CCLOSE if (!strcmp(&cartfile[strlen(cartfile)-3],".gz")) pclose(fp); else \
1029 fclose(fp)
1030 #else
1031 #define CCLOSE fclose(fp)
1032 #endif
1033 
1034 #ifdef VERBOSE
1035   fprintf(OUTSTREAM,"Opening cart: %s\n",cartfile);
1036 #endif
1037 
1038   for (i=0;i<GB_MAXROMBANKCOUNT;i++)
1039     bank[i]=NULL;
1040 
1041   for (i=0;i<GB_WORKBANKCOUNT;i++)
1042     iram[i]=NULL;
1043 
1044   oam=NULL;io=NULL;
1045   vram[0]=NULL;vram[1]=NULL;
1046   for (i=0;i<sramselectmask;i++)
1047     sram[i]=NULL;
1048   for (i=0;i<romselectmask;i++)
1049     bank[i]=NULL;
1050 
1051 #ifdef UNIX
1052   if (!strcmp(&cartfile[strlen(cartfile)-3],".gz")) {
1053     fprintf(OUTSTREAM,"Opening gzipped.\n");
1054     sprintf(filename,"gunzip -c \"%s\"",cartfile);
1055     if ((fp=popen(filename,"r"))==NULL) {
1056       fprintf(stderr,"Failed to open gzipped cartridge.\n");
1057       exit(1);
1058     }
1059 
1060     pclose(fp);
1061 
1062     if ((fp=popen(filename,"r"))==NULL) {
1063       fprintf(stderr,"Failed to open gzipped cartridge.\n");
1064       exit(1);
1065     }
1066   } else {
1067 #endif
1068     if ((fp=fopen(cartfile,"r"))==NULL) {
1069       sprintf(filename,"%s.gb",cartfile);
1070       if ((fp=fopen(filename,"r"))==NULL) {
1071 	sprintf(filename,"%s.GB",cartfile);
1072 	if ((fp=fopen(filename,"r"))==NULL) {
1073 	  fprintf(stderr,"Failed to open cartridge.\n");
1074 	  exit(1);
1075 	}
1076       }
1077     }
1078 #ifdef UNIX
1079   }
1080 #endif
1081 
1082   /* alloc ROM banks */
1083   i=0;
1084   while (!feof(fp)) {
1085     if (i>=GB_MAXROMBANKCOUNT) {
1086       fprintf(stderr,"The cartridge is too big.\n");
1087       CCLOSE;
1088       return 1;
1089     }
1090     bank[i]=malloc(GB_ROMBANKSIZE);
1091     if (bank[i]==NULL) {
1092       fprintf(stderr,"Out of memory.\n");
1093       CCLOSE;
1094       exit(1);
1095     }
1096 
1097     if ((l=fread(bank[i],1,GB_ROMBANKSIZE,fp))==0) break;
1098 
1099     if (l!=GB_ROMBANKSIZE) {
1100       fprintf(stderr,"error reading data (reading %i,returned: %d).\n",i,l);
1101       exit(1);
1102     }
1103 
1104     if (i==0) {
1105       ccs=(((uint)bank[0][0x14E]<< 8)|
1106                   bank[0][0x14F]);
1107       cs=0;
1108       cs-=bank[0][0x14E];
1109       cs-=bank[0][0x14F];
1110     }
1111 
1112     for (k=0;k<GB_ROMBANKSIZE;k++) cs+=bank[i][k];
1113     i++;
1114   }
1115   romselectmask=j=i;
1116   CCLOSE;
1117 
1118   if (ccs!=cs) {
1119     out_failed;
1120     fprintf(stderr,"Checksum failure (is: %04X should be: %04X).\n",cs,ccs);
1121     fprintf(stderr,"Cartridge file broken ?\n");
1122     return 1;
1123   } else out_ok;
1124 
1125   /* cart check --- nintendo logo */
1126 
1127   for (i=0;i<0x30;i++)
1128     if (bank[0][0x104+i]!=Nintendo_Logo[i])
1129       {
1130 	fprintf(stderr,"I don't recognize this rom.\n");
1131 	fprintf(stderr,"Nintendo logo not found.\n");
1132 	return 1;
1133       }
1134 
1135   for (i=0;i<16;i++)
1136     romname[i]=bank[0][0x134+i];
1137   romname[16]=0;
1138   fprintf(OUTSTREAM,"Rom: %s\nCheck complete.\n",romname);
1139 
1140   /* figure out the MBC type */
1141   fprintf(OUTSTREAM,"MBC type (%02X): ",bank[0][0x147]);
1142   switch (bank[0][0x147]) {
1143   case 0:
1144     fprintf(OUTSTREAM,"ROM ONLY");
1145     mbctype=0;
1146     break;
1147   case 1:
1148     mbctype=1;
1149     fprintf(OUTSTREAM,"ROM+MBC1");
1150     break;
1151   case 2:
1152     mbctype=1;
1153     fprintf(OUTSTREAM,"ROM+MBC1+SRAM");
1154     break;
1155   case 3:
1156     mbctype=1;
1157     fprintf(OUTSTREAM,"ROM+MBC1+RAM+BATTERY");
1158     break;
1159   case 5:
1160     mbctype=2;
1161     fprintf(OUTSTREAM,"ROM+MBC2");
1162     break;
1163   case 6:
1164     mbctype=2;
1165     fprintf(OUTSTREAM,"ROM+MBC2+BATTERY");
1166     break;
1167   case 8:
1168     mbctype=0;
1169     fprintf(OUTSTREAM,"ROM+SRAM");
1170     break;
1171   case 9:
1172     mbctype=0;
1173     fprintf(OUTSTREAM,"ROM+SRAM+BATTERY");
1174     break;
1175   case 0x10:
1176   case 0x13:
1177   case 0x1C:
1178     mbctype=5;
1179     fprintf(OUTSTREAM,"ROM+MBC5 (?)");
1180     break;
1181   case 0x19:
1182     mbctype=5;
1183     fprintf(OUTSTREAM,"ROM+MBC5");
1184     break;
1185   case 0x1A:
1186     mbctype=5;
1187     fprintf(OUTSTREAM,"ROM+SRAM+MBC5");
1188     break;
1189   case 0x1B:
1190   case 0x1E:
1191     mbctype=5;
1192     fprintf(OUTSTREAM,"MBC5+ROM+SRAM+BATTERY");
1193     break;
1194   case 255:                  /* HuC1 - could be buggy */
1195     mbctype=1;
1196     fprintf(OUTSTREAM,"Warning: HuC1 detected ... this is not supported.");
1197     break;
1198   default:
1199     fprintf(stderr,
1200 	     "\nI don't know this cartridge type (%02X). Sorry ...\n",
1201 	   bank[0][0x147]);
1202     fprintf(stderr,"You can report this to me. (Thanks)\n");
1203     return 1;
1204   }
1205   fprintf(OUTSTREAM,"\n");
1206 
1207   /* allocate RAMs 'n co */
1208   vram[0]=calloc(GB_VRAMSIZE,1);
1209   vram[1]=calloc(GB_VRAMSIZE,1);
1210   io=calloc(GB_IOAREASIZE,1);
1211   oam=calloc(GB_OAMSIZE,1);
1212   for (i=0;i<GB_WORKBANKCOUNT;i++)
1213     if ((iram[i]=calloc(GB_WORKRAMBANKSIZE,1))==NULL) {
1214       fprintf(OUTSTREAM,"Failed to allocate 4kB WORKRAM.\n");
1215       return 1;
1216     }
1217 
1218   if ((vram[0]==NULL)||(vram[1]==NULL)||(io==NULL)||(oam==NULL))
1219     return 1;
1220 
1221   /* alloc SRAM banks */
1222 
1223   srambanksize=0x2000;
1224   for (i=0;i<4;i++) {
1225     if ((sram[i]=calloc(srambanksize,1))==NULL) {
1226       fprintf(OUTSTREAM,"Failed to allocate 8kB SRAM.\n");
1227       return 1;
1228     }
1229   }
1230   sramsize=0x8000;sramselectmask=4;
1231 
1232 #ifdef VERBOSE
1233   fprintf(OUTSTREAM,"Allocated SRAM (%d kB).\n",sramsize/1024);
1234 #endif
1235 
1236   strcpy(sramfile,cartfile);
1237   *strrchr(sramfile,'.')=0;
1238   strcat(sramfile,".GBS");
1239   fprintf(OUTSTREAM,"Trying to open SRAM-file '%s' ... ",sramfile);
1240   fp=fopen(sramfile,"rb");
1241   if (fp!=NULL) {
1242     fseek(fp,0,SEEK_END);
1243     j=ftell(fp);rewind(fp);
1244     if (j<=sramsize) {
1245       k=GB_SRAMBANKCOUNT[bank[0][0x149]];
1246       if (k==0) k++;
1247       i=0;
1248       while (j>0) {
1249 	l=j>srambanksize ? srambanksize : j;
1250 	cs=fread(sram[i++],1,l,fp);
1251 	if (cs<l) {
1252 	  fprintf(OUTSTREAM,"read error (wanted %d, got %d)\n",l,cs);
1253 	  CCLOSE;
1254 	  return 1;
1255 	}
1256 	j-=l;
1257       }
1258       out_ok;
1259     } else {
1260       fprintf(OUTSTREAM,"corrupt state\n");
1261     }
1262     CCLOSE;
1263   } else {
1264     fprintf(OUTSTREAM,"not found\n");
1265   }
1266 
1267 
1268   /* mem init */
1269   for (i=0;i<0x100;i++)
1270     io[i]=Area_0xFF00_init[i];
1271 
1272   /* init registers */
1273   Z80_REG.W.AF= force_stdgameboy ? 0x01B0 : 0x11B0;
1274 
1275   Z80_REG.W.BC=0x0013;
1276   Z80_REG.W.DE=0x00D8;
1277   Z80_REG.W.HL=0x014D;
1278   Z80_REG.W.SP=0xFFFE;
1279   Z80_REG.W.PC=0x0100;
1280   Z80_HALTED=Z80_IE=0;
1281   Z80_CPUCLKS=0;
1282 
1283   /* and stuff */
1284   rombanknr=1;workbanknr=1;
1285   rambanknr=0;
1286   rambankenabled=0;
1287   colormode=mbcmode=0;
1288   newjoypadstate=joypadstate=0xFF;
1289   timerclks=timerfreq=GB_TIMERFRQ[TAC&0x03];
1290   dividerclks=GB_DIVLOAD;
1291   lcdphase=0;STAT|=2;     /* lcd phase 2 */
1292   lcdclks=GB_VCLKS[0];
1293   IE=0x00;/* IM=0xFF; */
1294   ABORT_EMULATION=0;
1295   joypadclks=GB_JOYCLKS;
1296   soundcounter=-1;
1297   vblankdelay=GB_VBLANKDELAYCLKS;
1298   vblankoccured=0;
1299   SVBK=VBK=KEY1=0x00;
1300   hdmastarted=hdmasrc=hdmadst=0;
1301   snd_updateclks=0xFFFF;
1302   serialioclks=0;
1303 
1304   if (!(i=initsys())) {
1305     switch (bitmapbits) {
1306     case 8:scanline=gb_scanline8;break;
1307     case 16:scanline=gb_scanline16;break;
1308     case 32:scanline=gb_scanline32;break;
1309     default:
1310       printf("Error: Cannot handle resolution %i\n",bitmapbits);
1311       return 1;
1312     }
1313   }
1314 
1315   return i;
1316 }
1317 
SetWordAt(uint addr,uint value)1318 void SetWordAt(uint addr,uint value)
1319 {
1320   SetByteAt(addr,(uchar)(value & 0xFF));
1321   SetByteAt(addr+1,(uchar)(value >> 8));
1322 }
1323 
1324 #define do_tilepix(pixeltype, pack) \
1325 {\
1326 	unsigned int zpos;\
1327 	zpos=(unsigned int)x;\
1328 \
1329 	if (!doublesize) {\
1330 		pixeltype *p; \
1331 \
1332 		p=(pixeltype *)lcdbuffer+y+x;\
1333 \
1334 		*p++=FPAL[zbuffer[zpos++]=tilepix  >> 14];\
1335 		*p++=FPAL[zbuffer[zpos++]=(tilepix >>  6)&0x03];\
1336 		*p++=FPAL[zbuffer[zpos++]=(tilepix >> 12)&0x03];\
1337 		*p++=FPAL[zbuffer[zpos++]=(tilepix >>  4)&0x03];\
1338 		*p++=FPAL[zbuffer[zpos++]=(tilepix >> 10)&0x03];\
1339 		*p++=FPAL[zbuffer[zpos++]=(tilepix >>  2)&0x03];\
1340 		*p++=FPAL[zbuffer[zpos++]=(tilepix >>  8)&0x03];\
1341 		*p=FPAL[zbuffer[zpos]=tilepix        &0x03];\
1342 	} else {\
1343 		pixeltype *p; \
1344 \
1345 		p=(pixeltype *)lcdbuffer+y+(x<<1);\
1346 \
1347 		*(p+1)=*p=\
1348 			FPAL[zbuffer[zpos++]=tilepix  >> 14]; \
1349 		p+=pack; \
1350 		\
1351 		*(p+1)=*p=\
1352 			FPAL[zbuffer[zpos++]=(tilepix >>  6)&0x03];\
1353 		p+=pack; \
1354 		\
1355 		*(p+1)=*p=\
1356 			FPAL[zbuffer[zpos++]=(tilepix >> 12)&0x03];\
1357 		p+=pack; \
1358 		\
1359 		*(p+1)=*p=\
1360 			FPAL[zbuffer[zpos++]=(tilepix >>  4)&0x03];\
1361 		p+=pack; \
1362 		\
1363 		*(p+1)=*p=\
1364 			FPAL[zbuffer[zpos++]=(tilepix >> 10)&0x03];\
1365 		p+=pack; \
1366 		\
1367 		*(p+1)=*p=\
1368 			FPAL[zbuffer[zpos++]=(tilepix >>  2)&0x03];\
1369 		p+=pack; \
1370 		\
1371 		*(p+1)=*p=\
1372 			FPAL[zbuffer[zpos++]=(tilepix >> 8)&0x03];\
1373 		p+=pack; \
1374 		\
1375 		*(p+1)=*p=\
1376 			FPAL[zbuffer[zpos]=tilepix&0x03];\
1377 		\
1378 	}\
1379 }
1380 
gb_scanline8(void)1381 void gb_scanline8(void)
1382 {
1383   int x,y,tx,ty,xc,tmp;
1384   uchar *tileofs,*tiledata,*sprofs;
1385   uchar tile,tile1,tile2;
1386   uint tilepix;
1387   uchar zbuffer[GB_XBUFFERSIZE];
1388   uchar FPAL[4];
1389 
1390   FPAL[0]=(uchar)GB_STDPAL[BGP & 0x03];
1391   FPAL[1]=(uchar)GB_STDPAL[(BGP >> 2)& 0x03];
1392   FPAL[2]=(uchar)GB_STDPAL[(BGP >> 4)& 0x03];
1393   FPAL[3]=(uchar)GB_STDPAL[BGP >> 6];
1394 
1395 
1396   y=LY*GB_XBUFFERSIZE;
1397   if (doublesize) y<<=2;
1398 
1399   if (LCDC & 0x01) { /* if BG enabled */
1400 
1401 
1402     tileofs=vram[0]
1403       +((((LY+SCY)&0xFF) >> 3)<<5)+(LCDC & 0x08 ? 0x1C00 : 0x1800);
1404     xc=((LCDC & 0x20)&&(WY<=LY) ? ((WX<7 ? 0 : WX-7) >> 3) : 21);
1405     xc=xc>21 ? 21 : xc;
1406 
1407     for (tx=0,x=8-(SCX & 7);tx<xc;tx++,x+=8) {
1408       tile=tileofs[(tx+(SCX>>3))&0x1F];
1409       tiledata=LCDC & 0x10 ? vram[0]+(int)tile*16
1410 	: vram[0]+0x1000+(int)((signed char)tile)*16;
1411       tiledata+=((LY+SCY)&7)<<1;
1412       tilepix=((uint)(tiledata[1]&0xAA)<<8)|((uint)(tiledata[0]&0xAA)<<7)|
1413 	(tiledata[0]&0x55)|((tiledata[1]&0x55)<<1);
1414 
1415 	do_tilepix(uchar, 2);
1416 
1417     }
1418   } else { /* if BG not enabled */
1419 	  memset(zbuffer,0,GB_XBUFFERSIZE);
1420 	  memset((uchar*)lcdbuffer+y, FPAL[0],
1421 		doublesize ? GB_XBUFFERSIZE<<1 : GB_XBUFFERSIZE);
1422   }
1423 
1424 
1425   if ((LCDC & 0x20)&&(WY<=LY)&&(WX<167)) { /* if window is on and visible */
1426 
1427     y=LY*GB_XBUFFERSIZE;
1428     if (doublesize) y<<=2;
1429 
1430     x=WX+1;xc=167-WX;
1431     tileofs=vram[0]+(((LY-WY) >> 3)<<5)+(LCDC & 0x40 ? 0x1C00 : 0x1800);
1432 
1433     for (tx=0;xc>0;xc-=8,x+=8,tx++) {
1434       tiledata=LCDC & 0x10 ? vram[0]+(int)tileofs[tx]*16
1435 	: vram[0]+0x1000+(int)((signed char)tileofs[tx])*16;
1436       tiledata+=((LY-WY)&7)<<1;
1437       tilepix=((uint)(tiledata[1]&0xAA)<<8)|((uint)(tiledata[0]&0xAA)<<7)|
1438 	(tiledata[0]&0x55)|((tiledata[1]&0x55)<<1);
1439 
1440 	do_tilepix(uchar, 2);
1441     }
1442   }
1443 
1444   if (LCDC & 0x02) { /* sprites enabled */
1445     ty=LCDC & 0x04 ? 16 : 8;
1446 
1447     y=LY*GB_XBUFFERSIZE;
1448     if (doublesize) y<<=2;
1449 
1450     /* background sprites */
1451     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
1452       tmp=LY-sprofs[0]+16;
1453       if ((sprofs[3]&0x80)&&(tmp>=0)&&(tmp<ty)&&
1454 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
1455 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
1456 	tiledata=vram[0]
1457 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
1458 	  +(tmp<<1);
1459 	if (sprofs[3]&0x20) {
1460 	  tile1=H_Flip[tiledata[0]];
1461 	  tile2=H_Flip[tiledata[1]];
1462 	} else {
1463 	  tile1=tiledata[0];
1464 	  tile2=tiledata[1];
1465 	}
1466 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1467 	  (tile1&0x55)|((tile2&0x55)<<1);
1468 	x=sprofs[1];
1469 
1470 	if (sprofs[3]&0x10) {
1471 	  FPAL[0]=(uchar)GB_STDPAL[OBP1 & 0x03];
1472 	  FPAL[1]=(uchar)GB_STDPAL[(OBP1 >> 2)& 0x03];
1473 	  FPAL[2]=(uchar)GB_STDPAL[(OBP1 >> 4)& 0x03];
1474 	  FPAL[3]=(uchar)GB_STDPAL[OBP1 >> 6];
1475 	} else {
1476 	  FPAL[0]=(uchar)GB_STDPAL[OBP0 & 0x03];
1477 	  FPAL[1]=(uchar)GB_STDPAL[(OBP0 >> 2)& 0x03];
1478 	  FPAL[2]=(uchar)GB_STDPAL[(OBP0 >> 4)& 0x03];
1479 	  FPAL[3]=(uchar)GB_STDPAL[OBP0 >> 6];
1480 	}
1481 
1482 	if (!doublesize ) {
1483 	  if ((zbuffer[x]==0)&&(tilepix>>14))
1484 	    ((uchar *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
1485 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
1486 	    ((uchar *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
1487 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
1488 	    ((uchar *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
1489 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
1490 	    ((uchar *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
1491 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
1492 	    ((uchar *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
1493 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
1494 	    ((uchar *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
1495 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
1496 	    ((uchar *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
1497 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
1498 	    ((uchar *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
1499 	} else {
1500 	  if ((zbuffer[x]==0)&&(tilepix>>14))
1501 	    ((uchar *)lcdbuffer)[y+(x<<1)  ]=
1502 	      ((uchar *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
1503 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
1504 	    ((uchar *)lcdbuffer)[y+(x<<1)+2]=
1505 	      ((uchar *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
1506 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
1507 	    ((uchar *)lcdbuffer)[y+(x<<1)+4]=
1508 	      ((uchar *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
1509 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
1510 	    ((uchar *)lcdbuffer)[y+(x<<1)+6]=
1511 	      ((uchar *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
1512 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
1513 	    ((uchar *)lcdbuffer)[y+(x<<1)+8]=
1514 	      ((uchar *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
1515 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
1516 	    ((uchar *)lcdbuffer)[y+(x<<1)+10]=
1517 	      ((uchar *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
1518 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
1519 	    ((uchar *)lcdbuffer)[y+(x<<1)+12]=
1520 	      ((uchar *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
1521 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
1522 	    ((uchar *)lcdbuffer)[y+(x<<1)+14]=
1523 	      ((uchar *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
1524 	}
1525       }
1526     }
1527 
1528     /* foreground sprites */
1529     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
1530       tmp=LY-sprofs[0]+16;
1531       if (((sprofs[3]&0x80)==0)&&(tmp>=0)&&(tmp<ty)&&
1532 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
1533 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
1534 	tiledata=vram[0]
1535 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
1536 	  +(tmp<<1);
1537 	if (sprofs[3]&0x20) {
1538 	  tile1=H_Flip[tiledata[0]];
1539 	  tile2=H_Flip[tiledata[1]];
1540 	} else {
1541 	  tile1=tiledata[0];
1542 	  tile2=tiledata[1];
1543 	}
1544 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1545 	  (tile1&0x55)|((tile2&0x55)<<1);
1546 	x=sprofs[1];
1547 
1548 	if (sprofs[3]&0x10) {
1549 	  FPAL[0]=(uchar)GB_STDPAL[OBP1 & 0x03];
1550 	  FPAL[1]=(uchar)GB_STDPAL[(OBP1 >> 2)& 0x03];
1551 	  FPAL[2]=(uchar)GB_STDPAL[(OBP1 >> 4)& 0x03];
1552 	  FPAL[3]=(uchar)GB_STDPAL[OBP1 >> 6];
1553 	} else {
1554 	  FPAL[0]=(uchar)GB_STDPAL[OBP0 & 0x03];
1555 	  FPAL[1]=(uchar)GB_STDPAL[(OBP0 >> 2)& 0x03];
1556 	  FPAL[2]=(uchar)GB_STDPAL[(OBP0 >> 4)& 0x03];
1557 	  FPAL[3]=(uchar)GB_STDPAL[OBP0 >> 6];
1558 	}
1559 
1560 	if (!doublesize) {
1561 	  if (tilepix>>14)
1562 	    ((uchar *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
1563 	  if ((tilepix>>6)&0x03)
1564 	    ((uchar *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
1565 	  if ((tilepix>>12)&0x03)
1566 	    ((uchar *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
1567 	  if ((tilepix>>4)&0x03)
1568 	    ((uchar *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
1569 	  if ((tilepix>>10)&0x03)
1570 	    ((uchar *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
1571 	  if ((tilepix>>2)&0x03)
1572 	    ((uchar *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
1573 	  if ((tilepix>>8)&0x03)
1574 	    ((uchar *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
1575 	  if (tilepix&0x03)
1576 	    ((uchar *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
1577 	} else {
1578 	  if (tilepix>>14)
1579 	    ((uchar *)lcdbuffer)[y+(x<<1)  ]=
1580 	      ((uchar *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
1581 	  if ((tilepix>>6)&0x03)
1582 	    ((uchar *)lcdbuffer)[y+(x<<1)+2]=
1583 	      ((uchar *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
1584 	  if ((tilepix>>12)&0x03)
1585 	    ((uchar *)lcdbuffer)[y+(x<<1)+4]=
1586 	      ((uchar *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
1587 	  if ((tilepix>>4)&0x03)
1588 	    ((uchar *)lcdbuffer)[y+(x<<1)+6]=
1589 	      ((uchar *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
1590 	  if ((tilepix>>10)&0x03)
1591 	    ((uchar *)lcdbuffer)[y+(x<<1)+8]=
1592 	      ((uchar *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
1593 	  if ((tilepix>>2)&0x03)
1594 	    ((uchar *)lcdbuffer)[y+(x<<1)+10]=
1595 	      ((uchar *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
1596 	  if ((tilepix>>8)&0x03)
1597 	    ((uchar *)lcdbuffer)[y+(x<<1)+12]=
1598 	      ((uchar *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
1599 	  if (tilepix&0x03)
1600 	    ((uchar *)lcdbuffer)[y+(x<<1)+14]=
1601 	      ((uchar *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
1602 	}
1603       }
1604     }
1605 
1606 
1607   }
1608 }
1609 
cgb_scanline8(void)1610 void cgb_scanline8(void)
1611 {
1612   int x,y,tx,ty,xc,tmp;
1613   uchar *tileofs1,*tileofs2,*tiledata,*sprofs;
1614   uchar tile,tile1,tile2,tile_a;
1615   uint tilepix,tilenum;
1616   uchar zbuffer[GB_XBUFFERSIZE];
1617   uchar FPAL[4];
1618 
1619   y=LY*GB_XBUFFERSIZE;
1620   if (doublesize) y<<=2;
1621 
1622   if (LCDC & 0x01) { /* if BG enabled */
1623     tilenum=((((LY+SCY)&0xFF) >> 3)<<5)+(LCDC & 0x08 ? 0x1C00 : 0x1800);
1624     tileofs1=vram[0]+tilenum;
1625     tileofs2=vram[1]+tilenum;
1626     xc=((LCDC & 0x20)&&(WY<=LY) ? ((WX<7 ? 0 : WX-7) >> 3) : 21);
1627     xc=xc>21 ? 21 : xc;
1628     for (tx=0,x=8-(SCX & 7);tx<xc;tx++,x+=8) {
1629       tile=tileofs1[(tx+(SCX>>3))&0x1F];
1630       tile_a=tileofs2[(tx+(SCX>>3))&0x1F];
1631       tiledata=LCDC & 0x10 ? vram[(tile_a>>3)&1]+((int)tile<<4)
1632 	: vram[(tile_a>>3)&1]+0x1000+((int)((signed char)tile)<<4);
1633       tiledata+=(tile_a&0x40) ? (7-((LY+SCY)&7))<<1:((LY+SCY)&7)<<1;
1634       tile1=tiledata[0];tile2=tiledata[1];
1635       if (tile_a&0x20) {tile1=H_Flip[tile1];tile2=H_Flip[tile2];}
1636 
1637       tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1638 	(tile1&0x55)|((tile2&0x55)<<1);
1639 
1640       FPAL[0]=(uchar)BGPAL[tile_a&7][0];
1641       FPAL[1]=(uchar)BGPAL[tile_a&7][1];
1642       FPAL[2]=(uchar)BGPAL[tile_a&7][2];
1643       FPAL[3]=(uchar)BGPAL[tile_a&7][3];
1644 
1645 	do_tilepix(uchar, 2);
1646     }
1647   } else { /* if BG not enabled */
1648     memset(zbuffer,0,GB_XBUFFERSIZE);
1649 	  memset((uchar*)lcdbuffer+y, 0, /* 0 or background ? */
1650 		doublesize ? GB_XBUFFERSIZE<<1 : GB_XBUFFERSIZE);
1651   }
1652 
1653   if ((LCDC & 0x20)&&(WY<=LY)&&(WX<167)) { /* if window is on and visible */
1654 
1655     y=LY*GB_XBUFFERSIZE;
1656     if (doublesize) y<<=2;
1657 
1658     x=WX+1;xc=167-WX;
1659     tilenum=(((LY-WY) >> 3)<<5)+(LCDC & 0x40 ? 0x1C00 : 0x1800);
1660     tileofs1=vram[0]+tilenum;
1661     tileofs2=vram[1]+tilenum;
1662     for (tx=0;xc>0;xc-=8,x+=8,tx++) {
1663       tile_a=tileofs2[tx];
1664       tiledata=LCDC & 0x10 ? vram[(tile_a>>3)&1]+((int)tileofs1[tx]<<4)
1665 	: vram[(tile_a>>3)&1]+0x1000+((int)((signed char)tileofs1[tx])<<4);
1666 
1667       tiledata+=(tile_a&0x40) ? (7-((LY-WY)&7))<<1:((LY-WY)&7)<<1;
1668       tile1=tiledata[0];tile2=tiledata[1];
1669       if (tile_a&0x20) {tile1=H_Flip[tile1];tile2=H_Flip[tile2];}
1670 
1671       tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1672 	(tile1&0x55)|((tile2&0x55)<<1);
1673 
1674       FPAL[0]=(uchar)BGPAL[tile_a&7][0];
1675       FPAL[1]=(uchar)BGPAL[tile_a&7][1];
1676       FPAL[2]=(uchar)BGPAL[tile_a&7][2];
1677       FPAL[3]=(uchar)BGPAL[tile_a&7][3];
1678 
1679 	do_tilepix(uchar, 2);
1680     }
1681   }
1682 
1683   if (LCDC & 0x02) { /* sprites enabled */
1684     ty=LCDC & 0x04 ? 16 : 8;
1685 
1686     y=LY*GB_XBUFFERSIZE;
1687     if (doublesize) y<<=2;
1688 
1689     /* background sprites */
1690     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
1691       tmp=LY-sprofs[0]+16;
1692       if ((sprofs[3]&0x80)&&(tmp>=0)&&(tmp<ty)&&
1693 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
1694 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
1695 	tiledata=vram[(sprofs[3]>>3)&1]
1696 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
1697 	  +(tmp<<1);
1698 	if (sprofs[3]&0x20) {
1699 	  tile1=H_Flip[tiledata[0]];
1700 	  tile2=H_Flip[tiledata[1]];
1701 	} else {
1702 	  tile1=tiledata[0];
1703 	  tile2=tiledata[1];
1704 	}
1705 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1706 	  (tile1&0x55)|((tile2&0x55)<<1);
1707 	x=sprofs[1];
1708 
1709 	FPAL[0]=(uchar)OBJPAL[sprofs[3]&7][0];
1710 	FPAL[1]=(uchar)OBJPAL[sprofs[3]&7][1];
1711 	FPAL[2]=(uchar)OBJPAL[sprofs[3]&7][2];
1712 	FPAL[3]=(uchar)OBJPAL[sprofs[3]&7][3];
1713 
1714 	if (!doublesize) {
1715 	  if ((zbuffer[x]==0)&&(tilepix>>14))
1716 	    ((uchar *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
1717 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
1718 	    ((uchar *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
1719 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
1720 	    ((uchar *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
1721 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
1722 	    ((uchar *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
1723 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
1724 	    ((uchar *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
1725 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
1726 	    ((uchar *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
1727 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
1728 	    ((uchar *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
1729 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
1730 	    ((uchar *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
1731 	} else {
1732 	  if ((zbuffer[x]==0)&&(tilepix>>14))
1733 	    ((uchar *)lcdbuffer)[y+(x<<1)  ]=
1734 	      ((uchar *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
1735 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
1736 	    ((uchar *)lcdbuffer)[y+(x<<1)+2]=
1737 	      ((uchar *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
1738 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
1739 	    ((uchar *)lcdbuffer)[y+(x<<1)+4]=
1740 	      ((uchar *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
1741 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
1742 	    ((uchar *)lcdbuffer)[y+(x<<1)+6]=
1743 	      ((uchar *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
1744 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
1745 	    ((uchar *)lcdbuffer)[y+(x<<1)+8]=
1746 	      ((uchar *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
1747 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
1748 	    ((uchar *)lcdbuffer)[y+(x<<1)+10]=
1749 	      ((uchar *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
1750 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
1751 	    ((uchar *)lcdbuffer)[y+(x<<1)+12]=
1752 	      ((uchar *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
1753 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
1754 	    ((uchar *)lcdbuffer)[y+(x<<1)+14]=
1755 	      ((uchar *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
1756 	}
1757       }
1758     }
1759 
1760     /* foreground sprites */
1761     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
1762       tmp=LY-sprofs[0]+16;
1763       if (((sprofs[3]&0x80)==0)&&(tmp>=0)&&(tmp<ty)&&
1764 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
1765 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
1766 	tiledata=vram[(sprofs[3]>>3)&1]
1767 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
1768 	  +(tmp<<1);
1769 	if (sprofs[3]&0x20) {
1770 	  tile1=H_Flip[tiledata[0]];
1771 	  tile2=H_Flip[tiledata[1]];
1772 	} else {
1773 	  tile1=tiledata[0];
1774 	  tile2=tiledata[1];
1775 	}
1776 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1777 	  (tile1&0x55)|((tile2&0x55)<<1);
1778 	x=sprofs[1];
1779 
1780 	FPAL[0]=(uchar)OBJPAL[sprofs[3]&7][0];
1781 	FPAL[1]=(uchar)OBJPAL[sprofs[3]&7][1];
1782 	FPAL[2]=(uchar)OBJPAL[sprofs[3]&7][2];
1783 	FPAL[3]=(uchar)OBJPAL[sprofs[3]&7][3];
1784 
1785 	if (!doublesize) {
1786 	  if (tilepix>>14)
1787 	    ((uchar *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
1788 	  if ((tilepix>>6)&0x03)
1789 	    ((uchar *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
1790 	  if ((tilepix>>12)&0x03)
1791 	    ((uchar *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
1792 	  if ((tilepix>>4)&0x03)
1793 	    ((uchar *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
1794 	  if ((tilepix>>10)&0x03)
1795 	    ((uchar *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
1796 	  if ((tilepix>>2)&0x03)
1797 	    ((uchar *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
1798 	  if ((tilepix>>8)&0x03)
1799 	    ((uchar *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
1800 	  if (tilepix&0x03)
1801 	    ((uchar *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
1802 	} else {
1803 	  if (tilepix>>14)
1804 	    ((uchar *)lcdbuffer)[y+(x<<1)  ]=
1805 	      ((uchar *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
1806 	  if ((tilepix>>6)&0x03)
1807 	    ((uchar *)lcdbuffer)[y+(x<<1)+2]=
1808 	      ((uchar *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
1809 	  if ((tilepix>>12)&0x03)
1810 	    ((uchar *)lcdbuffer)[y+(x<<1)+4]=
1811 	      ((uchar *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
1812 	  if ((tilepix>>4)&0x03)
1813 	    ((uchar *)lcdbuffer)[y+(x<<1)+6]=
1814 	      ((uchar *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
1815 	  if ((tilepix>>10)&0x03)
1816 	    ((uchar *)lcdbuffer)[y+(x<<1)+8]=
1817 	      ((uchar *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
1818 	  if ((tilepix>>2)&0x03)
1819 	    ((uchar *)lcdbuffer)[y+(x<<1)+10]=
1820 	      ((uchar *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
1821 	  if ((tilepix>>8)&0x03)
1822 	    ((uchar *)lcdbuffer)[y+(x<<1)+12]=
1823 	      ((uchar *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
1824 	  if (tilepix&0x03)
1825 	    ((uchar *)lcdbuffer)[y+(x<<1)+14]=
1826 	      ((uchar *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
1827 	}
1828       }
1829     }
1830 
1831 
1832   }
1833 }
1834 
gb_scanline16(void)1835 void gb_scanline16(void)
1836 {
1837   int x,y,tx,ty,xc,tmp;
1838   uchar *tileofs,*tiledata,*sprofs;
1839   uchar tile,tile1,tile2;
1840   uint tilepix;
1841   uchar zbuffer[GB_XBUFFERSIZE];
1842   uint FPAL[4];
1843 
1844   FPAL[0]=GB_STDPAL[BGP & 0x03];
1845   FPAL[1]=GB_STDPAL[(BGP >> 2)& 0x03];
1846   FPAL[2]=GB_STDPAL[(BGP >> 4)& 0x03];
1847   FPAL[3]=GB_STDPAL[BGP >> 6];
1848 
1849 
1850   y=LY*GB_XBUFFERSIZE;
1851   if (doublesize) y<<=2;
1852 
1853   if (LCDC & 0x01) { /* if BG enabled */
1854     tileofs=vram[0]
1855       +((((LY+SCY)&0xFF) >> 3)<<5)+(LCDC & 0x08 ? 0x1C00 : 0x1800);
1856     xc=((LCDC & 0x20)&&(WY<=LY) ? ((WX<7 ? 0 : WX-7) >> 3) : 21);
1857     xc=xc>21 ? 21 : xc;
1858     for (tx=0,x=8-(SCX & 7);tx<xc;tx++,x+=8) {
1859       tile=tileofs[(tx+(SCX>>3))&0x1F];
1860       tiledata=LCDC & 0x10 ? vram[0]+((int)tile<<4)
1861 	: vram[0]+0x1000+((int)((signed char)tile)<<4);
1862       tiledata+=((LY+SCY)&7)<<1;
1863       tilepix=((uint)(tiledata[1]&0xAA)<<8)|((uint)(tiledata[0]&0xAA)<<7)|
1864 	(tiledata[0]&0x55)|((tiledata[1]&0x55)<<1);
1865 
1866 	do_tilepix(uint, 2);
1867     }
1868   } else { /* if BG not enabled */
1869 
1870 	uint *p;
1871 
1872     memset(zbuffer,0,GB_XBUFFERSIZE);
1873 
1874 	p=(uint *)lcdbuffer+y;
1875     if (doublesize)
1876       for (x=0;x<GB_XBUFFERSIZE*2;x++) *p++=FPAL[0];
1877     else
1878       for (x=0;x<GB_XBUFFERSIZE;x++) *p++=FPAL[0];
1879   }
1880 
1881   if ((LCDC & 0x20)&&(WY<=LY)&&(WX<167)) { /* if window is on and visible */
1882 
1883     y=LY*GB_XBUFFERSIZE;
1884     if (doublesize) y<<=2;
1885 
1886     x=WX+1;xc=167-WX;
1887     tileofs=vram[0]+(((LY-WY) >> 3)<<5)+(LCDC & 0x40 ? 0x1C00 : 0x1800);
1888     for (tx=0;xc>0;xc-=8,x+=8,tx++) {
1889       tiledata=LCDC & 0x10 ? vram[0]+((int)tileofs[tx]<<4)
1890 	: vram[0]+0x1000+((int)((signed char)tileofs[tx])<<4);
1891       tiledata+=((LY-WY)&7)<<1;
1892       tilepix=((uint)(tiledata[1]&0xAA)<<8)|((uint)(tiledata[0]&0xAA)<<7)|
1893 	(tiledata[0]&0x55)|((tiledata[1]&0x55)<<1);
1894 
1895 	do_tilepix(uint, 2);
1896     }
1897   }
1898 
1899   if (LCDC & 0x02) { /* sprites enabled */
1900     ty=LCDC & 0x04 ? 16 : 8;
1901 
1902     y=LY*GB_XBUFFERSIZE;
1903     if (doublesize) y<<=2;
1904 
1905     /* background sprites */
1906     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
1907       tmp=LY-sprofs[0]+16;
1908       if ((sprofs[3]&0x80)&&(tmp>=0)&&(tmp<ty)&&
1909 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
1910 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
1911 	tiledata=vram[0]
1912 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
1913 	  +(tmp<<1);
1914 	if (sprofs[3]&0x20) {
1915 	  tile1=H_Flip[tiledata[0]];
1916 	  tile2=H_Flip[tiledata[1]];
1917 	} else {
1918 	  tile1=tiledata[0];
1919 	  tile2=tiledata[1];
1920 	}
1921 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
1922 	  (tile1&0x55)|((tile2&0x55)<<1);
1923 	x=sprofs[1];
1924 
1925 	if (sprofs[3]&0x10) {
1926 	  FPAL[0]=GB_STDPAL[OBP1 & 0x03];
1927 	  FPAL[1]=GB_STDPAL[(OBP1 >> 2)& 0x03];
1928 	  FPAL[2]=GB_STDPAL[(OBP1 >> 4)& 0x03];
1929 	  FPAL[3]=GB_STDPAL[OBP1 >> 6];
1930 	} else {
1931 	  FPAL[0]=GB_STDPAL[OBP0 & 0x03];
1932 	  FPAL[1]=GB_STDPAL[(OBP0 >> 2)& 0x03];
1933 	  FPAL[2]=GB_STDPAL[(OBP0 >> 4)& 0x03];
1934 	  FPAL[3]=GB_STDPAL[OBP0 >> 6];
1935 	}
1936 
1937 	if (!doublesize) {
1938 	  if ((zbuffer[x]==0)&&(tilepix>>14))
1939 	    ((uint *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
1940 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
1941 	    ((uint *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
1942 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
1943 	    ((uint *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
1944 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
1945 	    ((uint *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
1946 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
1947 	    ((uint *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
1948 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
1949 	    ((uint *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
1950 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
1951 	    ((uint *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
1952 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
1953 	    ((uint *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
1954 	} else {
1955 	  if ((zbuffer[x]==0)&&(tilepix>>14))
1956 	    ((uint *)lcdbuffer)[y+(x<<1)  ]=
1957 	      ((uint *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
1958 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
1959 	    ((uint *)lcdbuffer)[y+(x<<1)+2]=
1960 	      ((uint *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
1961 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
1962 	    ((uint *)lcdbuffer)[y+(x<<1)+4]=
1963 	      ((uint *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
1964 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
1965 	    ((uint *)lcdbuffer)[y+(x<<1)+6]=
1966 	      ((uint *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
1967 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
1968 	    ((uint *)lcdbuffer)[y+(x<<1)+8]=
1969 	      ((uint *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
1970 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
1971 	    ((uint *)lcdbuffer)[y+(x<<1)+10]=
1972 	      ((uint *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
1973 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
1974 	    ((uint *)lcdbuffer)[y+(x<<1)+12]=
1975 	      ((uint *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
1976 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
1977 	    ((uint *)lcdbuffer)[y+(x<<1)+14]=
1978 	      ((uint *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
1979 	}
1980       }
1981     }
1982 
1983     /* foreground sprites */
1984     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
1985       tmp=LY-sprofs[0]+16;
1986       if (((sprofs[3]&0x80)==0)&&(tmp>=0)&&(tmp<ty)&&
1987 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
1988 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
1989 	tiledata=vram[0]
1990 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
1991 	  +(tmp<<1);
1992 	if (sprofs[3]&0x20) {
1993 	  tile1=H_Flip[tiledata[0]];
1994 	  tile2=H_Flip[tiledata[1]];
1995 	} else {
1996 	  tile1=tiledata[0];
1997 	  tile2=tiledata[1];
1998 	}
1999 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2000 	  (tile1&0x55)|((tile2&0x55)<<1);
2001 	x=sprofs[1];
2002 
2003 	if (sprofs[3]&0x10) {
2004 	  FPAL[0]=GB_STDPAL[OBP1 & 0x03];
2005 	  FPAL[1]=GB_STDPAL[(OBP1 >> 2)& 0x03];
2006 	  FPAL[2]=GB_STDPAL[(OBP1 >> 4)& 0x03];
2007 	  FPAL[3]=GB_STDPAL[OBP1 >> 6];
2008 	} else {
2009 	  FPAL[0]=GB_STDPAL[OBP0 & 0x03];
2010 	  FPAL[1]=GB_STDPAL[(OBP0 >> 2)& 0x03];
2011 	  FPAL[2]=GB_STDPAL[(OBP0 >> 4)& 0x03];
2012 	  FPAL[3]=GB_STDPAL[OBP0 >> 6];
2013 	}
2014 
2015 	if (!doublesize) {
2016 	  if (tilepix>>14)
2017 	    ((uint *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
2018 	  if ((tilepix>>6)&0x03)
2019 	    ((uint *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
2020 	  if ((tilepix>>12)&0x03)
2021 	    ((uint *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
2022 	  if ((tilepix>>4)&0x03)
2023 	    ((uint *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
2024 	  if ((tilepix>>10)&0x03)
2025 	    ((uint *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
2026 	  if ((tilepix>>2)&0x03)
2027 	    ((uint *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
2028 	  if ((tilepix>>8)&0x03)
2029 	    ((uint *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
2030 	  if (tilepix&0x03)
2031 	    ((uint *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
2032 	} else {
2033 	  if (tilepix>>14)
2034 	    ((uint *)lcdbuffer)[y+(x<<1)  ]=
2035 	      ((uint *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2036 	  if ((tilepix>>6)&0x03)
2037 	    ((uint *)lcdbuffer)[y+(x<<1)+2]=
2038 	      ((uint *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2039 	  if ((tilepix>>12)&0x03)
2040 	    ((uint *)lcdbuffer)[y+(x<<1)+4]=
2041 	      ((uint *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2042 	  if ((tilepix>>4)&0x03)
2043 	    ((uint *)lcdbuffer)[y+(x<<1)+6]=
2044 	      ((uint *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2045 	  if ((tilepix>>10)&0x03)
2046 	    ((uint *)lcdbuffer)[y+(x<<1)+8]=
2047 	      ((uint *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2048 	  if ((tilepix>>2)&0x03)
2049 	    ((uint *)lcdbuffer)[y+(x<<1)+10]=
2050 	      ((uint *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2051 	  if ((tilepix>>8)&0x03)
2052 	    ((uint *)lcdbuffer)[y+(x<<1)+12]=
2053 	      ((uint *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2054 	  if (tilepix&0x03)
2055 	    ((uint *)lcdbuffer)[y+(x<<1)+14]=
2056 	      ((uint *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2057 	}
2058       }
2059     }
2060 
2061 
2062   }
2063 }
2064 
cgb_scanline16(void)2065 void cgb_scanline16(void)
2066 {
2067   int x,y,tx,ty,xc,tmp;
2068   uchar *tileofs1,*tileofs2,*tiledata,*sprofs;
2069   uchar tile,tile1,tile2,tile_a;
2070   uint tilepix,tilenum;
2071   uchar zbuffer[GB_XBUFFERSIZE];
2072   uint FPAL[4];
2073 
2074   y=LY*GB_XBUFFERSIZE;
2075   if (doublesize) y<<=2;
2076 
2077   if (LCDC & 0x01) { /* if BG enabled */
2078     tilenum=((((LY+SCY)&0xFF) >> 3)<<5)+(LCDC & 0x08 ? 0x1C00 : 0x1800);
2079     tileofs1=vram[0]+tilenum;
2080     tileofs2=vram[1]+tilenum;
2081     xc=((LCDC & 0x20)&&(WY<=LY) ? ((WX<7 ? 0 : WX-7) >> 3) : 21);
2082     xc=xc>21 ? 21 : xc;
2083     for (tx=0,x=8-(SCX & 7);tx<xc;tx++,x+=8) {
2084       tile=tileofs1[(tx+(SCX>>3))&0x1F];
2085       tile_a=tileofs2[(tx+(SCX>>3))&0x1F];
2086       tiledata=LCDC & 0x10 ? vram[(tile_a>>3)&1]+((int)tile<<4)
2087 	: vram[(tile_a>>3)&1]+0x1000+((int)((signed char)tile)<<4);
2088       tiledata+=(tile_a&0x40) ? (7-((LY+SCY)&7))<<1:((LY+SCY)&7)<<1;
2089       tile1=tiledata[0];tile2=tiledata[1];
2090       if (tile_a&0x20) {tile1=H_Flip[tile1];tile2=H_Flip[tile2];}
2091 
2092       tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2093 	(tile1&0x55)|((tile2&0x55)<<1);
2094 
2095       FPAL[0]=BGPAL[tile_a&7][0];
2096       FPAL[1]=BGPAL[tile_a&7][1];
2097       FPAL[2]=BGPAL[tile_a&7][2];
2098       FPAL[3]=BGPAL[tile_a&7][3];
2099 
2100 	do_tilepix(uint, 2);
2101     }
2102   } else { /* if BG not enabled */
2103 	uint *p;
2104 
2105     memset(zbuffer,0,GB_XBUFFERSIZE);
2106 
2107 	p=(uint *)lcdbuffer+y;
2108     if (doublesize)
2109       for (x=0;x<GB_XBUFFERSIZE*2;x++) *p++=0; /* 0 or background ? */
2110     else
2111       for (x=0;x<GB_XBUFFERSIZE;x++) *p++=0; /* 0 or background ? */
2112 
2113   }
2114 
2115   if ((LCDC & 0x20)&&(WY<=LY)&&(WX<167)) { /* if window is on and visible */
2116 
2117     y=LY*GB_XBUFFERSIZE;
2118     if (doublesize) y<<=2;
2119 
2120     x=WX+1;xc=167-WX;
2121     tilenum=(((LY-WY) >> 3)<<5)+(LCDC & 0x40 ? 0x1C00 : 0x1800);
2122     tileofs1=vram[0]+tilenum;
2123     tileofs2=vram[1]+tilenum;
2124     for (tx=0;xc>0;xc-=8,x+=8,tx++) {
2125       tile_a=tileofs2[tx];
2126       tiledata=LCDC & 0x10 ? vram[(tile_a>>3)&1]+((int)tileofs1[tx]<<4)
2127 	: vram[(tile_a>>3)&1]+0x1000+((int)((signed char)tileofs1[tx])<<4);
2128 
2129       tiledata+=(tile_a&0x40) ? (7-((LY-WY)&7))<<1:((LY-WY)&7)<<1;
2130       tile1=tiledata[0];tile2=tiledata[1];
2131       if (tile_a&0x20) {tile1=H_Flip[tile1];tile2=H_Flip[tile2];}
2132 
2133       tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2134 	(tile1&0x55)|((tile2&0x55)<<1);
2135 
2136       FPAL[0]=BGPAL[tile_a&7][0];
2137       FPAL[1]=BGPAL[tile_a&7][1];
2138       FPAL[2]=BGPAL[tile_a&7][2];
2139       FPAL[3]=BGPAL[tile_a&7][3];
2140 
2141 	do_tilepix(uint, 2);
2142     }
2143   }
2144 
2145   if (LCDC & 0x02) { /* sprites enabled */
2146     ty=LCDC & 0x04 ? 16 : 8;
2147 
2148     y=LY*GB_XBUFFERSIZE;
2149     if (doublesize) y<<=2;
2150 
2151     /* background sprites */
2152     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
2153       tmp=LY-sprofs[0]+16;
2154       if ((sprofs[3]&0x80)&&(tmp>=0)&&(tmp<ty)&&
2155 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
2156 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
2157 	tiledata=vram[(sprofs[3]>>3)&1]
2158 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
2159 	  +(tmp<<1);
2160 	if (sprofs[3]&0x20) {
2161 	  tile1=H_Flip[tiledata[0]];
2162 	  tile2=H_Flip[tiledata[1]];
2163 	} else {
2164 	  tile1=tiledata[0];
2165 	  tile2=tiledata[1];
2166 	}
2167 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2168 	  (tile1&0x55)|((tile2&0x55)<<1);
2169 	x=sprofs[1];
2170 
2171 	FPAL[0]=OBJPAL[sprofs[3]&7][0];
2172 	FPAL[1]=OBJPAL[sprofs[3]&7][1];
2173 	FPAL[2]=OBJPAL[sprofs[3]&7][2];
2174 	FPAL[3]=OBJPAL[sprofs[3]&7][3];
2175 
2176 	if (!doublesize) {
2177 	  if ((zbuffer[x]==0)&&(tilepix>>14))
2178 	    ((uint *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
2179 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
2180 	    ((uint *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
2181 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
2182 	    ((uint *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
2183 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
2184 	    ((uint *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
2185 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
2186 	    ((uint *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
2187 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
2188 	    ((uint *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
2189 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
2190 	    ((uint *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
2191 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
2192 	    ((uint *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
2193 	} else {
2194 	  if ((zbuffer[x]==0)&&(tilepix>>14))
2195 	    ((uint *)lcdbuffer)[y+(x<<1)  ]=
2196 	      ((uint *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2197 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
2198 	    ((uint *)lcdbuffer)[y+(x<<1)+2]=
2199 	      ((uint *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2200 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
2201 	    ((uint *)lcdbuffer)[y+(x<<1)+4]=
2202 	      ((uint *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2203 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
2204 	    ((uint *)lcdbuffer)[y+(x<<1)+6]=
2205 	      ((uint *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2206 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
2207 	    ((uint *)lcdbuffer)[y+(x<<1)+8]=
2208 	      ((uint *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2209 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
2210 	    ((uint *)lcdbuffer)[y+(x<<1)+10]=
2211 	      ((uint *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2212 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
2213 	    ((uint *)lcdbuffer)[y+(x<<1)+12]=
2214 	      ((uint *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2215 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
2216 	    ((uint *)lcdbuffer)[y+(x<<1)+14]=
2217 	      ((uint *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2218 	}
2219       }
2220     }
2221 
2222     /* foreground sprites */
2223     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
2224       tmp=LY-sprofs[0]+16;
2225       if (((sprofs[3]&0x80)==0)&&(tmp>=0)&&(tmp<ty)&&
2226 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
2227 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
2228 	tiledata=vram[(sprofs[3]>>3)&1]
2229 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
2230 	  +(tmp<<1);
2231 	if (sprofs[3]&0x20) {
2232 	  tile1=H_Flip[tiledata[0]];
2233 	  tile2=H_Flip[tiledata[1]];
2234 	} else {
2235 	  tile1=tiledata[0];
2236 	  tile2=tiledata[1];
2237 	}
2238 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2239 	  (tile1&0x55)|((tile2&0x55)<<1);
2240 	x=sprofs[1];
2241 
2242 	FPAL[0]=OBJPAL[sprofs[3]&7][0];
2243 	FPAL[1]=OBJPAL[sprofs[3]&7][1];
2244 	FPAL[2]=OBJPAL[sprofs[3]&7][2];
2245 	FPAL[3]=OBJPAL[sprofs[3]&7][3];
2246 
2247 	if (!doublesize) {
2248 	  if (tilepix>>14)
2249 	    ((uint *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
2250 	  if ((tilepix>>6)&0x03)
2251 	    ((uint *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
2252 	  if ((tilepix>>12)&0x03)
2253 	    ((uint *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
2254 	  if ((tilepix>>4)&0x03)
2255 	    ((uint *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
2256 	  if ((tilepix>>10)&0x03)
2257 	    ((uint *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
2258 	  if ((tilepix>>2)&0x03)
2259 	    ((uint *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
2260 	  if ((tilepix>>8)&0x03)
2261 	    ((uint *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
2262 	  if (tilepix&0x03)
2263 	    ((uint *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
2264 	} else {
2265 	  if (tilepix>>14)
2266 	    ((uint *)lcdbuffer)[y+(x<<1)  ]=
2267 	      ((uint *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2268 	  if ((tilepix>>6)&0x03)
2269 	    ((uint *)lcdbuffer)[y+(x<<1)+2]=
2270 	      ((uint *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2271 	  if ((tilepix>>12)&0x03)
2272 	    ((uint *)lcdbuffer)[y+(x<<1)+4]=
2273 	      ((uint *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2274 	  if ((tilepix>>4)&0x03)
2275 	    ((uint *)lcdbuffer)[y+(x<<1)+6]=
2276 	      ((uint *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2277 	  if ((tilepix>>10)&0x03)
2278 	    ((uint *)lcdbuffer)[y+(x<<1)+8]=
2279 	      ((uint *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2280 	  if ((tilepix>>2)&0x03)
2281 	    ((uint *)lcdbuffer)[y+(x<<1)+10]=
2282 	      ((uint *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2283 	  if ((tilepix>>8)&0x03)
2284 	    ((uint *)lcdbuffer)[y+(x<<1)+12]=
2285 	      ((uint *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2286 	  if (tilepix&0x03)
2287 	    ((uint *)lcdbuffer)[y+(x<<1)+14]=
2288 	      ((uint *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2289 	}
2290       }
2291     }
2292 
2293   }
2294 }
2295 
gb_scanline32(void)2296 void gb_scanline32(void)
2297 {
2298   register int x,y,tx,ty,xc,tmp;
2299   register uchar *tileofs,*tiledata,*sprofs;
2300   register uchar tile,tile1,tile2;
2301   register uint tilepix;
2302   register ulong *lcdbuf;
2303   register uchar *zbuf;
2304   uchar zbuffer[GB_XBUFFERSIZE];
2305   ulong FPAL[4];
2306 
2307   FPAL[0]=GB_STDPAL[BGP & 0x03];
2308   FPAL[1]=GB_STDPAL[(BGP >> 2)& 0x03];
2309   FPAL[2]=GB_STDPAL[(BGP >> 4)& 0x03];
2310   FPAL[3]=GB_STDPAL[BGP >> 6];
2311 
2312   y=LY*GB_XBUFFERSIZE;
2313   if (doublesize) y<<=2;
2314 
2315   if (LCDC & 0x01) { /* if BG enabled */
2316     tileofs=vram[0]
2317       +((((LY+SCY)&0xFF) >> 3)<<5)+(LCDC & 0x08 ? 0x1C00 : 0x1800);
2318     xc=((LCDC & 0x20)&&(WY<=LY) ? ((WX<7 ? 0 : WX-7) >> 3) : 21);
2319     xc=xc>21 ? 21 : xc;
2320     for (tx=0,x=8-(SCX & 7);tx<xc;tx++,x+=8) {
2321       tile=tileofs[(tx+(SCX>>3))&0x1F];
2322       tiledata=LCDC & 0x10 ? vram[0]+((int)tile<<4)
2323 	: vram[0]+0x1000+((int)((signed char)tile)<<4);
2324       tiledata+=((LY+SCY)&7)<<1;
2325       tilepix=((uint)(tiledata[1]&0xAA)<<8)|((uint)(tiledata[0]&0xAA)<<7)|
2326 	(tiledata[0]&0x55)|((tiledata[1]&0x55)<<1);
2327 
2328 	do_tilepix(ulong, 2);
2329     }
2330   } else { /* if BG not enabled */
2331 	ulong *p;
2332 
2333     memset(zbuffer,0,GB_XBUFFERSIZE);
2334 
2335 	p=(ulong *)lcdbuffer+y;
2336     if (doublesize)
2337       for (x=0;x<GB_XBUFFERSIZE*2;x++) *p++=FPAL[0];
2338     else
2339       for (x=0;x<GB_XBUFFERSIZE;x++) *p++=FPAL[0];
2340 
2341   }
2342 
2343   if ((LCDC & 0x20)&&(WY<=LY)&&(WX<167)) { /* if window is on and visible */
2344 
2345     y=LY*GB_XBUFFERSIZE;
2346     if (doublesize) y<<=2;
2347 
2348     x=WX+1;xc=167-WX;
2349     tileofs=vram[0]+(((LY-WY) >> 3)<<5)+(LCDC & 0x40 ? 0x1C00 : 0x1800);
2350     for (tx=0;xc>0;xc-=8,x+=8,tx++) {
2351       tiledata=LCDC & 0x10 ? vram[0]+((int)tileofs[tx]<<4)
2352 	: vram[0]+0x1000+((int)((signed char)tileofs[tx])<<4);
2353       tiledata+=((LY-WY)&7)<<1;
2354       tilepix=((uint)(tiledata[1]&0xAA)<<8)|((uint)(tiledata[0]&0xAA)<<7)|
2355 	(tiledata[0]&0x55)|((tiledata[1]&0x55)<<1);
2356 
2357 	do_tilepix(ulong, 2);
2358     }
2359   }
2360 
2361   if (LCDC & 0x02) { /* sprites enabled */
2362     ty=LCDC & 0x04 ? 16 : 8;
2363 
2364     y=LY*GB_XBUFFERSIZE;
2365     if (doublesize) y<<=2;
2366 
2367     /* sprites */
2368     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
2369       tmp=LY-sprofs[0]+16;
2370       if ((tmp>=0)&&(tmp<ty)&&(sprofs[1]<GB_LCDXSCREENSIZE+8)) {
2371 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
2372 	tiledata=vram[0]
2373 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
2374 	  +(tmp<<1);
2375 	if (sprofs[3]&0x20) {
2376 	  tile1=H_Flip[tiledata[0]];
2377 	  tile2=H_Flip[tiledata[1]];
2378 	} else {
2379 	  tile1=tiledata[0];
2380 	  tile2=tiledata[1];
2381 	}
2382 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2383 	  (tile1&0x55)|((tile2&0x55)<<1);
2384 	x=sprofs[1];
2385 
2386 	if (sprofs[3]&0x10) {
2387 	  FPAL[0]=GB_STDPAL[OBP1 & 0x03];
2388 	  FPAL[1]=GB_STDPAL[(OBP1 >> 2)& 0x03];
2389 	  FPAL[2]=GB_STDPAL[(OBP1 >> 4)& 0x03];
2390 	  FPAL[3]=GB_STDPAL[OBP1 >> 6];
2391 	} else {
2392 	  FPAL[0]=GB_STDPAL[OBP0 & 0x03];
2393 	  FPAL[1]=GB_STDPAL[(OBP0 >> 2)& 0x03];
2394 	  FPAL[2]=GB_STDPAL[(OBP0 >> 4)& 0x03];
2395 	  FPAL[3]=GB_STDPAL[OBP0 >> 6];
2396 	}
2397 
2398 	if (sprofs[3]&0x80) {
2399 
2400 	  if (!doublesize) {
2401 	    lcdbuf=(ulong*)lcdbuffer+x+y;
2402 	    zbuf=zbuffer+x;
2403 	    if ((!*zbuf++)&&(tilepix>>14))
2404 	      *lcdbuf=FPAL[tilepix >> 14];
2405 	    if ((!*zbuf++)&&((tilepix>>6)&0x03))
2406 	      *(lcdbuf+1)=FPAL[(tilepix >> 6)&0x03];
2407 	    if ((!*zbuf++)&&((tilepix>>12)&0x03))
2408 	      *(lcdbuf+2)=FPAL[(tilepix >> 12)&0x03];
2409 	    if ((!*zbuf++)&&((tilepix>>4)&0x03))
2410 	      *(lcdbuf+3)=FPAL[(tilepix >> 4)&0x03];
2411 	    if ((!*zbuf++)&&((tilepix>>10)&0x03))
2412 	      *(lcdbuf+4)=FPAL[(tilepix >> 10)&0x03];
2413 	    if ((!*zbuf++)&&((tilepix>>2)&0x03))
2414 	      *(lcdbuf+5)=FPAL[(tilepix >> 2)&0x03];
2415 	    if ((!*zbuf++)&&((tilepix>>8)&0x03))
2416 	      *(lcdbuf+6)=FPAL[(tilepix >> 8)&0x03];
2417 	    if ((!*zbuf++)&&(tilepix&0x03))
2418 	      *(lcdbuf+7)=FPAL[tilepix&0x03];
2419 	  } else {
2420 	    if ((zbuffer[x]==0)&&(tilepix>>14))
2421 	      ((ulong *)lcdbuffer)[y+(x<<1)  ]=
2422 		((ulong *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2423 	    if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
2424 	      ((ulong *)lcdbuffer)[y+(x<<1)+2]=
2425 		((ulong *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2426 	    if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
2427 	      ((ulong *)lcdbuffer)[y+(x<<1)+4]=
2428 		((ulong *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2429 	    if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
2430 	      ((ulong *)lcdbuffer)[y+(x<<1)+6]=
2431 		((ulong *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2432 	    if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
2433 	      ((ulong *)lcdbuffer)[y+(x<<1)+8]=
2434 		((ulong *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2435 	    if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
2436 	      ((ulong *)lcdbuffer)[y+(x<<1)+10]=
2437 		((ulong *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2438 	    if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
2439 	      ((ulong *)lcdbuffer)[y+(x<<1)+12]=
2440 		((ulong *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2441 	    if ((zbuffer[x+7]==0)&&(tilepix&0x03))
2442 	      ((ulong *)lcdbuffer)[y+(x<<1)+14]=
2443 		((ulong *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2444 	  }
2445 	} else {
2446 
2447 	  if (!doublesize) {
2448 	    lcdbuf=(ulong*)lcdbuffer+x+y;
2449 	    if (tilepix>>14)
2450 	      *lcdbuf=FPAL[tilepix >> 14];
2451 	    if ((tilepix>>6)&0x03)
2452 	      *(lcdbuf+1)=FPAL[(tilepix >> 6)&0x03];
2453 	    if ((tilepix>>12)&0x03)
2454 	      *(lcdbuf+2)=FPAL[(tilepix >> 12)&0x03];
2455 	    if ((tilepix>>4)&0x03)
2456 	      *(lcdbuf+3)=FPAL[(tilepix >> 4)&0x03];
2457 	    if ((tilepix>>10)&0x03)
2458 	      *(lcdbuf+4)=FPAL[(tilepix >> 10)&0x03];
2459 	    if ((tilepix>>2)&0x03)
2460 	      *(lcdbuf+5)=FPAL[(tilepix >> 2)&0x03];
2461 	    if ((tilepix>>8)&0x03)
2462 	      *(lcdbuf+6)=FPAL[(tilepix >> 8)&0x03];
2463 	    if (tilepix&0x03)
2464 	      *(lcdbuf+7)=FPAL[tilepix&0x03];
2465 	  } else {
2466 	    if (tilepix>>14)
2467 	      ((ulong *)lcdbuffer)[y+(x<<1)  ]=
2468 		((ulong *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2469 	    if ((tilepix>>6)&0x03)
2470 	      ((ulong *)lcdbuffer)[y+(x<<1)+2]=
2471 		((ulong *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2472 	    if ((tilepix>>12)&0x03)
2473 	      ((ulong *)lcdbuffer)[y+(x<<1)+4]=
2474 		((ulong *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2475 	    if ((tilepix>>4)&0x03)
2476 	      ((ulong *)lcdbuffer)[y+(x<<1)+6]=
2477 		((ulong *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2478 	    if ((tilepix>>10)&0x03)
2479 	      ((ulong *)lcdbuffer)[y+(x<<1)+8]=
2480 		((ulong *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2481 	    if ((tilepix>>2)&0x03)
2482 	      ((ulong *)lcdbuffer)[y+(x<<1)+10]=
2483 		((ulong *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2484 	    if ((tilepix>>8)&0x03)
2485 	      ((ulong *)lcdbuffer)[y+(x<<1)+12]=
2486 		((ulong *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2487 	    if (tilepix&0x03)
2488 	      ((ulong *)lcdbuffer)[y+(x<<1)+14]=
2489 		((ulong *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2490 	  }
2491 	}
2492       }
2493     }
2494   }
2495 }
2496 
cgb_scanline32(void)2497 void cgb_scanline32(void)
2498 {
2499   int x,y,tx,ty,xc,tmp;
2500   uchar *tileofs1,*tileofs2,*tiledata,*sprofs;
2501   uchar tile,tile1,tile2,tile_a;
2502   uint tilepix,tilenum;
2503   uchar zbuffer[GB_XBUFFERSIZE];
2504   ulong FPAL[4];
2505 
2506   y=LY*GB_XBUFFERSIZE;
2507   if (doublesize) y<<=2;
2508 
2509   if (LCDC & 0x01) { /* if BG enabled */
2510     tilenum=((((LY+SCY)&0xFF) >> 3)<<5)+(LCDC & 0x08 ? 0x1C00 : 0x1800);
2511     tileofs1=vram[0]+tilenum;
2512     tileofs2=vram[1]+tilenum;
2513     xc=((LCDC & 0x20)&&(WY<=LY) ? ((WX<7 ? 0 : WX-7) >> 3) : 21);
2514     xc=xc>21 ? 21 : xc;
2515     for (tx=0,x=8-(SCX & 7);tx<xc;tx++,x+=8) {
2516       tile=tileofs1[(tx+(SCX>>3))&0x1F];
2517       tile_a=tileofs2[(tx+(SCX>>3))&0x1F];
2518       tiledata=LCDC & 0x10 ? vram[(tile_a>>3)&1]+((int)tile<<4)
2519 	: vram[(tile_a>>3)&1]+0x1000+((int)((signed char)tile)<<4);
2520       tiledata+=(tile_a&0x40) ? (7-((LY+SCY)&7))<<1:((LY+SCY)&7)<<1;
2521       tile1=tiledata[0];tile2=tiledata[1];
2522       if (tile_a&0x20) {tile1=H_Flip[tile1];tile2=H_Flip[tile2];}
2523 
2524       tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2525 	(tile1&0x55)|((tile2&0x55)<<1);
2526 
2527       FPAL[0]=BGPAL[tile_a&7][0];
2528       FPAL[1]=BGPAL[tile_a&7][1];
2529       FPAL[2]=BGPAL[tile_a&7][2];
2530       FPAL[3]=BGPAL[tile_a&7][3];
2531 
2532 	do_tilepix(ulong, 2);
2533     }
2534   } else { /* if BG not enabled */
2535 	ulong *p;
2536 
2537     memset(zbuffer,0,GB_XBUFFERSIZE);
2538 
2539 	p=(ulong *)lcdbuffer+y;
2540     if (doublesize)
2541       for (x=0;x<GB_XBUFFERSIZE*2;x++) *p++=0; /* 0 or background ? */
2542     else
2543       for (x=0;x<GB_XBUFFERSIZE;x++) *p++=0; /* 0 or background ? */
2544 
2545   }
2546 
2547   if ((LCDC & 0x20)&&(WY<=LY)&&(WX<167)) { /* if window is on and visible */
2548 
2549     y=LY*GB_XBUFFERSIZE;
2550     if (doublesize) y<<=2;
2551 
2552     x=WX+1;xc=167-WX;
2553     tilenum=(((LY-WY) >> 3)<<5)+(LCDC & 0x40 ? 0x1C00 : 0x1800);
2554     tileofs1=vram[0]+tilenum;
2555     tileofs2=vram[1]+tilenum;
2556     for (tx=0;xc>0;xc-=8,x+=8,tx++) {
2557       tile_a=tileofs2[tx];
2558       tiledata=LCDC & 0x10 ? vram[(tile_a>>3)&1]+((int)tileofs1[tx]<<4)
2559 	: vram[(tile_a>>3)&1]+0x1000+((int)((signed char)tileofs1[tx])<<4);
2560 
2561       tiledata+=(tile_a&0x40) ? (7-((LY-WY)&7))<<1:((LY-WY)&7)<<1;
2562       tile1=tiledata[0];tile2=tiledata[1];
2563       if (tile_a&0x20) {tile1=H_Flip[tile1];tile2=H_Flip[tile2];}
2564 
2565       tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2566 	(tile1&0x55)|((tile2&0x55)<<1);
2567 
2568       FPAL[0]=BGPAL[tile_a&7][0];
2569       FPAL[1]=BGPAL[tile_a&7][1];
2570       FPAL[2]=BGPAL[tile_a&7][2];
2571       FPAL[3]=BGPAL[tile_a&7][3];
2572 
2573 	do_tilepix(ulong, 2);
2574     }
2575   }
2576 
2577   if (LCDC & 0x02) { /* sprites enabled */
2578     ty=LCDC & 0x04 ? 16 : 8;
2579 
2580     y=LY*GB_XBUFFERSIZE;
2581     if (doublesize) y<<=2;
2582 
2583     /* background sprites */
2584     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
2585       tmp=LY-sprofs[0]+16;
2586       if ((sprofs[3]&0x80)&&(tmp>=0)&&(tmp<ty)&&
2587 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
2588 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
2589 	tiledata=vram[(sprofs[3]>>3)&1]
2590 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
2591 	  +(tmp<<1);
2592 	if (sprofs[3]&0x20) {
2593 	  tile1=H_Flip[tiledata[0]];
2594 	  tile2=H_Flip[tiledata[1]];
2595 	} else {
2596 	  tile1=tiledata[0];
2597 	  tile2=tiledata[1];
2598 	}
2599 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2600 	  (tile1&0x55)|((tile2&0x55)<<1);
2601 	x=sprofs[1];
2602 
2603 	FPAL[0]=OBJPAL[sprofs[3]&7][0];
2604 	FPAL[1]=OBJPAL[sprofs[3]&7][1];
2605 	FPAL[2]=OBJPAL[sprofs[3]&7][2];
2606 	FPAL[3]=OBJPAL[sprofs[3]&7][3];
2607 
2608 	if (!doublesize) {
2609 	  if ((zbuffer[x]==0)&&(tilepix>>14))
2610 	    ((ulong *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
2611 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
2612 	    ((ulong *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
2613 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
2614 	    ((ulong *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
2615 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
2616 	    ((ulong *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
2617 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
2618 	    ((ulong *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
2619 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
2620 	    ((ulong *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
2621 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
2622 	    ((ulong *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
2623 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
2624 	    ((ulong *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
2625 	} else {
2626 	  if ((zbuffer[x]==0)&&(tilepix>>14))
2627 	    ((ulong *)lcdbuffer)[y+(x<<1)  ]=
2628 	      ((ulong *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2629 	  if ((zbuffer[x+1]==0)&&((tilepix>>6)&0x03))
2630 	    ((ulong *)lcdbuffer)[y+(x<<1)+2]=
2631 	      ((ulong *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2632 	  if ((zbuffer[x+2]==0)&&((tilepix>>12)&0x03))
2633 	    ((ulong *)lcdbuffer)[y+(x<<1)+4]=
2634 	      ((ulong *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2635 	  if ((zbuffer[x+3]==0)&&((tilepix>>4)&0x03))
2636 	    ((ulong *)lcdbuffer)[y+(x<<1)+6]=
2637 	      ((ulong *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2638 	  if ((zbuffer[x+4]==0)&&((tilepix>>10)&0x03))
2639 	    ((ulong *)lcdbuffer)[y+(x<<1)+8]=
2640 	      ((ulong *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2641 	  if ((zbuffer[x+5]==0)&&((tilepix>>2)&0x03))
2642 	    ((ulong *)lcdbuffer)[y+(x<<1)+10]=
2643 	      ((ulong *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2644 	  if ((zbuffer[x+6]==0)&&((tilepix>>8)&0x03))
2645 	    ((ulong *)lcdbuffer)[y+(x<<1)+12]=
2646 	      ((ulong *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2647 	  if ((zbuffer[x+7]==0)&&(tilepix&0x03))
2648 	    ((ulong *)lcdbuffer)[y+(x<<1)+14]=
2649 	      ((ulong *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2650 	}
2651       }
2652     }
2653 
2654     /* foreground sprites */
2655     for (xc=GB_SPRITECOUNT-1,sprofs=oam+0x9C;xc>=0;xc--,sprofs-=4) {
2656       tmp=LY-sprofs[0]+16;
2657       if (((sprofs[3]&0x80)==0)&&(tmp>=0)&&(tmp<ty)&&
2658 	  (sprofs[1]<GB_LCDXSCREENSIZE+8)) {
2659 	if (sprofs[3]&0x40) tmp=ty-1-tmp;
2660 	tiledata=vram[(sprofs[3]>>3)&1]
2661 	  +(((uint)(sprofs[2] & (LCDC & 0x04 ? 0xFE : 0xFF)))<<4)
2662 	  +(tmp<<1);
2663 	if (sprofs[3]&0x20) {
2664 	  tile1=H_Flip[tiledata[0]];
2665 	  tile2=H_Flip[tiledata[1]];
2666 	} else {
2667 	  tile1=tiledata[0];
2668 	  tile2=tiledata[1];
2669 	}
2670 	tilepix=((uint)(tile2&0xAA)<<8)|((uint)(tile1&0xAA)<<7)|
2671 	  (tile1&0x55)|((tile2&0x55)<<1);
2672 	x=sprofs[1];
2673 
2674 	FPAL[0]=OBJPAL[sprofs[3]&7][0];
2675 	FPAL[1]=OBJPAL[sprofs[3]&7][1];
2676 	FPAL[2]=OBJPAL[sprofs[3]&7][2];
2677 	FPAL[3]=OBJPAL[sprofs[3]&7][3];
2678 
2679 	if (!doublesize) {
2680 	  if (tilepix>>14)
2681 	    ((ulong *)lcdbuffer)[y+x]=FPAL[tilepix >> 14];
2682 	  if ((tilepix>>6)&0x03)
2683 	    ((ulong *)lcdbuffer)[y+x+1]=FPAL[(tilepix >> 6)&0x03];
2684 	  if ((tilepix>>12)&0x03)
2685 	    ((ulong *)lcdbuffer)[y+x+2]=FPAL[(tilepix >> 12)&0x03];
2686 	  if ((tilepix>>4)&0x03)
2687 	    ((ulong *)lcdbuffer)[y+x+3]=FPAL[(tilepix >> 4)&0x03];
2688 	  if ((tilepix>>10)&0x03)
2689 	    ((ulong *)lcdbuffer)[y+x+4]=FPAL[(tilepix >> 10)&0x03];
2690 	  if ((tilepix>>2)&0x03)
2691 	    ((ulong *)lcdbuffer)[y+x+5]=FPAL[(tilepix >> 2)&0x03];
2692 	  if ((tilepix>>8)&0x03)
2693 	    ((ulong *)lcdbuffer)[y+x+6]=FPAL[(tilepix >> 8)&0x03];
2694 	  if (tilepix&0x03)
2695 	    ((ulong *)lcdbuffer)[y+x+7]=FPAL[tilepix&0x03];
2696 	} else {
2697 	  if (tilepix>>14)
2698 	    ((ulong *)lcdbuffer)[y+(x<<1)  ]=
2699 	      ((ulong *)lcdbuffer)[y+(x<<1)+1]=FPAL[tilepix >> 14];
2700 	  if ((tilepix>>6)&0x03)
2701 	    ((ulong *)lcdbuffer)[y+(x<<1)+2]=
2702 	      ((ulong *)lcdbuffer)[y+(x<<1)+3]=FPAL[(tilepix >> 6)&0x03];
2703 	  if ((tilepix>>12)&0x03)
2704 	    ((ulong *)lcdbuffer)[y+(x<<1)+4]=
2705 	      ((ulong *)lcdbuffer)[y+(x<<1)+5]=FPAL[(tilepix >> 12)&0x03];
2706 	  if ((tilepix>>4)&0x03)
2707 	    ((ulong *)lcdbuffer)[y+(x<<1)+6]=
2708 	      ((ulong *)lcdbuffer)[y+(x<<1)+7]=FPAL[(tilepix >> 4)&0x03];
2709 	  if ((tilepix>>10)&0x03)
2710 	    ((ulong *)lcdbuffer)[y+(x<<1)+8]=
2711 	      ((ulong *)lcdbuffer)[y+(x<<1)+9]=FPAL[(tilepix >> 10)&0x03];
2712 	  if ((tilepix>>2)&0x03)
2713 	    ((ulong *)lcdbuffer)[y+(x<<1)+10]=
2714 	      ((ulong *)lcdbuffer)[y+(x<<1)+11]=FPAL[(tilepix >> 2)&0x03];
2715 	  if ((tilepix>>8)&0x03)
2716 	    ((ulong *)lcdbuffer)[y+(x<<1)+12]=
2717 	      ((ulong *)lcdbuffer)[y+(x<<1)+13]=FPAL[(tilepix >> 8)&0x03];
2718 	  if (tilepix&0x03)
2719 	    ((ulong *)lcdbuffer)[y+(x<<1)+14]=
2720 	      ((ulong *)lcdbuffer)[y+(x<<1)+15]=FPAL[tilepix&0x03];
2721 	}
2722       }
2723     }
2724 
2725 
2726   }
2727 }
2728 
storescanline(void)2729 void storescanline(void)
2730 {
2731 #ifdef HARDDEBUG
2732   fprintf(OUTSTREAM,"Drawing scanline %d (LCDC: %02X).\n",LY,LCDC);
2733 #endif
2734 
2735   if ((LCDC & 0x80)==0) {
2736     memset(lcdbuffer+(uint)LY*GB_XBUFFERSIZE*(bitmapbits>>3),
2737 	   0,GB_XBUFFERSIZE*(bitmapbits>>3));
2738     return;
2739   }
2740 
2741   (*scanline)();
2742 }
2743 
2744 /* horizontal HDMA processing */
hdma_update(void)2745 void hdma_update(void)
2746 {
2747   int i;
2748 
2749   if (hdmastarted) {
2750 #ifdef HARDDEBUG
2751     printf("Horizontal blank transfer.\n");
2752 #endif
2753 
2754     for (i=16;i>0;i--,hdmadst++,hdmasrc++)
2755       vram[VBK&1][hdmadst&0x1FFF]=GetByteAt(hdmasrc);
2756     if (((HDMA5&0x7F)==0)||(hdmastarted<0)) {
2757       hdmastarted=0;
2758       HDMA5=0x80;
2759     } else
2760       /*  HDMA5=(HDMA5&0x80)|((HDMA5&0x7F)-1);*/
2761       HDMA5--;
2762   }
2763   HDMA1=hdmasrc>>8;
2764   HDMA2=hdmasrc&0xF0;
2765   HDMA3=(hdmadst>>8)&0x1F;
2766   HDMA4=hdmadst&0xF0;
2767 }
2768 
gameboyspecifics(void)2769 void gameboyspecifics(void)
2770 {
2771 #ifdef DIALOGLINK
2772   int n;
2773 #endif
2774 
2775   /* global ticks */
2776   Z80_CPUCLKS+=Z80_TICKS;
2777 
2778   /* divider update */
2779   dividerclks-=Z80_TICKS;
2780   if (dividerclks<0) {
2781     dividerclks+=GB_DIVLOAD;
2782     DIV++;
2783   }
2784 
2785   soundclks-=Z80_TICKS;
2786   if (soundclks<0) {
2787     soundclks+=snd_updateclks;
2788 #ifdef SOUND
2789     if (usingsound) processSound();
2790 #endif
2791   }
2792 
2793 #ifdef DIALOGLINK
2794   serialioclks-=Z80_TICKS;
2795   if (serialioclks<0) {
2796     if (colormode)
2797       serialioclks=serialclks[(SC&2)>>1][DBLSPEED];
2798     else serialioclks=serialclks[0][0];
2799 
2800     if ((n=dlglink_getbyte())>=0) {
2801       if ((SC&0x01)==0) dlglink_sndbyte(siosendout);
2802       SB=n;
2803 #ifdef HARDDEBUG
2804       printf("Got: %02X\n",SB);
2805 #endif
2806       SC&=0x7F;
2807       IF|=0x08;
2808     }
2809 
2810   }
2811 #endif
2812 
2813   /* ******************** */
2814 #ifndef SOUND
2815   soundcounter-=Z80_TICKS;
2816   if (soundcounter<0) NR52&=0xF7;
2817 #endif
2818   /* ******************** */
2819 
2820   /* video update */
2821 
2822   lcdclks-=Z80_TICKS;
2823   if (LCDC & 0x80) { /* if lcd on */
2824     if (lcdclks<0) {
2825       lcdphase++;
2826       if (lcdphase==3) {
2827 	if ((LY>142)&&(LY<153)) {
2828 	  lcdclks=GB_VCLKS[3];lcdphase--;
2829 	  hdma_update();
2830 	  if ((STAT&3)!=1) { /* v-blank */
2831 	    STAT=(STAT&0xFC)|1;vblankoccured=1;
2832 	    vblankdelay=GB_VBLANKDELAYCLKS;
2833 	  } else {
2834 	    if (LY==148) drawscreen();
2835 	  }
2836 	} else {
2837 	  lcdphase=0;STAT=(STAT&0xFC)|2;
2838 	  lcdclks=GB_VCLKS[0];
2839 	  if ((IE&2)&&(STAT&0x20)) IF|=2; /* lcd oam */
2840 	  hdma_update();
2841 	}
2842 	LY=LY==153 ? 0 : LY+1;
2843 
2844 	STAT&=0xFB;
2845 	STAT|=(((LYC==0)&&(LY==153))||(LY==LYC)) ? 0x04 : 0;
2846 
2847 	if (/*(IE&2)&&*/(STAT&0x40))
2848 	  if (((LYC!=0)&&(LY==LYC))||((LYC==0)&&(LY==153))) IF|=2;
2849 	                                       /* lcd y coincidence */
2850 	                                       /* & double null coincidence */
2851       } else {
2852 	if (LY<144) {
2853 	  lcdclks=GB_VCLKS[lcdphase];
2854 	  if (lcdphase==1) STAT=(STAT&0xFC)|3;
2855 	  else {
2856 	    STAT&=0xFC;
2857 	    storescanline();
2858 	    if ((IE&2)&&(STAT&0x08)) IF|=2; /* lcd h-blank */
2859 	  }
2860 	}
2861       }
2862     }
2863   } else {
2864     if (lcdclks<0) {
2865       lcdphase=lcdphase==2 ? 0 : lcdphase+1;
2866       lcdclks=GB_VCLKS[lcdphase];
2867       STAT&=0xFC;
2868       switch (lcdphase) {
2869       case 0:STAT|=2;break;
2870       case 1:STAT|=3;storescanline();break;
2871       }
2872     }
2873   }
2874 
2875   /* v-blank interrupt handler */
2876   if (vblankdelay<0) {
2877     if ((vblankoccured)||(IF&1)) {
2878       IF|=STAT & 0x10 ? 3 : 1;vblankoccured=0;
2879       if ((Z80_IE)&&(IE&1)) {
2880 	Z80_IE=0;Z80_HALTED=0;IF&=0xFE;
2881 #if 0
2882 	for (soundclks=0x10;soundclks<0x27;soundclks++)
2883 	  printf("%02X,",io[soundclks]);
2884 	printf("\n");
2885 #endif
2886 
2887 
2888 #ifdef HARDDEBUG
2889 	fprintf(OUTSTREAM,"V-blank interrupt.\n");
2890 #endif
2891 	M_RST(0x40);/* lcdclks-=16;*/
2892       }
2893     }
2894   } else vblankdelay-=Z80_TICKS;
2895 
2896   if ((Z80_IE)&&(IF&2)&&(IE&2)) {
2897     Z80_IE=0;Z80_HALTED=0;IF&=0xFD;
2898 #ifdef HARDDEBUG
2899 	fprintf(OUTSTREAM,"LCDSTAT interrupt.\n");
2900 #endif
2901 	M_RST(0x48);/* lcdclks-=24;*/
2902   }
2903 
2904   /* timer interrupt handler */
2905   if (TAC&0x04) {
2906     timerclks-=Z80_TICKS;
2907     if (timerclks<0) {
2908       timerclks+=timerfreq;
2909       TIMA++;
2910       if (TIMA==0) {
2911 	TIMA=TMA;IF|=0x04;
2912       }
2913     }
2914   }
2915   if (Z80_IE && (IE&4) && (IF&4)) {
2916     Z80_IE=0;IF&=0xFB;Z80_HALTED=0;
2917 #ifdef HARDDEBUG
2918     fprintf(OUTSTREAM,"Timer interrupt.\n");
2919 #endif
2920     M_RST(0x50);
2921   }
2922 
2923   /* serial interrupt handler */
2924   if (IF&0x08) {
2925 #ifndef DIALOGLINK
2926       SC&=0x7F;SB=0xFF;
2927 #endif
2928       if (Z80_IE && (IE&0x08)) {
2929 	IF&=0xF7;
2930 	Z80_IE=0;Z80_HALTED=0;
2931 #ifdef HARDDEBUG
2932 	fprintf(OUTSTREAM,"Serial interrupt.\n");
2933 #endif
2934 	M_RST(0x58);
2935       }
2936   }
2937 
2938 
2939   /* joypad interrupt handler (lowest priority) */
2940 
2941   joypadclks-=Z80_TICKS;
2942   if (joypadclks<0) {
2943     joypadclks=GB_JOYCLKS;
2944     joypad();
2945     if (joypadstate!=newjoypadstate || IF&0x10) {
2946       IF|=0x10;joypadstate=newjoypadstate;
2947       if ((IE&0x10)&&(Z80_IE)) {
2948 	Z80_IE=0;Z80_HALTED=0;
2949 	IF&=0xEF;
2950 #ifdef HARDDEBUG
2951 	fprintf(OUTSTREAM,"Joypad interrupt.\n");
2952 #endif
2953 	M_RST(0x60);
2954       }
2955     }
2956   }
2957 }
2958 
2959