Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/wonderswan/gfx.cpp
2 views
1
/* Cygne
2
*
3
* Copyright notice for this file:
4
* Copyright (C) 2002 Dox [email protected]
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
21
#include "system.h"
22
#include <cstring>
23
24
namespace MDFN_IEN_WSWAN
25
{
26
GFX::GFX()
27
:LayerEnabled(7) // 1 = bg, 2 = fg, 4 = sprite
28
{
29
//SetPixelFormat();
30
}
31
32
33
void GFX::PaletteRAMWrite(uint32 ws_offset, uint8 data)
34
{
35
ws_offset=(ws_offset&0xfffe)-0xfe00;
36
wsCols[(ws_offset>>1)>>4][(ws_offset>>1)&15] = sys->memory.wsRAM[ws_offset+0xfe00] | ((sys->memory.wsRAM[ws_offset+0xfe01]&0x0f) << 8);
37
}
38
39
void GFX::Write(uint32 A, uint8 V)
40
{
41
if(A >= 0x1C && A <= 0x1F)
42
{
43
wsColors[(A - 0x1C) * 2 + 0] = 0xF - (V & 0xf);
44
wsColors[(A - 0x1C) * 2 + 1] = 0xF - (V >> 4);
45
}
46
else if(A >= 0x20 && A <= 0x3F)
47
{
48
wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) + 0] = V&7;
49
wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) | 1] = (V>>4)&7;
50
}
51
else switch(A)
52
{
53
case 0x00: DispControl = V; break;
54
case 0x01: BGColor = V; break;
55
case 0x03: LineCompare = V; break;
56
case 0x04: SPRBase = V & 0x3F; break;
57
case 0x05: SpriteStart = V; break;
58
case 0x06: SpriteCount = V; break;
59
case 0x07: FGBGLoc = V; break;
60
case 0x08: FGx0 = V; break;
61
case 0x09: FGy0 = V; break;
62
case 0x0A: FGx1 = V; break;
63
case 0x0B: FGy1 = V; break;
64
case 0x0C: SPRx0 = V; break;
65
case 0x0D: SPRy0 = V; break;
66
case 0x0E: SPRx1 = V; break;
67
case 0x0F: SPRy1 = V; break;
68
case 0x10: BGXScroll = V; break;
69
case 0x11: BGYScroll = V; break;
70
case 0x12: FGXScroll = V; break;
71
case 0x13: FGYScroll = V; break;
72
73
case 0x14: LCDControl = V; break; // if((!(wsIO[0x14]&1))&&(data&1)) { wsLine=0; }break; /* LCD off ??*/
74
case 0x15: LCDIcons = V; break;
75
76
case 0x60: VideoMode = V;
77
SetVideo(V>>5, false);
78
//printf("VideoMode: %02x, %02x\n", V, V >> 5);
79
break;
80
81
case 0xa2: if((V & 0x01) && !(BTimerControl & 0x01))
82
HBCounter = HBTimerPeriod;
83
if((V & 0x04) && !(BTimerControl & 0x04))
84
VBCounter = VBTimerPeriod;
85
BTimerControl = V;
86
//printf("%04x:%02x\n", A, V);
87
break;
88
case 0xa4: HBTimerPeriod &= 0xFF00; HBTimerPeriod |= (V << 0); /*printf("%04x:%02x, %d\n", A, V, wsLine);*/ break;
89
case 0xa5: HBTimerPeriod &= 0x00FF; HBTimerPeriod |= (V << 8); HBCounter = HBTimerPeriod; /*printf("%04x:%02x, %d\n", A, V, wsLine);*/ break;
90
case 0xa6: VBTimerPeriod &= 0xFF00; VBTimerPeriod |= (V << 0); /*printf("%04x:%02x, %d\n", A, V, wsLine);*/ break;
91
case 0xa7: VBTimerPeriod &= 0x00FF; VBTimerPeriod |= (V << 8); VBCounter = VBTimerPeriod; /*printf("%04x:%02x, %d\n", A, V, wsLine);*/ break;
92
//default: printf("%04x:%02x\n", A, V); break;
93
}
94
}
95
96
uint8 GFX::Read(uint32 A)
97
{
98
if(A >= 0x1C && A <= 0x1F)
99
{
100
uint8 ret = 0;
101
102
ret |= 0xF - wsColors[(A - 0x1C) * 2 + 0];
103
ret |= (0xF - wsColors[(A - 0x1C) * 2 + 1]) << 4;
104
105
return(ret);
106
}
107
else if(A >= 0x20 && A <= 0x3F)
108
{
109
uint8 ret = wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) + 0] | (wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) | 1] << 4);
110
111
return(ret);
112
}
113
else switch(A)
114
{
115
case 0x00: return(DispControl);
116
case 0x01: return(BGColor);
117
case 0x02: return(wsLine);
118
case 0x03: return(LineCompare);
119
case 0x04: return(SPRBase);
120
case 0x05: return(SpriteStart);
121
case 0x06: return(SpriteCount);
122
case 0x07: return(FGBGLoc);
123
case 0x08: return(FGx0); break;
124
case 0x09: return(FGy0); break;
125
case 0x0A: return(FGx1); break;
126
case 0x0B: return(FGy1); break;
127
case 0x0C: return(SPRx0); break;
128
case 0x0D: return(SPRy0); break;
129
case 0x0E: return(SPRx1); break;
130
case 0x0F: return(SPRy1); break;
131
case 0x10: return(BGXScroll);
132
case 0x11: return(BGYScroll);
133
case 0x12: return(FGXScroll);
134
case 0x13: return(FGYScroll);
135
case 0x14: return(LCDControl);
136
case 0x15: return(LCDIcons);
137
case 0x60: return(VideoMode);
138
case 0xa0: return(wsc ? 0x87 : 0x86);
139
case 0xa2: return(BTimerControl);
140
case 0xa4: return((HBTimerPeriod >> 0) & 0xFF);
141
case 0xa5: return((HBTimerPeriod >> 8) & 0xFF);
142
case 0xa6: return((VBTimerPeriod >> 0) & 0xFF);
143
case 0xa7: return((VBTimerPeriod >> 8) & 0xFF);
144
case 0xa8: /*printf("%04x\n", A);*/ return((HBCounter >> 0) & 0xFF);
145
case 0xa9: /*printf("%04x\n", A);*/ return((HBCounter >> 8) & 0xFF);
146
case 0xaa: /*printf("%04x\n", A);*/ return((VBCounter >> 0) & 0xFF);
147
case 0xab: /*printf("%04x\n", A);*/ return((VBCounter >> 8) & 0xFF);
148
default: return(0);
149
//default: printf("GfxRead: %04x\n", A); return(0);
150
}
151
}
152
153
bool GFX::ExecuteLine(uint32 *surface, bool skip)
154
{
155
bool ret = false; // true if we finish frame here
156
157
if(wsLine < 144)
158
{
159
if(!skip)
160
{
161
if (sys->rotate)
162
Scanline(surface + 223 * 144 + wsLine);
163
else
164
Scanline(surface + wsLine * 224);
165
}
166
}
167
168
sys->memory.CheckSoundDMA();
169
170
// Update sprite data table
171
if(wsLine == 142)
172
{
173
SpriteCountCache = SpriteCount;
174
175
if(SpriteCountCache > 0x80)
176
SpriteCountCache = 0x80;
177
178
memcpy(SpriteTable, &sys->memory.wsRAM[(SPRBase << 9) + (SpriteStart << 2)], SpriteCountCache << 2);
179
}
180
181
if(wsLine == 144)
182
{
183
ret = true;
184
sys->interrupt.DoInterrupt(WSINT_VBLANK);
185
//printf("VBlank: %d\n", wsLine);
186
}
187
188
189
if(HBCounter && (BTimerControl & 0x01))
190
{
191
HBCounter--;
192
if(!HBCounter)
193
{
194
// Loop mode?
195
if(BTimerControl & 0x02)
196
HBCounter = HBTimerPeriod;
197
sys->interrupt.DoInterrupt(WSINT_HBLANK_TIMER);
198
}
199
}
200
201
// CPU ==========================
202
sys->cpu.execute(224);
203
// CPU ==========================
204
205
wsLine = (wsLine + 1) % 159;
206
if(wsLine == LineCompare)
207
{
208
sys->interrupt.DoInterrupt(WSINT_LINE_HIT);
209
//printf("Line hit: %d\n", wsLine);
210
}
211
212
// CPU ==========================
213
sys->cpu.execute(32);
214
// CPU ==========================
215
216
sys->rtc.Clock(256);
217
218
if(!wsLine)
219
{
220
if(VBCounter && (BTimerControl & 0x04))
221
{
222
VBCounter--;
223
if(!VBCounter)
224
{
225
if(BTimerControl & 0x08) // Loop mode?
226
VBCounter = VBTimerPeriod;
227
228
sys->interrupt.DoInterrupt(WSINT_VBLANK_TIMER);
229
}
230
}
231
wsLine = 0;
232
}
233
234
return ret;
235
}
236
237
void GFX::SetLayerEnableMask(uint32 mask)
238
{
239
LayerEnabled = mask;
240
}
241
242
void GFX::SetBWPalette(const uint32 *colors)
243
{
244
std::memcpy(ColorMapG, colors, sizeof(ColorMapG));
245
}
246
void GFX::SetColorPalette(const uint32 *colors)
247
{
248
std::memcpy(ColorMap, colors, sizeof(ColorMap));
249
}
250
251
/*
252
void GFX::SetPixelFormat()
253
{
254
for(int r = 0; r < 16; r++)
255
{
256
for(int g = 0; g < 16; g++)
257
{
258
for(int b = 0; b < 16; b++)
259
{
260
uint32 neo_r, neo_g, neo_b;
261
262
neo_r = r * 17;
263
neo_g = g * 17;
264
neo_b = b * 17;
265
266
ColorMap[(r << 8) | (g << 4) | (b << 0)] = 0xff000000 | neo_r << 16 | neo_g << 8 | neo_b << 0;
267
}
268
269
for(int i = 0; i < 16; i++)
270
{
271
uint32 neo_r, neo_g, neo_b;
272
273
neo_r = (i) * 17;
274
neo_g = (i) * 17;
275
neo_b = (i) * 17;
276
277
ColorMapG[i] = 0xff000000 | neo_r << 16 | neo_g << 8 | neo_b << 0;
278
}
279
}
280
}
281
}*/
282
283
void GFX::Scanline(uint32 *target)
284
{
285
uint32 start_tile_n,map_a,startindex,adrbuf,b1,b2,j,t,l;
286
char ys2;
287
uint8 b_bg[256];
288
uint8 b_bg_pal[256];
289
const uint8 *ram = sys->memory.wsRAM;
290
291
if(!wsVMode)
292
memset(b_bg, wsColors[BGColor&0xF]&0xF, 256);
293
else
294
{
295
memset(&b_bg[0], BGColor & 0xF, 256);
296
memset(&b_bg_pal[0], (BGColor>>4) & 0xF, 256);
297
}
298
start_tile_n=(wsLine+BGYScroll)&0xff;/*First line*/
299
map_a=(((uint32)(FGBGLoc&0xF))<<11)+((start_tile_n&0xfff8)<<3);
300
startindex = BGXScroll >> 3; /*First tile in row*/
301
adrbuf = 7-(BGXScroll&7); /*Pixel in tile*/
302
303
if((DispControl & 0x01) && (LayerEnabled & 0x01)) /*BG layer*/
304
{
305
for(t=0;t<29;t++)
306
{
307
b1=ram[map_a+(startindex<<1)];
308
b2=ram[map_a+(startindex<<1)+1];
309
uint32 palette=(b2>>1)&15;
310
b2=(b2<<8)|b1;
311
GetTile(b2&0x1ff,start_tile_n&7,b2&0x8000,b2&0x4000,b2&0x2000);
312
313
if(wsVMode)
314
{
315
if(wsVMode & 0x2)
316
{
317
for(int x = 0; x < 8; x++)
318
if(wsTileRow[x])
319
{
320
b_bg[adrbuf + x] = wsTileRow[x];
321
b_bg_pal[adrbuf + x] = palette;
322
}
323
}
324
else
325
{
326
for(int x = 0; x < 8; x++)
327
if(wsTileRow[x] || !(palette & 0x4))
328
{
329
b_bg[adrbuf + x] = wsTileRow[x];
330
b_bg_pal[adrbuf + x] = palette;
331
}
332
}
333
}
334
else
335
{
336
for(int x = 0; x < 8; x++)
337
if(wsTileRow[x] || !(palette & 4))
338
{
339
b_bg[adrbuf + x] = wsColors[wsMonoPal[palette][wsTileRow[x]]];
340
}
341
}
342
adrbuf += 8;
343
startindex=(startindex + 1)&31;
344
} // end for(t = 0 ...
345
} // End BG layer drawing
346
347
if((DispControl & 0x02) && (LayerEnabled & 0x02))/*FG layer*/
348
{
349
uint8 windowtype = DispControl&0x30;
350
bool in_window[256 + 8*2];
351
352
if(windowtype)
353
{
354
memset(in_window, 0, sizeof(in_window));
355
356
if(windowtype == 0x20) // Display FG only inside window
357
{
358
if((wsLine >= FGy0) && (wsLine < FGy1))
359
for(j = FGx0; j <= FGx1 && j < 224; j++)
360
in_window[7 + j] = 1;
361
}
362
else if(windowtype == 0x30) // Display FG only outside window
363
{
364
for(j = 0; j < 224; j++)
365
{
366
if(!(j >= FGx0 && j < FGx1) || !((wsLine >= FGy0) && (wsLine < FGy1)))
367
in_window[7 + j] = 1;
368
}
369
}
370
else
371
{
372
Debug::puts("Bad windowtype??");
373
}
374
}
375
else
376
memset(in_window, 1, sizeof(in_window));
377
378
start_tile_n=(wsLine+FGYScroll)&0xff;
379
map_a=(((uint32)((FGBGLoc>>4)&0xF))<<11)+((start_tile_n>>3)<<6);
380
startindex = FGXScroll >> 3;
381
adrbuf = 7-(FGXScroll&7);
382
383
for(t=0; t<29; t++)
384
{
385
b1=ram[map_a+(startindex<<1)];
386
b2=ram[map_a+(startindex<<1)+1];
387
uint32 palette=(b2>>1)&15;
388
b2=(b2<<8)|b1;
389
GetTile(b2&0x1ff,start_tile_n&7,b2&0x8000,b2&0x4000,b2&0x2000);
390
391
if(wsVMode)
392
{
393
if(wsVMode & 0x2)
394
for(int x = 0; x < 8; x++)
395
{
396
if(wsTileRow[x] && in_window[adrbuf + x])
397
{
398
b_bg[adrbuf + x] = wsTileRow[x] | 0x10;
399
b_bg_pal[adrbuf + x] = palette;
400
}
401
}
402
else
403
for(int x = 0; x < 8; x++)
404
{
405
if((wsTileRow[x] || !(palette & 0x4)) && in_window[adrbuf + x])
406
{
407
b_bg[adrbuf + x] = wsTileRow[x] | 0x10;
408
b_bg_pal[adrbuf + x] = palette;
409
}
410
}
411
}
412
else
413
{
414
for(int x = 0; x < 8; x++)
415
if((wsTileRow[x] || !(palette & 4)) && in_window[adrbuf + x])
416
{
417
b_bg[adrbuf + x] = wsColors[wsMonoPal[palette][wsTileRow[x]]] | 0x10;
418
}
419
}
420
adrbuf += 8;
421
startindex=(startindex + 1)&31;
422
} // end for(t = 0 ...
423
424
} // end FG drawing
425
426
if((DispControl & 0x04) && SpriteCountCache && (LayerEnabled & 0x04))/*Sprites*/
427
{
428
int xs,ts,as,ys,ysx,h;
429
bool in_window[256 + 8*2];
430
431
if(DispControl & 0x08)
432
{
433
memset(in_window, 0, sizeof(in_window));
434
if((wsLine >= SPRy0) && (wsLine < SPRy1))
435
for(j = SPRx0; j < SPRx1 && j < 256; j++)
436
in_window[7 + j] = 1;
437
}
438
else
439
memset(in_window, 1, sizeof(in_window));
440
441
for(h = SpriteCountCache - 1; h >= 0; h--)
442
{
443
ts = SpriteTable[h][0];
444
as = SpriteTable[h][1];
445
ysx = SpriteTable[h][2];
446
ys2 = (int8)SpriteTable[h][2];
447
xs = SpriteTable[h][3];
448
449
if(xs >= 249) xs -= 256;
450
451
if(ysx > 150)
452
ys = ys2;
453
else
454
ys = ysx;
455
456
ys = wsLine - ys;
457
458
if(ys >= 0 && ys < 8 && xs < 224)
459
{
460
uint32 palette = ((as >> 1) & 0x7);
461
462
ts |= (as&1) << 8;
463
GetTile(ts, ys, as & 0x80, as & 0x40, 0);
464
465
if(wsVMode)
466
{
467
if(wsVMode & 0x2)
468
{
469
for(int x = 0; x < 8; x++)
470
if(wsTileRow[x])
471
{
472
if((as & 0x20) || !(b_bg[xs + x + 7] & 0x10))
473
{
474
bool drawthis = 0;
475
476
if(!(DispControl & 0x08))
477
drawthis = TRUE;
478
else if((as & 0x10) && !in_window[7 + xs + x])
479
drawthis = TRUE;
480
else if(!(as & 0x10) && in_window[7 + xs + x])
481
drawthis = TRUE;
482
483
if(drawthis)
484
{
485
b_bg[xs + x + 7] = wsTileRow[x] | (b_bg[xs + x + 7] & 0x10);
486
b_bg_pal[xs + x + 7] = 8 + palette;
487
}
488
}
489
}
490
}
491
else
492
{
493
for(int x = 0; x < 8; x++)
494
if(wsTileRow[x] || !(palette & 0x4))
495
{
496
if((as & 0x20) || !(b_bg[xs + x + 7] & 0x10))
497
{
498
bool drawthis = 0;
499
500
if(!(DispControl & 0x08))
501
drawthis = TRUE;
502
else if((as & 0x10) && !in_window[7 + xs + x])
503
drawthis = TRUE;
504
else if(!(as & 0x10) && in_window[7 + xs + x])
505
drawthis = TRUE;
506
507
if(drawthis)
508
{
509
b_bg[xs + x + 7] = wsTileRow[x] | (b_bg[xs + x + 7] & 0x10);
510
b_bg_pal[xs + x + 7] = 8 + palette;
511
}
512
}
513
}
514
515
}
516
517
}
518
else
519
{
520
for(int x = 0; x < 8; x++)
521
if(wsTileRow[x] || !(palette & 4))
522
{
523
if((as & 0x20) || !(b_bg[xs + x + 7] & 0x10))
524
{
525
bool drawthis = 0;
526
527
if(!(DispControl & 0x08))
528
drawthis = TRUE;
529
else if((as & 0x10) && !in_window[7 + xs + x])
530
drawthis = TRUE;
531
else if(!(as & 0x10) && in_window[7 + xs + x])
532
drawthis = TRUE;
533
534
if(drawthis)
535
//if((as & 0x10) || in_window[7 + xs + x])
536
{
537
b_bg[xs + x + 7] = wsColors[wsMonoPal[8 + palette][wsTileRow[x]]] | (b_bg[xs + x + 7] & 0x10);
538
}
539
}
540
}
541
542
}
543
}
544
}
545
546
} // End sprite drawing
547
548
const int hinc = sys->rotate ? -144 : 1;
549
550
if(wsVMode)
551
{
552
for(l=0;l<224;l++)
553
{
554
target[0] = ColorMap[wsCols[b_bg_pal[l+7]][b_bg[(l+7)]&0xf]];
555
target += hinc;
556
}
557
}
558
else
559
{
560
for(l=0;l<224;l++)
561
{
562
target[0] = ColorMapG[(b_bg[l+7])&15];
563
target += hinc;
564
}
565
}
566
}
567
568
void GFX::Init(bool color)
569
{
570
wsc = color;
571
}
572
573
void GFX::Reset()
574
{
575
wsLine = 145; // all frames same length
576
SetVideo(0, true);
577
578
std::memset(SpriteTable, 0, sizeof(SpriteTable));
579
SpriteCountCache = 0;
580
DispControl = 0;
581
BGColor = 0;
582
LineCompare = 0xBB;
583
SPRBase = 0;
584
585
SpriteStart = 0;
586
SpriteCount = 0;
587
FGBGLoc = 0;
588
589
FGx0 = 0;
590
FGy0 = 0;
591
FGx1 = 0;
592
FGy1 = 0;
593
SPRx0 = 0;
594
SPRy0 = 0;
595
SPRx1 = 0;
596
SPRy1 = 0;
597
598
BGXScroll = BGYScroll = 0;
599
FGXScroll = FGYScroll = 0;
600
LCDControl = 0;
601
LCDIcons = 0;
602
603
BTimerControl = 0;
604
HBTimerPeriod = 0;
605
VBTimerPeriod = 0;
606
607
HBCounter = 0;
608
VBCounter = 0;
609
610
std::memset(wsCols, 0, sizeof(wsCols));
611
}
612
613
SYNCFUNC(GFX)
614
{
615
616
// TCACHE stuff. we invalidate the cache instead of saving it
617
if (isReader)
618
{
619
std::memset(wsTCacheUpdate, 0, sizeof(wsTCacheUpdate));
620
std::memset(wsTCacheUpdate2, 0, sizeof(wsTCacheUpdate2));
621
}
622
/*
623
NSS(tiles);
624
NSS(wsTCache);
625
NSS(wsTCache2);
626
NSS(wsTCacheFlipped);
627
NSS(wsTCacheFlipped2);
628
NSS(wsTCacheUpdate);
629
NSS(wsTCacheUpdate2);
630
NSS(wsTileRow);
631
*/
632
633
NSS(wsVMode);
634
635
NSS(wsMonoPal);
636
NSS(wsColors);
637
NSS(wsCols);
638
639
/* non-sync settings related to output
640
NSS(ColorMapG); // b&w color output
641
NSS(ColorMap); // color color output
642
NSS(LayerEnabled); // layer enable mask
643
*/
644
NSS(wsLine);
645
646
NSS(SpriteTable);
647
NSS(SpriteCountCache);
648
NSS(DispControl);
649
NSS(BGColor);
650
NSS(LineCompare);
651
NSS(SPRBase);
652
NSS(SpriteStart);
653
NSS(SpriteCount);
654
NSS(FGBGLoc);
655
NSS(FGx0);
656
NSS(FGy0);
657
NSS(FGx1);
658
NSS(FGy1);
659
NSS(SPRx0);
660
NSS(SPRy0);
661
NSS(SPRx1);
662
NSS(SPRy1);
663
664
NSS(BGXScroll);
665
NSS(BGYScroll);
666
NSS(FGXScroll);
667
NSS(FGYScroll);
668
NSS(LCDControl);
669
NSS(LCDIcons);
670
671
NSS(BTimerControl);
672
NSS(HBTimerPeriod);
673
NSS(VBTimerPeriod);
674
675
NSS(HBCounter);
676
NSS(VBCounter);
677
NSS(VideoMode);
678
679
NSS(wsc); // mono / color
680
}
681
}
682
683