Fast 565 RGB->BGR Conversion Needed

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Fast 565 RGB->BGR Conversion Needed

Post by ChaosKnight »

Does anyone have code for quickly converting RGB to BGR on the fly. The best I've been able to make is this (and the color is still somewhat off):

Code: Select all

// Color correction (aligned)
u32 *fbcc = (u32 *)PspFrameBuffer;
u32 *fbcce = (u32 *)(PspFrameBuffer + ((SCREEN_WIDTH * SCREEN_HEIGHT) >> 1));
while &#40;fbcc < fbcce&#41;
&#123;
	*fbcc = &#40;*fbcc & 0x07e007e0&#41; | &#40;&#40;*fbcc & 0xf800f800&#41; >> 11&#41; | &#40;&#40;*fbcc & 0x001f001f&#41; << 11&#41;;
	fbcc++;
&#125;
Any help would be greatly appreciated. And feel free to suggest crazy GU or assembly functions that I've never even dreamed of.
w00t
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Re: Fast 565 RGB->BGR Conversion Needed

Post by jsgf »

ChaosKnight wrote:Does anyone have code for quickly converting RGB to BGR on the fly. The best I've been able to make is this (and the color is still somewhat off):
First question is whether you're using cached or uncached pointers here. Is this the real framebuffer, or something in system memory? Because uncached reads are going to be pretty slow.

The other thing you should do is read the value into a local before playing with it:

Code: Select all

&#123;
    u32 pix = *fbcc;
    *fbcc = &#40;pix & 0x07e007e0&#41; | &#40;&#40;pix & 0xf800f800&#41; >> 11&#41; | &#40;&#40;pix & 0x001f001f&#41; << 11&#41;;
&#125;
Also, its unclear what SCREEN_WIDTH is. If you're using the real framebuffer, which has a width of 512 pixels, then you'll end up converting quite a few invisible ones, since only 480 are visible.

The VFPU may have instructions to help with this, or at least be able to operate in larger chunks. That will need more investigation though.
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Re: Fast 565 RGB->BGR Conversion Needed

Post by ChaosKnight »

jsgf wrote:First question is whether you're using cached or uncached pointers here. Is this the real framebuffer, or something in system memory? Because uncached reads are going to be pretty slow.
This is not the real framebuffer, but rather in system memory.
jsgf wrote:Also, its unclear what SCREEN_WIDTH is. If you're using the real framebuffer, which has a width of 512 pixels, then you'll end up converting quite a few invisible ones, since only 480 are visible.
SCREEN_WIDTH = 480, HEIGHT = 272.

To be honest, at this point my problem is not so much speed as it is the conversion itself does not result in the proper colors being generated. It's close, but not exact. I have very little experiance with 565 comparitively speaking to my experiance with 8 bit or 24/32 bit modes. The 565 packing is still quite foriegn to me.
w00t
User avatar
Saotome
Posts: 182
Joined: Sat Apr 03, 2004 3:45 am

Post by Saotome »

jsgf wrote:The other thing you should do is read the value into a local before playing with it
actually the compiler does that allready (I've checked the generated asm code).

but that should be faster:

Code: Select all

	u32 pix0,pix1;
	// Color correction &#40;aligned&#41; 
	u32 *fbcc = &#40;u32 *&#41;PspFrameBuffer; 
	u32 *fbcce = &#40;u32 *&#41;&#40;PspFrameBuffer + &#40;&#40;SCREEN_WIDTH * SCREEN_HEIGHT&#41; >> 1&#41;&#41;; 
	while &#40;fbcc < fbcce&#41; 
	&#123; 
		pix0 = *fbcc;
		pix1 = *&#40;fbcc+1&#41;;
		*fbcc = &#40;pix0 & 0x07e007e0&#41; | &#40;&#40;pix0 & 0xf800f800&#41; >> 11&#41; | &#40;&#40;pix0 & 0x001f001f&#41; << 11&#41;;
		*&#40;fbcc+1&#41; = &#40;pix1 & 0x07e007e0&#41; | &#40;&#40;pix1 & 0xf800f800&#41; >> 11&#41; | &#40;&#40;pix1 & 0x001f001f&#41; << 11&#41;;
		fbcc += 2;
		
	&#125;
the compiler interleaves the two "instruction streams" so that most of the instructions are executed as a pair (in one cycle). see here for more info.
ChaosKnight wrote:To be honest, at this point my problem is not so much speed as it is the conversion itself does not result in the proper colors being generated
are you sure the color format is really 565 for both, source and destination buffer?
infj
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

I guess I should have just posted all the code straight out, so here it is with Saotome's mod in it:

Code: Select all

// Video setup
#define FB_TYPE                 u16
#define PSP_MODE                GU_PSM_5650
#define MAC_MODE                FLAYOUT_HOST_565
#define PIXEL_SIZE              2
#define SCREEN_WIDTH            480
#define SCREEN_HEIGHT           272
#define PSP_LINE_SIZE           512
#define MAC_COLOR_MODE          VMODE_16BIT
#define PSP_COLOR_MODE          PSP_DISPLAY_PIXEL_FORMAT_565
#define FRAMEBUFFER_SIZE        &#40;PSP_LINE_SIZE * SCREEN_HEIGHT * PIXEL_SIZE&#41;
FB_TYPE *g_vram_base = &#40;FB_TYPE *&#41;&#40;0x40000000 | 0x04000000&#41;;
static unsigned int __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; list&#91;256&#93;;
static int dispBufferNumber;
inline FB_TYPE *getVramDrawBuffer&#40;&#41;
&#123;
	return &#40;&#40;!dispBufferNumber&#41; ? g_vram_base + &#40;FRAMEBUFFER_SIZE >> 1&#41; &#58; g_vram_base&#41;;
&#125;

// Basilisk display configuration
static FB_TYPE __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; PspFrameBuffer&#91;SCREEN_WIDTH * SCREEN_HEIGHT&#93;;

/*
 *  Initialization
 */

bool VideoInit&#40;bool classic&#41;
&#123;
#if !DEBUG
	// guInit - Taken from initGraphics&#40;&#41; in graphics.c from LUAPlayer
        sceDisplaySetMode&#40;0, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;

        dispBufferNumber = 0;
        sceDisplayWaitVblankStart&#40;&#41;;
	sceDisplaySetFrameBuf&#40;&#40;void*&#41; g_vram_base, PSP_LINE_SIZE, PSP_COLOR_MODE, 1&#41;;

        sceGuInit&#40;&#41;;

        sceGuStart&#40;GU_DIRECT, list&#41;;
        sceGuDrawBuffer&#40;PSP_MODE, &#40;void*&#41;FRAMEBUFFER_SIZE, PSP_LINE_SIZE&#41;;
        sceGuDispBuffer&#40;SCREEN_WIDTH, SCREEN_HEIGHT, &#40;void*&#41;0, PSP_LINE_SIZE&#41;;
        sceGuClear&#40;GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT&#41;;
        sceGuDepthBuffer&#40;&#40;void*&#41; 0x110000, PSP_LINE_SIZE&#41;;
        sceGuOffset&#40;2048 - &#40;SCREEN_WIDTH / 2&#41;, 2048 - &#40;SCREEN_HEIGHT / 2&#41;&#41;;
        sceGuViewport&#40;2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
        sceGuDepthRange&#40;0xc350, 0x2710&#41;;
        sceGuScissor&#40;0, 0, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
        sceGuEnable&#40;GU_SCISSOR_TEST&#41;;
        sceGuAlphaFunc&#40;GU_GREATER, 0, 0xff&#41;;
        sceGuEnable&#40;GU_ALPHA_TEST&#41;;
        sceGuDepthFunc&#40;GU_GEQUAL&#41;;
        sceGuEnable&#40;GU_DEPTH_TEST&#41;;
        sceGuFrontFace&#40;GU_CW&#41;;
        sceGuShadeModel&#40;GU_SMOOTH&#41;;
        sceGuEnable&#40;GU_CULL_FACE&#41;;
        sceGuEnable&#40;GU_TEXTURE_2D&#41;;
        sceGuTexMode&#40;PSP_MODE, 0, 0, 0&#41;;
        sceGuTexFunc&#40;GU_TFX_REPLACE, GU_TCC_RGBA&#41;;
        sceGuTexFilter&#40;GU_NEAREST, GU_NEAREST&#41;;
        sceGuAmbientColor&#40;0xffffffff&#41;;
        sceGuFinish&#40;&#41;;
        sceGuSync&#40;0, 0&#41;;

        sceDisplayWaitVblankStart&#40;&#41;;
        sceGuDisplay&#40;1&#41;;
#endif
	// Configure the Basilisk II framebuffer.
	VideoMonitor.x = SCREEN_WIDTH;
	VideoMonitor.y = SCREEN_HEIGHT;
	VideoMonitor.mode = MAC_COLOR_MODE;
	VideoMonitor.bytes_per_row = SCREEN_WIDTH * PIXEL_SIZE;
	VideoMonitor.mac_frame_base = MacFrameBaseMac;

	MacFrameBaseHost = &#40;uint8 *&#41;PspFrameBuffer;
	MacFrameSize = VideoMonitor.bytes_per_row * VideoMonitor.y;
	MacFrameLayout = MAC_MODE;

	// Done.
	D&#40;bug&#40;"video "&#41;&#41;;
	return true;
&#125;

void video_set_palette&#40;unsigned char *p&#41;
&#123;
	D&#40;bug&#40;"video_set_palette called\n"&#41;&#41;;
&#125;

/*
 *  Deinitialization
 */

void VideoExit&#40;void&#41;
&#123;
#if !DEBUG
	sceGuTerm&#40;&#41;;
#endif
&#125;


/*
 *  Video message handling
 */

void VideoInterrupt&#40;void&#41;
&#123;
	// Color correction &#40;aligned&#41;
	u32 pix0,pix1;
	u32 *fbcc = &#40;u32 *&#41;PspFrameBuffer;
	u32 *fbcce = &#40;u32 *&#41;&#40;PspFrameBuffer + &#40;&#40;SCREEN_WIDTH * SCREEN_HEIGHT&#41; >> 1&#41;&#41;;
	while &#40;fbcc < fbcce&#41;
	&#123;
		pix0 = *fbcc;
		pix1 = *&#40;fbcc+1&#41;;
		*fbcc = &#40;pix0 & 0x07e007e0&#41; | &#40;&#40;pix0 & 0xf800f800&#41; >> 11&#41; | &#40;&#40;pix0 & 0x001f001f&#41; << 11&#41;;
		*&#40;fbcc+1&#41; = &#40;pix1 & 0x07e007e0&#41; | &#40;&#40;pix1 & 0xf800f800&#41; >> 11&#41; | &#40;&#40;pix1 & 0x001f001f&#41; << 11&#41;;
		fbcc += 2;
	&#125; 
#if !DEBUG
	// blitImageToScreen&#40;...&#41; with some modifications.
	FB_TYPE* vram = getVramDrawBuffer&#40;&#41;;
	sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
	sceGuStart&#40;GU_DIRECT,list&#41;;
	sceGuCopyImage&#40;PSP_MODE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
		SCREEN_WIDTH, PspFrameBuffer, 0, 0, PSP_LINE_SIZE, vram&#41;;
	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0,0&#41;;
	
	// flipScreen&#40;&#41;
	sceGuSwapBuffers&#40;&#41;;
	sceDisplaySetFrameBuf&#40;vram, PSP_LINE_SIZE, PSP_COLOR_MODE, 1&#41;;
	dispBufferNumber ^= 1;
#endif
&#125;
w00t
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

be sure that your color buffers are word-aligned, or you decrease performance by unaligned load/store instructions. Using uncached accesses should also improve performance and avoid cache-pollution, but requires flushing the cache before starting the conversion.

Using the VFPU you can further increase memory throughput, by loading 4 32-bit-words at once, maybe the overall performance is still better (especially for unaligned buffers, since you need to do only a single unaligned load/store for 8 pixels), even when moving values to GPRs for shift/and/or. The VFPU instruction set contains instructions named vt5650.q, vt5551.q and vt4444.q, but we still have no idea how they work, maybe they're related.

Another problem is right now that some lv.q cause exceptions when the loaded bit pattern is not a valid floating point number, we need to find out how to switch this off using the VFPU control registers. For fast unaligned loads on use lvl.q/lvr.q.
memon
Posts: 63
Joined: Mon Oct 03, 2005 10:51 pm

Post by memon »

Couldn't you use the source 565 as a paletted texture and get the conversion 'for free'? Sure that hogs 256Kb of video memory, but since you don't need it anyway for the emulator you loose nothing :)
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

