From: ljsebald <ljs...@us...> - 2023-12-29 02:17:17
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via e1c2a4a3124fb40019c1dd4857e0f4a5d1641339 (commit) from b8a7ada874b94303dca9288ecb0457ef1083051b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e1c2a4a3124fb40019c1dd4857e0f4a5d1641339 Author: Ruslan Rostovtsev <sw...@21...> Date: Fri Dec 29 09:16:54 2023 +0700 Fixes and improvements for Store Queues, Sound and PVR. (#385) * Fixed snd_pcm16_split_sq(). Also few minor fixes for streams. * Minor fixes for SPU memload, memread and memset. * Added dcache_wback_sq() and fix sq_set32(). * Apply suggestions from code review * Updated authors and remove unused declaration. Also fix suggestions. * Re-design Store Queues i/f, improved PVR SQ, ... - Fixed PVR DMA bus selection. - Do not disable IRQ due SQ transfer over G2 bus. * Manage Store Queues for PVR Direct Rendering. * Added sq_flush() and hide QACR0/1 regs. * Re-organize PVR memory destination. Add DMA over Root bus. * Added pvr_sq_set32() and some fixes. * Fixed PVR examples with Direct Render. * Fixed SET_QACR_REGS for TA bus. * Get back single destination for SQ. Also don't wait SQ on lock. * Added spu_memset_sq() and minor fixes. * Updated YUV examples. * Improved bus selection for TA->VRAM. * Updated description of PVR and TA memory addresses. Also remove rootbus/sysbus because need implement CH0 PVR i/f DMA first. * Use pvr_sq_load() for pvr textures. Also minor fixes. * Updated yuv420 example to use SQ better. * Fixed PVR Direct Rendering. And removed unused param from PVR state. ----------------------------------------------------------------------- Summary of changes: examples/dreamcast/parallax/bubbles/bubbles.c | 2 +- .../pvrmark_strips_direct/pvrmark_strips_direct.c | 2 +- .../dreamcast/pvr/yuv_converter/YUV420/yuv420.c | 45 +++---- .../dreamcast/pvr/yuv_converter/YUV422/yuv422.c | 18 +-- kernel/arch/dreamcast/exports-naomi.txt | 5 + kernel/arch/dreamcast/exports-pristine.txt | 5 + kernel/arch/dreamcast/hardware/pvr/pvr_dma.c | 106 +++++++++++++--- .../dreamcast/hardware/pvr/pvr_init_shutdown.c | 1 + kernel/arch/dreamcast/hardware/pvr/pvr_internal.h | 3 +- kernel/arch/dreamcast/hardware/pvr/pvr_scene.c | 25 +++- kernel/arch/dreamcast/hardware/pvr/pvr_texture.c | 13 +- kernel/arch/dreamcast/hardware/spu.c | 52 +++++--- kernel/arch/dreamcast/hardware/sq.c | 100 ++++++---------- kernel/arch/dreamcast/include/arch/cache.h | 8 ++ kernel/arch/dreamcast/include/dc/pvr.h | 133 +++++++++++++++++---- kernel/arch/dreamcast/include/dc/sound/sfxmgr.h | 3 + kernel/arch/dreamcast/include/dc/sound/sound.h | 1 + kernel/arch/dreamcast/include/dc/spu.h | 16 ++- kernel/arch/dreamcast/include/dc/sq.h | 109 ++++++----------- kernel/arch/dreamcast/sound/snd_iface.c | 4 +- kernel/arch/dreamcast/sound/snd_pcm_split.s | 58 +-------- kernel/arch/dreamcast/sound/snd_sfxmgr.c | 1 + kernel/arch/dreamcast/sound/snd_stream.c | 86 ++++++++++--- 23 files changed, 484 insertions(+), 312 deletions(-) diff --git a/examples/dreamcast/parallax/bubbles/bubbles.c b/examples/dreamcast/parallax/bubbles/bubbles.c index 0290b64..303ad90 100644 --- a/examples/dreamcast/parallax/bubbles/bubbles.c +++ b/examples/dreamcast/parallax/bubbles/bubbles.c @@ -99,7 +99,7 @@ static void sphere_frame_opaque(void) { pvr_list_begin(PVR_LIST_OP_POLY); /* Setup our Direct Render state: pick a store queue and setup QACR0/1 */ - pvr_dr_init(dr_state); + pvr_dr_init(&dr_state); plx_mat3d_identity(); plx_mat3d_translate(0.0f, 0.0f, -12.0f); diff --git a/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c b/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c index c9c3eda..62af9a2 100644 --- a/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c +++ b/examples/dreamcast/pvr/pvrmark_strips_direct/pvrmark_strips_direct.c @@ -87,7 +87,7 @@ void do_frame(void) { pvr_list_begin(PVR_LIST_OP_POLY); pvr_prim(&hdr, sizeof(hdr)); - pvr_dr_init(dr_state); + pvr_dr_init(&dr_state); x = getnum(1024); nextnum(); diff --git a/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c b/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c index 970c72f..da41464 100644 --- a/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c +++ b/examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c @@ -1,6 +1,7 @@ /* KallistiOS ##version## examples/dreamcast/pvr/yuv_converter/YUV420/yuv420.c Copyright (C) 2023 Andy Barajas + Copyright (C) 2023 Ruslan Rostovtsev This example shows how to use TA's YUV converter for YUV420p format. A sample YUV420p image in the romdisk was made via ffmpeg: @@ -181,19 +182,26 @@ static int setup_pvr(void) { static void convert_YUV420_to_YUV422_texture(void) { int i, j, index, x_blk, y_blk; + size_t dummies = (BYTE_SIZE_FOR_16x16_BLOCK * + ((PVR_TEXTURE_WIDTH >> 4) - (FRAME_TEXTURE_WIDTH >> 4))) >> 5; + uint32_t *db = (uint32_t *)SQ_MASK_DEST_ADDR(PVR_TA_YUV_CONV); + uint8_t *u_block = (uint8_t *)SQ_MASK_DEST_ADDR(PVR_TA_YUV_CONV); + uint8_t *v_block = (uint8_t *)SQ_MASK_DEST_ADDR(PVR_TA_YUV_CONV + 64); + uint8_t *y_block = (uint8_t *)SQ_MASK_DEST_ADDR(PVR_TA_YUV_CONV + 128); - unsigned char u_block[64] __attribute__((aligned(32))); - unsigned char v_block[64] __attribute__((aligned(32))); - unsigned char y_block[256] __attribute__((aligned(32))); + sq_lock((void *)PVR_TA_YUV_CONV); for(y_blk = 0; y_blk < FRAME_TEXTURE_HEIGHT; y_blk += 16) { for(x_blk = 0; x_blk < FRAME_TEXTURE_WIDTH; x_blk += 16) { - + /* U data for 16x16 pixels */ for(i = 0; i < 8; ++i) { index = (y_blk / 2 + i) * (FRAME_TEXTURE_WIDTH / 2) + (x_blk / 2); *((uint64_t*)&u_block[i * 8]) = *((uint64_t*)&u_plane[index]); + if(!((i + 1) & 3)) { + sq_flush(&u_block[i * 8]); + } } /* V data for 16x16 pixels */ @@ -201,6 +209,9 @@ static void convert_YUV420_to_YUV422_texture(void) { index = (y_blk / 2 + i) * (FRAME_TEXTURE_WIDTH / 2) + (x_blk / 2); *((uint64_t*)&v_block[i * 8]) = *((uint64_t*)&v_plane[index]); + if(!((i + 1) & 3)) { + sq_flush(&v_block[i * 8]); + } } /* Y data for 4 (8x8 pixels) */ @@ -210,27 +221,21 @@ static void convert_YUV420_to_YUV422_texture(void) { x_blk + (i % 2 * 8); *((uint64_t*)&y_block[i * 64 + j * 8]) = *((uint64_t*)&y_plane[index]); + if(!((j + 1) & 3)) { + sq_flush(&y_block[i * 64 + j * 8]); + } } } - - // dcache_flush_range((uint32_t)u_block, 64); - // pvr_dma_yuv_conv( (void*)u_block, 64, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)u_block, 64); - - // dcache_flush_range((uint32_t)v_block, 64); - // pvr_dma_yuv_conv( (void*)v_block, 64, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)v_block, 64); - - // dcache_flush_range((uint32_t)y_block, 256); - // pvr_dma_yuv_conv( (void*)y_block, 256, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)y_block, 256); } - /* Send dummies if frame texture width doesn't match pvr texture width */ - sq_set((void *)PVR_TA_YUV_CONV, 0, - BYTE_SIZE_FOR_16x16_BLOCK * - ((PVR_TEXTURE_WIDTH >> 4) - (FRAME_TEXTURE_WIDTH >> 4))); + for(i = 0; i < dummies; ++i) { + db[i] = db[i + 1] = db[i + 2] = db[i + 3] = + db[i + 4] = db[i + 5] = db[i + 6] = db[i + 7] = 0; + sq_flush(&db[i]); + } } + + sq_unlock(); } static void show_image(void) { diff --git a/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c b/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c index 9d8fb48..a1bd803 100644 --- a/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c +++ b/examples/dreamcast/pvr/yuv_converter/YUV422/yuv422.c @@ -213,33 +213,33 @@ static void convert_YUV422_to_YUV422_texture(void) { // dcache_flush_range((uint32_t)u_block, 64); // pvr_dma_yuv_conv( (void*)u_block, 64, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)u_block, 64); + pvr_sq_load((void *)0, (void *)u_block, 64, PVR_DMA_YUV); // dcache_flush_range((uint32_t)v_block, 64); // pvr_dma_yuv_conv( (void*)v_block, 64, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)v_block, 64); + pvr_sq_load((void *)0, (void *)v_block, 64, PVR_DMA_YUV); // dcache_flush_range((uint32_t)y_block, 128); // pvr_dma_yuv_conv( (void*)y_block, 128, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)y_block, 128); + pvr_sq_load((void *)0, (void *)y_block, 128, PVR_DMA_YUV); // dcache_flush_range((uint32_t)(u_block+64), 64); // pvr_dma_yuv_conv( (void*)(u_block+64), 64, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)(u_block+64), 64); + pvr_sq_load((void *)0, (void *)(u_block+64), 64, PVR_DMA_YUV); // dcache_flush_range((uint32_t)(v_block+64), 64); // pvr_dma_yuv_conv( (void*)(v_block+64), 64, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)(v_block+64), 64); + pvr_sq_load((void *)0, (void *)(v_block+64), 64, PVR_DMA_YUV); // dcache_flush_range((uint32_t)(y_block+128), 128); // pvr_dma_yuv_conv( (void*)(y_block+128), 128, 1, NULL, 0); - sq_cpy((void *)PVR_TA_YUV_CONV, (void *)(y_block+128), 128); + pvr_sq_load((void *)0, (void *)(y_block+128), 128, PVR_DMA_YUV); } /* Send dummies if frame texture width doesn't match pvr texture width */ - sq_set((void *)PVR_TA_YUV_CONV, 0, - BYTE_SIZE_FOR_16x16_BLOCK * - ((PVR_TEXTURE_WIDTH >> 4) - (FRAME_TEXTURE_WIDTH >> 4))); + pvr_sq_set32((void *)PVR_TA_YUV_CONV, 0, + BYTE_SIZE_FOR_16x16_BLOCK * + ((PVR_TEXTURE_WIDTH >> 4) - (FRAME_TEXTURE_WIDTH >> 4)), PVR_DMA_YUV); } } diff --git a/kernel/arch/dreamcast/exports-naomi.txt b/kernel/arch/dreamcast/exports-naomi.txt index 7f7a5c3..181b33c 100644 --- a/kernel/arch/dreamcast/exports-naomi.txt +++ b/kernel/arch/dreamcast/exports-naomi.txt @@ -78,6 +78,7 @@ spu_memload spu_memload_sq spu_memread spu_memset +spu_memset_sq spu_dma_transfer spu_reset_chans spu_enable @@ -92,6 +93,7 @@ sq_set16 sq_set32 sq_lock sq_unlock +sq_wait # Sound snd_mem_init @@ -185,6 +187,9 @@ pvr_txr_load_dma pvr_dma_ready pvr_dma_load_ta pvr_dma_yuv_conv +pvr_sq_load +pvr_sq_set16 +pvr_sq_set32 pvr_fog_table_color pvr_fog_vertex_color pvr_fog_far_depth diff --git a/kernel/arch/dreamcast/exports-pristine.txt b/kernel/arch/dreamcast/exports-pristine.txt index e655d0f..6b88062 100644 --- a/kernel/arch/dreamcast/exports-pristine.txt +++ b/kernel/arch/dreamcast/exports-pristine.txt @@ -121,6 +121,7 @@ spu_memload spu_memload_sq spu_memread spu_memset +spu_memset_sq spu_dma_transfer spu_reset_chans spu_enable @@ -135,6 +136,7 @@ sq_set16 sq_set32 sq_lock sq_unlock +sq_wait # Sound snd_mem_init @@ -228,6 +230,9 @@ pvr_txr_load_dma pvr_dma_ready pvr_dma_load_ta pvr_dma_yuv_conv +pvr_sq_load +pvr_sq_set16 +pvr_sq_set32 pvr_fog_table_color pvr_fog_vertex_color pvr_fog_far_depth diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c b/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c index 716dfc5..639e492 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c @@ -1,9 +1,11 @@ /* KallistiOS ##version## pvr_dma.c - Copyright (C)2002 Roger Cattermole - Copyright (C)2004 Megan Potter - Copyright (C)2023 Andy Barajas + Copyright (C) 2002 Roger Cattermole + Copyright (C) 2004 Megan Potter + Copyright (C) 2023 Andy Barajas + Copyright (C) 2023 Ruslan Rostovtsev + http://www.boob.co.uk */ @@ -12,6 +14,7 @@ #include <dc/pvr.h> #include <dc/asic.h> #include <dc/dmac.h> +#include <dc/sq.h> #include <kos/thread.h> #include <kos/sem.h> @@ -62,18 +65,38 @@ static void pvr_dma_irq_hnd(uint32_t code) { } } -int pvr_dma_transfer(void *src, uintptr_t dest, size_t count, int type, - int block, pvr_dma_callback_t callback, void *cbdata) { - uint32_t src_addr = ((uint32_t)src); - uint32_t dest_addr; +static uintptr_t pvr_dest_addr(uintptr_t dest, int type) { + uintptr_t dest_addr; /* Send the data to the right place */ - if(type == PVR_DMA_TA) - dest_addr = (dest & 0xFFFFFF) | PVR_TA_INPUT; - else if(type == PVR_DMA_YUV) - dest_addr = (dest & 0xFFFFFF) | PVR_TA_YUV_CONV; - else - dest_addr = (dest & 0xFFFFFF) | PVR_TA_TEX_MEM; + if(type == PVR_DMA_TA) { + dest_addr = ((uintptr_t)dest & 0xffffff) | PVR_TA_INPUT; + } + else if(type == PVR_DMA_YUV) { + dest_addr = ((uintptr_t)dest & 0xffffff) | PVR_TA_YUV_CONV; + } + else if(type == PVR_DMA_VRAM64) { + dest_addr = ((uintptr_t)dest & 0xffffff) | PVR_TA_TEX_MEM; + } + else if(type == PVR_DMA_VRAM32) { + dest_addr = ((uintptr_t)dest & 0xffffff) | PVR_TA_TEX_MEM_32; + } + else if(type == PVR_DMA_VRAM64_SB) { + dest_addr = ((uintptr_t)dest & 0xffffff) | PVR_RAM_BASE_64_P0; + } + else if(type == PVR_DMA_VRAM32_SB) { + dest_addr = ((uintptr_t)dest & 0xffffff) | PVR_RAM_BASE_32_P0; + } + else { + dest_addr = dest; + } + + return dest_addr; +} + +int pvr_dma_transfer(void *src, uintptr_t dest, size_t count, int type, + int block, pvr_dma_callback_t callback, void *cbdata) { + uintptr_t src_addr = ((uintptr_t)src); /* Check for 32-byte alignment */ if(src_addr & 0x1F) { @@ -109,8 +132,7 @@ int pvr_dma_transfer(void *src, uintptr_t dest, size_t count, int type, return -1; } - pvr_dma[PVR_LMMODE0] = type == PVR_DMA_VRAM64 ? 0 : 1; - pvr_dma[PVR_STATE] = dest_addr; + pvr_dma[PVR_STATE] = pvr_dest_addr(dest, type); pvr_dma[PVR_LEN] = count; pvr_dma[PVR_DST] = 0x1; @@ -149,6 +171,12 @@ void pvr_dma_init(void) { dma_callback = NULL; dma_cbdata = 0; + /* Use 2x32-bit TA->VRAM buses for PVR_TA_TEX_MEM */ + pvr_dma[PVR_LMMODE0] = 0; + + /* Use single 32-bit TA->VRAM bus for PVR_TA_TEX_MEM_32 */ + pvr_dma[PVR_LMMODE1] = 1; + /* Hook the necessary interrupts */ asic_evt_set_handler(ASIC_EVT_PVR_DMA, pvr_dma_irq_hnd); asic_evt_enable(ASIC_EVT_PVR_DMA, ASIC_IRQ_DEFAULT); @@ -165,3 +193,51 @@ void pvr_dma_shutdown(void) { asic_evt_set_handler(ASIC_EVT_PVR_DMA, NULL); sem_destroy(&dma_done); } + +/* Copies n bytes from src to PVR dest, dest must be 32-byte aligned */ +void *pvr_sq_load(void *dest, const void *src, size_t n, int type) { + void *dma_area_ptr; + + if(pvr_dma[PVR_DST] != 0) { + dbglog(DBG_ERROR, "pvr_sq_load: PVR DMA has not finished\n"); + errno = EINPROGRESS; + return NULL; + } + + dma_area_ptr = (void *)pvr_dest_addr((uintptr_t)dest, type); + sq_cpy(dma_area_ptr, src, n); + + return dest; +} + +/* Fills n bytes at PVR dest with 16-bit c, dest must be 32-byte aligned */ +void *pvr_sq_set16(void *dest, uint32_t c, size_t n, int type) { + void *dma_area_ptr; + + if(pvr_dma[PVR_DST] != 0) { + dbglog(DBG_ERROR, "pvr_sq_set16: PVR DMA has not finished\n"); + errno = EINPROGRESS; + return NULL; + } + + dma_area_ptr = (void *)pvr_dest_addr((uintptr_t)dest, type); + sq_set16(dma_area_ptr, c, n); + + return dest; +} + +/* Fills n bytes at PVR dest with 32-bit c, dest must be 32-byte aligned */ +void *pvr_sq_set32(void *dest, uint32_t c, size_t n, int type) { + void *dma_area_ptr; + + if(pvr_dma[PVR_DST] != 0) { + dbglog(DBG_ERROR, "pvr_sq_set32: PVR DMA has not finished\n"); + errno = EINPROGRESS; + return NULL; + } + + dma_area_ptr = (void *)pvr_dest_addr((uintptr_t)dest, type); + sq_set32(dma_area_ptr, c, n); + + return dest; +} diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_init_shutdown.c b/kernel/arch/dreamcast/hardware/pvr/pvr_init_shutdown.c index 06c0596..317568d 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_init_shutdown.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_init_shutdown.c @@ -119,6 +119,7 @@ int pvr_init(pvr_init_params_t *params) { 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(vid_mode->cable_type == CT_VGA) { diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_internal.h b/kernel/arch/dreamcast/hardware/pvr/pvr_internal.h index 85ec9c7..9cfba93 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_internal.h +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_internal.h @@ -223,8 +223,7 @@ typedef struct { // Output address for to-texture mode uint32 to_txr_addr[2]; - // Number of additional OPBs to allocate, allowing more geometry per tile. - uint32 opb_overflow_count; + uint32 dr_used; } pvr_state_t; /* There will be exactly one of these in KOS (in pvr_globals.c) */ diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_scene.c b/kernel/arch/dreamcast/hardware/pvr/pvr_scene.c index e4135da..0b897ba 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_scene.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_scene.c @@ -176,6 +176,11 @@ int pvr_list_finish(void) { #endif /* !NDEBUG */ if(!pvr_state.dma_mode) { + /* Release Store Queues if they are used */ + if(pvr_state.dr_used) { + pvr_dr_finish(); + } + /* In case we haven't sent anything in this list, send a dummy */ pvr_blank_polyhdr(pvr_state.list_reg_open); @@ -183,7 +188,7 @@ int pvr_list_finish(void) { pvr_state.lists_closed |= (1 << pvr_state.list_reg_open); /* Send an EOL marker */ - sq_set32((void *)PVR_TA_INPUT, 0, 32); + pvr_sq_set32((void *)0, 0, 32, PVR_DMA_TA); } pvr_state.list_reg_open = -1; @@ -203,7 +208,7 @@ int pvr_prim(void * data, int size) { if(!pvr_state.dma_mode) { /* Send the data */ - sq_cpy((void *)PVR_TA_INPUT, data, size); + pvr_sq_load((void *)0, data, size, PVR_DMA_TA); } else { return pvr_list_prim(pvr_state.list_reg_open, data, size); @@ -227,6 +232,17 @@ int pvr_list_prim(pvr_list_t list, void * data, int size) { return 0; } +void pvr_dr_init(pvr_dr_state_t *vtx_buf_ptr) { + *vtx_buf_ptr = 0; + sq_lock((void *)PVR_TA_INPUT); + pvr_state.dr_used = 1; +} + +void pvr_dr_finish(void) { + pvr_state.dr_used = 0; + sq_unlock(); +} + int pvr_list_flush(pvr_list_t list) { (void)list; @@ -242,6 +258,11 @@ int pvr_scene_finish(void) { int i, o; volatile pvr_dma_buffers_t * b; + /* Release Store Queues if they are used */ + if(pvr_state.dr_used) { + pvr_dr_finish(); + } + // If we're in DMA mode, then this works a little differently... if(pvr_state.dma_mode) { // DBG(("pvr_scene_finish(dma -> %d)\n", pvr_state.ram_target)); diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_texture.c b/kernel/arch/dreamcast/hardware/pvr/pvr_texture.c index c2dad74..8fb435f 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_texture.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_texture.c @@ -21,10 +21,11 @@ /* Load raw texture data from an SH-4 buffer into PVR RAM */ void pvr_txr_load(void * src, pvr_ptr_t dst, uint32 count) { - if(count % 4) - count = (count & 0xfffffffc) + 4; + if(count & 3) { + count = (count + 4) & ~3; + } - sq_cpy((uint32 *)dst, (uint32 *)src, count); + pvr_sq_load((uint32 *)dst, (uint32 *)src, count, PVR_DMA_VRAM64); } /* Linear/iterative twiddling algorithm from Marcus' tatest */ @@ -194,14 +195,10 @@ void pvr_txr_load_kimg(kos_img_t *img, pvr_ptr_t dst, uint32 flags) { mutex_unlock((mutex_t *)&pvr_state.dma_lock); } ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |