mirror of
https://gitlab.com/skmp/dca3-game.git
synced 2025-04-28 21:17:59 +03:00
287 lines
9.1 KiB
C++
287 lines
9.1 KiB
C++
![]() |
/* KallistiOS ##version##
|
||
|
|
||
|
pvr_misc.c
|
||
|
Copyright (C) 2002 Megan Potter
|
||
|
Copyright (C) 2014 Lawrence Sebald
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <assert.h>
|
||
|
#include <string.h>
|
||
|
// #include <arch/timer.h>
|
||
|
#include "dc/pvr.h"
|
||
|
// #include <dc/video.h>
|
||
|
#include "pvr_internal.h"
|
||
|
#include <cstdio>
|
||
|
|
||
|
/*
|
||
|
These are miscellaneous parameters you can set which affect the
|
||
|
rendering process.
|
||
|
*/
|
||
|
|
||
|
/* Set the background plane color (the area of the screen not covered by
|
||
|
any other polygons) */
|
||
|
void pvr_set_bg_color(float r, float g, float b) {
|
||
|
int ir, ig, ib;
|
||
|
|
||
|
ir = (int)(255 * r);
|
||
|
ig = (int)(255 * g);
|
||
|
ib = (int)(255 * b);
|
||
|
|
||
|
pvr_state.bg_color = (ir << 16) | (ig << 8) | (ib << 0);
|
||
|
}
|
||
|
|
||
|
/* Enable/disable cheap shadow mode and set the cheap shadow scale register. */
|
||
|
void pvr_set_shadow_scale(int enable, float scale_value) {
|
||
|
int s = (int)(scale_value * 255);
|
||
|
|
||
|
PVR_SET(PVR_CHEAP_SHADOW, ((!!enable) << 8) | (s & 0xFF));
|
||
|
}
|
||
|
|
||
|
/* Set the Z-Clip value (that is to say the depth of the background layer). */
|
||
|
void pvr_set_zclip(float zc) {
|
||
|
pvr_state.zclip = zc;
|
||
|
}
|
||
|
|
||
|
/* Set a callback to be called before rendering starts */
|
||
|
pvr_before_render_hook_t pvr_set_before_render_callback(pvr_before_render_hook_t callback) {
|
||
|
pvr_before_render_hook_t rv = pvr_state.isp_start_callback;
|
||
|
pvr_state.isp_start_callback = callback;
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/* Return the current VBlank count */
|
||
|
int pvr_get_vbl_count(void) {
|
||
|
return pvr_state.vbl_count;
|
||
|
}
|
||
|
|
||
|
/* Fill in a statistics structure (above) from current data. This
|
||
|
is a super-set of frame count. */
|
||
|
int pvr_get_stats(pvr_stats_t *stat) {
|
||
|
if(!pvr_state.valid)
|
||
|
return -1;
|
||
|
|
||
|
assert(stat != NULL);
|
||
|
|
||
|
stat->enabled_list_mask = pvr_state.lists_enabled;
|
||
|
stat->vbl_count = pvr_state.vbl_count;
|
||
|
stat->frame_last_time = pvr_state.frame_last_len;
|
||
|
stat->reg_last_time = pvr_state.reg_last_len;
|
||
|
stat->rnd_last_time = pvr_state.rnd_last_len;
|
||
|
|
||
|
if(stat->frame_last_time != 0)
|
||
|
stat->frame_rate = 1000000000.0f / stat->frame_last_time;
|
||
|
else
|
||
|
stat->frame_rate = -1.0f;
|
||
|
|
||
|
stat->vtx_buffer_used = pvr_state.vtx_buf_used;
|
||
|
stat->vtx_buffer_used_max = pvr_state.vtx_buf_used_max;
|
||
|
stat->buf_last_time = pvr_state.buf_last_len;
|
||
|
stat->frame_count = pvr_state.frame_count;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int pvr_vertex_dma_enabled(void) {
|
||
|
return pvr_state.dma_mode;
|
||
|
}
|
||
|
|
||
|
/******** INTERNAL STUFF ************************************************/
|
||
|
|
||
|
/* Update statistical counters */
|
||
|
void pvr_sync_stats(int event) {
|
||
|
uint64_t t;
|
||
|
volatile pvr_ta_buffers_t *buf;
|
||
|
|
||
|
if(event == PVR_SYNC_VBLANK) {
|
||
|
pvr_state.vbl_count++;
|
||
|
}
|
||
|
else {
|
||
|
/* Get the current time */
|
||
|
t = 0;// timer_ns_gettime64();
|
||
|
|
||
|
switch(event) {
|
||
|
case PVR_SYNC_REGSTART:
|
||
|
pvr_state.reg_start_time = t;
|
||
|
break;
|
||
|
|
||
|
case PVR_SYNC_REGDONE:
|
||
|
pvr_state.reg_last_len = t - pvr_state.reg_start_time;
|
||
|
|
||
|
buf = pvr_state.ta_buffers + pvr_state.ta_target;
|
||
|
pvr_state.vtx_buf_used = PVR_GET(PVR_TA_VERTBUF_POS) - buf->vertex;
|
||
|
|
||
|
if(pvr_state.vtx_buf_used > pvr_state.vtx_buf_used_max)
|
||
|
pvr_state.vtx_buf_used_max = pvr_state.vtx_buf_used;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case PVR_SYNC_RNDSTART:
|
||
|
pvr_state.rnd_start_time = t;
|
||
|
break;
|
||
|
|
||
|
case PVR_SYNC_RNDDONE:
|
||
|
pvr_state.rnd_last_len = t - pvr_state.rnd_start_time;
|
||
|
break;
|
||
|
|
||
|
case PVR_SYNC_BUFSTART:
|
||
|
pvr_state.buf_start_time = t;
|
||
|
break;
|
||
|
|
||
|
case PVR_SYNC_BUFDONE:
|
||
|
pvr_state.buf_last_len = t - pvr_state.buf_start_time;
|
||
|
break;
|
||
|
|
||
|
case PVR_SYNC_PAGEFLIP:
|
||
|
pvr_state.frame_last_len = t - pvr_state.frame_last_time;
|
||
|
pvr_state.frame_last_time = t;
|
||
|
pvr_state.frame_count++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Synchronize the viewed page with what's in pvr_state */
|
||
|
void pvr_sync_view(void) {
|
||
|
// TODO: present?
|
||
|
//vid_set_start(pvr_state.frame_buffers[pvr_state.view_target].frame);
|
||
|
PVR_SET(PVR_FB_ADDR, pvr_state.frame_buffers[pvr_state.view_target].frame);
|
||
|
}
|
||
|
|
||
|
/* Synchronize the registration buffer with what's in pvr_state */
|
||
|
void pvr_sync_reg_buffer(void) {
|
||
|
volatile pvr_ta_buffers_t *buf;
|
||
|
|
||
|
buf = pvr_state.ta_buffers + pvr_state.ta_target;
|
||
|
|
||
|
/* Reset TA */
|
||
|
//PVR_SET(PVR_RESET, PVR_RESET_TA);
|
||
|
//PVR_SET(PVR_RESET, PVR_RESET_NONE);
|
||
|
|
||
|
/* Set buffer pointers */
|
||
|
PVR_SET(PVR_TA_OPB_START, buf->opb);
|
||
|
PVR_SET(PVR_TA_OPB_INIT, buf->opb + buf->opb_size);
|
||
|
PVR_SET(PVR_TA_OPB_END, buf->opb + buf->opb_size * (1 + buf->opb_overflow_count));
|
||
|
PVR_SET(PVR_TA_VERTBUF_START, buf->vertex);
|
||
|
PVR_SET(PVR_TA_VERTBUF_END, buf->vertex + buf->vertex_size);
|
||
|
|
||
|
/* Misc config parameters */
|
||
|
PVR_SET(PVR_TILEMAT_CFG, pvr_state.tsize_const); /* Tile count: (H/32-1) << 16 | (W/32-1) */
|
||
|
PVR_SET(PVR_OPB_CFG, pvr_state.list_reg_mask); /* List enables */
|
||
|
PVR_SET(PVR_TA_INIT, PVR_TA_INIT_GO); /* Confirm settings */
|
||
|
(void)PVR_GET(PVR_TA_INIT);
|
||
|
|
||
|
#if 0
|
||
|
printf("== SYNC REG BUFFER:\n");
|
||
|
printf("TA_OL_BASE: %08lx\nTA_OL_LIMIT: %08lx\nTA_NEXT_OPB: %08lx\n",
|
||
|
PVR_GET(TA_OL_BASE), PVR_GET(TA_OL_LIMIT), PVR_GET(TA_NEXT_OPB) << 2);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Begin a render operation that has been queued completely (i.e., the
|
||
|
opposite of ta_target) */
|
||
|
void pvr_begin_queued_render(void) {
|
||
|
volatile pvr_ta_buffers_t * tbuf;
|
||
|
volatile pvr_frame_buffers_t * rbuf;
|
||
|
pvr_bkg_poly_t bkg;
|
||
|
b32_uint32 *vrl;
|
||
|
uint32 *bkgdata;
|
||
|
uint32 vert_end;
|
||
|
int i;
|
||
|
int bufn = pvr_state.view_target;
|
||
|
union {
|
||
|
float f;
|
||
|
uint32 i;
|
||
|
} zclip;
|
||
|
|
||
|
/* Get the appropriate buffer */
|
||
|
tbuf = pvr_state.ta_buffers + (pvr_state.ta_target ^ 1);
|
||
|
rbuf = pvr_state.frame_buffers + (bufn ^ 1);
|
||
|
|
||
|
/* Calculate background value for below */
|
||
|
/* Small side note: during setup, the value is originally
|
||
|
0x01203000... I'm thinking that the upper word signifies
|
||
|
the length of the background plane list in dwords
|
||
|
shifted up by 4. */
|
||
|
vert_end = 0x01000000 | ((PVR_GET(PVR_TA_VERTBUF_POS) - tbuf->vertex) << 1);
|
||
|
|
||
|
/* Throw the background data on the end of the TA's list */
|
||
|
bkg.flags1 = 0x90800000; /* These are from libdream.. ought to figure out */
|
||
|
bkg.flags2 = 0x20800440; /* what they mean for sure... heh =) */
|
||
|
bkg.dummy = 0;
|
||
|
bkg.x1 = 0.0f;
|
||
|
bkg.y1 = 480.0f;
|
||
|
bkg.z1 = 0.2f;
|
||
|
bkg.argb1 = pvr_state.bg_color;
|
||
|
bkg.x2 = 0.0f;
|
||
|
bkg.y2 = 0.0f;
|
||
|
bkg.z2 = 0.2f;
|
||
|
bkg.argb2 = pvr_state.bg_color;
|
||
|
bkg.x3 = 640.0f;
|
||
|
bkg.y3 = 480.0f;
|
||
|
bkg.z3 = 0.2f;
|
||
|
bkg.argb3 = pvr_state.bg_color;
|
||
|
bkgdata = (uint32 *)&bkg;
|
||
|
// vrl = (uint32*)(PVR_RAM_BASE | PVR_GET(PVR_TA_VERTBUF_POS));
|
||
|
vrl = (b32_uint32*)(emu_vram + PVR_GET(PVR_TA_VERTBUF_POS));
|
||
|
|
||
|
for(i = 0; i < 15; i++)
|
||
|
vrl[i] = bkgdata[i];
|
||
|
|
||
|
/* Reset the ISP/TSP, just in case */
|
||
|
//PVR_SET(PVR_RESET, PVR_RESET_ISPTSP);
|
||
|
//PVR_SET(PVR_RESET, PVR_RESET_NONE);
|
||
|
|
||
|
/* Finish up rendering the current frame (into the other buffer) */
|
||
|
PVR_SET(PVR_ISP_TILEMAT_ADDR, tbuf->tile_matrix);
|
||
|
PVR_SET(PVR_ISP_VERTBUF_ADDR, tbuf->vertex);
|
||
|
|
||
|
if(!pvr_state.to_texture[bufn])
|
||
|
PVR_SET(PVR_RENDER_ADDR, rbuf->frame);
|
||
|
else {
|
||
|
PVR_SET(PVR_RENDER_ADDR, pvr_state.to_txr_addr[bufn] | (1 << 24));
|
||
|
PVR_SET(PVR_RENDER_ADDR_2, pvr_state.to_txr_addr[bufn] | (1 << 24));
|
||
|
}
|
||
|
|
||
|
PVR_SET(PVR_BGPLANE_CFG, vert_end); /* Bkg plane location */
|
||
|
zclip.f = pvr_state.zclip;
|
||
|
PVR_SET(PVR_BGPLANE_Z, zclip.i);
|
||
|
PVR_SET(PVR_PCLIP_X, pvr_state.pclip_x);
|
||
|
PVR_SET(PVR_PCLIP_Y, pvr_state.pclip_y);
|
||
|
|
||
|
if(!pvr_state.to_texture[bufn])
|
||
|
PVR_SET(PVR_RENDER_MODULO, (pvr_state.w * 2) / 8);
|
||
|
else
|
||
|
PVR_SET(PVR_RENDER_MODULO, pvr_state.to_txr_rp[bufn]);
|
||
|
|
||
|
// XXX Do we _really_ need this every time?
|
||
|
// SETREG(PVR_FB_CFG_2, 0x00000009); /* Alpha mode */
|
||
|
|
||
|
printf("VERBUF_FREE: %d, OPB_FREE: %d\n", PVR_GET(PVR_TA_VERTBUF_END) - PVR_GET(PVR_TA_VERTBUF_POS), PVR_GET(PVR_TA_OPB_END) - PVR_GET(PVR_TA_OPB_POS)*4);
|
||
|
if (!pvr_state.isp_start_callback || pvr_state.isp_start_callback())
|
||
|
PVR_SET(PVR_ISP_START, PVR_ISP_START_GO); /* Start render */
|
||
|
}
|
||
|
|
||
|
void pvr_blank_polyhdr(int type) {
|
||
|
pvr_poly_hdr_t poly;
|
||
|
|
||
|
// Make it.
|
||
|
pvr_blank_polyhdr_buf(type, &poly);
|
||
|
|
||
|
// Submit it
|
||
|
pvr_prim(&poly, sizeof(poly));
|
||
|
}
|
||
|
|
||
|
void pvr_blank_polyhdr_buf(int type, pvr_poly_hdr_t * poly) {
|
||
|
/* Empty it out */
|
||
|
memset(poly, 0, sizeof(pvr_poly_hdr_t));
|
||
|
|
||
|
/* Put in the list type */
|
||
|
poly->cmd = (type << PVR_TA_CMD_TYPE_SHIFT) | 0x80840012;
|
||
|
|
||
|
/* Fill in dummy values */
|
||
|
poly->d1 = poly->d2 = poly->d3 = poly->d4 = 0xffffffff;
|
||
|
|
||
|
}
|