memon wrote:Couldn't you use the source 565 as a paletted texture and get the conversion 'for free'? Sure that hogs 256Kb of video memory, but since you don't need it anyway for the emulator you loose nothing :)
Interesting. I wouldn't know how to go about doing that, could you enlighten me?
w00t
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

ah, yes... nice idea, too. just st up a color lookup table (LUT) with 65535 entries where the color components of entries at each index are swapped by the formula you implemented above.
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

That's really brilliant. However, I need to get the formula right. So back OT, does anyone have a working RGB->BGR 565 formula.
w00t
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

clut[i] = (i & 0x07e0) | ((i & 0xf800) >> 11) | ((i & 0x001f) << 11);

looks right to me. haven't tested it, though. Copy the table to VRAM, if possible, to keep memory bandwidth free for other code. i and clut[i] should be unsigned.
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Re: Fast 565 RGB->BGR Conversion Needed

Post by jsgf »

ChaosKnight wrote:To be honest, at this point my problem is not so much speed as it is the conversion itself does not result in the proper colors being generated. It's close, but not exact. I have very little experiance with 565 comparitively speaking to my experiance with 8 bit or 24/32 bit modes. The 565 packing is still quite foriegn to me.
It looks fine to me. I'm using the same shifts and masks to do it in PSPGL. How is it coming out wrong? Are blue and red obviously interchanged? Something else?

Are you sure its 565, and not 5551 or 4444?

J
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Re: Fast 565 RGB->BGR Conversion Needed

Post by ChaosKnight »

jsgf wrote:It looks fine to me. I'm using the same shifts and masks to do it in PSPGL. How is it coming out wrong? Are blue and red obviously interchanged? Something else?

Are you sure its 565, and not 5551 or 4444?
It's coming out purple. But now it's red again because I'm not sure how to apply the CLUT to the sceGuCopyImage()... I create the CLUT first thing off, then I do this after sceGuInit()

Code: Select all

        sceGuClutMode&#40;PSP_MODE, 0, 0, 0&#41;;
        sceGuClutLoad&#40;8192, &#40;void *&#41;&PspCLUT&#41;;
Do I need to do this for every render? Sorry for my GU n00bishness, but if even someone had a link to a sample or article decribing this sort of thing would be nice.

As far as the 555 or 565, see the code above to find this:

Code: Select all

#define PSP_MODE                GU_PSM_5650
#define MAC_MODE                FLAYOUT_HOST_565
...
#define PSP_COLOR_MODE          PSP_DISPLAY_PIXEL_FORMAT_565
w00t
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Re: Fast 565 RGB->BGR Conversion Needed

Post by jsgf »

ChaosKnight wrote:It's coming out purple. But now it's red again because I'm not sure how to apply the CLUT to the sceGuCopyImage()...
I don't think you can; sceGuCopyImage is just a bit-for-bit copy. You need to set your image up as a texture, and then draw a textured sprite. See samples/gu/sprite/sprite.c for a guide. The main difference from what you're doing now is that you'll need to arrange your image to have a stride of 512 pixels wide, because the texture unit can only handle textures with power of 2 dimensions. You don't need to worry about making the texture 512 pixels high because you won't be drawing the parts below 272 rows.
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

