Example #1
0
//---------------------------------------------------------------------------
void gs_load_texture(u16 x, u16 y, u16 w, u16 h, u32 data_adr, u32 dest_adr, u16 dest_w)
{
u32 i;			// DMA buffer loop counter
u32 frac;		// flag for whether to run a fractional buffer or not
u32 current;		// number of pixels to transfer in current DMA
u32 qtotal;		// total number of qwords of data to transfer

	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 4, 1, 0, 0, 0);
	GIF_DATA_AD(gs_dma_buf, bitbltbuf,
		GS_BITBLTBUF(0, 0, 0,
			dest_adr/256,		// frame buffer address
			dest_w/64,			// frame buffer width
			0));
	GIF_DATA_AD(gs_dma_buf, trxpos,
		GS_TRXPOS(
			0,
			0,
			x,
			y,
			0));	// left to right/top to bottom
	GIF_DATA_AD(gs_dma_buf, trxreg, GS_TRXREG(w, h));
	GIF_DATA_AD(gs_dma_buf, trxdir, GS_TRXDIR(XDIR_EE_GS));
	SEND_GS_PACKET(gs_dma_buf);

	qtotal = w*h/4;					// total number of quadwords to transfer.
	current = qtotal % MAX_TRANSFER;// work out if a partial buffer transfer is needed.
	frac=1;							// assume yes.
	if(!current)					// if there is no need for partial buffer
	{
		current = MAX_TRANSFER;		// start with a full buffer
		frac=0;						// and don't do extra partial buffer first
	}
	for(i=0; i<(qtotal/MAX_TRANSFER)+frac; i++)
	{
		BEGIN_GS_PACKET(gs_dma_buf);
		GIF_TAG_IMG(gs_dma_buf, current);
		SEND_GS_PACKET(gs_dma_buf);

		SET_QWC(GIF_QWC, current);
		SET_MADR(GIF_MADR, data_adr, 0);
		SET_CHCR(GIF_CHCR, 1, 0, 0, 0, 0, 1, 0);
		DMA_WAIT(GIF_CHCR);

		data_adr += current*16;
		current = MAX_TRANSFER;		// after the first one, all are full buffers
	}

	// Access the TEXFLUSH register with anything to flush the texture
	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 1, 1, 0, 0, 0);
	GIF_DATA_AD(gs_dma_buf, texflush, 0x42);
	SEND_GS_PACKET(gs_dma_buf);
}
Example #2
0
//---------------------------------------------------------------------------
void g2_fill_rect(s16 x0, s16 y0, s16 x1, s16 y1)
{
	x0 += gs_origin_x;
	y0 += gs_origin_y;
	x1 += gs_origin_x;
	y1 += gs_origin_y;

	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 4, 1, 0, 0, 0);

	GIF_DATA_AD(gs_dma_buf, prim,
		GS_PRIM(PRIM_SPRITE, 0, 0, 0, 0, 0, 0, 0, 0));

	GIF_DATA_AD(gs_dma_buf, rgbaq,
		GS_RGBAQ(g2_fill_r, g2_fill_g, g2_fill_b, 0x80, 0));

	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2(x0<<4, y0<<4, 0));

	// It looks like the default operation for the SPRITE primitive is to
	// not draw the right and bottom 'lines' of the rectangle refined by
	// the parameters. Add +1 to change this.
	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2((x1+1)<<4, (y1+1)<<4, 0));

	SEND_GS_PACKET(gs_dma_buf);
}
Example #3
0
void gsKit_set_test(GSGLOBAL *gsGlobal, u8 Preset)
{
	u64 *p_data;
	u64 *p_store;

	if(Preset == GS_ZTEST_OFF)
		gsGlobal->Test->ZTST = 1;
	else if (Preset == GS_ZTEST_ON)
		gsGlobal->Test->ZTST = 2;
	else if (Preset == GS_ATEST_OFF)
		gsGlobal->Test->ATE = 0;
	else if (Preset == GS_ATEST_ON)
		gsGlobal->Test->ATE = 1;
	else if (Preset == GS_D_ATEST_OFF)
		gsGlobal->Test->DATE = 0;
	else if (Preset == GS_D_ATEST_ON)
		gsGlobal->Test->DATE = 1;

	p_data = p_store = gsKit_heap_alloc(gsGlobal, 1, 16, GIF_AD);

	*p_data++ = GIF_TAG_AD(1);
	*p_data++ = GIF_AD;

	*p_data++ = GS_SETREG_TEST( gsGlobal->Test->ATE, gsGlobal->Test->ATST,
				    gsGlobal->Test->AREF, gsGlobal->Test->AFAIL,
				    gsGlobal->Test->DATE, gsGlobal->Test->DATM,
				    gsGlobal->Test->ZTE, gsGlobal->Test->ZTST );

	*p_data++ = GS_TEST_1+gsGlobal->PrimContext;

}
Example #4
0
//---------------------------------------------------------------------------
void g2_put_image(s16 x, s16 y, s16 w, s16 h, u32 *data)
{
	x += gs_origin_x;
	y += gs_origin_y;

	// - Call this to copy the texture data from EE memory to GS memory.
	// - The g2_texbuf_addr variable holds the byte address of the
	//   'texture buffer' and is setup in g2_init() to be just after
	//   the frame buffer(s). When only the standard resolutions are
	//   used this buffer is guaranteed to be correctly aligned on 256
	//   bytes.
	gs_load_texture(0, 0, w, h, (u32)data, g2_texbuf_addr, g2_max_x+1);

	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 6, 1, 0, 0, 0);

	// Setup the Texture Buffer register. Note the width and height! They
	// must both be a power of 2.
	GIF_DATA_AD(gs_dma_buf, tex0_1,
		GS_TEX0(
			g2_texbuf_addr/256,	// base pointer
			(g2_max_x+1)/64,	// width
			0,					// 32bit RGBA
			gs_texture_wh(w),	// width
			gs_texture_wh(h),	// height
			1,					// RGBA
			TEX_DECAL,			// just overwrite existing pixels
			0,0,0,0,0));

	GIF_DATA_AD(gs_dma_buf, prim,
		GS_PRIM(PRIM_SPRITE,
			0,			// flat shading
			1, 			// texture mapping ON
			0, 0, 0,	// no fog, alpha, or antialiasing
			1, 			// use UV register for coordinates.
			0,
			0));

	// Texture and vertex coordinates are specified consistently, with
	// the last four bits being the decimal part (always X.0 here).

	// Top/Left, texture coordinates (0, 0).
	GIF_DATA_AD(gs_dma_buf, uv,    GS_UV(0, 0));
	GIF_DATA_AD(gs_dma_buf, xyz2,  GS_XYZ2(x<<4, y<<4, 0));

	// Bottom/Right, texture coordinates (w, h).
	GIF_DATA_AD(gs_dma_buf, uv,    GS_UV(w<<4, h<<4));
	GIF_DATA_AD(gs_dma_buf, xyz2,  GS_XYZ2((x+w)<<4, (y+h)<<4, 0));

	// Finally send the command buffer to the GIF.
	SEND_GS_PACKET(gs_dma_buf);
}
Example #5
0
void gsKit_set_texfilter(GSGLOBAL *gsGlobal, u8 FilterMode)
{
	u64 *p_data;
	u64 *p_store;

	p_data = p_store = gsKit_heap_alloc(gsGlobal, 1, 16, GIF_AD);

	*p_data++ = GIF_TAG_AD(1);
	*p_data++ = GIF_AD;

	*p_data++ = GS_SETREG_TEX1(0, 0, FilterMode, FilterMode, 0, 0, 0);
	*p_data++ = GS_TEX1_1+gsGlobal->PrimContext;
}
Example #6
0
//---------------------------------------------------------------------------
void g2_set_viewport(u16 x0, u16 y0, u16 x1, u16 y1)
{
	g2_view_x0 = x0;
	g2_view_x1 = x1;
	g2_view_y0 = y0;
	g2_view_y1 = y1;

	BEGIN_GS_PACKET(gs_dma_buf);

	GIF_TAG_AD(gs_dma_buf, 1, 1, 0, 0, 0);

	GIF_DATA_AD(gs_dma_buf, scissor_1,
		GS_SCISSOR(x0, x1, y0, y1));

	SEND_GS_PACKET(gs_dma_buf);
}
Example #7
0
//---------------------------------------------------------------------------
void g2_set_active_frame(u8 frame)
{
	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 1, 1, 0, 0, 0);

	GIF_DATA_AD(gs_dma_buf, frame_1,
		GS_FRAME(
			g2_frame_addr[frame]/8192,	// FrameBuffer base pointer = Address/8192
			cur_mode->width/64,			// Frame buffer width (Pixels/64)
			cur_mode->psm,				// Pixel Storage Format
			0));

	SEND_GS_PACKET(gs_dma_buf);

	g2_active_frame = frame;
}
Example #8
0
void gsKit_set_dither_matrix(GSGLOBAL *gsGlobal)
{
    u64 *p_data;
    u64 *p_store;

    p_data = p_store = gsKit_heap_alloc(gsGlobal, 1 ,16, GIF_AD);

    *p_data++ = GIF_TAG_AD(1);
    *p_data++ = GIF_AD;

    *p_data++ = GS_SETREG_DIMX( gsGlobal->DitherMatrix[0],  gsGlobal->DitherMatrix[1],  gsGlobal->DitherMatrix[2],  gsGlobal->DitherMatrix[3],
                                gsGlobal->DitherMatrix[4],  gsGlobal->DitherMatrix[5],  gsGlobal->DitherMatrix[6],  gsGlobal->DitherMatrix[7],
                                gsGlobal->DitherMatrix[8],  gsGlobal->DitherMatrix[9], gsGlobal->DitherMatrix[10], gsGlobal->DitherMatrix[11],
                                gsGlobal->DitherMatrix[12], gsGlobal->DitherMatrix[13], gsGlobal->DitherMatrix[14], gsGlobal->DitherMatrix[15]);
    *p_data++ = GS_DIMX;
}
Example #9
0
/*
// taken from libgraph
void gsKit_set_drawfield(GSGLOBAL *gsGlobal, u8 field)
{
    u64 *p_data;
    u64 *p_store;

    (u32)p_data = (u32)p_store = gsGlobal->dma_misc;

    *p_data++ = GIF_TAG( 1, 1, 0, 0, 0, 1);
    *p_data++ = GIF_AD;

    if (field == GS_FIELD_NORMAL) { //Draw both
        *p_data++ = GIF_TAG_SCANMSK(0);
    }
    else if (field == GS_FIELD_ODD) { // Draw only odd
        *p_data++ = GIF_TAG_SCANMSK(2);
    }
    else if (field == GS_FIELD_EVEN) { // Draw only even
        *p_data++ = GIF_TAG_SCANMSK(3);
    }

    *p_data++ = GS_SCANMSK;

    dmaKit_wait_fast();
	dmaKit_send_ucab(DMA_CHANNEL_GIF, p_store, 2);
}
*/
GSQUEUE gsKit_set_finish(GSGLOBAL *gsGlobal)
{
	u64 *p_data;
	u64 *p_store;

	GSQUEUE oldQueue = *gsGlobal->CurQueue;

	p_data = p_store = gsKit_heap_alloc(gsGlobal, 1, 16, GIF_AD);

	*p_data++ = GIF_TAG_AD(1);
	*p_data++ = GIF_AD;

	*p_data++ = 0;
	*p_data++ = GS_FINISH;

	return oldQueue;
}
Example #10
0
void gsKit_set_dither(GSGLOBAL *gsGlobal)
{
    u64 *p_data;
    u64 *p_store;

    p_data = p_store = gsKit_heap_alloc(gsGlobal, 1, 16, GIF_AD);

    *p_data++ = GIF_TAG_AD(1);
    *p_data++ = GIF_AD;

    if(gsGlobal->Dithering == GS_SETTING_ON)
        *p_data++ = 1;
    else
        *p_data++ = 0;

    *p_data++ = GS_DTHE;
}
Example #11
0
//---------------------------------------------------------------------------
void g2_set_font_color(u8 red, u8 green, u8 blue)
{
u64 x0;
u64 y0;
u64 x1;
u64 y1;

	x0 = gs_origin_x-10;
	y0 = gs_origin_y-10;
	x1 = g2_fontbuf_w + gs_origin_x;
	y1 = g2_fontbuf_h + gs_origin_y;

	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 6, 1, 0, 0, 0);

	// Restore the frame buffer to the current active frame buffer.
	GIF_DATA_AD(gs_dma_buf, frame_1,
		GS_FRAME(
			g2_fontbuf_addr/8192,
			cur_mode->width/64,
			cur_mode->psm,
			0));

	// Draw the colored rectangle over the entire Font Bitmap.
	GIF_DATA_AD(gs_dma_buf, prim,
		GS_PRIM(PRIM_LINE, 0, 0, 0, 0, 0, 0, 0, 0));
