Code: Select all
#include <pspctrl.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <GLES/egl.h>
#include <GLES/gl.h>
#define EGLCHK(x) x
#define GLCHK(x) x
static const EGLint attrib_list [] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_NONE
};
struct clear_vertex { short x, y, z; };
#include "../pspgl_internal.h"
static
void set_depth_pixel (int x, int y, int z)
{
struct pspgl_dlist *dlist = pspgl_curctx->dlist_current;
struct clear_vertex *vbuf = pspgl_dlist_insert_space(dlist, 2 * sizeof(struct clear_vertex));
vbuf[0].x = x;
vbuf[0].y = y;
vbuf[0].z = z;
vbuf[1].x = x+1;
vbuf[1].y = y+1;
vbuf[1].z = z;
/* enable clear mode */
sendCommandi(211, 1 | (1 << 10));
/* draw array */
sendCommandi(18, 0x800100); /* xform: 2D, vertex format: RGB8888 (uint32), xyz (int16) */
sendCommandi(16, (((unsigned long) vbuf) >> 8) & 0xf0000); /* vertex array BASE */
sendCommandi(1, ((unsigned long) vbuf) & 0xffffff); /* vertex array, Adress */
sendCommandiUncached(4, (6 << 16) | 2); /* sprite (type 6), 2 vertices */
/* leave clear mode */
sendCommandi(211, 0);
}
int main(int argc, char* argv[])
{
EGLDisplay dpy;
EGLConfig config;
EGLint num_configs;
EGLContext ctx;
EGLSurface surface;
unsigned int x, y;
/* pass NativeDisplay=0, we only have one screen... */
EGLCHK(dpy = eglGetDisplay(0));
EGLCHK(eglInitialize(dpy, NULL, NULL));
EGLCHK(eglChooseConfig(dpy, attrib_list, &config, 1, &num_configs));
EGLCHK(ctx = eglCreateContext(dpy, config, NULL, NULL));
EGLCHK(surface = eglCreateWindowSurface(dpy, config, 0, NULL));
EGLCHK(eglMakeCurrent(dpy, surface, surface, ctx));
/* swap bytes so that they look in order in the hex-editor... */
#define swap16(val) (((unsigned) val << 8) | ((unsigned) val >> 8))
for (y=0; y<272-1; y++) {
for (x=0; x<480-1; x++) {
set_depth_pixel(x, y, swap16(x));
GLCHK(glFinish());
}
}
__pspgl_vram_dump();
for (y=0; y<272-1; y++) {
for (x=0; x<480-1; x++) {
set_depth_pixel(x, y, swap16(y));
GLCHK(glFinish());
}
}
__pspgl_vram_dump();
EGLCHK(eglTerminate(dpy));
return 0;
}
Code: Select all
$ dd if=/Volumes/PSP/pspgl.ge of=/tmp/depthmap-x bs=1 count=278528 skip=1114128
$ dd if=/Volumes/PSP/pspgl.ge of=/tmp/depthmap-y bs=1 count=278528 skip=3211296
$ hexdump -v /tmp/depthmap-x | less
$ hexdump -v /tmp/depthmap-y | less
The depth buffer seems to be laid out like this:
vertical y rows are sorted 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x18, 0x1a, ... , 0x1f, 0x10, 0x11, ... , 0x16, 0x17, ...
horizontal x pixels are sorted in 16-pixel-blocks (32 bytes), beginning in this order: 16-31, 272-287, 0-15, 256-271, 48-63, 304-319, 32-47, 288-303, 80-95, 336-351, 64-79, ...
This may look confusing on a first look, but if we consider byte-swapped address lines and the power-of-two requirement it seems logical.
This codelet does xy-to-adress-in-depthbuffer conversion:
Code: Select all
/* compile using: gcc -Wall -g -O0 -o xy2adr xy2adr.c */
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
int x = strtol(argv[1], NULL, 0);
int y = strtol(argv[2], NULL, 0);
int adr;
adr = (2*512) * (y ^ 8);
adr |= (x >> 3) & 0x20;
adr |= ((x & 0xf0) << 2) ^ 0x40;
adr |= (x & 0xf) << 1;
printf(" adr 0x%08x: x = %d/0x%04x, y = %d/0x%04x\n", adr, x, x, y, y);
return 0;
}
This one the other way round:
Code: Select all
/* compile using: gcc -Wall -g -O0 -o adr2xy adr2xy.c */
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
int adr = strtol(argv[1], NULL, 0);
int x, y;
y = (adr >> 10) ^ 8;
x = (adr & 0x20) << 3;
x |= ((adr >> 2) & 0xf0) ^ 0x10;
x |= (adr >> 1) & 0xf;
printf(" adr 0x%08x: x = %d/0x%04x, y = %d/0x%04x\n", adr, x, x, y, y);
return 0;
}