sdk/samples/gu/blit/blit.c is maybe easier to understand.
Arwin
Posts: 426
Joined: Tue Jul 12, 2005 7:00 pm

Post by Arwin »

While we're on this topic, I think we also need either a virtual screen of 640x480 or scaling of 640x480 to 480x272. Maybe efficient to combine the two routines, but it's no doubt something ChaosKnight wouldn't mind having some help with (I don't know anything about graphics myself, anyway).
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

when you blit using the texture unit you can scale on-the-fly. When enabling linear interpolation, a copy to VRAM (using sceGuCopyImage) before rendering the texture could minimize the required bandwidth (direct access to system RAM for linear interpolated textures means 4 accesses per texel instead of one).
Last edited by holger on Thu Oct 13, 2005 4:28 am, edited 1 time in total.
sHARD>>
Posts: 10
Joined: Wed Oct 05, 2005 10:09 am

Post by sHARD>> »

Arwin wrote:While we're on this topic, I think we also need either a virtual screen of 640x480 or scaling of 640x480 to 480x272. Maybe efficient to combine the two routines, but it's no doubt something ChaosKnight wouldn't mind having some help with (I don't know anything about graphics myself, anyway).
Since it's already been proven that Mac OS is actually comfortable with any resolution, why not just make the option to double the screen size to twice that of the PSP (960x544)? Not sure if full screen games would work so well, but at least you can still preserve the aspect ratio. The Bochs port is ugly and harder to use partly due to it's destroying of the aspect ratio. Most applications would support this resolution without being cut off, as System 7 was designed to be compatable with the Macintosh SE, which I believe has a height of somewhere around 538. I'll check Apple docs and get back to you on that.
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

sHARD>> wrote:
Arwin wrote:While we're on this topic, I think we also need either a virtual screen of 640x480 or scaling of 640x480 to 480x272. Maybe efficient to combine the two routines, but it's no doubt something ChaosKnight wouldn't mind having some help with (I don't know anything about graphics myself, anyway).
Since it's already been proven that Mac OS is actually comfortable with any resolution, why not just make the option to double the screen size to twice that of the PSP (960x544)? Not sure if full screen games would work so well, but at least you can still preserve the aspect ratio. The Bochs port is ugly and harder to use partly due to it's destroying of the aspect ratio. Most applications would support this resolution without being cut off, as System 7 was designed to be compatable with the Macintosh SE, which I believe has a height of somewhere around 538. I'll check Apple docs and get back to you on that.
This is my thinking as well. I will attempt to do the doubling and rescaling once I get it on a texture to start out with.

Thanks all.
w00t
sHARD>>
Posts: 10
Joined: Wed Oct 05, 2005 10:09 am

Post by sHARD>> »

I surfed around, the SE uses a display with 512 x 342 pixels, so any application designed for System 7 should work great on that low resolution, I know almost everything works on my SE at least.
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

Ok, now it's a texture (as in blit.c) and everything is working, just as fast as before but still it does not seem to be using the CLUT. I will post my code here:

Code: Select all

// Video setup
#define FB_TYPE                 u16
#define PSP_MODE                GU_PSM_5650
#define MAC_MODE                FLAYOUT_HOST_565
#define SLICE_SIZE              64
#define PIXEL_SIZE              2
#define SCREEN_WIDTH            480
#define SCREEN_HEIGHT           272
#define PSP_LINE_SIZE           512
#define BII_SCR_WIDTH           480
#define BII_SCR_HEIGHT          272
#define MAC_COLOR_MODE          VMODE_16BIT
#define PSP_COLOR_MODE          PSP_DISPLAY_PIXEL_FORMAT_565
#define PSP_COLOR_MODE2         GU_COLOR_5650
#define FRAMEBUFFER_SIZE        &#40;PSP_LINE_SIZE * SCREEN_HEIGHT * PIXEL_SIZE&#41;
FB_TYPE *g_vram_base = &#40;FB_TYPE *&#41;&#40;0x40000000 | 0x04000000&#41;;
static unsigned int __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; list&#91;256&#93;;
static int dispBufferNumber;
inline FB_TYPE *getVramDrawBuffer&#40;&#41;
&#123;
	return &#40;&#40;!dispBufferNumber&#41; ? g_vram_base + &#40;FRAMEBUFFER_SIZE >> 1&#41; &#58; g_vram_base&#41;;
&#125;
struct Vertex
&#123;
	unsigned short u, v;
	unsigned short color;
	short x, y, z;
&#125;;

// Basilisk display configuration
static FB_TYPE __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; PspCLUT&#91;65536&#93;;
static FB_TYPE __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; PspFrameBuffer&#91;PSP_LINE_SIZE * SCREEN_HEIGHT&#93;;

/*
 *  Initialization
 */

bool VideoInit&#40;bool classic&#41;
&#123;
#if !DEBUG
	// Build color lookup table
	for &#40;int i = 0; i < 65536; i++&#41;
		PspCLUT&#91;i&#93; = &#40;i & 0x07e0&#41; | &#40;&#40;i & 0xf800&#41; >> 11&#41; | &#40;&#40;i & 0x001f&#41; << 11&#41;; 

	sceGuInit&#40;&#41;;

	// setup
	sceGuStart&#40;GU_DIRECT, list&#41;;
	sceGuDrawBuffer&#40;PSP_MODE, &#40;void*&#41;0, PSP_LINE_SIZE&#41;;
	sceGuDispBuffer&#40;SCREEN_WIDTH, SCREEN_HEIGHT, &#40;void*&#41;0x88000, PSP_LINE_SIZE&#41;;
	sceGuDepthBuffer&#40;&#40;void*&#41;0x110000, PSP_LINE_SIZE&#41;;
	sceGuOffset&#40;2048 - &#40;SCREEN_WIDTH / 2&#41;, 2048 - &#40;SCREEN_HEIGHT / 2&#41;&#41;;
	sceGuViewport&#40;2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
	sceGuDepthRange&#40;0xc350, 0x2710&#41;;
	sceGuScissor&#40;0, 0, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
	sceGuEnable&#40;GU_SCISSOR_TEST&#41;;
	sceGuFrontFace&#40;GU_CW&#41;;
	sceGuEnable&#40;GU_TEXTURE_2D&#41;;
	sceGuClear&#40;GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT&#41;;
        sceGuClutMode&#40;PSP_MODE, 0, 0, 0&#41;;
        sceGuClutLoad&#40;8192, &#40;void *&#41;&PspCLUT&#41;;
	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0,0&#41;;

	sceDisplayWaitVblankStart&#40;&#41;;
	sceGuDisplay&#40;1&#41;;
#endif

	// Configure the Basilisk II framebuffer.
	VideoMonitor.x = BII_SCR_WIDTH;
	VideoMonitor.y = BII_SCR_HEIGHT;
	VideoMonitor.mode = MAC_COLOR_MODE;
	VideoMonitor.bytes_per_row = PSP_LINE_SIZE * PIXEL_SIZE;
	VideoMonitor.mac_frame_base = MacFrameBaseMac;

	MacFrameSize = VideoMonitor.bytes_per_row * VideoMonitor.y;
	MacFrameLayout = MAC_MODE;
	MacFrameBaseHost = &#40;uint8 *&#41;PspFrameBuffer;

	// Done.
	D&#40;bug&#40;"video "&#41;&#41;;
	return true;
