/* KallistiOS ##version## pvr_init_shutdown.c Copyright (C) 2002, 2004 Megan Potter */ #include "emu/emu.h" #include #include #include #include "dc/pvr.h" #define dbglog(channel, ...) printf(__VA_ARGS__) // #include // #include // #include #include "pvr_internal.h" /* Initialization and shutdown: stuff you should only ever have to do once in your program. */ /* Simpler function which initializes the PVR using 16/16 for the opaque and translucent lists, and 0's for everything else; 512k of vertex buffer. This is equivalent to the old ta_init_defaults() for now. */ int pvr_init_defaults(void) { pvr_init_params_t params = { /* Enable opaque and translucent polygons with size 16 */ { PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_0 }, /* Vertex buffer size 512K */ 512 * 1024, /* No DMA */ 0, /* No FSAA */ 0, /* Translucent Autosort enabled. */ 0, /* Extra OPBs */ 3 }; return pvr_init(¶ms); } /* Initialize the PVR chip to ready status, enabling the specified lists and using the specified parameters; note that bins and vertex buffers come from the texture memory pool! Expects that a 2D mode was initialized already using the vid_* API. */ int pvr_init(pvr_init_params_t *params) { emu_init(); /* If we're already initialized, fail */ if(pvr_state.valid == 1) { dbglog(DBG_WARNING, "pvr: pvr_init called twice!\n"); return -1; } /* Make sure we got valid parameters */ assert(params != NULL); // /* Make sure that a video mode has been initialized */ // assert(vid_mode != NULL); // assert(vid_mode->width != 0 && vid_mode->height != 0); // /* Check for compatibility with 3D stuff */ // if((vid_mode->width % 32) != 0) { // dbglog(DBG_WARNING, "pvr: mode %dx%d isn't usable for 3D (width not multiples of 32)\n", // vid_mode->width, vid_mode->height); // return -1; // } /* Clear out video memory */ // vid_empty(); memset(emu_vram, 0, sizeof(emu_vram)); /* Reset all PVR systems (in case it's still doing something) */ PVR_SET(PVR_RESET, PVR_RESET_ALL); PVR_SET(PVR_RESET, PVR_RESET_NONE); /* Start off with a nice empty structure */ memset((void *)&pvr_state, 0, sizeof(pvr_state)); // Enable DMA if the user wants that. pvr_state.dma_mode = params->dma_enabled; // Copy over FSAA setting. pvr_state.fsaa = params->fsaa_enabled; /* Everything's clear, do the initial buffer pointer setup */ pvr_allocate_buffers(params); // Initialize tile matrices pvr_init_tile_matrices(!!params->autosort_disabled); // Setup all pipeline targets. Yes, this is redundant. :) I just // like to have it explicit. pvr_state.ram_target = 0; pvr_state.ta_target = 0; pvr_state.view_target = 0; pvr_state.list_reg_open = -1; // Sync all the hardware registers with our pipeline state. pvr_sync_view(); pvr_sync_reg_buffer(); // Clear out our stats pvr_state.vbl_count = 0; pvr_state.frame_last_time = 0; pvr_state.buf_start_time = 0; pvr_state.reg_start_time = 0; pvr_state.rnd_start_time = 0; pvr_state.frame_last_len = -1; pvr_state.buf_last_len = -1; pvr_state.reg_last_len = -1; pvr_state.rnd_last_len = -1; pvr_state.vtx_buf_used = 0; pvr_state.vtx_buf_used_max = 0; pvr_state.dr_used = 0; /* If we're on a VGA box, disable vertical smoothing */ if(1 /*vid_mode->cable_type == CT_VGA*/) { #if !defined(DC_TEXCONV) dbglog(DBG_KDEBUG, "pvr: disabling vertical scaling for VGA\n"); #endif if(pvr_state.fsaa) PVR_SET(PVR_SCALER_CFG, 0x10400); else PVR_SET(PVR_SCALER_CFG, 0x400); //TODO: these are some vid_ function? PVR_SET(PVR_FB_SIZE, ((640-1)/2 << 0) | ((480-1) << 10) | (1 << 20 ) ); PVR_SET(PVR_FB_CFG_1, (1<<0) | (0<<1) | (1 << 2)); // PVR_SET(PVR_FB_ADDR); } else { dbglog(DBG_KDEBUG, "pvr: enabling vertical scaling for non-VGA\n"); if(pvr_state.fsaa) PVR_SET(PVR_SCALER_CFG, 0x10401); else PVR_SET(PVR_SCALER_CFG, 0x401); } // TODO: hookup reicast's interrupts here // /* Hook the PVR interrupt events on G2 */ // pvr_state.vbl_handle = vblank_handler_add(pvr_int_handler, NULL); // asic_evt_set_handler(ASIC_EVT_PVR_OPAQUEDONE, pvr_int_handler, NULL); // asic_evt_enable(ASIC_EVT_PVR_OPAQUEDONE, ASIC_IRQ_DEFAULT); // asic_evt_set_handler(ASIC_EVT_PVR_OPAQUEMODDONE, pvr_int_handler, NULL); // asic_evt_enable(ASIC_EVT_PVR_OPAQUEMODDONE, ASIC_IRQ_DEFAULT); // asic_evt_set_handler(ASIC_EVT_PVR_TRANSDONE, pvr_int_handler, NULL); // asic_evt_enable(ASIC_EVT_PVR_TRANSDONE, ASIC_IRQ_DEFAULT); // asic_evt_set_handler(ASIC_EVT_PVR_TRANSMODDONE, pvr_int_handler, NULL); // asic_evt_enable(ASIC_EVT_PVR_TRANSMODDONE, ASIC_IRQ_DEFAULT); // asic_evt_set_handler(ASIC_EVT_PVR_PTDONE, pvr_int_handler, NULL); // asic_evt_enable(ASIC_EVT_PVR_PTDONE, ASIC_IRQ_DEFAULT); // asic_evt_set_handler(ASIC_EVT_PVR_RENDERDONE_TSP, pvr_int_handler, NULL); // asic_evt_enable(ASIC_EVT_PVR_RENDERDONE_TSP, ASIC_IRQ_DEFAULT); #ifdef PVR_RENDER_DBG /* Hook up interrupt handlers for error events */ asic_evt_set_handler(ASIC_EVT_PVR_ISP_OUTOFMEM, pvr_int_handler, NULL); asic_evt_enable(ASIC_EVT_PVR_ISP_OUTOFMEM, ASIC_IRQ_DEFAULT); asic_evt_set_handler(ASIC_EVT_PVR_STRIP_HALT, pvr_int_handler, NULL); asic_evt_enable(ASIC_EVT_PVR_STRIP_HALT, ASIC_IRQ_DEFAULT); asic_evt_set_handler(ASIC_EVT_PVR_OPB_OUTOFMEM, pvr_int_handler, NULL); asic_evt_enable(ASIC_EVT_PVR_OPB_OUTOFMEM, ASIC_IRQ_DEFAULT); asic_evt_set_handler(ASIC_EVT_PVR_TA_INPUT_ERR, pvr_int_handler, NULL); asic_evt_enable(ASIC_EVT_PVR_TA_INPUT_ERR, ASIC_IRQ_DEFAULT); asic_evt_set_handler(ASIC_EVT_PVR_TA_INPUT_OVERFLOW, pvr_int_handler, NULL); asic_evt_enable(ASIC_EVT_PVR_TA_INPUT_OVERFLOW, ASIC_IRQ_DEFAULT); #endif /* 3d-specific parameters; these are all about rendering and nothing to do with setting up the video; some stuff in here is still unknown. */ PVR_SET(PVR_UNK_00A8, 0x15d1c951); /* M (Unknown magic value) */ PVR_SET(PVR_UNK_00A0, 0x00000020); /* M */ PVR_SET(PVR_FB_CFG_2, 0x00000009); /* alpha config */ PVR_SET(PVR_UNK_0110, 0x00093f39); /* M */ PVR_SET(PVR_UNK_0098, 0x00800408 | (params->autosort_disabled?1:0)); /* M */ // this is a hack for refsw limitations PVR_SET(PVR_TEXTURE_CLIP, 0x00000000); /* texture clip distance */ PVR_SET(PVR_SPANSORT_CFG, 0x00000101); /* M */ PVR_SET(PVR_FOG_TABLE_COLOR, 0x007f7f7f); /* Fog table color */ PVR_SET(PVR_FOG_VERTEX_COLOR, 0x007f7f7f); /* Fog vertex color */ PVR_SET(PVR_COLOR_CLAMP_MIN, 0x00000000); /* color clamp min */ PVR_SET(PVR_COLOR_CLAMP_MAX, 0xffffffff); /* color clamp max */ PVR_SET(PVR_UNK_0080, 0x00000007); /* M */ PVR_SET(PVR_CHEAP_SHADOW, 0x00000001); /* cheap shadow */ PVR_SET(PVR_UNK_007C, 0x0027df77); /* M */ PVR_SET(PVR_TEXTURE_MODULO, 0x00000000); /* stride width */ PVR_SET(PVR_FOG_DENSITY, 0x0000ff07); /* fog density */ PVR_SET(PVR_UNK_0118, 0x00008040); /* M */ /* Initialize PVR DMA */ // mutex_init((mutex_t *)&pvr_state.dma_lock, MUTEX_TYPE_NORMAL); pvr_dma_init(); /* Setup our wait-ready semaphore */ sem_init((semaphore_t *)&pvr_state.ready_sem, 1); // TODO: This has been hacked to be 1 from 0 in kos /* Set us as valid and return success */ pvr_state.valid = 1; /* Validate our memory pool */ pvr_mem_reset(); /* This doesn't work right now... */ /*#ifndef NDEBUG dbglog(DBG_KDEBUG, "pvr: free memory is %08lx bytes\n", pvr_mem_available()); #endif*//* !NDEBUG */ return 0; } /* Shut down the PVR chip from ready status, leaving it in 2D mode as it was before the init. */ int pvr_shutdown(void) { if(!pvr_state.valid) return -1; /* Set us invalid */ pvr_state.valid = 0; /* Stop anything that might be going on */ PVR_SET(PVR_RESET, PVR_RESET_ALL); PVR_SET(PVR_RESET, PVR_RESET_NONE); /* Unhook any int handlers */ // vblank_handler_remove(pvr_state.vbl_handle); // asic_evt_remove_handler(ASIC_EVT_PVR_OPAQUEDONE); // asic_evt_disable(ASIC_EVT_PVR_OPAQUEDONE, ASIC_IRQ_DEFAULT); // asic_evt_remove_handler(ASIC_EVT_PVR_OPAQUEMODDONE); // asic_evt_disable(ASIC_EVT_PVR_OPAQUEMODDONE, ASIC_IRQ_DEFAULT); // asic_evt_remove_handler(ASIC_EVT_PVR_TRANSDONE); // asic_evt_disable(ASIC_EVT_PVR_TRANSDONE, ASIC_IRQ_DEFAULT); // asic_evt_remove_handler(ASIC_EVT_PVR_TRANSMODDONE); // asic_evt_disable(ASIC_EVT_PVR_TRANSMODDONE, ASIC_IRQ_DEFAULT); // asic_evt_remove_handler(ASIC_EVT_PVR_PTDONE); // asic_evt_disable(ASIC_EVT_PVR_PTDONE, ASIC_IRQ_DEFAULT); // asic_evt_remove_handler(ASIC_EVT_PVR_RENDERDONE_TSP); // asic_evt_disable(ASIC_EVT_PVR_RENDERDONE_TSP, ASIC_IRQ_DEFAULT); /* Shut down PVR DMA */ pvr_dma_shutdown(); /* Invalidate our memory pool */ pvr_mem_reset(); /* Destroy the semaphore */ sem_destroy((semaphore_t *)&pvr_state.ready_sem); // mutex_destroy((mutex_t *)&pvr_state.dma_lock); // /* Clear video memory */ // vid_empty(); memset(emu_vram, 0, sizeof(emu_vram)); // /* Reset the frame buffer offset */ // vid_waitvbl(); // vid_set_start(0); emu_term(); /* Return success */ return 0; }