//		GS_PRIM(PRIM_SPRITE, 0, 0, 0, 0, 0, 0, 0, 0));

	GIF_DATA_AD(gs_dma_buf, rgbaq,
		GS_RGBAQ(red, green, blue, 0x80, 0));

	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2(x0<<4, y0<<4, 0));
	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2(x1<<4, y1<<4, 0));

	// Restore the frame buffer to the current active frame buffer.
	GIF_DATA_AD(gs_dma_buf, frame_1,
		GS_FRAME(
			g2_frame_addr[g2_active_frame]/8192,
			cur_mode->width/64,
			cur_mode->psm,
			0));

	SEND_GS_PACKET(gs_dma_buf);
}
Example #12
0
void gsKit_set_primalpha(GSGLOBAL *gsGlobal, u64 AlphaMode, u8 PerPixel)
{
	u64 *p_data;
	u64 *p_store;

	gsGlobal->PrimAlpha = AlphaMode;
	gsGlobal->PABE = PerPixel;

	p_data = p_store = gsKit_heap_alloc(gsGlobal, 2, 32, GIF_AD);

	*p_data++ = GIF_TAG_AD(2);
	*p_data++ = GIF_AD;

	*p_data++ = gsGlobal->PABE;
	*p_data++ = GS_PABE;

	*p_data++ = gsGlobal->PrimAlpha;
	*p_data++ = GS_ALPHA_1+gsGlobal->PrimContext;
}
Example #13
0
//---------------------------------------------------------------------------
void g2_line(s16 x0, s16 y0, s16 x1, s16 y1)
{
	x0 += gs_origin_x;
	y0 += gs_origin_y;
	x1 += gs_origin_x;
	y1 += gs_origin_y;

	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 4, 1, 0, 0, 0);

	GIF_DATA_AD(gs_dma_buf, prim,
		GS_PRIM(PRIM_LINE, 0, 0, 0, 0, 0, 0, 0, 0));

	GIF_DATA_AD(gs_dma_buf, rgbaq,
		GS_RGBAQ(g2_col_r, g2_col_g, g2_col_b, 0x80, 0));

	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2(x0<<4, y0<<4, 0));
	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2(x1<<4, y1<<4, 0));

	SEND_GS_PACKET(gs_dma_buf);
}
Example #14
0
//---------------------------------------------------------------------------
void g2_put_pixel(s16 x, s16 y)
{
	x += gs_origin_x;
	y += gs_origin_y;

	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 4, 1, 0, 0, 0);

	GIF_DATA_AD(gs_dma_buf, prim,
		GS_PRIM(PRIM_POINT, 0, 0, 0, 0, 0, 0, 0, 0));

	GIF_DATA_AD(gs_dma_buf, rgbaq,
		GS_RGBAQ(g2_col_r, g2_col_g, g2_col_b, 0x80, 0));

	// The XYZ coordinates are actually floating point numbers between
	// 0 and 4096 represented as unsigned integers where the lowest order
	// four bits are the fractional point. That's why all coordinates are
	// shifted left 4 bits.
	GIF_DATA_AD(gs_dma_buf, xyz2, GS_XYZ2(x<<4, y<<4, 0));

	SEND_GS_PACKET(gs_dma_buf);
}
Example #15
0
// taken from libgraph
void gsKit_set_drawfield(GSGLOBAL *gsGlobal, u8 field)
{
    u64 *p_data;
    u64 *p_store;

    p_data = p_store = gsKit_heap_alloc(gsGlobal, 1 ,16, GIF_AD);

    *p_data++ = GIF_TAG_AD(1);
    *p_data++ = GIF_AD;

    if (field == GS_FIELD_NORMAL) { //Draw both
        *p_data++ = 0;;
    }
    else if (field == GS_FIELD_ODD) { // Draw only odd
        *p_data++ = 2;
    }
    else if (field == GS_FIELD_EVEN) { // Draw only even
        *p_data++ = 3;
    }

    *p_data++ = GS_SCANMSK;
}
Example #16
0
void gsKit_set_clamp(GSGLOBAL *gsGlobal, u8 Preset)
{
	u64 *p_data;
	u64 *p_store;

	if(Preset == GS_CMODE_REPEAT)
	{
		gsGlobal->Clamp->WMS = GS_CMODE_REPEAT;
		gsGlobal->Clamp->WMT = GS_CMODE_REPEAT;
	}
	else if(Preset == GS_CMODE_CLAMP)
	{
		gsGlobal->Clamp->WMS = GS_CMODE_CLAMP;
		gsGlobal->Clamp->WMT = GS_CMODE_CLAMP;
	}
	else if(Preset == GS_CMODE_REGION_CLAMP)
	{
		gsGlobal->Clamp->WMS = GS_CMODE_REGION_CLAMP;
		gsGlobal->Clamp->WMT = GS_CMODE_REGION_CLAMP;
	}
	else if(Preset == GS_CMODE_REGION_REPEAT)
	{
		gsGlobal->Clamp->WMS = GS_CMODE_REGION_REPEAT;
		gsGlobal->Clamp->WMT = GS_CMODE_REGION_REPEAT;
	}

	p_data = p_store = gsKit_heap_alloc(gsGlobal, 1, 16, GIF_AD);

	*p_data++ = GIF_TAG_AD(1);
	*p_data++ = GIF_AD;

	*p_data++ = GS_SETREG_CLAMP(gsGlobal->Clamp->WMS, gsGlobal->Clamp->WMT,
				gsGlobal->Clamp->MINU, gsGlobal->Clamp->MAXU,
				gsGlobal->Clamp->MINV, gsGlobal->Clamp->MAXV);

	*p_data++ = GS_CLAMP_1+gsGlobal->PrimContext;
}
Example #17
0
//---------------------------------------------------------------------------
void g2_out_text(s16 x, s16 y, char *str)
{
char	c;				// current character
u16	*tc;			// current texture coordinates [4]
u16	x0, y0, x1, y1;	// rectangle for current character
u16	w, h;			// width and height of above rectangle

	x += gs_origin_x;
	y += gs_origin_y;

	c = *str;
	while(c)
	{
		// Read the texture coordinates for current character
		tc = &g2_font_tc[c*4];
		x0 = *tc++;
		y0 = *tc++;
		x1 = *tc++;
		y1 = *tc++;
		w  = x1-x0+1;
		h  = y1-y0+1;

		// Draw a sprite with current character mapped onto it
		BEGIN_GS_PACKET(gs_dma_buf);
		GIF_TAG_AD(gs_dma_buf, 6, 1, 0, 0, 0);

		GIF_DATA_AD(gs_dma_buf, tex0_1,
			GS_TEX0(
				g2_fontbuf_addr/256,		// base pointer
				(g2_fontbuf_w)/64,			// width
				0,							// 32bit RGBA
				gs_texture_wh(g2_fontbuf_w),// width
				gs_texture_wh(g2_fontbuf_w),// height
				1,							// RGBA
				TEX_DECAL,					// just overwrite existing pixels
				0,0,0,0,0));
/*
		GIF_DATA_AD(gs_dma_buf, tex1_1,
			GS_TEX1(
				0, 0,
				FILTER_LINEAR,
				FILTER_LINEAR,
				0, 0, 0));

		GIF_DATA_AD(gs_dma_buf, clamp_1, 0x05);
*/
		GIF_DATA_AD(gs_dma_buf, prim,
			GS_PRIM(PRIM_SPRITE,
				0,			// flat shading
				1, 			// texture mapping ON
				0, 1, 0,	// no fog or antialiasing, but use alpha
				1, 			// use UV register for coordinates.
				0,
				0));

		GIF_DATA_AD(gs_dma_buf, uv,    GS_UV(x0<<4, y0<<4));
		GIF_DATA_AD(gs_dma_buf, xyz2,  GS_XYZ2(x<<4, y<<4, 0));
		GIF_DATA_AD(gs_dma_buf, uv,    GS_UV((x1+1)<<4, (y1+1)<<4));
		GIF_DATA_AD(gs_dma_buf, xyz2,  GS_XYZ2(
				(x+w*g2_font_mag)<<4, (y+h*g2_font_mag)<<4, 0));

		SEND_GS_PACKET(gs_dma_buf);

		// Advance drawing position
		x += (w + g2_font_spacing) * g2_font_mag;

		// Get next character
		str++;
		c = *str;
	}
}
Example #18
0
//---------------------------------------------------------------------------
int g2_init(g2_video_mode mode)
{
vmode_t *v;

	v = &(vmodes[mode]);
	cur_mode = v;

	g2_max_x = v->width - 1;
	g2_max_y = v->height - 1;

	g2_view_x0 = 0;
	g2_view_y0 = 0;
	g2_view_x1 = g2_max_x;
	g2_view_y1 = g2_max_y;

	gs_origin_x = 1024;
	gs_origin_y = 1024;

	gs_mem_current = 0;		// nothing allocated yet

	g2_visible_frame = 0;	// display frame 0
	g2_active_frame  = 0;	// draw to frame 0

	// - Initialize the DMA.
	// - Writes a 0 to most of the DMA registers.
	dma_reset();

	// - Sets the RESET bit if the GS CSR register.
	GS_RESET();

#ifndef FLASH
	// - Can someone please tell me what the sync.p
	// instruction does. Synchronizes something :-)
	__asm__("
		sync.p
		nop
	");
#endif

	// - Sets up the GS IMR register (i guess).
	// - The IMR register is used to mask and unmask certain interrupts,
	//   for example VSync and HSync. We'll use this properly in Tutorial 2.
	// - Does anyone have code to do this without using the 0x71 syscall?
	// - I havn't gotten around to looking at any PS2 bios code yet.
	gs_set_imr();

	// - Use syscall 0x02 to setup some video mode stuff.
	// - Pretty self explanatory I think.
	// - Does anyone have code to do this without using the syscall? It looks
	//   like it should only set the SMODE2 register, but if I remove this syscall
	//   and set the SMODE2 register myself, it donesn't work. What else does
	//   syscall 0x02 do?
	gs_set_crtc(NON_INTERLACED, v->ntsc_pal, FRAME);

	// - I havn't attempted to understand what the Alpha parameters can do. They
	//   have been blindly copied from the 3stars demo (although they don't seem
	//   do have any impact in this simple 2D code.
	GS_SET_PMODE(
		0,		// ReadCircuit1 OFF
		1,		// ReadCircuit2 ON
		1,		// Use ALP register for Alpha Blending
		1,		// Alpha Value of ReadCircuit2 for output selection
		0,		// Blend Alpha with the output of ReadCircuit2
		0xFF	// Alpha Value = 1.0
	);
/*
	// - Non needed if we use gs_set_crt()
	GS_SET_SMODE2(
		0,		// Non-Interlaced mode
		1,		// FRAME mode (read every line)
		0		// VESA DPMS Mode = ON		??? please explain ???
	);
*/
	GS_SET_DISPFB2(
		0,				// Frame Buffer base pointer = 0 (Address/8192)
		v->width/64,	// Buffer Width (Pixels/64)
		v->psm,			// Pixel Storage Format
		0,				// Upper Left X in Buffer = 0
		0				// Upper Left Y in Buffer = 0
	);

	// Why doesn't (0, 0) equal the very top-left of the TV?
	GS_SET_DISPLAY2(
		656,		// X position in the display area (in VCK units)
		36,			// Y position in the display area (in Raster units)
		v->magh-1,	// Horizontal Magnification - 1
		0,						// Vertical Magnification = 1x
		v->width*v->magh-1,		// Display area width  - 1 (in VCK units) (Width*HMag-1)
		v->height-1				// Display area height - 1 (in pixels)	  (Height-1)
	);

	GS_SET_BGCOLOR(
		0,	// RED
		0,	// GREEN
		0	// BLUE
	);


	BEGIN_GS_PACKET(gs_dma_buf);
	GIF_TAG_AD(gs_dma_buf, 6, 1, 0, 0, 0);

	// Use drawing parameters from PRIM register
	GIF_DATA_AD(gs_dma_buf, prmodecont, 1);

	// Setup frame buffers. Point to 0 initially.
	GIF_DATA_AD(gs_dma_buf, frame_1,
		GS_FRAME(
			0,					// FrameBuffer base pointer = 0 (Address/8192)
			v->width/64,		// Frame buffer width (Pixels/64)
			v->psm,				// Pixel Storage Format
			0));

	// Save address and advance GS memory pointer by buffer size (in bytes)
	// Do this for both frame buffers.
	g2_frame_addr[0] = gs_mem_current;
	gs_mem_current += v->width * v->height * (v->bpp/8);

	g2_frame_addr[1] = gs_mem_current;
	gs_mem_current += v->width * v->height * (v->bpp/8);

	// Displacement between Primitive and Window coordinate systems.
	GIF_DATA_AD(gs_dma_buf, xyoffset_1,
		GS_XYOFFSET(
			gs_origin_x<<4,
			gs_origin_y<<4));

	// Clip to frame buffer.
	GIF_DATA_AD(gs_dma_buf, scissor_1,
		GS_SCISSOR(
			0,
			g2_max_x,
			0,
			g2_max_y));

	// Create a single 256x128 font buffer
	g2_fontbuf_addr = gs_mem_current;
	gs_mem_current += g2_fontbuf_w * g2_fontbuf_h * (v->bpp/8);

	// Create a texture buffer as big as the screen.
	// Just save the address advance GS memory pointer by buffer size (in bytes)
	// The TEX registers are set later, when drawing.
	g2_texbuf_addr = gs_mem_current;
	gs_mem_current += v->width * v->height * (v->bpp/8);

	// Setup test_1 register to allow transparent texture regions where A=0
	GIF_DATA_AD(gs_dma_buf, test_1,
		GS_TEST(
			1,						// Alpha Test ON
			ATST_NOTEQUAL, 0x00,	// Reject pixels with A=0
			AFAIL_KEEP,				// Don't update frame or Z buffers
			0, 0, 0, 0));			// No Destination Alpha or Z-Buffer Tests

	// Setup the ALPHA_1 register to correctly blend edges of
	// pre-antialiased fonts using Alpha Blending stage.
	// The blending formula is
	//   PIXEL=(SRC-FRAME)*SRC_ALPHA>>7+FRAME
	GIF_DATA_AD(gs_dma_buf, alpha_1,
		GS_ALPHA(
			0,			// A - source
			1, 			// B - frame buffer
			0,			// C - alpha from source
			1, 			// D - frame buffer
			0));		// FIX - not needed

	SEND_GS_PACKET(gs_dma_buf);

	return(1);
}