&#125;

void video_set_palette&#40;unsigned char *p&#41;
&#123;
	D&#40;bug&#40;"video_set_palette called\n"&#41;&#41;;
&#125;

/*
 *  Deinitialization
 */

void VideoExit&#40;void&#41;
&#123;
#if !DEBUG
	sceGuTerm&#40;&#41;;
#endif
&#125;


/*
 *  Video message handling
 */

void VideoInterrupt&#40;void&#41;
&#123;
	unsigned int j;
	struct Vertex* vertices;

	sceGuStart&#40;GU_DIRECT,list&#41;;
	sceGuTexMode&#40;PSP_MODE, 0, 0, 0&#41;;
	sceGuTexImage&#40;0, PSP_LINE_SIZE, PSP_LINE_SIZE, PSP_LINE_SIZE, PspFrameBuffer&#41;;
	sceGuTexFunc&#40;GU_TFX_REPLACE, GU_TCC_RGB&#41;;
	sceGuTexFilter&#40;GU_NEAREST, GU_NEAREST&#41;;
	sceGuTexScale&#40;1.0f / &#40;&#40;float&#41;PSP_LINE_SIZE&#41;, 1.0f / &#40;&#40;float&#41;PSP_LINE_SIZE&#41;&#41;;
	sceGuTexOffset&#40;0.0f, 0.0f&#41;;
	sceGuAmbientColor&#40;0xffffffff&#41;;
        sceGuClutMode&#40;PSP_MODE, 0, 0, 0&#41;;

	// do a striped blit &#40;takes the page-cache into account&#41;
	for &#40;j = 0; j < BII_SCR_WIDTH; j = j + SLICE_SIZE&#41;
	&#123;
		vertices = &#40;struct Vertex*&#41;sceGuGetMemory&#40;2 * sizeof&#40;struct Vertex&#41;&#41;;

		vertices&#91;0&#93;.u = j; vertices&#91;0&#93;.v = 0;
		vertices&#91;0&#93;.color = 0;
		vertices&#91;0&#93;.x = j; vertices&#91;0&#93;.y = 0; vertices&#91;0&#93;.z = 0;
		vertices&#91;1&#93;.u = j + SLICE_SIZE; vertices&#91;1&#93;.v = BII_SCR_HEIGHT;
		vertices&#91;1&#93;.color = 0;
		vertices&#91;1&#93;.x = j + SLICE_SIZE; vertices&#91;1&#93;.y = BII_SCR_HEIGHT; vertices&#91;1&#93;.z = 0;

		sceGuDrawArray&#40;GU_SPRITES,
			GU_TEXTURE_16BIT | PSP_COLOR_MODE2 | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 
			2, 0, vertices&#41;;
	&#125;

	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0,0&#41;;

	sceGuSwapBuffers&#40;&#41;;
&#125;
Hopefully I am just forgetting something ignorant. Also you will see some extra defines, I tried to double up the video size and have the texture automatically scale down but it just resulted in a black screen (mostly due to a lack of understanding on my part, there are a lot of moving parts in this code).
w00t
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

ChaosKnight wrote:

Code: Select all

	sceGuTexMode&#40;PSP_MODE, 0, 0, 0&#41;;
	sceGuTexImage&#40;0, PSP_LINE_SIZE, PSP_LINE_SIZE, PSP_LINE_SIZE, PspFrameBuffer&#41;;
You need to set the texture mode to GU_PSM_T16 - 16 bit palette lookup.

J
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

jsgf wrote:You need to set the texture mode to GU_PSM_T16 - 16 bit palette lookup.

J
This results in a black screen. Are there any other spots I need to setup? I looked through the CLUT example but to no avail.
w00t
holger
Posts: 204
Joined: Thu Aug 18, 2005 10:57 am

Post by holger »

Code: Select all

sceGuClutLoad&#40;8192, &#40;void *&#41;&PspCLUT&#41;; 
should read

