From: quzar <qu...@us...> - 2024-11-17 20:13:59
|
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 99308c534d03c585d4b4aa14ad278e072081300b (commit) via a60375e8ff1fdd99431cfbae34f54a3429d1bd94 (commit) via 43ba9b2e4b1a50b6e7a12bbc58685e5601963260 (commit) via 829d092102cd832b7b5d43ad114d5edff50e7ffc (commit) via 84a66f8d4a06b071365c637a10efd3ac41e90c9f (commit) from 33958108179edd3a73e21ef7437ed9a49b996fd9 (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 99308c534d03c585d4b4aa14ad278e072081300b Author: Paul Cercueil <pa...@cr...> Date: Sun Nov 17 02:17:24 2024 +0100 Make: Avoid complaints from Make about redefined clean rules (#852) Fixes #822. Signed-off-by: Paul Cercueil <pa...@cr...> commit a60375e8ff1fdd99431cfbae34f54a3429d1bd94 Author: Falco Girgis <gyr...@gm...> Date: Fri Nov 15 22:18:48 2024 -0600 Gracefully return 0 for ARM/PVR pre-initted stats. (#830) - Rather than asserting and crashing, which isn't really warranted, modified pvr_mem_available() and snd_mem_available() to gracefully return 0 when called before PVR/Sound RAM has been initialized. - This way profilers and monitors in other threads can still boot up and show proper stats while things are being initialized, rather than simply crashing in debug builds and returning garbage in release builds. commit 43ba9b2e4b1a50b6e7a12bbc58685e5601963260 Author: Paul Cercueil <pa...@cr...> Date: Sat Nov 16 04:49:09 2024 +0100 Add support for Store Queues with MMU (#779) * mmu: Add function mmu_enabled() This function can be used to know whether or not the MMU is in use. * mmu: Support address translation of store queues Reserve the last two TLB entries and map a 1 MiB page each for use with the SQ area. Add the function mmu_set_sq_addr(), which will overwrite the physical address that the SQ area points to in the TLB. * sq: Update sq_lock() prototype to work with MMU Change its prototype: it now returns a pointer, which is the translated address of the source pointer. In non-MMU use, it's returns the same value as SQ_MASK_DEST(src). When MMU is enabled, sq_lock() will reset the address translation for the SQ memory area, and convert the source address as an offset to that memory area, making it possible to use SQs when MMU is enabled. The caveat is that we only map one megabyte of SQ memory area for simplicity, and therefore the SQ memory window is reduced. This should be fine though, as apart from e.g. a whole-VRAM clear, nobody will ever need such a big window. * sq: Update sq_cpy() to work with MMU When using the MMU the SQ area is a 1 MiB page, so we must not copy data outside this area. * sq: Update sq_set32() to work with MMU When using the MMU the SQ area is a 1 MiB page, so we must not copy data outside this area. * mmu: Remove mmu_disable() / mmu_restore() Now that SQs work with MMU, those two functions aren't useful anymore and can be dropped. --------- Signed-off-by: Paul Cercueil <pa...@cr...> commit 829d092102cd832b7b5d43ad114d5edff50e7ffc Author: Paul Cercueil <pa...@cr...> Date: Sat Nov 9 03:16:26 2024 +0100 Add new regfield.h header, and clean up PVR code (#839) * Add new <kos/regfield.h> include This new include will provide macros that are useful when dealing with register fields. * pvr.h: Add new macros for the TA command fields These new macros will replace the old ones, which are now deprecated. * pvr: Simplify code using the new register field macros Use the new <dc/regfield.h> to clean up the context->header compilation functions in pvr_prim.c and pvr_misc.c. commit 84a66f8d4a06b071365c637a10efd3ac41e90c9f Author: Donald Haase <qu...@ya...> Date: Thu Nov 7 23:04:00 2024 -0500 Revert "Update position when playing (#764)" (#846) This reverts commit 41c37da08d71af6ee29f3b5195897971ee718485. The change had left a gap by which the position will not get updated for it's last run it will no longer be playing. ----------------------------------------------------------------------- Summary of changes: Makefile.prefab | 4 +- include/kos.h | 1 + include/kos/regfield.h | 55 ++ kernel/Makefile | 2 +- kernel/arch/dreamcast/hardware/pvr/pvr_mem.c | 3 +- kernel/arch/dreamcast/hardware/pvr/pvr_misc.c | 2 +- kernel/arch/dreamcast/hardware/pvr/pvr_prim.c | 591 ++++++--------------- kernel/arch/dreamcast/hardware/sq.c | 122 +++-- kernel/arch/dreamcast/include/arch/mmu.h | 22 +- kernel/arch/dreamcast/include/dc/pvr.h | 55 +- kernel/arch/dreamcast/include/dc/sq.h | 5 +- kernel/arch/dreamcast/kernel/mmu.c | 29 +- kernel/arch/dreamcast/sound/arm/main.c | 7 +- .../arch/dreamcast/sound/arm/stream.drv.prebuilt | Bin 3312 -> 3272 bytes kernel/arch/dreamcast/sound/snd_mem.c | 3 +- kernel/exports/Makefile | 4 +- 16 files changed, 382 insertions(+), 523 deletions(-) create mode 100644 include/kos/regfield.h diff --git a/Makefile.prefab b/Makefile.prefab index adcba60e..dc9a3e86 100644 --- a/Makefile.prefab +++ b/Makefile.prefab @@ -15,9 +15,11 @@ endif defaultall: $(OBJS) subdirs -cp $(OBJS) $(KOS_BASE)/$(BUILD_TARGET)/build/ -clean: clean_subdirs +defaultclean: clean_subdirs -rm -f $(OBJS) *.bck +clean: defaultclean + include $(KOS_BASE)/Makefile.rules diff --git a/include/kos.h b/include/kos.h index 4731e25f..f2d48638 100644 --- a/include/kos.h +++ b/include/kos.h @@ -59,6 +59,7 @@ __BEGIN_DECLS #include <kos/string.h> #include <kos/init.h> #include <kos/oneshot_timer.h> +#include <kos/regfield.h> #include <arch/arch.h> #include <arch/cache.h> diff --git a/include/kos/regfield.h b/include/kos/regfield.h new file mode 100644 index 00000000..f3e66ed3 --- /dev/null +++ b/include/kos/regfield.h @@ -0,0 +1,55 @@ +/* KallistiOS ##version## + + kos/compiler.h + Copyright (C) 2024 Paul Cercueil + + Macros to extract / insert bit fields +*/ + +/** \file kos/regfield.h + \brief Macros to help dealing with register fields. + \ingroup kernel + + \author Paul Cercueil +*/ + +#ifndef __KOS_REGFIELD_H +#define __KOS_REGFIELD_H + +#include <sys/cdefs.h> +__BEGIN_DECLS + +/** \brief Create a mask with a bit set + + \param bit The bit to set (from 0 to 31) + \return A 32-bit mask with the corresponding bit set + */ +#define BIT(bit) (1u << (bit)) + +/** \brief Create a mask with a range of bits set + + \param h The high bit of the range to set, included + \param l The low bit of the range to set, included + \return A 32-bit mask with the corresponding bits set + */ +#define GENMASK(h, l) ((0xffffffff << (l)) & (0xffffffff >> (31 - (h)))) + +/** \brief Extract a field value from a variable + + \param var The 32-bit variable containing the field + \param field A 32-bit mask that corresponds to the field + \return The value of the field (shifted) + */ +#define FIELD_GET(var, field) \ + (((var) & (field)) >> __builtin_ctz(field)) + +/** \brief Prepare a field with a given value + + \param field A 32-bit mask that corresponds to the field + \param value The value to be put in the field + */ +#define FIELD_PREP(field, value) \ + (((value) << __builtin_ctz(field)) & (field)) + +__END_DECLS +#endif /* __KOS_REGFIELD_H */ diff --git a/kernel/Makefile b/kernel/Makefile index 5a438c65..62dfa91c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -26,7 +26,7 @@ stubs/arch_export_stubs.c: arch/$(KOS_ARCH)/exports-$(KOS_SUBARCH).txt include $(KOS_BASE)/Makefile.prefab -clean: clean_subdirs +clean: defaultclean rm -f build/*.o rm -f build/libc/*.o rm -f romdisk/*.o diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_mem.c b/kernel/arch/dreamcast/hardware/pvr/pvr_mem.c index 19fdf92c..eeddf80c 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_mem.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_mem.c @@ -179,7 +179,8 @@ static uint32 pvr_mem_available_int(void) { } uint32 pvr_mem_available(void) { - CHECK_MEM_BASE; + if(!pvr_mem_base) + return 0; return pvr_mem_available_int() + (PVR_RAM_INT_TOP - (uint32)pvr_mem_base); diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c b/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c index b484dc99..e2efa10a 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_misc.c @@ -263,7 +263,7 @@ void pvr_blank_polyhdr_buf(int type, pvr_poly_hdr_t * poly) { memset(poly, 0, sizeof(pvr_poly_hdr_t)); /* Put in the list type */ - poly->cmd = (type << PVR_TA_CMD_TYPE_SHIFT) | 0x80840012; + poly->cmd = FIELD_PREP(PVR_TA_CMD_TYPE, type) | 0x80840012; /* Fill in dummy values */ poly->d1 = poly->d2 = poly->d3 = poly->d4 = 0xffffffff; diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_prim.c b/kernel/arch/dreamcast/hardware/pvr/pvr_prim.c index 55952e5e..2558b1e8 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_prim.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_prim.c @@ -21,148 +21,78 @@ /* Compile a polygon context into a polygon header */ void pvr_poly_compile(pvr_poly_hdr_t *dst, const pvr_poly_cxt_t *src) { - int u, v; uint32_t txr_base; /* Temporary variables we can read-write-modify, since we cannot do so from within the SQs, and we want to be able to compile this header from a PVR DR API submission target. */ - uint32_t cmd, mode[3]; + uint32_t mode2, mode3; /* Basically we just take each parameter, clip it, shift it into place, and OR it into the final result. */ /* The base values for CMD */ - cmd = PVR_CMD_POLYHDR; - - if(src->txr.enable == PVR_TEXTURE_ENABLE) - cmd |= 8; - - /* Or in the list type, shading type, color and UV formats */ - cmd |= (src->list_type << PVR_TA_CMD_TYPE_SHIFT) & PVR_TA_CMD_TYPE_MASK; - cmd |= (src->fmt.color << PVR_TA_CMD_CLRFMT_SHIFT) & PVR_TA_CMD_CLRFMT_MASK; - cmd |= (src->gen.shading << PVR_TA_CMD_SHADE_SHIFT) & PVR_TA_CMD_SHADE_MASK; - cmd |= (src->fmt.uv << PVR_TA_CMD_UVFMT_SHIFT) & PVR_TA_CMD_UVFMT_MASK; - cmd |= (src->gen.clip_mode << PVR_TA_CMD_USERCLIP_SHIFT) & PVR_TA_CMD_USERCLIP_MASK; - cmd |= (src->fmt.modifier << PVR_TA_CMD_MODIFIER_SHIFT) & PVR_TA_CMD_MODIFIER_MASK; - cmd |= (src->gen.modifier_mode << PVR_TA_CMD_MODIFIERMODE_SHIFT) & PVR_TA_CMD_MODIFIERMODE_MASK; - cmd |= (src->gen.specular << PVR_TA_CMD_SPECULAR_SHIFT) & PVR_TA_CMD_SPECULAR_MASK; - - dst->cmd = cmd; + dst->cmd = PVR_CMD_POLYHDR + | FIELD_PREP(PVR_TA_CMD_TXRENABLE, src->txr.enable) + | FIELD_PREP(PVR_TA_CMD_TYPE, src->list_type) + | FIELD_PREP(PVR_TA_CMD_CLRFMT, src->fmt.color) + | FIELD_PREP(PVR_TA_CMD_SHADE, src->gen.shading) + | FIELD_PREP(PVR_TA_CMD_UVFMT, src->fmt.uv) + | FIELD_PREP(PVR_TA_CMD_USERCLIP, src->gen.clip_mode) + | FIELD_PREP(PVR_TA_CMD_MODIFIER, src->fmt.modifier) + | FIELD_PREP(PVR_TA_CMD_MODIFIERMODE, src->gen.modifier_mode) + | FIELD_PREP(PVR_TA_CMD_SPECULAR, src->gen.specular); /* Polygon mode 1 */ - mode[0] = (src->depth.comparison << PVR_TA_PM1_DEPTHCMP_SHIFT) & PVR_TA_PM1_DEPTHCMP_MASK; - mode[0] |= (src->gen.culling << PVR_TA_PM1_CULLING_SHIFT) & PVR_TA_PM1_CULLING_MASK; - mode[0] |= (src->depth.write << PVR_TA_PM1_DEPTHWRITE_SHIFT) & PVR_TA_PM1_DEPTHWRITE_MASK; - mode[0] |= (src->txr.enable << PVR_TA_PM1_TXRENABLE_SHIFT) & PVR_TA_PM1_TXRENABLE_MASK; - - dst->mode1 = mode[0]; + dst->mode1 = FIELD_PREP(PVR_TA_PM1_DEPTHCMP, src->depth.comparison) + | FIELD_PREP(PVR_TA_PM1_CULLING, src->gen.culling) + | FIELD_PREP(PVR_TA_PM1_DEPTHWRITE, src->depth.write) + | FIELD_PREP(PVR_TA_PM1_TXRENABLE, src->txr.enable); /* Polygon mode 2 */ - mode[1] = (src->blend.src << PVR_TA_PM2_SRCBLEND_SHIFT) & PVR_TA_PM2_SRCBLEND_MASK; - mode[1] |= (src->blend.dst << PVR_TA_PM2_DSTBLEND_SHIFT) & PVR_TA_PM2_DSTBLEND_MASK; - mode[1] |= (src->blend.src_enable << PVR_TA_PM2_SRCENABLE_SHIFT) & PVR_TA_PM2_SRCENABLE_MASK; - mode[1] |= (src->blend.dst_enable << PVR_TA_PM2_DSTENABLE_SHIFT) & PVR_TA_PM2_DSTENABLE_MASK; - mode[1] |= (src->gen.fog_type << PVR_TA_PM2_FOG_SHIFT) & PVR_TA_PM2_FOG_MASK; - mode[1] |= (src->gen.color_clamp << PVR_TA_PM2_CLAMP_SHIFT) & PVR_TA_PM2_CLAMP_MASK; - mode[1] |= (src->gen.alpha << PVR_TA_PM2_ALPHA_SHIFT) & PVR_TA_PM2_ALPHA_MASK; + mode2 = FIELD_PREP(PVR_TA_PM2_SRCBLEND, src->blend.src) + | FIELD_PREP(PVR_TA_PM2_DSTBLEND, src->blend.dst) + | FIELD_PREP(PVR_TA_PM2_SRCENABLE, src->blend.src_enable) + | FIELD_PREP(PVR_TA_PM2_DSTENABLE, src->blend.dst_enable) + | FIELD_PREP(PVR_TA_PM2_FOG, src->gen.fog_type) + | FIELD_PREP(PVR_TA_PM2_CLAMP, src->gen.color_clamp) + | FIELD_PREP(PVR_TA_PM2_ALPHA, src->gen.alpha); if(src->txr.enable == PVR_TEXTURE_DISABLE) { - dst->mode2 = mode[1]; - mode[2] = 0; - dst->mode3 = mode[2]; + mode3 = 0; } else { - mode[1] |= (src->txr.alpha << PVR_TA_PM2_TXRALPHA_SHIFT) & PVR_TA_PM2_TXRALPHA_MASK; - mode[1] |= (src->txr.uv_flip << PVR_TA_PM2_UVFLIP_SHIFT) & PVR_TA_PM2_UVFLIP_MASK; - mode[1] |= (src->txr.uv_clamp << PVR_TA_PM2_UVCLAMP_SHIFT) & PVR_TA_PM2_UVCLAMP_MASK; - mode[1] |= (src->txr.filter << PVR_TA_PM2_FILTER_SHIFT) & PVR_TA_PM2_FILTER_MASK; - mode[1] |= (src->txr.mipmap_bias << PVR_TA_PM2_MIPBIAS_SHIFT) & PVR_TA_PM2_MIPBIAS_MASK; - mode[1] |= (src->txr.env << PVR_TA_PM2_TXRENV_SHIFT) & PVR_TA_PM2_TXRENV_MASK; - - switch(src->txr.width) { - case 8: - u = 0; - break; - case 16: - u = 1; - break; - case 32: - u = 2; - break; - case 64: - u = 3; - break; - case 128: - u = 4; - break; - case 256: - u = 5; - break; - case 512: - u = 6; - break; - case 1024: - u = 7; - break; - default: - assert_msg(0, "Invalid texture U size"); - u = 0; - break; - } - - switch(src->txr.height) { - case 8: - v = 0; - break; - case 16: - v = 1; - break; - case 32: - v = 2; - break; - case 64: - v = 3; - break; - case 128: - v = 4; - break; - case 256: - v = 5; - break; - case 512: - v = 6; - break; - case 1024: - v = 7; - break; - default: - assert_msg(0, "Invalid texture V size"); - v = 0; - break; - } - - mode[1] |= (u << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_MASK; - mode[1] |= (v << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK; - - dst->mode2 = mode[1]; - - /* Polygon mode 3 */ - mode[2] = (src->txr.mipmap << PVR_TA_PM3_MIPMAP_SHIFT) & PVR_TA_PM3_MIPMAP_MASK; - mode[2] |= (src->txr.format << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK; + assert_msg(__builtin_popcount(src->txr.width) == 1 + && src->txr.width <= 1024, "Invalid texture U size"); + assert_msg(__builtin_popcount(src->txr.height) == 1 + && src->txr.height <= 1024, "Invalid texture V size"); + + mode2 |= FIELD_PREP(PVR_TA_PM2_TXRALPHA, src->txr.alpha) + | FIELD_PREP(PVR_TA_PM2_UVFLIP, src->txr.uv_flip) + | FIELD_PREP(PVR_TA_PM2_UVCLAMP, src->txr.uv_clamp) + | FIELD_PREP(PVR_TA_PM2_FILTER, src->txr.filter) + | FIELD_PREP(PVR_TA_PM2_MIPBIAS, src->txr.mipmap_bias) + | FIELD_PREP(PVR_TA_PM2_TXRENV, src->txr.env) + | FIELD_PREP(PVR_TA_PM2_USIZE, __builtin_ctz(src->txr.width) - 3) + | FIELD_PREP(PVR_TA_PM2_VSIZE, __builtin_ctz(src->txr.height) - 3); /* Convert the texture address */ txr_base = (uint32_t)src->txr.base; txr_base = (txr_base & 0x00fffff8) >> 3; - mode[2] |= txr_base; - dst->mode3 = mode[2]; + /* Polygon mode 3 */ + mode3 = FIELD_PREP(PVR_TA_PM3_MIPMAP, src->txr.mipmap) + | src->txr.format + | txr_base; } + dst->mode2 = mode2; + dst->mode3 = mode3; + if(src->fmt.modifier && src->gen.modifier_mode) { /* If we're affected by a modifier volume, silently promote the header to the one that is affected by a modifier volume. */ - dst->d1 = mode[1]; - dst->d2 = mode[2]; + dst->d1 = mode2; + dst->d2 = mode3; } else { dst->d1 = 0xffffffff; @@ -338,145 +268,75 @@ void pvr_sprite_cxt_txr(pvr_sprite_cxt_t *dst, pvr_list_t list, } void pvr_sprite_compile(pvr_sprite_hdr_t *dst, const pvr_sprite_cxt_t *src) { - int u, v; - uint32_t txr_base; - uint32_t cmd, mode[3]; + uint32_t txr_base, mode2, mode3; /* Basically we just take each parameter, clip it, shift it into place, and OR it into the final result. */ /* The base values for CMD */ - cmd = PVR_CMD_SPRITE; - - if(src->txr.enable == PVR_TEXTURE_ENABLE) - cmd |= 8; - - /* Or in the list type, clipping mode, and UV formats */ - cmd |= (src->list_type << PVR_TA_CMD_TYPE_SHIFT) & PVR_TA_CMD_TYPE_MASK; - cmd |= (PVR_UVFMT_16BIT << PVR_TA_CMD_UVFMT_SHIFT) & PVR_TA_CMD_UVFMT_MASK; - cmd |= (src->gen.clip_mode << PVR_TA_CMD_USERCLIP_SHIFT) & PVR_TA_CMD_USERCLIP_MASK; - cmd |= (src->gen.specular << PVR_TA_CMD_SPECULAR_SHIFT) & PVR_TA_CMD_SPECULAR_MASK; - - dst->cmd = cmd; + dst->cmd = PVR_CMD_SPRITE + | FIELD_PREP(PVR_TA_CMD_TXRENABLE, src->txr.enable) + | FIELD_PREP(PVR_TA_CMD_TYPE, src->list_type) + | FIELD_PREP(PVR_TA_CMD_UVFMT, PVR_UVFMT_16BIT) + | FIELD_PREP(PVR_TA_CMD_USERCLIP, src->gen.clip_mode) + | FIELD_PREP(PVR_TA_CMD_SPECULAR, src->gen.specular); /* Polygon mode 1 */ - mode[0] = (src->depth.comparison << PVR_TA_PM1_DEPTHCMP_SHIFT) & PVR_TA_PM1_DEPTHCMP_MASK; - mode[0] |= (src->gen.culling << PVR_TA_PM1_CULLING_SHIFT) & PVR_TA_PM1_CULLING_MASK; - mode[0] |= (src->depth.write << PVR_TA_PM1_DEPTHWRITE_SHIFT) & PVR_TA_PM1_DEPTHWRITE_MASK; - mode[0] |= (src->txr.enable << PVR_TA_PM1_TXRENABLE_SHIFT) & PVR_TA_PM1_TXRENABLE_MASK; - - dst->mode1 = mode[0]; + dst->mode1 = FIELD_PREP(PVR_TA_PM1_DEPTHCMP, src->depth.comparison) + | FIELD_PREP(PVR_TA_PM1_CULLING, src->gen.culling) + | FIELD_PREP(PVR_TA_PM1_DEPTHWRITE, src->depth.write) + | FIELD_PREP(PVR_TA_PM1_TXRENABLE, src->txr.enable); /* Polygon mode 2 */ - mode[1] = (src->blend.src << PVR_TA_PM2_SRCBLEND_SHIFT) & PVR_TA_PM2_SRCBLEND_MASK; - mode[1] |= (src->blend.dst << PVR_TA_PM2_DSTBLEND_SHIFT) & PVR_TA_PM2_DSTBLEND_MASK; - mode[1] |= (src->blend.src_enable << PVR_TA_PM2_SRCENABLE_SHIFT) & PVR_TA_PM2_SRCENABLE_MASK; - mode[1] |= (src->blend.dst_enable << PVR_TA_PM2_DSTENABLE_SHIFT) & PVR_TA_PM2_DSTENABLE_MASK; - mode[1] |= (src->gen.fog_type << PVR_TA_PM2_FOG_SHIFT) & PVR_TA_PM2_FOG_MASK; - mode[1] |= (src->gen.color_clamp << PVR_TA_PM2_CLAMP_SHIFT) & PVR_TA_PM2_CLAMP_MASK; - mode[1] |= (src->gen.alpha << PVR_TA_PM2_ALPHA_SHIFT) & PVR_TA_PM2_ALPHA_MASK; + mode2 = FIELD_PREP(PVR_TA_PM2_SRCBLEND, src->blend.src) + | FIELD_PREP(PVR_TA_PM2_DSTBLEND, src->blend.dst) + | FIELD_PREP(PVR_TA_PM2_SRCENABLE, src->blend.src_enable) + | FIELD_PREP(PVR_TA_PM2_DSTENABLE, src->blend.dst_enable) + | FIELD_PREP(PVR_TA_PM2_FOG, src->gen.fog_type) + | FIELD_PREP(PVR_TA_PM2_CLAMP, src->gen.color_clamp) + | FIELD_PREP(PVR_TA_PM2_ALPHA, src->gen.alpha); if(src->txr.enable == PVR_TEXTURE_DISABLE) { - dst->mode2 = mode[1]; - dst->mode3 = 0; + mode3 = 0; } else { - mode[1] |= (src->txr.alpha << PVR_TA_PM2_TXRALPHA_SHIFT) & PVR_TA_PM2_TXRALPHA_MASK; - mode[1] |= (src->txr.uv_flip << PVR_TA_PM2_UVFLIP_SHIFT) & PVR_TA_PM2_UVFLIP_MASK; - mode[1] |= (src->txr.uv_clamp << PVR_TA_PM2_UVCLAMP_SHIFT) & PVR_TA_PM2_UVCLAMP_MASK; - mode[1] |= (src->txr.filter << PVR_TA_PM2_FILTER_SHIFT) & PVR_TA_PM2_FILTER_MASK; - mode[1] |= (src->txr.mipmap_bias << PVR_TA_PM2_MIPBIAS_SHIFT) & PVR_TA_PM2_MIPBIAS_MASK; - mode[1] |= (src->txr.env << PVR_TA_PM2_TXRENV_SHIFT) & PVR_TA_PM2_TXRENV_MASK; - - switch(src->txr.width) { - case 8: - u = 0; - break; - case 16: - u = 1; - break; - case 32: - u = 2; - break; - case 64: - u = 3; - break; - case 128: - u = 4; - break; - case 256: - u = 5; - break; - case 512: - u = 6; - break; - case 1024: - u = 7; - break; - default: - assert_msg(0, "Invalid texture U size"); - u = 0; - break; - } - - switch(src->txr.height) { - case 8: - v = 0; - break; - case 16: - v = 1; - break; - case 32: - v = 2; - break; - case 64: - v = 3; - break; - case 128: - v = 4; - break; - case 256: - v = 5; - break; - case 512: - v = 6; - break; - case 1024: - v = 7; - break; - default: - assert_msg(0, "Invalid texture V size"); - v = 0; - break; - } - - mode[1] |= (u << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_MASK; - mode[1] |= (v << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK; - - dst->mode2 = mode[1]; - - /* Polygon mode 3 */ - mode[2] = (src->txr.mipmap << PVR_TA_PM3_MIPMAP_SHIFT) & PVR_TA_PM3_MIPMAP_MASK; - mode[2] |= (src->txr.format << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK; + assert_msg(__builtin_popcount(src->txr.width) == 1 + && src->txr.width <= 1024, "Invalid texture U size"); + assert_msg(__builtin_popcount(src->txr.height) == 1 + && src->txr.height <= 1024, "Invalid texture V size"); + + mode2 |= FIELD_PREP(PVR_TA_PM2_TXRALPHA, src->txr.alpha) + | FIELD_PREP(PVR_TA_PM2_UVFLIP, src->txr.uv_flip) + | FIELD_PREP(PVR_TA_PM2_UVCLAMP, src->txr.uv_clamp) + | FIELD_PREP(PVR_TA_PM2_FILTER, src->txr.filter) + | FIELD_PREP(PVR_TA_PM2_MIPBIAS, src->txr.mipmap_bias) + | FIELD_PREP(PVR_TA_PM2_TXRENV, src->txr.env) + | FIELD_PREP(PVR_TA_PM2_USIZE, __builtin_ctz(src->txr.width) - 3) + | FIELD_PREP(PVR_TA_PM2_VSIZE, __builtin_ctz(src->txr.height) - 3); + /* Convert the texture address */ txr_base = (uint32_t)src->txr.base; txr_base = (txr_base & 0x00fffff8) >> 3; - mode[2] |= txr_base; - dst->mode3 = mode[2]; + /* Polygon mode 3 */ + mode3 = FIELD_PREP(PVR_TA_PM3_MIPMAP, src->txr.mipmap) ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |