This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_ipodvideo.c
795 lines (660 loc) · 21.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <ctype.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include <linux/fb.h>
#include "SDL_video.h"
#include "SDL_mouse.h"
40
41
42
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
43
44
45
46
47
#include "SDL_sysevents.h"
#include "SDL_ipodvideo.h"
#define _THIS SDL_VideoDevice *this
48
49
50
51
52
53
54
55
56
57
58
static int iPod_VideoInit(_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **iPod_ListModes(_THIS, SDL_PixelFormat * format,
Uint32 flags);
static SDL_Surface *iPod_SetVideoMode(_THIS, SDL_Surface * current,
int width, int height, int bpp,
Uint32 flags);
static int iPod_SetColors(_THIS, int firstcolor, int ncolors,
SDL_Color * colors);
static void iPod_UpdateRects(_THIS, int nrects, SDL_Rect * rects);
static void iPod_VideoQuit(_THIS);
static void iPod_PumpEvents(_THIS);
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
static long iPod_GetGeneration();
static int initd = 0;
static int kbfd = -1;
static int fbfd = -1;
static int oldvt = -1;
static int curvt = -1;
static int old_kbmode = -1;
static long generation = 0;
static struct termios old_termios, cur_termios;
FILE *dbgout;
#define LCD_DATA 0x10
#define LCD_CMD 0x08
#define IPOD_OLD_LCD_BASE 0xc0001000
#define IPOD_OLD_LCD_RTC 0xcf001110
#define IPOD_NEW_LCD_BASE 0x70003000
#define IPOD_NEW_LCD_RTC 0x60005010
static unsigned long lcd_base, lcd_rtc, lcd_width, lcd_height;
82
83
static long
iPod_GetGeneration()
84
85
86
87
88
{
int i;
char cpuinfo[256];
char *ptr;
FILE *file;
89
90
if ((file = fopen("/proc/cpuinfo", "r")) != NULL) {
91
92
93
94
while (fgets(cpuinfo, sizeof(cpuinfo), file) != NULL)
if (SDL_strncmp(cpuinfo, "Revision", 8) == 0)
break;
fclose(file);
95
96
97
98
}
for (i = 0; !isspace(cpuinfo[i]); i++);
for (; isspace(cpuinfo[i]); i++);
ptr = cpuinfo + i + 2;
99
100
return SDL_strtol(ptr, NULL, 10);
101
102
}
103
104
static int
iPod_Available()
105
106
107
108
{
return 1;
}
109
110
static void
iPod_DeleteDevice(SDL_VideoDevice * device)
111
{
112
113
free(device->hidden);
free(device);
114
115
}
116
117
118
119
void
iPod_InitOSKeymap(_THIS)
{
}
120
121
122
static SDL_VideoDevice *
iPod_CreateDevice(int devindex)
123
124
{
SDL_VideoDevice *this;
125
126
this = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
127
if (this) {
128
129
130
memset(this, 0, sizeof *this);
this->hidden = (struct SDL_PrivateVideoData *)
SDL_malloc(sizeof(struct SDL_PrivateVideoData));
131
132
}
if (!this || !this->hidden) {
133
134
135
136
SDL_OutOfMemory();
if (this)
SDL_free(this);
return 0;
137
}
138
139
memset(this->hidden, 0, sizeof(struct SDL_PrivateVideoData));
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
generation = iPod_GetGeneration();
this->VideoInit = iPod_VideoInit;
this->ListModes = iPod_ListModes;
this->SetVideoMode = iPod_SetVideoMode;
this->SetColors = iPod_SetColors;
this->UpdateRects = iPod_UpdateRects;
this->VideoQuit = iPod_VideoQuit;
this->AllocHWSurface = 0;
this->CheckHWBlit = 0;
this->FillHWRect = 0;
this->SetHWColorKey = 0;
this->SetHWAlpha = 0;
this->LockHWSurface = 0;
this->UnlockHWSurface = 0;
this->FlipHWSurface = 0;
this->FreeHWSurface = 0;
this->SetCaption = 0;
this->SetIcon = 0;
this->IconifyWindow = 0;
this->GrabInput = 0;
this->GetWMInfo = 0;
this->InitOSKeymap = iPod_InitOSKeymap;
this->PumpEvents = iPod_PumpEvents;
this->free = iPod_DeleteDevice;
return this;
}
VideoBootStrap iPod_bootstrap = {
"ipod", "iPod Framebuffer Driver",
iPod_Available, iPod_CreateDevice
};
//--//
176
177
static int
iPod_VideoInit(_THIS, SDL_PixelFormat * vformat)
178
179
{
if (!initd) {
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/*** Code adapted/copied from SDL fbcon driver. ***/
static const char *const tty0[] = { "/dev/tty0", "/dev/vc/0", 0 };
static const char *const vcs[] = { "/dev/vc/%d", "/dev/tty%d", 0 };
int i, tty0_fd;
dbgout =
fdopen(open("/etc/sdlpod.log", O_WRONLY | O_SYNC | O_APPEND),
"a");
if (dbgout) {
setbuf(dbgout, 0);
fprintf(dbgout, "--> Started SDL <--\n");
}
// Try to query for a free VT
tty0_fd = -1;
for (i = 0; tty0[i] && (tty0_fd < 0); ++i) {
tty0_fd = open(tty0[i], O_WRONLY, 0);
}
if (tty0_fd < 0) {
tty0_fd = dup(0); /* Maybe stdin is a VT? */
}
ioctl(tty0_fd, VT_OPENQRY, &curvt);
close(tty0_fd);
tty0_fd = open("/dev/tty", O_RDWR, 0);
if (tty0_fd >= 0) {
ioctl(tty0_fd, TIOCNOTTY, 0);
close(tty0_fd);
}
if ((geteuid() == 0) && (curvt > 0)) {
for (i = 0; vcs[i] && (kbfd < 0); ++i) {
char vtpath[12];
SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], curvt);
kbfd = open(vtpath, O_RDWR);
}
}
if (kbfd < 0) {
if (dbgout)
fprintf(dbgout, "Couldn't open any VC\n");
return -1;
}
if (dbgout)
fprintf(stderr, "Current VT: %d\n", curvt);
if (kbfd >= 0) {
/* Switch to the correct virtual terminal */
if (curvt > 0) {
struct vt_stat vtstate;
if (ioctl(kbfd, VT_GETSTATE, &vtstate) == 0) {
oldvt = vtstate.v_active;
}
if (ioctl(kbfd, VT_ACTIVATE, curvt) == 0) {
if (dbgout)
fprintf(dbgout, "Waiting for switch to this VT... ");
ioctl(kbfd, VT_WAITACTIVE, curvt);
if (dbgout)
fprintf(dbgout, "done!\n");
}
}
// Set terminal input mode
if (tcgetattr(kbfd, &old_termios) < 0) {
if (dbgout)
fprintf(dbgout, "Can't get termios\n");
return -1;
}
cur_termios = old_termios;
// cur_termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
// cur_termios.c_iflag |= (BRKINT);
// cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
// cur_termios.c_oflag &= ~(OPOST);
// cur_termios.c_oflag |= (ONOCR | ONLRET);
cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
cur_termios.c_iflag &=
~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
cur_termios.c_cc[VMIN] = 0;
cur_termios.c_cc[VTIME] = 0;
if (tcsetattr(kbfd, TCSAFLUSH, &cur_termios) < 0) {
if (dbgout)
fprintf(dbgout, "Can't set termios\n");
return -1;
}
if (ioctl(kbfd, KDSKBMODE, K_MEDIUMRAW) < 0) {
if (dbgout)
fprintf(dbgout, "Can't set medium-raw mode\n");
return -1;
}
if (ioctl(kbfd, KDSETMODE, KD_GRAPHICS) < 0) {
if (dbgout)
fprintf(dbgout, "Can't set graphics\n");
return -1;
}
}
// Open the framebuffer
if ((fbfd = open("/dev/fb0", O_RDWR)) < 0) {
if (dbgout)
fprintf(dbgout, "Can't open framebuffer\n");
return -1;
} else {
struct fb_var_screeninfo vinfo;
if (dbgout)
fprintf(dbgout, "Generation: %ld\n", generation);
if (generation >= 40000) {
lcd_base = IPOD_NEW_LCD_BASE;
} else {
lcd_base = IPOD_OLD_LCD_BASE;
}
ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
close(fbfd);
if (lcd_base == IPOD_OLD_LCD_BASE)
lcd_rtc = IPOD_OLD_LCD_RTC;
else if (lcd_base == IPOD_NEW_LCD_BASE)
lcd_rtc = IPOD_NEW_LCD_RTC;
else {
SDL_SetError("Unknown iPod version");
return -1;
}
lcd_width = vinfo.xres;
lcd_height = vinfo.yres;
if (dbgout)
fprintf(dbgout, "LCD is %dx%d\n", lcd_width, lcd_height);
}
fcntl(kbfd, F_SETFL, O_RDWR | O_NONBLOCK);
/* Determine the current screen size */
this->info.current_w = lcd_width;
this->info.current_h = lcd_height;
if ((generation >= 60000) && (generation < 70000)) {
vformat->BitsPerPixel = 16;
vformat->Rmask = 0xF800;
vformat->Gmask = 0x07E0;
vformat->Bmask = 0x001F;
} else {
vformat->BitsPerPixel = 8;
vformat->Rmask = vformat->Gmask = vformat->Bmask = 0;
}
initd = 1;
if (dbgout)
fprintf(dbgout, "Initialized.\n\n");
331
332
333
334
}
return 0;
}
335
336
static SDL_Rect **
iPod_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
337
338
339
340
341
{
int width, height, fd;
static SDL_Rect r;
static SDL_Rect *rs[2] = { &r, 0 };
342
343
if ((fd = open("/dev/fb0", O_RDWR)) < 0) {
return 0;
344
} else {
345
346
347
348
349
350
351
struct fb_var_screeninfo vinfo;
ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
close(fbfd);
width = vinfo.xres;
height = vinfo.yres;
352
353
354
355
356
357
358
359
}
r.x = r.y = 0;
r.w = width;
r.h = height;
return rs;
}
360
361
362
static SDL_Surface *
iPod_SetVideoMode(_THIS, SDL_Surface * current, int width, int height,
int bpp, Uint32 flags)
363
364
365
{
Uint32 Rmask, Gmask, Bmask;
if (bpp > 8) {
366
367
368
Rmask = 0xF800;
Gmask = 0x07E0;
Bmask = 0x001F;
369
} else {
370
Rmask = Gmask = Bmask = 0;
371
372
}
373
374
375
if (this->hidden->buffer)
SDL_free(this->hidden->buffer);
this->hidden->buffer = SDL_malloc(width * height * (bpp / 8));
376
if (!this->hidden->buffer) {
377
378
SDL_SetError("Couldn't allocate buffer for requested mode");
return 0;
379
380
}
381
memset(this->hidden->buffer, 0, width * height * (bpp / 8));
382
383
384
385
386
387
if (!SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0)) {
SDL_SetError("Couldn't allocate new pixel format");
SDL_free(this->hidden->buffer);
this->hidden->buffer = 0;
return 0;
388
389
390
}
if (bpp <= 8) {
391
392
393
394
395
396
397
398
int i, j;
for (i = 0; i < 256; i += 4) {
for (j = 0; j < 4; j++) {
current->format->palette->colors[i + j].r = 85 * j;
current->format->palette->colors[i + j].g = 85 * j;
current->format->palette->colors[i + j].b = 85 * j;
}
}
399
400
401
402
403
404
405
406
407
408
409
}
current->flags = flags & SDL_FULLSCREEN;
this->hidden->w = current->w = width;
this->hidden->h = current->h = height;
current->pitch = current->w * (bpp / 8);
current->pixels = this->hidden->buffer;
return current;
}
410
411
static int
iPod_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
412
{
413
414
415
416
417
418
419
420
421
422
if (SDL_VideoSurface && SDL_VideoSurface->format
&& SDL_VideoSurface->format->palette) {
int i, j;
for (i = 0; i < 256; i += 4) {
for (j = 0; j < 4; j++) {
SDL_VideoSurface->format->palette->colors[i + j].r = 85 * j;
SDL_VideoSurface->format->palette->colors[i + j].g = 85 * j;
SDL_VideoSurface->format->palette->colors[i + j].b = 85 * j;
}
}
423
424
425
426
}
return 0;
}
427
428
static void
iPod_VideoQuit(_THIS)
429
{
430
431
ioctl(kbfd, KDSETMODE, KD_TEXT);
tcsetattr(kbfd, TCSAFLUSH, &old_termios);
432
433
434
old_kbmode = -1;
if (oldvt > 0)
435
436
ioctl(kbfd, VT_ACTIVATE, oldvt);
437
if (kbfd > 0)
438
close(kbfd);
439
440
if (dbgout) {
441
442
fprintf(dbgout, "<-- Ended SDL -->\n");
fclose(dbgout);
443
}
444
445
446
447
448
kbfd = -1;
}
static char iPod_SC_keymap[] = {
449
450
0, /* 0 - no key */
'[' - 0x40, /* ESC (Ctrl+[) */
451
452
'1', '2', '3', '4', '5', '6', '7', '8', '9',
'-', '=',
453
'\b', '\t', /* Backspace, Tab (Ctrl+H,Ctrl+I) */
454
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
455
'\n', 0, /* Enter, Left CTRL */
456
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
457
0, '\\', /* left shift, backslash */
458
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
459
460
461
462
463
464
465
466
467
468
469
470
471
0, '*', 0, ' ', 0, /* right shift, KP mul, left alt, space, capslock */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-10 */
0, 0, /* numlock, scrollock */
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', /* numeric keypad */
0, 0, /* padding */
0, 0, 0, /* "less" (?), F11, F12 */
0, 0, 0, 0, 0, 0, 0, /* padding */
'\n', 0, '/', 0, 0, /* KP enter, Rctrl, Ctrl, KP div, PrtSc, RAlt */
0, 0, 0, 0, 0, 0, 0, 0, 0, /* Break, Home, Up, PgUp, Left, Right, End, Down, PgDn */
0, 0, /* Ins, Del */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* padding */
0, 0, /* RWin, LWin */
0 /* no key */
472
473
};
474
475
476
static void
iPod_keyboard()
477
478
479
480
481
482
483
484
{
unsigned char keybuf[128];
int i, nread;
SDL_keysym keysym;
SDL_Event ev;
keysym.mod = 0;
keysym.scancode = 0xff;
485
memset(&ev, 0, sizeof(SDL_Event));
486
487
nread = read(kbfd, keybuf, 128);
488
for (i = 0; i < nread; i++) {
489
char ascii = iPod_SC_keymap[keybuf[i] & 0x7f];
490
491
492
493
if (dbgout)
fprintf(dbgout, "Key! %02x is %c %s", keybuf[i], ascii,
(keybuf[i] & 0x80) ? "up" : "down");
494
495
496
497
498
499
keysym.sym = keysym.unicode = ascii;
ev.type = (keybuf[i] & 0x80) ? SDL_KEYUP : SDL_KEYDOWN;
ev.key.state = 0;
ev.key.keysym = keysym;
SDL_PushEvent(&ev);
500
501
502
}
}
503
504
static void
iPod_PumpEvents(_THIS)
505
506
507
508
509
510
511
{
fd_set fdset;
int max_fd = 0;
static struct timeval zero;
int posted;
do {
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
posted = 0;
FD_ZERO(&fdset);
if (kbfd >= 0) {
FD_SET(kbfd, &fdset);
max_fd = kbfd;
}
if (dbgout)
fprintf(dbgout, "Selecting");
if (select(max_fd + 1, &fdset, 0, 0, &zero) > 0) {
if (dbgout)
fprintf(dbgout, " -> match!\n");
iPod_keyboard();
posted++;
}
if (dbgout)
fprintf(dbgout, "\n");
529
} while (posted);
530
531
532
}
// enough space for 160x128x2
533
static char ipod_scr[160 * (128 / 4)];
534
535
536
537
538
539
540
541
#define outl(datum,addr) (*(volatile unsigned long *)(addr) = (datum))
#define inl(addr) (*(volatile unsigned long *)(addr))
/*** The following LCD code is taken from Linux kernel uclinux-2.4.24-uc0-ipod2,
file arch/armnommu/mach-ipod/fb.c. A few modifications have been made. ***/
/* get current usec counter */
542
543
static int
M_timer_get_current(void)
544
{
545
return inl(lcd_rtc);
546
547
548
}
/* check if number of useconds has past */
549
550
static int
M_timer_check(int clock_start, int usecs)
551
{
552
553
554
555
556
557
558
559
unsigned long clock;
clock = inl(lcd_rtc);
if ((clock - clock_start) >= usecs) {
return 1;
} else {
return 0;
}
560
561
562
}
/* wait for LCD with timeout */
563
564
static void
M_lcd_wait_write(void)
565
{
566
567
568
569
570
571
if ((inl(lcd_base) & 0x8000) != 0) {
int start = M_timer_get_current();
do {
if ((inl(lcd_base) & (unsigned int) 0x8000) == 0)
break;
572
} while (M_timer_check(start, 1000) == 0);
573
}
574
575
576
577
}
/* send LCD data */
578
579
static void
M_lcd_send_data(int data_lo, int data_hi)
580
{
581
582
583
584
585
586
587
M_lcd_wait_write();
outl(data_lo, lcd_base + LCD_DATA);
M_lcd_wait_write();
outl(data_hi, lcd_base + LCD_DATA);
588
589
590
591
592
593
594
}
/* send LCD command */
static void
M_lcd_prepare_cmd(int cmd)
{
595
M_lcd_wait_write();
596
597
598
599
600
601
outl(0x0, lcd_base + LCD_CMD);
M_lcd_wait_write();
outl(cmd, lcd_base + LCD_CMD);
602
603
604
605
}
/* send LCD command and data */
606
607
static void
M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi)
608
{
609
M_lcd_prepare_cmd(cmd);
610
611
M_lcd_send_data(data_lo, data_hi);
612
613
614
}
// Copied from uW
615
616
static void
M_update_display(int sx, int sy, int mx, int my)
617
{
618
619
int y;
unsigned short cursor_pos;
620
621
622
sx >>= 3;
mx >>= 3;
623
624
cursor_pos = sx + (sy << 5);
625
626
627
628
for (y = sy; y <= my; y++) {
unsigned char *img_data;
int x;
629
630
631
/* move the cursor */
M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff);
632
633
634
/* setup for printing */
M_lcd_prepare_cmd(0x12);
635
636
img_data = ipod_scr + (sx << 1) + (y * (lcd_width / 4));
637
638
639
640
641
/* loops up to 160 times */
for (x = sx; x <= mx; x++) {
/* display eight pixels */
M_lcd_send_data(*(img_data + 1), *img_data);
642
643
644
img_data += 2;
}
645
646
647
648
/* update cursor pos counter */
cursor_pos += 0x20;
}
649
650
651
}
/* get current usec counter */
652
653
static int
C_timer_get_current(void)
654
{
655
return inl(0x60005010);
656
657
658
}
/* check if number of useconds has past */
659
660
static int
C_timer_check(int clock_start, int usecs)
661
{
662
663
664
665
666
667
668
669
unsigned long clock;
clock = inl(0x60005010);
if ((clock - clock_start) >= usecs) {
return 1;
} else {
return 0;
}
670
671
672
}
/* wait for LCD with timeout */
673
674
static void
C_lcd_wait_write(void)
675
{
676
677
678
679
680
681
if ((inl(0x70008A0C) & 0x80000000) != 0) {
int start = C_timer_get_current();
do {
if ((inl(0x70008A0C) & 0x80000000) == 0)
break;
682
} while (C_timer_check(start, 1000) == 0);
683
}
684
}
685
686
687
static void
C_lcd_cmd_data(int cmd, int data)
688
{
689
690
C_lcd_wait_write();
outl(cmd | 0x80000000, 0x70008A0C);
691
692
693
C_lcd_wait_write();
outl(data | 0x80000000, 0x70008A0C);
694
695
}
696
697
static void
C_update_display(int sx, int sy, int mx, int my)
698
{
699
700
int height = (my - sy) + 1;
int width = (mx - sx) + 1;
701
702
char *addr = SDL_VideoSurface->pixels;
703
704
705
if (width & 1)
width++;
706
707
708
709
/* start X and Y */
C_lcd_cmd_data(0x12, (sy & 0xff));
C_lcd_cmd_data(0x13, (((SDL_VideoSurface->w - 1) - sx) & 0xff));
710
711
712
713
714
/* max X and Y */
C_lcd_cmd_data(0x15, (((sy + height) - 1) & 0xff));
C_lcd_cmd_data(0x16,
(((((SDL_VideoSurface->w - 1) - sx) - width) + 1) & 0xff));
715
716
addr += sx + sy * SDL_VideoSurface->pitch;
717
718
719
while (height > 0) {
int h, x, y, pixels_to_write;
720
721
pixels_to_write = (width * height) * 2;
722
723
724
725
726
727
728
/* calculate how much we can do in one go */
h = height;
if (pixels_to_write > 64000) {
h = (64000 / 2) / width;
pixels_to_write = (width * h) * 2;
}
729
730
731
732
outl(0x10000080, 0x70008A20);
outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24);
outl(0x34000000, 0x70008A20);
733
734
735
736
737
738
/* for each row */
for (x = 0; x < h; x++) {
/* for each column */
for (y = 0; y < width; y += 2) {
unsigned two_pixels;
739
740
741
two_pixels = addr[0] | (addr[1] << 16);
addr += 2;
742
743
while ((inl(0x70008A20) & 0x1000000) == 0);
744
745
746
747
/* output 2 pixels */
outl(two_pixels, 0x70008B00);
}
748
749
750
addr += SDL_VideoSurface->w - width;
}
751
752
while ((inl(0x70008A20) & 0x4000000) == 0);
753
754
outl(0x0, 0x70008A24);
755
756
757
height = height - h;
}
758
759
760
}
// Should work with photo. However, I don't have one, so I'm not sure.
761
762
static void
iPod_UpdateRects(_THIS, int nrects, SDL_Rect * rects)
763
764
{
if (SDL_VideoSurface->format->BitsPerPixel == 16) {
765
C_update_display(0, 0, lcd_width, lcd_height);
766
} else {
767
768
769
770
771
772
773
774
775
776
777
778
779
780
int i, y, x;
for (i = 0; i < nrects; i++) {
SDL_Rect *r = rects + i;
if (!r) {
continue;
}
for (y = r->y; (y < r->y + r->h) && y < lcd_height; y++) {
for (x = r->x; (x < r->x + r->w) && x < lcd_width; x++) {
ipod_scr[y * (lcd_width / 4) + x / 4] &=
~(3 << (2 * (x % 4)));
ipod_scr[y * (lcd_width / 4) + x / 4] |=
(((Uint8 *) (SDL_VideoSurface->pixels))[y *
SDL_VideoSurface->
781
782
783
784
785
786
pitch +
x] & 3) << (2
*
(x
%
4));
787
788
789
790
791
}
}
}
M_update_display(0, 0, lcd_width, lcd_height);
792
793
}
}
794
795
/* vi: set ts=4 sw=4 expandtab: */