Code: Select all

sceGuClutLoad&#40;8192, &#40;void *&#41;&PspCLUT&#91;0&#93;&#41;; 
or

Code: Select all

sceGuClutLoad&#40;8192, &#40;void *&#41;PspCLUT&#41;; 
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

holger wrote:

Code: Select all

sceGuClutLoad&#40;8192, &#40;void *&#41;&PspCLUT&#41;; 
should read

Code: Select all

sceGuClutLoad&#40;8192, &#40;void *&#41;&PspCLUT&#91;0&#93;&#41;; 
or

Code: Select all

sceGuClutLoad&#40;8192, &#40;void *&#41;PspCLUT&#41;; 
Good catch, I feel pretty foolish about now.
w00t
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

I think I have this 99% done. Looks like the screen was black both because I did not have a CLUT properly loaded, but also because the PSP needs to be in 8888 color mode to do this. Which makes perfect sense. Tricky thing is now my clut is turning the screen black and aqua. Of course my #1 culprit is this code:

Code: Select all

   // Build color lookup table 
   for &#40;int i = 0; i < 65536; i++&#41; 
      PspCLUT&#91;i&#93; = &#40;i & 0x07e0&#41; | &#40;&#40;i & 0xf800&#41; >> 11&#41; | &#40;&#40;i & 0x001f&#41; << 11&#41;; 
Is this correct for building a CLUT?
w00t
ector
Posts: 195
Joined: Thu May 12, 2005 10:22 pm

Post by ector »

Your problem is that the CLUT memory on-chip is only 512 (or possibly 1024?) bytes as far as I can tell.
You can't use a 65536-color palette.
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
jsgf
Posts: 254
Joined: Tue Jul 12, 2005 11:02 am
Contact:

Post by jsgf »

ector wrote:Your problem is that the CLUT memory on-chip is only 512 (or possibly 1024?) bytes as far as I can tell.
Should be at least 1024, otherwise you wouldn't be able to have a 256x32bpp colour table. So does that mean the CLUT is uploaded when you execute command 196, rather than simply setting a pointer for later use?
You can't use a 65536-color palette.
I wonder why the hardware (apparently) supports 16 and 32 bit index formats then?
ector
Posts: 195
Joined: Thu May 12, 2005 10:22 pm

Post by ector »

jsgf wrote:
ector wrote:Your problem is that the CLUT memory on-chip is only 512 (or possibly 1024?) bytes as far as I can tell.
Should be at least 1024, otherwise you wouldn't be able to have a 256x32bpp colour table. So does that mean the CLUT is uploaded when you execute command 196, rather than simply setting a pointer for later use?
You can't use a 65536-color palette.
I wonder why the hardware (apparently) supports 16 and 32 bit index formats then?
Yeah oops didn't think properly there... of course it's at least 1024b.
But yeah i'm pretty sure that it gets uploaded. Making an additional read over the memory bus every time the chip needed a color would be too slow.

Don't know what the big index formats would be useful for, other than crude pixel skipping :P
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
User avatar
ChaosKnight
Posts: 142
Joined: Thu Apr 14, 2005 2:08 am
Location: Florida, USA

Post by ChaosKnight »

So then i'm back to doing a while on my buffer to convert blocks of 2px?

-- EDIT --
Went back to Saotome's formula and I discovered something interesting. It was working this whole time but didn't seem like it. I will explain. The video is rendered on two differant threads simultaniously. Basilisk II has access to the "framebuffer" and that was the same one i was working with. So foolishly two threads were touching it at the same time, making the picture purple (red + blue). I created another buffer and used Saotome's method to write to it, which now results in perfect color but a severe slowdown... so here's the question... How do I get a block of memory on VRAM? do I just have to point to a certain address? If so what is that address and how much space am I allowed to use within it. It seems i'm only using ~265K for a buffer, so it's pretty small yet, but I wish to experiment with larger resolutions and scaling.
w00t
Post Reply