From eaf0155978c5e596a0a285bbb22300342a4101b3 Mon Sep 17 00:00:00 2001 From: FIXME <> Date: Sat, 28 Jun 2003 19:31:07 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'glide-devel- branch'. --- Device3Dfx/3dfx_driver.c | 807 +++++++ Device3Dfx/Makefile | 110 + glide2x/cvg/glide/oem/oeminit.h | 93 + glide2x/cvg/glide/src/cpudetect.c | 48 + glide2x/cvg/glide/src/fxglide.h | 2394 ++++++++++++++++++++ glide2x/h3/glide/src/fxglide.h | 3384 +++++++++++++++++++++++++++++ glide2x/h3/glide/src/gsplash.c | 1015 +++++++++ glide2x/h3/glide/src/xdraw2.S | 258 +++ glide2x/h3/minihwc/fxhwc.h | 49 + glide2x/makefile.linux | 62 + 10 files changed, 8220 insertions(+) create mode 100644 Device3Dfx/3dfx_driver.c create mode 100644 Device3Dfx/Makefile create mode 100644 glide2x/cvg/glide/oem/oeminit.h create mode 100644 glide2x/cvg/glide/src/cpudetect.c create mode 100644 glide2x/cvg/glide/src/fxglide.h create mode 100644 glide2x/h3/glide/src/fxglide.h create mode 100644 glide2x/h3/glide/src/gsplash.c create mode 100644 glide2x/h3/glide/src/xdraw2.S create mode 100644 glide2x/h3/minihwc/fxhwc.h create mode 100644 glide2x/makefile.linux diff --git a/Device3Dfx/3dfx_driver.c b/Device3Dfx/3dfx_driver.c new file mode 100644 index 0000000..16efeda --- /dev/null +++ b/Device3Dfx/3dfx_driver.c @@ -0,0 +1,807 @@ +/* + + /dev/3dfx device for 2.x kernels with MTRR settings enabled. + + Compile with : + + gcc -O2 -DMODULE -D__KERNEL__ -I/usr/src/linux/include -pipe + -fno-strength-reduce -malign-loops=2 -malign-jumps=2 + -malign-functions=2 -c -o 3dfx.o 3dfx_driver.c + + Add -D__SMP__ if you're running of an multi-processor system. + Add -DHAVE_MTRR if you have and want MTRR settings. + Add -g -Wall -Wstrict-prototypes -DDEBUG, if you are debugging. + + Original by Daryll Straus. + Port to 2.1 kernel by Jon Taylor. + setmtrr_3dfx() added by Jens Axboe. + Combining 2.0 and 2.1/2.2 kernels into one rpm, + resetmtrr_3df(), and using correct pci calls for + 2.1/2.2 kernels by Carlo Wood. + + ChangeLog + + 2002/05/05 Guillem Jover + + * Re-included VOODOO pci id, accidentally removed in last patch, + thanks to Jan Kuipers to point this out. + + 2002/01/29 Guillem Jover + + * Fixed bug when compiling for 2.4 kernels with modversions. + * Added devfs support. + * Added MODULE_* declarations. + * Cleaned detection code. + + 2000/02/04 Joseph Kain + + * Updated Carlo Woord's email address. + + 1999/12/22 Joseph Kain + + * Support for new VMA structure in Kernels 2.3.14 and higher. + This patch is based on Dieter Nuetzel's work. + + 1999/11/09 Joseph Kain + + * Made cards static to remove conflict with hisax ISDN driver. + + 1998/10/30 Carlo Wood + + * Re-included module versions (this source was based on the + source by Jon Taylor which was based on an older version + by Daryll Straus. I now included the later changes made + by Daryll in this source too). + * Use pci_find_device for 2.1/2.2 kernels instead of the old + pcibios_find_device. Idem pci_present(). + + 1998/10/21 Carlo Wood + + * Fixed compile bugs related to 2.0 kernels. + + 1998/10/21 Carlo Wood + + * `struct file_operations' was changed as of kernel 2.1.118, + fixed this module to also work with versions > 2.1.117. + + * Machines that don't have mtrr still need . + + 1998/10/20 Carlo Wood + + * Finally fixed in init_module() the right way. This time I tested + it too (it now really works). + + * Added resetmtrr_3dfx() to clean up the MTRR settings when the + module is unloaded. This is not really necessary but its clean. + It allows to compare using this device WITH MTRR with another + method WITHOUT MTRR, without being confused by sticky MTRR settings + for instance. + + 1998/10/18 Carlo Wood + + * Forgot the '== -EBUSY' in init_module(), causing the registration of + character device to always fail. You need to reboot if you tried + the previous version (if there is junk in `cat /proc/devices' major 107). + + 1998/10/18 Carlo Wood + + * struct file_operations fops_3dfx was initialized wrong: + `release_3dfx' was put on the place of `fsync', causing weird + behaviour :). + + * Several warning fixes. + + * setmtrr_3dfx did not always return a value, and the value was + ignored, effectively ignoring errors returned by mtrr_add(). + + */ + +/* Include this first as it defines things that affect the kernel headers */ +#include +#include + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#define KERNEL_MIN_VER(a,b,c) (LINUX_VERSION_CODE >= KERNEL_VERSION(a,b,c)) + +#if !KERNEL_MIN_VER (2, 1, 115) +/* It might work with smaller kernels, but I never tested that */ +#error "Upgrade your kernel" +#endif + +#ifdef MODULE +#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) +#define MODVERSIONS +#endif +#ifdef MODVERSIONS +#include +#endif +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#if KERNEL_MIN_VER(2,3,46) || defined(DEVFS_SUPPORT) +#include +#endif +#include +#include +#include +#include +#include + +#include +#ifdef HAVE_MTRR +#include +#endif + +#define MAJOR_3DFX 107 +#define DEVICE_VOODOO 0 + +#define PCI_VENDOR_ID_LINUX 0x0 +#define PCI_DEVICE_ID_LINUX 0x2 +#define PCI_COMMAND_LINUX 0x4 +#define PCI_REVISION_ID_LINUX 0x8 +#define PCI_BASE_ADDRESS_0_LINUX 0x10 +#define PCI_BASE_ADDRESS_1_LINUX 0x14 +#define SST1_PCI_SPECIAL1_LINUX 0x40 +#define SST1_PCI_SPECIAL2_LINUX 0x44 +#define SST1_PCI_SPECIAL3_LINUX 0x48 +#define SST1_PCI_SPECIAL4_LINUX 0x54 + +#define VGA_INPUT_STATUS_1C 0x3DA +#define VGA_MISC_OUTPUT_READ 0x3cc +#define VGA_MISC_OUTPUT_WRITE 0x3c2 +#define SC_INDEX 0x3c4 +#define SC_DATA 0x3c5 + +#ifndef PCI_VENDOR_ID_3DFX +#define PCI_VENDOR_ID_3DFX 0x121a +#endif + +#ifndef PCI_VENDOR_ID_ALLIANCE +#define PCI_VENDOR_ID_ALLIANCE 0x1142 +#endif + +#ifndef PCI_DEVICE_ID_3DFX_VOODOO2 +#define PCI_DEVICE_ID_3DFX_VOODOO2 2 +#endif + +#ifndef PCI_DEVICE_ID_ALLIANCE_AT3D +#define PCI_DEVICE_ID_ALLIANCE_AT3D 0x643d +#endif + +#ifndef PCI_DEVICE_ID_3DFX_BANSHEE +#define PCI_DEVICE_ID_3DFX_BANSHEE 3 +#endif + +#ifndef PCI_DEVICE_ID_3DFX_VOODOO3 +#define PCI_DEVICE_ID_3DFX_VOODOO3 5 +#endif + +static struct pci_card { + unsigned short vendor; + unsigned short device; +} pci_card_list[] = { + {PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO}, + {PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2}, + {PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D}, + {PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE}, + {PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3} +}; + +#ifdef DEBUG +#define DEBUGMSG(x) printk x +#else +#define DEBUGMSG(x) +#endif + +/* This macro is for accessing vma->vm_offset or vma->vm_pgoff depending + * on kernel version */ +#if !KERNEL_MIN_VER(2, 3, 14) +#define VM_OFFSET(vma) (vma->vm_offset) +#else +#define VM_OFFSET(vma) (vma->vm_pgoff << PAGE_SHIFT) +#endif + +struct pioData_t { + short port; + short size; + int device; + void *value; +}; + +struct cardInfo_t { + int vendor; + int type; + int addr0; + int addr1; + unsigned char bus; + unsigned char dev; + struct file *curFile; +#ifdef HAVE_MTRR + int mtrr_buf; + int mtrr_ctl; +#endif +}; + +typedef struct pioData_t pioData; +typedef struct cardInfo_t cardInfo; + +#ifdef MODULE +void cleanup_module(void); +#endif + +#define MAXCARDS 16 + +static cardInfo cards[MAXCARDS]; +static int numCards = 0; +#if KERNEL_MIN_VER(2,3,46) || defined(DEVFS_SUPPORT) +static devfs_handle_t devfs_handle; +#endif + +static void findCardType(int vendor, int device) +{ + struct pci_dev *dev = NULL; + while (numCards < MAXCARDS && (dev = pci_find_device(vendor, device, dev))) { + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cards[numCards].addr0); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &cards[numCards].addr1); + cards[numCards].bus = dev->bus->number; + cards[numCards].dev = dev->devfn; + + cards[numCards].addr0 &= ~0xF; + cards[numCards].addr1 &= ~0xF; + cards[numCards].vendor = vendor; + cards[numCards].type = device; + cards[numCards].curFile = 0; + + DEBUGMSG(("3dfx: board vendor %d type %d located at %x/%x bus %d dev %d\n", + vendor, device, cards[numCards].addr0, cards[numCards].addr1, cards[numCards].bus, cards[numCards].dev)); + + ++numCards; + } +} + +static int findCards(void) +{ + int i; + if (!pci_present()) + return 0; + numCards = 0; + for (i = 0; i < (sizeof(pci_card_list)/sizeof(struct pci_card)); i++) + findCardType(pci_card_list[i].vendor, pci_card_list[i].device); + return numCards; +} + +static int open_3dfx(struct inode *inode, struct file *file) +{ + DEBUGMSG(("3dfx: Entering open_3dfx\n")); + if (!numCards) { + printk("3dfx: No 3Dfx cards found\n"); + return -ENODEV; + } + MOD_INC_USE_COUNT; + return 0; +} + +static int release_3dfx(struct inode *inode, struct file *file) +{ + int i; + + DEBUGMSG(("3dfx: Entering release_3dfx\n")); + for (i = 0; i < numCards; ++i) + if (cards[i].curFile == file) + cards[i].curFile = 0; + MOD_DEC_USE_COUNT; + + return 0; +} + +static int mmap_3dfx(struct file *file, struct vm_area_struct *vma) +{ + size_t len; + int i; + + DEBUGMSG(("3dfx: Entering mmap_3dfx\n")); + for (i = 0; i < numCards; ++i) { + if ((cards[i].addr0 == VM_OFFSET(vma)) || + (cards[i].addr1 == VM_OFFSET(vma))) + break; + } + if (i == numCards) { + DEBUGMSG(("3dfx: Couldn't match address %lx to a card\n", + VM_OFFSET(vma))); + return -EPERM; + } + /* This one is a special case, the macro doesn't help */ +#if !KERNEL_MIN_VER(2, 3, 14) + if ((vma->vm_offset) & ~PAGE_MASK) { + DEBUGMSG(("3dfx: Map request not page aligned\n")); + return -ENXIO; + } +#else + if ((vma->vm_pgoff) & ~PAGE_MASK) { + DEBUGMSG(("3dfx: Map request not page aligned\n")); + return -ENXIO; + } +#endif + len = vma->vm_end - vma->vm_start; + if ((len < 0) || (len > 0x2000000)) { + DEBUGMSG(("3dfx: Invalid mapping size requested\n")); + return -EINVAL; + } +#if defined(__i386__) + pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; +#endif + if (remap_page_range(vma->vm_start, VM_OFFSET(vma), len, + vma->vm_page_prot)) { + DEBUGMSG(("3dfx: Page remap failed\n")); + return -EAGAIN; + } + return 0; +} + +static int doQueryBoards(void) +{ + return numCards; +} + +static int doQueryFetch(pioData *desc) +{ + int retval; + char retchar; + short retword; + int retlong; + + if (desc->device < 0 || desc->device >= numCards) + return -EINVAL; + if ((retval = verify_area(VERIFY_WRITE, desc->value, desc->size))) + return retval; + switch (desc->port) { + case PCI_VENDOR_ID_LINUX: + if (desc->size != 2) + return -EINVAL; + copy_to_user(desc->value, &cards[desc->device].vendor, desc->size); + return 0; + case PCI_DEVICE_ID_LINUX: + if (desc->size != 2) + return -EINVAL; + copy_to_user(desc->value, &cards[desc->device].type, desc->size); + return 0; + case PCI_BASE_ADDRESS_0_LINUX: + if (desc->size != 4) + return -EINVAL; + copy_to_user(desc->value, &cards[desc->device].addr0, desc->size); + return 0; + case PCI_BASE_ADDRESS_1_LINUX: + if (desc->size != 4) + return -EINVAL; + copy_to_user(desc->value, &cards[desc->device].addr1, desc->size); + return 0; + case SST1_PCI_SPECIAL1_LINUX: + if (desc->size != 4) + return -EINVAL; + break; + case PCI_REVISION_ID: + if (desc->size != 1) + return -EINVAL; + break; + case SST1_PCI_SPECIAL4_LINUX: + if (desc->size != 4) + return -EINVAL; + break; + default: + return -EINVAL; + } + switch (desc->size) { + case 1: + pcibios_read_config_byte(cards[desc->device].bus, cards[desc->device].dev, desc->port, &retchar); + copy_to_user(desc->value, &retchar, 1); + break; + case 2: + pcibios_read_config_word(cards[desc->device].bus, cards[desc->device].dev, desc->port, &retword); + copy_to_user(desc->value, &retword, 2); + break; + case 4: + pcibios_read_config_dword(cards[desc->device].bus, cards[desc->device].dev, desc->port, &retlong); + copy_to_user(desc->value, &retlong, 4); + break; + default: + return -EINVAL; + } + return 0; +} + +static int doQueryUpdate(pioData *desc) +{ + int retval; + int preval; + int mask; + char retchar; + short retword; + int retlong; + + if (desc->device < 0 || desc->device >= numCards) + return -EINVAL; + if ((retval = verify_area(VERIFY_WRITE, desc->value, desc->size))) + return retval; + switch (desc->port) { + case PCI_COMMAND_LINUX: + if (desc->size != 2) + return -EINVAL; + break; + case SST1_PCI_SPECIAL1_LINUX: + if (desc->size != 4) + return -EINVAL; + break; + case SST1_PCI_SPECIAL2_LINUX: + if (desc->size != 4) + return -EINVAL; + break; + case SST1_PCI_SPECIAL3_LINUX: + if (desc->size != 4) + return -EINVAL; + break; + case SST1_PCI_SPECIAL4_LINUX: + if (desc->size != 4) + return -EINVAL; + break; + default: + return -EINVAL; + } + pcibios_read_config_dword(cards[desc->device].bus, cards[desc->device].dev, desc->port & ~0x3, &retval); + switch (desc->size) { + case 1: + copy_from_user(&retchar, desc->value, 1); + preval = retchar << (8 * (desc->port & 0x3)); + mask = 0xFF << (8 * (desc->port & 0x3)); + break; + case 2: + copy_from_user(&retword, desc->value, 2); + preval = retword << (8 * (desc->port & 0x3)); + mask = 0xFFFF << (8 * (desc->port & 0x3)); + break; + case 4: + copy_from_user(&retlong, desc->value, 4); + preval = retlong; + mask = ~0; + break; + default: + return -EINVAL; + } + retval = (retval & ~mask) | preval; + pcibios_write_config_dword(cards[desc->device].bus, cards[desc->device].dev, desc->port, retval); + return 0; +} + +static int doQuery(unsigned int cmd, unsigned long arg) +{ + pioData desc; + int retval; + + if (_IOC_NR(cmd) == 2) + return doQueryBoards(); + if ((retval = verify_area(VERIFY_READ, (void *)arg, sizeof(pioData)))) + return retval; + copy_from_user(&desc, (void *)arg, sizeof(pioData)); + if (_IOC_NR(cmd) == 3) + return doQueryFetch(&desc); + if (_IOC_NR(cmd) == 4) + return doQueryUpdate(&desc); + return -EINVAL; +} + +static int doPIORead(pioData *desc) +{ + int retval; + char retchar; + + if ((retval = verify_area(VERIFY_WRITE, desc->value, desc->size))) + return retval; + switch (desc->port) { + case VGA_INPUT_STATUS_1C: + break; + case SC_INDEX: + break; + case SC_DATA: + break; + case VGA_MISC_OUTPUT_READ: + break; + default: + return -EPERM; + } + + if (desc->size != 1) + return -EINVAL; + + retchar = inb(desc->port); + copy_to_user(desc->value, &retchar, sizeof(char)); + + return 0; +} + +static int doPIOWrite(pioData *desc) +{ + int retval; + char retchar; + + if ((retval = verify_area(VERIFY_READ, desc->value, desc->size))) + return retval; + + switch (desc->port) { + case SC_INDEX: + break; + case SC_DATA: + break; + case VGA_MISC_OUTPUT_WRITE: + break; + default: + return -EPERM; + } + + if (desc->size != 1) + return -EINVAL; + + copy_from_user(&retchar, desc->value, sizeof(char)); + outb(retchar, desc->port); + + return 0; +} + +static int doPIO(unsigned int cmd, unsigned long arg) +{ + pioData desc; + int retval; + + if ((retval = verify_area(VERIFY_READ, (void *)arg, sizeof(pioData)))) + return retval; + copy_from_user(&desc, (void *)arg, sizeof(pioData)); + if (_IOC_DIR(cmd) == _IOC_READ) + return doPIORead(&desc); + if (_IOC_DIR(cmd) == _IOC_WRITE) + return doPIOWrite(&desc); + + return -EINVAL; +} + +static int ioctl_3dfx(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + DEBUGMSG(("3dfx: Entering ioctl_3dfx, inode %p file %p cmd %x arg %lx\n", inode, file, cmd, arg)); + switch (_IOC_TYPE(cmd)) { + case '3': + return doQuery(cmd, arg); + case 0: + return doPIO(cmd, arg); + default: + DEBUGMSG(("3dfx: Unknown 3dfx request made\n")); + return -EINVAL; + } +} + +#ifdef HAVE_MTRR +int setmtrr_3dfx(void) +{ + int i = 0, retval = -2; + unsigned char dlc; + + /* First do a bios fixup if this system has a 82441FX chipset */ + struct pci_dev *dev = NULL; + if ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, dev))) { + pci_read_config_byte(dev, 0x82, &dlc); + if (!(dlc & 1 << 1)) { + dlc |= 1 << 1; + pci_write_config_byte(dev, 0x82, dlc); + printk("3dfx: PIIX3: Enabling Passive Release\n"); + } + } + + /* Set up the mtrr's */ + if (numCards == 0) + return -EIO; + for (i = 0; i < numCards; i++) { + if ((cards[i].vendor != PCI_VENDOR_ID_3DFX) || + (cards[i].type>PCI_DEVICE_ID_3DFX_VOODOO3)) + { + cards[i].mtrr_buf = -1; /* Used as flag in resetmtrr_3dfx() */ + continue; + } + switch (cards[i].type) { + case PCI_DEVICE_ID_3DFX_VOODOO: + case PCI_DEVICE_ID_3DFX_VOODOO2: + /* Frame buffer to write combining */ + retval = cards[i].mtrr_buf = mtrr_add(cards[i].addr0, 0x400000, MTRR_TYPE_WRCOMB, 1); + if (retval>=0) { + retval = cards[i].mtrr_ctl = mtrr_add(cards[i].addr0, 0x1000, MTRR_TYPE_UNCACHABLE, 1); + if (retval<0) { + mtrr_del(cards[i].mtrr_buf, 0, 0); + cards[i].mtrr_buf=-1; + } + } + if (retval < 0) { + printk("3dfx: Could not set MTRR for Voodoo card\n"); + /* Can still run */ + return 0; + } + break; + case PCI_DEVICE_ID_3DFX_BANSHEE: + case PCI_DEVICE_ID_3DFX_VOODOO3: + retval = cards[i].mtrr_buf = mtrr_add(cards[i].addr1, 0x1000000, MTRR_TYPE_WRCOMB, 1); + if (retval < 0) { + printk("3dfx: Could not set MTRR for Voodoo card\n"); + /* Can still run */ + return 0; + } + cards[i].mtrr_ctl=-1; + break; + default: + /* We should never hit this */ + } + } + if (retval == -2) + { + DEBUGMSG(("3dfx: Could not set MTRR for this graphics card\n")); + retval = 0; /* Can still run */ + } +#ifdef DEBUG + else if (retval >= 0) + DEBUGMSG(("3dfx: Successfully set MTRR, mtrr register: %d\n", retval)); +#endif + + return retval; +} + +int resetmtrr_3dfx(void) +{ + int i, ret, retval = 0; + for (i = 0; i < numCards; i++) { + if (cards[i].mtrr_buf >= 0) { + ret = mtrr_del(cards[i].mtrr_buf, 0, 0); + if (ret < 0) + retval = ret; + cards[i].mtrr_buf = -1; + if (cards[i].mtrr_ctl >= 0) { + ret = mtrr_del(cards[i].mtrr_ctl, 0, 0); + if (ret < 0) + retval = ret; + cards[i].mtrr_ctl = -1; + } + } + } + return retval; +} + +#endif /* HAVE_MTRR */ + +static struct file_operations fops_3dfx = { +#if KERNEL_MIN_VER(2, 4, 0) + owner: THIS_MODULE, +#endif + ioctl: ioctl_3dfx, /* ioctl */ + mmap: mmap_3dfx, /* mmap */ + open: open_3dfx, /* open */ + release: release_3dfx, /* release */ +}; + +#ifdef MODULE +int init_module(void) +{ + int ret; + DEBUGMSG(("3dfx: Entering init_module()\n")); + +#if KERNEL_MIN_VER(2,3,46) || defined(DEVFS_SUPPORT) + if ((ret = devfs_register_chrdev(MAJOR_3DFX, "3dfx", &fops_3dfx)) < 0) { + printk("3dfx: Unable to register character device with major %d\n", MAJOR_3DFX); + return ret; + } + + devfs_handle = devfs_register(NULL, "3dfx", DEVFS_FL_NONE, + MAJOR_3DFX, DEVICE_VOODOO, + S_IFCHR | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP, + &fops_3dfx, NULL); +#else + if ((ret = register_chrdev(MAJOR_3DFX, "3dfx", &fops_3dfx)) < 0) { + printk("3dfx: Unable to register character device with major %d\n", MAJOR_3DFX); + return ret; + } +#endif + DEBUGMSG(("3dfx: Successfully registered device 3dfx\n")); + findCards(); + +#ifdef HAVE_MTRR + ret = setmtrr_3dfx(); + if (ret < 0) + { + DEBUGMSG(("setmtrr_3dfx() failed, returned %d\n", ret)); + /* + unregister_chrdev(MAJOR_3DFX, "3dfx"); + return ret; + */ + } +#endif + + return 0; +} + +void cleanup_module(void) +{ + DEBUGMSG(("3dfx: Entering cleanup_module\n")); + +#ifdef HAVE_MTRR + resetmtrr_3dfx(); +#endif +#if KERNEL_MIN_VER(2,3,46) || defined(DEVFS_SUPPORT) + devfs_unregister(devfs_handle); + + if (devfs_unregister_chrdev(MAJOR_3DFX, "3dfx")) + { + DEBUGMSG(("3dfx: devfs_unregister_chrdev failed\n")); + return; + } +#else + if (unregister_chrdev(MAJOR_3DFX, "3dfx")) + { + DEBUGMSG(("3dfx: unregister_chrdev failed\n")); + return; + } +#endif +} +#else /* !MODULE */ + +long init_3dfx(long mem_start, long mem_end) +{ + if (register_chrdev(MAJOR_3DFX, "3dfx", &fops_3dfx)) + { + DEBUGMSG(("3dfx: Unable to register_chrdev with major %d\n", MAJOR_3DFX)); + return 0; + } + findCards(); + + return mem_start; +} +#endif /* !MODULE */ + +#if KERNEL_MIN_VER(2,1,21) +MODULE_AUTHOR("Daryll Strauss et al."); +MODULE_DESCRIPTION("3dfx glide kernel device driver"); +MODULE_LICENSE("GPL"); +#endif + +#if defined(DEBUG) +/* + * Kludge to get rid of: + * ./3dfx.o: unresolved symbol inb + * ./3dfx.o: unresolved symbol inl + * ./3dfx.o: unresolved symbol inw + * ./3dfx.o: unresolved symbol outb + * ./3dfx.o: unresolved symbol outl + * ./3dfx.o: unresolved symbol outw + * when compiling this module with -g during debugging. + */ +#undef __KERNEL__ +#define extern +#undef _ASM_IO_H +#include +/* + * And this is copied from asm/uaccess.h + * in order to get rid of + * ./3dfx.o: unresolved symbol verify_area + * when compiling this module with -g during debugging. + */ +inline int verify_area(int type, const void * addr, unsigned long size) +{ + return access_ok(type,addr,size) ? 0 : -EFAULT; +} + +int a_last_dummy_function(int a) +{ + return a; +} +#endif diff --git a/Device3Dfx/Makefile b/Device3Dfx/Makefile new file mode 100644 index 0000000..843bcbf --- /dev/null +++ b/Device3Dfx/Makefile @@ -0,0 +1,110 @@ +############################################################################### +# Makefile by Carlo Wood (and others) + +ifeq ($(OPT_CFLAGS),) + +# Determine the machine type +ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) + +# Setup machine dependant compiler flags +ifeq ($(ARCH), i386) +OPT_CFLAGS = -O2 -m486 -fomit-frame-pointer \ + -fno-strength-reduce \ + -malign-loops=2 -malign-jumps=2 -malign-functions=2 +endif + +ifeq ($(ARCH), alpha) +OPT_CFLAGS = -O2 -mno-fp-regs -mcpu=ev4 \ + -ffixed-8 \ + -Wa,-mev6 \ + -fomit-frame-pointer -fno-strict-aliasing +endif + +endif # ifeq ($OPT_CFLAGS),) + +CFLAGS := -DMODULE -D__KERNEL__ -I/usr/src/linux/include $(OPT_CFLAGS) + +############################################################################### +# You should never need to change anything below. + +all: sanity 3dfx.o + +# Sanity checks +sanity: + @( \ + if [ ! -e /usr/src/linux ]; then \ + echo "Expect kernel source at location /usr/src/linux"; \ + echo "Sym.link /usr/src/linux -> where you have your sources"; \ + exit -1; \ + fi; \ + if [ ! -r /usr/src/linux/include ]; then \ + echo "Expect readable headers in /usr/src/linux/include"; \ + exit -1; \ + fi; \ + if [ ! -r /usr/src/linux/include/linux/version.h ]; then \ + echo "Missing /usr/src/linux/include/linux/version.h"; \ + echo "Configure and install the kernel first"; \ + exit -1; \ + fi; \ + if [ ! -e /proc/cpuinfo ]; then \ + echo "You need the /proc file system"; \ + echo "Reconfigure kernel and say Yes to CONFIG_PROC_FS"; \ + exit -1; \ + fi; \ + ) + +kinfo: kinfo.c + $(CC) -o kinfo kinfo.c + +kinfo.h: kinfo + ./kinfo + +############################################################################### +# kernel 2.1+ + +3dfx.o: kinfo.h 3dfx_driver.c Makefile + $(CC) $(CFLAGS) -c -o $@ 3dfx_driver.c + +############################################################################### + +install: + mkdir -p /lib/modules/$(shell ./kinfo --UTS)/misc + cp 3dfx.o /lib/modules/$(shell ./kinfo --UTS)/misc/3dfx.o + @( \ + if [ -e /lib/modules/$(shell ./kinfo --UTS)/modules.dep ]; then \ + indep=`grep 'misc/3dfx.o:' /lib/modules/$(shell ./kinfo --UTS)/modules.dep`; \ + if [ -z "$$indep" ]; then \ + echo "/lib/modules/$(shell ./kinfo --UTS)/misc/3dfx.o:" >> /lib/modules/$(shell ./kinfo --UTS)/modules.dep; \ + echo "" >> /lib/modules/$(shell ./kinfo --UTS)/modules.dep; \ + fi; \ + fi; \ + if [ ! -e /dev/.devfsd -a ! -c /dev/3dfx ]; then \ + mknod /dev/3dfx c 107 0; \ + chmod go+w /dev/3dfx; \ + fi; \ + if [ "$(RPM_INSTALL)" = "1" ]; then \ + echo "/lib/modules/$(shell ./kinfo --UTS)/misc/3dfx.o"; \ + else \ + inconf=`grep 'alias char-major-107 3dfx' /etc/conf.modules`; \ + if [ -z "$$inconf" ]; then \ + echo "alias char-major-107 3dfx" >> /etc/conf.modules; \ + fi; \ + fi; \ + ) + +############################################################################### +# This is for debugging purposes by the developers: + +clean: + rm -f *.o *.s kinfo kinfo.h + +3dfx.s: 3dfx_driver.c Makefile + $(CC) $(CFLAGS) -S -c 3dfx_driver.c + +tar: + tar czf ../../SOURCES/Dev3Dfx-2.5.tar.gz 3dfx_driver.c Makefile + + +debug: + make OPT_CFLAGS="-g -Wall -Wstrict-prototypes -DDEBUG" + diff --git a/glide2x/cvg/glide/oem/oeminit.h b/glide2x/cvg/glide/oem/oeminit.h new file mode 100644 index 0000000..c114913 --- /dev/null +++ b/glide2x/cvg/glide/oem/oeminit.h @@ -0,0 +1,93 @@ +/* +** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +** FULL TEXT OF THE NON-WARRANTY PROVISIONS. +** +** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +** THE UNITED STATES. +** +** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +*/ + +#ifndef __OEMINIT_H__ +#define __OEMINIT_H__ + +#define OEMINIT_INVALID_BOARD_ID 0xdeadfeed +#define OEMINIT_VERSION 0x10001 + +#include "3dfx.h" +#define FX_DLL_DEFINITION +#include "fxdll.h" +#include "sst1vid.h" + +#define FX_OEM_CONTROL_ACTIVATE 1 +#define FX_OEM_CONTROL_DEACTIVATE 2 + +#define FX_OEM_TVOUT 1 +#define FX_OEM_SLIMASTER 2 +#define FX_OEM_SLISLAVE 3 + +#define FX_OEM_FBI_CONFIG_SHIFT 8 + +typedef enum { + OEM_READ_ONLY, + OEM_WRITE_ONLY, + OEM_READ_WRITE +} OemPciIOFlag; + +typedef struct { + FxU32 regAddress; + FxU32 sizeInBytes; + OemPciIOFlag rwFlag; +} OemPciRegister; + +typedef FxU32 (FX_CALL *PciConfigProc)(OemPciRegister, FxU32, FxU32 *); + +typedef struct { + GrScreenResolution_t res; + GrScreenRefresh_t refresh; + FxU32 depth; + FxU32 hSyncOn; + FxU32 hSyncOff; + FxU32 vSyncOn; + FxU32 vSyncOff; + FxU32 hBackPorch; + FxU32 vBackPorch; + FxU32 xDimension; + FxU32 yDimension; + float clkFreq16bpp; + float clkFreq24bpp; +} OemVideoTimingInfo; + +typedef struct { + FxU32 version; /* Version for this structure */ + FxU32 vendorID; /* PCI Vendor ID field */ + FxU32 subvendorID; /* PCI sub Vendor ID field */ + FxU32 deviceID; /* PCI Device ID field */ + FxU32 boardID; /* Board ID: defined for Voodoo2 only!!! */ + FxU32 *linearAddress; /* address for primary board */ + FxU32 *slaveAddress; /* address for slave board */ + PciConfigProc fxoemPciWriteConfig; + PciConfigProc fxoemPciReadConfig; + OemVideoTimingInfo vid; + FxU32 reserved[42]; +} OemInitInfo; + +FX_EXPORT FxU32 FX_CSTYLE fxoemInitMapBoard(OemInitInfo *oem); +FX_EXPORT FxI32 FX_CSTYLE fxoemGet(FxU32 pname, FxU32 plength, FxI32 *params); +FX_EXPORT FxU32 FX_CSTYLE fxoemInitVideoTiming(OemVideoTimingInfo *vid); +FX_EXPORT FxU32 FX_CSTYLE fxoemInitSetVideo(OemInitInfo *oem); +FX_EXPORT FxU32 FX_CSTYLE fxoemRestoreVideo(OemInitInfo *oem); +FX_EXPORT FxU32 FX_CSTYLE fxoemControl(FxU32 mode); + +#endif /* __OEMINIT_H__ */ + diff --git a/glide2x/cvg/glide/src/cpudetect.c b/glide2x/cvg/glide/src/cpudetect.c new file mode 100644 index 0000000..3430480 --- /dev/null +++ b/glide2x/cvg/glide/src/cpudetect.c @@ -0,0 +1,48 @@ +/* + * THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY + * PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT + * TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX + * INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE + * DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). + * THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A + * FULL TEXT OF THE NON-WARRANTY PROVISIONS. + * + * USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + * RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN + * TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + * AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + * SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + * THE UNITED STATES. + * + * COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED + */ + +#include +#include +#include + +int _cpu_detect_asm() { + struct utsname name; + + uname(&name); + if (!strcmp(name.machine, "i386")) return 3; + if (!strcmp(name.machine, "i486")) return 4; + if (!strcmp(name.machine, "i586")) return 5; + if (!strcmp(name.machine, "i686")) return 6; + fprintf(stderr, "Couldn't determine cpu type. Using i586\n"); + return 5; +} + +void single_precision_asm() { + asm("push %eax \n fnclex \n fstcw (%esp) \n movl (%esp), %eax \n " + "and $0x0000fcff, %eax \n movl %eax, (%esp) \n fldcw (%esp) \n pop %eax"); +} + + +void double_precision_asm() { + asm("push %eax \n fnclex \n fstcw (%esp) \n movw (%esp), %eax \n " + "and $0x0000fcff, %eax \n or $0x000002ff, %eax \n mov %eax, (%esp) \n " + "fldcw (%esp) \n pop %eax"); +} + diff --git a/glide2x/cvg/glide/src/fxglide.h b/glide2x/cvg/glide/src/fxglide.h new file mode 100644 index 0000000..e4ce305 --- /dev/null +++ b/glide2x/cvg/glide/src/fxglide.h @@ -0,0 +1,2394 @@ +/* +** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +** FULL TEXT OF THE NON-WARRANTY PROVISIONS. +** +** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +** THE UNITED STATES. +** +** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +** +** $Header$ +** $Log$ +** Revision 1.1.1.1 1999/12/07 21:49:09 joseph +** Initial checkin into SourceForge. +** +** +** 206 6/06/98 12:06p Peter +** gmt's trilinear hell bug +** +** 205 5/20/98 4:26p Peter +** one more direct register write fix +** +** 204 5/20/98 3:51p Peter +** no fifo glide +** +** 203 5/18/98 12:16p Peter +** culling enabling +** +** 202 4/01/98 2:57p Peter +** removed voodoo^2 strings +** +** 201 4/01/98 1:51p Peter +** fixed resetting unused tmu muckage +** +** 200 3/31/98 6:09p Peter +** sli origin everywhere (I think) and grLfbReadRegion/grRenderBuffer vs +** triple buffering +** +** 199 3/23/98 5:57p Peter +** fixed FX_CALL +** +** 198 3/17/98 6:50p Peter +** sli paired vs active +** +** 197 3/17/98 3:00p Peter +** removed unused stats +** +** 196 3/17/98 1:57p Atai +** added boardid and requireoemdll registry +** +** 195 3/14/98 1:07p Peter +** mac port happiness +** +** 194 3/13/98 2:56p Atai +** added oeminfo in GC +** +** 193 3/13/98 1:26p Peter +** re-fixed shadowing +** +** 192 3/09/98 3:16p Peter +** removed debugging code accidentally checked in +** +** 191 3/09/98 2:24p Peter +** change for new pci passthrough interface +** +** 190 3/03/98 9:37p Peter +** more sli origin fun +** +** 189 3/02/98 7:22p Peter +** more crybaby stuff +** +** 188 2/24/98 10:15a Peter +** oem dll muckage +** +** 187 2/20/98 5:31p Peter +** crybaby glide +** +** 186 2/20/98 11:00a Peter +** removed glide3 from glid2 tree +** +** 185 2/20/98 9:05a Peter +** removed remnants of comdex grot +** +** 184 2/19/98 5:53p Peter +** moved structure def for hanson +** +** 183 2/17/98 12:39p Peter +** sli monitor detect thing +** +** 182 2/12/98 3:40p Peter +** single buffering for opengl +** +** 181 2/11/98 5:26p Peter +** new write edge stuff +** +** 180 2/04/98 6:57p Atai +** added fxoem2x.dll for cvg +** +** 179 2/01/98 7:52p Peter +** grLfbWriteRegion byte count problems +** +** 178 1/30/98 4:23p Peter +** renamed curSwapBuf->curRenderBuf for clarity +** +** 177 1/20/98 11:03a Peter +** env var to force triple buffering + * + * 176 1/16/98 7:03p Peter + * fixed volatile + * + * 175 1/16/98 10:47a Peter + * fixed idle muckage + * + * 174 1/15/98 1:12p Peter + * dispatch w/o packing + * + * 173 1/13/98 12:42p Atai + * fixed grtexinfo, grVertexLayout, and draw triangle + * + * 172 1/10/98 4:01p Atai + * inititialize vertex layout, viewport, added defines + * + * 168 1/07/98 11:18a Atai + * remove GrMipMapInfo and GrGC.mm_table in glide3 + * + * 167 1/07/98 10:22a Peter + * lod dithering env var + * + * 166 1/06/98 6:47p Atai + * undo grSplash and remove gu routines + * + * 165 1/05/98 6:06p Atai + * glide extension stuff + * + * 164 12/18/97 10:52a Atai + * fixed grGet(GR_VIDEO_POS) + * + * 163 12/17/97 4:45p Peter + * groundwork for CrybabyGlide + * + * 162 12/17/97 4:05p Atai + * added grChromaRange(), grGammaCorrecionRGB(), grRest(), and grGet() + * functions + * + * 160 12/15/97 5:52p Atai + * disable obsolete glide2 api for glide3 + * + * 156 12/09/97 12:20p Peter + * mac glide port + * + * 155 12/09/97 10:28a Peter + * cleaned up some frofanity + * + * 154 12/09/97 9:46a Atai + * added viewport varibales + * + * 152 11/25/97 12:09p Peter + * nested calls to grLfbLock vs init code locking on v2 + * + * 151 11/21/97 6:05p Atai + * use one datalist (tsuDataList) in glide3 + * + * 150 11/21/97 3:20p Peter + * direct writes tsu registers + * + * 149 11/19/97 4:33p Atai + * #define GLIDE3_VERTEX_LAYOUT 1 + * + * 148 11/19/97 3:51p Dow + * Tex stuff for h3, def of GETENV when using fxHal + * + * 147 11/18/97 6:11p Peter + * fixed glide3 muckage + * + * 146 11/18/97 4:36p Peter + * chipfield stuff cleanup and w/ direct writes + * + * 145 11/18/97 3:25p Atai + * redefine vData + * + * 144 11/17/97 4:55p Peter + * watcom warnings/chipfield stuff + * + * 143 11/15/97 7:43p Peter + * more comdex silliness + * + * 142 11/14/97 11:10p Peter + * open vs hw init confusion + * + * 141 11/14/97 5:02p Peter + * more comdex stuff + * + * 140 11/14/97 12:09a Peter + * comdex thing and some other stuff + * + * 139 11/12/97 2:35p Peter + * fixed braino + * + * 138 11/12/97 2:27p Peter + * + * 137 11/12/97 11:38a Dow + * + * 136 11/12/97 11:15a Peter + * fixed tri/strip param send and used cvgdef.h constant + * + * 135 11/12/97 9:21a Dow + * Changed offset defs to those in h3defs.h + * + * 134 11/07/97 11:22a Atai + * remove GR_*_SMOOTH. use GR_SMOOTH + * + * 133 11/06/97 3:46p Peter + * dos ovl build problem + * + * 132 11/06/97 3:38p Dow + * More banshee stuff + * + * 131 11/04/97 6:35p Atai + * 1. sync with data structure changes + * 2. break up aa triangle routine + * + * 130 11/04/97 5:04p Peter + * cataclysm part deux + * + * 129 11/04/97 4:00p Dow + * Banshee Mods + * + * 128 11/03/97 3:43p Peter + * h3/cvg cataclysm + * + * 127 10/29/97 2:45p Peter + * C version of Taco's packing code + * +** +*/ + +/* +** fxglide.h +** +** Internal declarations for use inside Glide. +** +** GLIDE_LIB: Defined if building the Glide Library. This macro +** should ONLY be defined by a makefile intended to build +** GLIDE.LIB or glide.a. +** +** GLIDE_NUM_TMU: Number of physical TMUs installed. Valid values are 1 +** and 2. If this macro is not defined by the application +** it is automatically set to the value 2. +** +*/ + +#ifndef __FXGLIDE_H__ +#define __FXGLIDE_H__ + +/* +** ----------------------------------------------------------------------- +** INCLUDE FILES +** ----------------------------------------------------------------------- +*/ +#include +#include +#include +#include +#include + +#include <3dfx.h> +#include +#include + +#if (GLIDE_PLATFORM & GLIDE_HW_H3) +#include + +/* Compilation hacks for h3 */ + +/* Reserved fbzMode bits */ +#define SST_DRAWBUFFER_SHIFT 14 +#define SST_DRAWBUFFER (0x3 << SST_DRAWBUFFER_SHIFT) +#define SST_DRAWBUFFER_FRONT (0 << SST_DRAWBUFFER_SHIFT) +#define SST_DRAWBUFFER_BACK (1 << SST_DRAWBUFFER_SHIFT) + +/* Reserved lfbMode bits */ +#define SST_LFB_WRITEBUFSELECT_SHIFT 4 +#define SST_LFB_WRITEBUFSELECT (0x3< +#else +#error "Unknown HAL hw layer" +#endif + +#if GLIDE_INIT_HAL + +#include + +#ifdef GETENV +#undef GETENV +#endif +#define GETENV getenv + +/* + * P6 Fence + * + * Here's the stuff to do P6 Fencing. This is required for the + * certain things on the P6 + * + * dpc - 21 may 1997 - FixMe! + * This was yoinked from sst1/include/sst1init.h, and should be + * merged back into something if we decide that we need it later. + */ +extern FxU32 p6FenceVar; + +/* dpc - 2 june 1997 + * Moved the fence check out to avoid empty if body warning w/ gcc. + * This only applies to systems that require the p6 fencing. + */ +#define P6FENCE_CHECK if (i & 2) P6FENCE + +#if defined(__WATCOMC__) +void +p6Fence(void); +#pragma aux p6Fence = \ + "xchg eax, p6FenceVar" \ + modify [eax]; + +#define P6FENCE p6Fence() +#elif defined(__MSC__) +#define P6FENCE {_asm xchg eax, p6FenceVar} +#else +#error "P6 Fencing in-line assembler code needs to be added for this compiler" +#endif /* Compiler specific fence commands */ +#else /* !defined(GLIDE_INIT_HAL) */ + +/* All sst1init refs need to be protected inside + GLIDE_PLATFORM & GLIDE_HW_CVG + */ + +#include +/* dpc - 5 sep 1997 - FixMe! + * Currently we're mapping directly to the init code layer + * through the sst1XXX calls. + * + * #include + */ +#endif /* !defined(GLIDE_INIT_HAL) */ + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +typedef sst1VideoTimingStruct FxVideoTimingInfo; +#endif + +#if GLIDE_INIT_HAL +#define PLATFORM_IDLE_HW(__hwPtr) fxHalIdleNoNOP(__hwPtr) +#define IDLE_HW(__hwPtr) \ +do { \ + { \ + GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1); \ + GR_SET(BROADCAST_ID, __hwPtr, nopCMD, 0); \ + GR_CHECK_SIZE(); \ + } \ + PLATFORM_IDLE_HW(__hwPtr); \ +} while(0) +#else /* !GLIDE_INIT_HAL */ +#define IDLE_HW(__hwPtr) sst1InitIdle((FxU32*)__hwPtr) +#endif /* !GLIDE_INIT_HAL */ + +#if GLIDE_MULTIPLATFORM +#include "gcfuncs.h" +#endif + +#if (GLIDE_PLATFORM & GLIDE_OS_WIN32) +#include "oeminit.h" +#endif + +#define GR_SKIP_OEMDLL 0xee1feef +#define GR_NO_OEMDLL 0xee1feed + +/* isolate this 'hack' here so as to make the code look cleaner */ +#ifdef __WATCOMC__ +#define GR_CDECL __cdecl +#else +#define GR_CDECL +#endif + +/* Make sure GR_FLUSH_STATE is a noop if not Glide 3 */ +#define GR_FLUSH_STATE() + +/*==========================================================================*/ +/* +** GrState +** +** If something changes in here, then go into glide.h, and look for a +** declaration of the following form: +** +** #define GLIDE_STATE_PAD_SIZE N +** #ifndef GLIDE_LIB +** typedef struct { +** char pad[GLIDE_STATE_PAD_SIZE]; +** } GrState; +** #endif +** +** Then change N to sizeof(GrState) AS DECLARED IN THIS FILE! +** +*/ + +struct _GrState_s +{ + GrCullMode_t /* these go in front for cache hits */ + cull_mode; /* cull neg, cull pos, don't cull */ + + GrHint_t + paramHints; /* Tells us if we need to pointcast a + parameter to a specific chip */ + FxI32 + fifoFree; /* # free entries in FIFO */ + FxU32 + paramIndex, /* Index into array containing + parameter indeces to be sent ot the + triangle setup code */ + tmuMask; /* Tells the paramIndex updater which + TMUs need values */ + struct{ + FxU32 fbzColorPath; + FxU32 fogMode; + FxU32 alphaMode; + FxU32 fbzMode; + FxU32 lfbMode; + FxU32 clipLeftRight; + FxU32 clipBottomTop; + + FxU32 fogColor; + FxU32 zaColor; + FxU32 chromaKey; + FxU32 chromaRange; + + FxU32 stipple; + FxU32 color0; + FxU32 color1; + } fbi_config; /* fbi register shadow */ + + struct tmu_config_t { + FxU32 textureMode; + FxU32 tLOD; + FxU32 tDetail; + FxU32 texBaseAddr; + FxU32 texBaseAddr_1; + FxU32 texBaseAddr_2; + FxU32 texBaseAddr_3_8; + GrMipMapMode_t mmMode; /* saved to allow MM en/dis */ + GrLOD_t smallLod, largeLod; /* saved to allow MM en/dis */ + FxU32 evenOdd; + GrNCCTable_t nccTable; + } tmu_config[GLIDE_NUM_TMU]; /* tmu register shadow */ + + FxBool /* Values needed to determine which */ + ac_requires_it_alpha, /* parameters need gradients computed */ + ac_requires_texture, /* when drawing triangles */ + cc_requires_it_rgb, + cc_requires_texture, + cc_delta0mode, /* Use constants for flat shading */ + allowLODdither, /* allow LOD dithering */ + checkFifo; /* Check fifo status as specified by hints */ + + FxU32 + lfb_constant_depth; /* Constant value for depth buffer (LFBs) */ + GrAlpha_t + lfb_constant_alpha; /* Constant value for alpha buffer (LFBs) */ + + FxU32 + num_buffers; /* 2 or 3 */ + + GrColorFormat_t + color_format; /* ARGB, RGBA, etc. */ + + GrMipMapId_t + current_mm[GLIDE_NUM_TMU]; /* Which guTex** thing is the TMU set + up for? THIS NEEDS TO GO!!! */ + + float + clipwindowf_xmin, clipwindowf_ymin, /* Clipping info */ + clipwindowf_xmax, clipwindowf_ymax; + FxU32 + screen_width, screen_height; /* Screen width and height */ + float + a, r, g, b; /* Constant color values for Delta0 mode */ +}; + +typedef struct GrGC_s +{ + FxU32 + *base_ptr, /* base address of SST */ + *reg_ptr, /* pointer to base of SST registers */ + *tex_ptr, /* texture memory address */ + *lfb_ptr, /* linear frame buffer address */ + *slave_ptr; /* Scanline Interleave Slave address */ + +#if GLIDE_MULTIPLATFORM + GrGCFuncs + gcFuncs; +#endif + +#define kMaxVertexParam (20 + (12 * GLIDE_NUM_TMU) + 3) + struct dataList_s { + int i; + FxFloat* addr; + } regDataList[kMaxVertexParam]; + int tsuDataList[kMaxVertexParam]; + + GrState + state; /* state of Glide/SST */ + + struct cmdTransportInfo { + FxU32 triPacketHdr; /* Pre-computed packet header for + * independent triangles. + */ + + FxU32 cullStripHdr; /* Pre-computed packet header for generic + * case of packet 3 triangles. This needs + * command type and # of vertices to be complete. + */ + + FxU32 paramMask; /* Mask for specifying parameters of + * non-triangle packets. The parameter + * bits[21:10] mimic the packet3 header + * controlling which fields are sent, and + * pc[28] controls whether any color + * information is sent as packed. + */ + + /* Basic command fifo characteristics. These should be + * considered logically const after their initialization. + */ + FxU32* fifoStart; /* Virtual address of start of fifo */ + FxU32* fifoEnd; /* Virtual address of fba fifo */ + FxU32 fifoOffset; /* Offset from hw base to fifo start */ + FxU32 fifoSize; /* Size in bytes of the fifo */ + FxU32 fifoJmpHdr; /* Type0 packet for jmp to fifo start */ + + FxU32* fifoPtr; /* Current write pointer into fifo */ + FxU32 fifoRead; /* Last known hw read ptr. + * This is the sli master, if enabled. + */ + + /* Fifo checking information. In units of usuable bytes until + * the appropriate condition. + */ + FxI32 fifoRoom; /* Space until next fifo check */ + FxI32 roomToReadPtr;/* Bytes until last known hw ptr */ + FxI32 roomToEnd; /* # of bytes until last usable address before fifoEnd */ + + FxBool fifoLfbP; /* Do we expect lfb writes to go through the fifo? */ + FxBool lfbLockCount; /* Have we done an lfb lock? Count of the locks. */ + +#if GLIDE_DISPATCH_SETUP + FxI32 (FX_CALL *triSetupProc)(const GrVertex* a, const GrVertex* b, const GrVertex* c); +#endif /* GLIDE_DISPATCH_SETUP */ + +#if GLIDE_USE_SHADOW_FIFO + FxU32* fifoShadowBase; /* Buffer that shadows the hw fifo for debugging */ + FxU32* fifoShadowPtr; +#endif /* GLIDE_USE_SHADOW_FIFO */ + } cmdTransportInfo; + + union hwDep_u { + FxU32 noHwDep; + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) + struct cvgDep_s { +#if GLIDE_BLIT_CLEAR + /* xTilePages, yTileShift, tileSlopP, and numBufferPages are set + * in grSstWinOpen, and should be considered logically const + * until grSstWinClose at which point they are invalid. + * + * NB: The calculation of these values etc should really be + * moved into the init code at some point in my near future. + */ + FxU32 xTilePages; /* # of pages for video tiles in the x direction, + * the x-dimension of a tile is alwasy 32 pixels. + * Cons-ed up from fbiInit1[24], fbiInit1[7:4], and + * fbiInit6[30] in grSstWinOpen after all of the + * buffers etc are allocated. + */ + + FxBool tileSlopP; /* Set if the actual # of video tiles in the x + * direction will not evenly fit into a page. + * + * FixMe: Will this ever happen? + */ + + FxU32 yTileShift; /* (0x01UL << yTileShift) is the # of lines in a + * tile. This is dependent on the sli-ness of the + * board. + */ + + FxU32 numBufferPages;/* The number of pages used for an entire + * buffer (color or aux). + */ +#endif /* GLIDE_BLIT_CLEAR */ + + FxU32 renderBuf; /* Cached value of the current buffer swapped by the + * user via grBufferSwap. Legal values are + * [0 .. gc->state.num_buffers - 1]. + * + * NB: We need this because the current buffer + * availible in the status register lags the actual + * value due to the command fifo asynchrony (is that + * a word?). + */ + + FxU32 frontBuf; + FxU32 backBuf; + + /* CVG cannot really do single buffering */ + FxBool singleBufferP; + + /* Sli has an 'interesting' feature where the physical scanlines + * that are being rendered is dependent on the location of the y + * origin. There is some ugliness now in grSstOrigin and grSwapBuffer + * to deal w/ this correctly. + * + * Origin_Lower_Left: 0:Black [1 .. screenRezY]:Rendered screenRez+1:Black + * Origin_Upper_Left: [0 .. screenRezY - 1]:Rendered [screenRez-screenRez+1]:Black + */ + FxU32 sliOriginBufCount; + + /* Keep track of which tmu's we have set the lod to be the + * minimum possible to avoid texture thrashing. + */ + FxBool tmuLodDisable[GLIDE_NUM_TMU]; + } cvgDep; +#endif /* (GLIDE_PLATFORM & GLIDE_HW_CVG) */ + } hwDep; + + /* lfb config */ + FxU32 lockPtrs[2]; /* pointers to locked buffers */ + FxU32 fbStride; + + struct { + FxU32 freemem_base; + FxU32 total_mem; + FxU32 next_ncc_table; + GrMipMapId_t ncc_mmids[2]; + const GuNccTable *ncc_table[2]; + } tmu_state[GLIDE_NUM_TMU]; + + int + grSstRez, /* Video Resolution of board */ + grSstRefresh, /* Video Refresh of board */ + fbuf_size, /* in MB */ + num_tmu, /* number of TMUs attached */ + grColBuf, + grAuxBuf; + + /* sli config */ + FxBool sliPairP; /* Part of an sli pair? */ + FxBool scanline_interleaved; /* Enable sli for this pair */ + FxBool swapMasterSenseP; /* Swapped master and slave pointers */ + + struct { + GrMipMapInfo data[MAX_MIPMAPS_PER_SST]; + GrMipMapId_t free_mmid; + } mm_table; /* mip map table */ + + /* DEBUG and SANITY variables */ + FxI32 myLevel; /* debug level */ + FxI32 counter; /* counts bytes sent to HW */ + FxI32 expected_counter; /* the number of bytes expected to be sent */ + + FxU32 checkCounter; + FxU32 checkPtr; + + FxVideoTimingInfo* vidTimings;/* init code overrides */ + + FxBool open; /* Has GC Been Opened? */ + FxBool hwInitP; /* Has the hw associated w/ GC been initted and mapped? + * This is managed in _grDetectResources:gpci.c the first + * time that the board is detected, and in grSstWinOpen:gsst.c + * if the hw has been shutdown in a call to grSstWinClose. + */ + /* Oem Dll data */ +#if (GLIDE_PLATFORM & GLIDE_OS_WIN32) + void *oemInit; + OemInitInfo oemi; +#endif +} GrGC; + +/* NOTE: this changes the P6FENCE macro expansion from sst1init.h !!! */ +#define p6FenceVar _GlideRoot.p6Fencer + +/* if we are debugging, call a routine so we can trace fences */ +#ifdef GLIDE_DEBUG +#define GR_P6FENCE _grFence(); +#else +#define GR_P6FENCE P6FENCE +#endif + +/* +** The root of all Glide data, all global data is in here +** stuff near the top is accessed a lot +*/ +struct _GlideRoot_s { + int p6Fencer; /* xchg to here to keep this in cache!!! */ + int current_sst; + FxU32 CPUType; + GrGC *curGC; /* point to the current GC */ + FxU32 packerFixAddress; /* address to write packer fix to */ + FxBool windowsInit; /* Is the Windows part of glide initialized? */ + + FxI32 curTriSize; /* the size in bytes of the current triangle */ +#if GLIDE_HW_TRI_SETUP + FxI32 curVertexSize; /* Size in bytes of a single vertex's parameters */ +#endif + +#if !GLIDE_HW_TRI_SETUP || !GLIDE_PACKET3_TRI_SETUP + FxU32 paramCount; + FxI32 curTriSizeNoGradient; /* special for _trisetup_nogradients */ +#endif /* !GLIDE_HW_TRI_SETUP || !GLIDE_PACKET3_TRI_SETUP */ + +#if GLIDE_MULTIPLATFORM + GrGCFuncs + curGCFuncs; /* Current dd Function pointer table */ +#endif + int initialized; + + struct { /* constant pool (minimizes cache misses) */ + float f0; + float fHalf; + float f1; + float f255; + float ftemp1, ftemp2; /* temps to convert floats to ints */ + +#if GLIDE_PACKED_RGB +#define kPackBiasA _GlideRoot.pool.fBiasHi +#define kPackBiasR _GlideRoot.pool.fBiasHi +#define kPackBiasG _GlideRoot.pool.fBiasHi +#define kPackBiasB _GlideRoot.pool.fBiasLo + +#define kPackShiftA 16UL +#define kPackShiftR 8UL +#define kPackShiftG 0UL +#define kPackShiftB 0UL + +#define kPackMaskA 0x00FF00UL +#define kPackMaskR 0x00FF00UL +#define kPackMaskG 0x00FF00UL +#define kPackMaskB 0x00FFUL + + float fBiasHi; + float fBiasLo; +#endif /* GLIDE_PACKED_RGB */ + } pool; + + struct { /* environment data */ + FxBool ignoreReopen; + FxBool triBoundsCheck; /* check triangle bounds */ + FxBool noSplash; /* don't draw it */ + FxBool shamelessPlug; /* translucent 3Dfx logo in lower right */ + FxI32 swapInterval; /* swapinterval override */ + FxI32 swFifoLWM; + FxU32 snapshot; /* register trace snapshot */ + FxBool disableDitherSub; /* Turn off dither subtraction? */ + FxBool texLodDither; /* Always do lod-dithering */ + + /* Force alternate buffer strategy */ + FxI32 nColorBuffer; + FxI32 nAuxBuffer; + } environment; + + struct { + FxU32 bufferSwaps; /* number of buffer swaps */ + FxU32 pointsDrawn; + FxU32 linesDrawn; + FxU32 trisProcessed; + FxU32 trisDrawn; + + FxU32 texDownloads; /* number of texDownload calls */ + FxU32 texBytes; /* number of texture bytes downloaded */ + + FxU32 palDownloads; /* number of palette download calls */ + FxU32 palBytes; /* number of palette bytes downloaded */ + + FxU32 nccDownloads; /* # of NCC palette download calls */ + FxU32 nccBytes; /* # of NCC palette bytes downloaded */ + +#if USE_PACKET_FIFO + FxU32 fifoWraps; + FxU32 fifoWrapDepth; + FxU32 fifoStalls; + FxU32 fifoStallDepth; +#endif /* USE_PACKET_FIFO */ + } stats; + + GrHwConfiguration hwConfig; + + FxU32 gcNum; /* # of actual boards mapped */ + FxU32 gcMap[MAX_NUM_SST]; /* Logical mapping between selectable + * sst's and actual boards. + */ + GrGC GCs[MAX_NUM_SST]; /* one GC per board */ +}; + +extern struct _GlideRoot_s GR_CDECL _GlideRoot; +#if GLIDE_MULTIPLATFORM +extern GrGCFuncs _curGCFuncs; +#endif +/*==========================================================================*/ +/* Macros for declaring functions */ +#define GR_DDFUNC(name, type, args) \ + type FX_CSTYLE name args + +#define GR_ENTRY(name, type, args) \ + FX_EXPORT type FX_CSTYLE name args + +#define GR_DIENTRY(name, type, args) \ + FX_EXPORT type FX_CSTYLE name args + +#define GR_STATE_ENTRY(name, type, args) \ + GR_ENTRY(name, type, args) + +/*==========================================================================*/ + +#define STATE_REQUIRES_IT_DRGB FXBIT(0) +#define STATE_REQUIRES_IT_ALPHA FXBIT(1) +#define STATE_REQUIRES_OOZ FXBIT(2) +#define STATE_REQUIRES_OOW_FBI FXBIT(3) +#define STATE_REQUIRES_W_TMU0 FXBIT(4) +#define STATE_REQUIRES_ST_TMU0 FXBIT(5) +#define STATE_REQUIRES_W_TMU1 FXBIT(6) +#define STATE_REQUIRES_ST_TMU1 FXBIT(7) +#define STATE_REQUIRES_W_TMU2 FXBIT(8) +#define STATE_REQUIRES_ST_TMU2 FXBIT(9) + +#define GR_TMUMASK_TMU0 FXBIT(GR_TMU0) +#define GR_TMUMASK_TMU1 FXBIT(GR_TMU1) +#define GR_TMUMASK_TMU2 FXBIT(GR_TMU2) + +/* +** Parameter gradient offsets +** +** These are the offsets (in bytes)of the DPDX and DPDY registers from +** from the P register +*/ +#ifdef GLIDE_USE_ALT_REGMAP +#define DPDX_OFFSET 0x4 +#define DPDY_OFFSET 0x8 +#else +#define DPDX_OFFSET 0x20 +#define DPDY_OFFSET 0x40 +#endif + +#if (GLIDE_PLATFORM & GLIDE_HW_SST1) +#define GLIDE_DRIVER_NAME "Voodoo Graphics" +#elif (GLIDE_PLATFORM & GLIDE_HW_SST96) +#define GLIDE_DRIVER_NAME "Voodoo Rush" +#elif (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define GLIDE_DRIVER_NAME "Voodoo" +#else +#define GLIDE_DRIVER_NAME "Unknown" +#endif + +/*==========================================================================*/ +#ifndef FX_GLIDE_NO_FUNC_PROTO + +void _grMipMapInit(void); + +#if GLIDE_DISPATCH_SETUP +FxI32 FX_CSTYLE +_trisetup_cull(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); + +#define TRISETUP_NORGB(__cullMode) (((__cullMode) == GR_CULL_DISABLE) \ + ? _trisetup \ + : _trisetup_cull) + +#if GLIDE_PACKED_RGB +FxI32 FX_CSTYLE +_trisetup_cull_rgb(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup_cull_argb(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup_rgb(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup_argb(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); + +#define TRISETUP_RGB(__cullMode) (((__cullMode) == GR_CULL_DISABLE) \ + ? _trisetup_rgb \ + : _trisetup_cull_rgb) +#define TRISETUP_ARGB(__cullMode) (((__cullMode) == GR_CULL_DISABLE) \ + ? _trisetup_argb \ + : _trisetup_cull_argb) + +#else /* !GLIDE_PACKED_RGB */ +#define TRISETUP_RGB(__cullMode) TRISETUP_NORGB(__cullMode) +#define TRISETUP_ARGB(__cullMode) TRISETUP_NORGB(__cullMode) +#endif /* !GLIDE_PACKED_RGB */ +#define TRISETUP (*gc->cmdTransportInfo.triSetupProc) +#else /* !GLIDE_DISPATCH_SETUP */ +FxI32 FX_CSTYLE +_trisetup_asm(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup_nogradients(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); + +/* GMT: BUG need to make this dynamically switchable + That is not a bug. It is an opinion! + */ +#if GLIDE_USE_C_TRISETUP +# if (GLIDE_PLATFORM & GLIDE_HW_CVG) && USE_PACKET_FIFO +# define TRISETUP _trisetup_nogradients +# else /* !((GLIDE_PLATFORM & GLIDE_HW_CVG) && USE_PACKET_FIFO) */ +# define TRISETUP _trisetup_nogradients +# endif /* !((GLIDE_PLATFORM & GLIDE_HW_CVG) && USE_PACKET_FIFO) */ +#else /* !GLIDE_USE_C_TRISETUP */ +# define TRISETUP _trisetup_asm +#endif /* !GLIDE_USE_C_TRISETUP */ +#endif /* !GLIDE_DISPATCH_SETUP */ +#endif /* FX_GLIDE_NO_FUNC_PROTO */ + +/*==========================================================================*/ +/* +** Function Prototypes +*/ +#ifdef GLIDE_DEBUG +FxBool +_grCanSupportDepthBuffer(void); +#endif + +void +_grClipNormalizeAndGenerateRegValues(FxU32 minx, FxU32 miny, FxU32 maxx, + FxU32 maxy, FxU32 *clipLeftRight, + FxU32 *clipBottomTop); + +void +_grSwizzleColor(GrColor_t *color); + +void +_grDisplayStats(void); + +void +_GlideInitEnvironment(void); + +void FX_CSTYLE +_grColorCombineDelta0Mode(FxBool delta0Mode); + +void +_doGrErrorCallback(const char *name, const char *msg, FxBool fatal); + +void _grErrorDefaultCallback(const char *s, FxBool fatal); + +#ifdef __WIN32__ +void _grErrorWindowsCallback(const char *s, FxBool fatal); +#endif /* __WIN32__ */ + +extern void +(*GrErrorCallback)(const char *string, FxBool fatal); + +void GR_CDECL +_grFence(void); + +int +_guHeapCheck(void); + +void FX_CSTYLE +_grRebuildDataList(void); + +void +_grReCacheFifo(FxI32 n); + +FxI32 GR_CDECL +_grSpinFifo(FxI32 n); + +void +_grShamelessPlug(void); + +FxBool +_grSstDetectResources(void); + +FxU16 +_grTexFloatLODToFixedLOD(float value); + +void FX_CSTYLE +_grTexDetailControl(GrChipID_t tmu, FxU32 detail); + +void FX_CSTYLE +_grTexDownloadNccTable(GrChipID_t tmu, FxU32 which, + const GuNccTable *ncc_table, + int start, int end); + +void FX_CSTYLE +_grTexDownloadPalette(GrChipID_t tmu, + GuTexPalette *pal, + int start, int end); + +FxU32 +_grTexCalcBaseAddress( + FxU32 start_address, GrLOD_t largeLod, + GrAspectRatio_t aspect, GrTextureFormat_t fmt, + FxU32 odd_even_mask); + +void +_grTexForceLod(GrChipID_t tmu, int value); + +FxU32 +_grTexTextureMemRequired(GrLOD_t small_lod, GrLOD_t large_lod, + GrAspectRatio_t aspect, GrTextureFormat_t format, + FxU32 evenOdd); + +void FX_CSTYLE +_grUpdateParamIndex(void); + +/* ddgump.c */ +void FX_CSTYLE +_gumpTexCombineFunction(int virtual_tmu); + +/* disst.c - this is an un-documented external for arcade developers */ +extern FX_ENTRY void FX_CALL +grSstVidMode(FxU32 whichSst, FxVideoTimingInfo* vidTimings); + +/* glfb.c */ +extern FxBool +_grLfbWriteRegion(FxBool pixPipelineP, + GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y, + GrLfbSrcFmt_t src_format, + FxU32 src_width, FxU32 src_height, + FxI32 src_stride, void *src_data); + +/* gglide.c - Flushes the current state in gc->state.fbi_config to the hw. + */ +extern void +_grFlushCommonStateRegs(void); + +#if USE_PACKET_FIFO +/* cvg.c */ +extern void +_grSet32(volatile FxU32* const sstAddr, const FxU32 val); + +extern FxU32 +_grGet32(volatile FxU32* const sstAddr); + +typedef struct cmdTransportInfo GrCmdTransportInfo; +extern void +_grGetCommandTransportInfo(GrCmdTransportInfo*); +#endif /* USE_PACKET_FIFO */ + +/*==========================================================================*/ +/* GMT: have to figure out when to include this and when not to +*/ +#if GLIDE_DEBUG || GLIDE_ASSERT || GLIDE_SANITY_ASSERT || GLIDE_SANITY_SIZE +#define DEBUG_MODE 1 +// #include +#endif + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) || (GLIDE_PLATFORM & GLIDE_HW_H3) + +#if ASSERT_FAULT +#define ASSERT_FAULT_IMMED(__x) if (!(__x)) { \ + *(FxU32*)NULL = 0; \ + _grAssert(#__x, __FILE__, __LINE__); \ + } +#else +#define ASSERT_FAULT_IMMED(__x) GR_ASSERT(__x) +#endif + +#if !USE_PACKET_FIFO +/* NOTE: fifoFree is the number of entries, each is 8 bytes */ +#define GR_CHECK_FOR_ROOM(n,p) \ +{ \ + FxI32 fifoFree = gc->state.fifoFree - (n); \ + if (fifoFree < 0) \ + fifoFree = _grSpinFifo(n); \ + gc->state.fifoFree = fifoFree;\ +} +#elif USE_PACKET_FIFO +/* Stuff to manage the command fifo on cvg + * + * NB: All of the addresses are in 'virtual' address space, and the + * sizes are in bytes. + */ + +/* The Voodoo^2 fifo is 4 byte aligned */ +#define FIFO_ALIGN_MASK 0x03 + +/* We claim space at the end of the fifo for: + * 1 nop (2 32-bit words) + * 1 jmp (1 32-bit word) + * 1 pad word + */ +#define FIFO_END_ADJUST (sizeof(FxU32) << 3) + +/* NB: This should be used sparingly because it does a 'real' hw read + * which is *SLOW*. + * + * NB: This address is always in sli master relative coordinates. + */ +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define HW_FIFO_PTR(__masterP)\ +((FxU32)gc->cmdTransportInfo.fifoStart + \ + (GET(((SstRegs*)((__masterP) \ + ? gc->reg_ptr \ + : gc->slave_ptr))->cmdFifoReadPtr) - \ + gc->cmdTransportInfo.fifoOffset)) +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) +# define HW_FIFO_PTR(__masterP) \ + ((FxU32)gc->cmdTransportInfo.fifoStart +\ + (GET(((SstCRegs*)(gc->hwDep.h3Dep.cRegs))->cmdFifo0.readPtrL)) - \ + gc->cmdTransportInfo.fifoOffset) +#else +# error "Define HW_FIFO_PTR for this hardware!" +#endif + +#if FIFO_ASSERT_FULL +extern const FxU32 kFifoCheckMask; +extern FxU32 gFifoCheckCount; + +#define FIFO_ASSERT() \ +if ((gFifoCheckCount++ & kFifoCheckMask) == 0) { \ + const FxU32 cmdFifoDepth = GR_GET(((SstRegs*)(gc->reg_ptr))->cmdFifoDepth); \ + const FxU32 maxFifoDepth = ((gc->cmdTransportInfo.fifoSize - FIFO_END_ADJUST) >> 2); \ + if(cmdFifoDepth > maxFifoDepth) { \ + gdbg_printf(__FILE__"(%ld): cmdFifoDepth > size: 0x%X : 0x%X : (0x%X : 0x%X)\n", \ + __LINE__, cmdFifoDepth, maxFifoDepth, \ + HW_FIFO_PTR(FXTRUE), gc->cmdTransportInfo.fifoPtr); \ + ASSERT_FAULT_IMMED(cmdFifoDepth <= maxFifoDepth); \ + } else if (cmdFifoDepth + (gc->cmdTransportInfo.fifoRoom >> 2) > maxFifoDepth) { \ + gdbg_printf(__FILE__"(%ld): cmdFifoDepth + fifoRoom > size: (0x%X : 0x%X) : 0x%X\n", \ + __LINE__, cmdFifoDepth, (gc->cmdTransportInfo.fifoRoom >> 2), maxFifoDepth); \ + ASSERT_FAULT_IMMED(cmdFifoDepth + (gc->cmdTransportInfo.fifoRoom >> 2) <= maxFifoDepth); \ + } \ +} \ +ASSERT_FAULT_IMMED(HW_FIFO_PTR(FXTRUE) >= (FxU32)gc->cmdTransportInfo.fifoStart); \ +ASSERT_FAULT_IMMED(HW_FIFO_PTR(FXTRUE) < (FxU32)gc->cmdTransportInfo.fifoEnd); \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoRoom < gc->cmdTransportInfo.fifoSize); \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoPtr < (FxU32)gc->cmdTransportInfo.fifoEnd) +#else /* !FIFO_ASSERT_FULL */ +#define FIFO_ASSERT() \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoRoom < gc->cmdTransportInfo.fifoSize); \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoPtr < (FxU32)gc->cmdTransportInfo.fifoEnd) +#endif /* !FIFO_ASSERT_FULL */ + +void GR_CDECL +_FifoMakeRoom(const FxI32 blockSize, const char* fName, const int fLine); + +#define GR_CHECK_FOR_ROOM(__n, __p) \ +do { \ + const FxU32 writeSize = (__n) + ((__p) * sizeof(FxU32)); /* Adjust for size of hdrs */ \ + ASSERT(((FxU32)(gc->cmdTransportInfo.fifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + ASSERT(writeSize < gc->cmdTransportInfo.fifoSize - sizeof(FxU32)); \ + FIFO_ASSERT(); \ + if (gc->cmdTransportInfo.fifoRoom < (FxI32)writeSize) { \ + GDBG_INFO(280, "Fifo Addr Check: (0x%X : 0x%X)\n", \ + gc->cmdTransportInfo.fifoRoom, writeSize); \ + _FifoMakeRoom(writeSize, __FILE__, __LINE__); \ + } \ + ASSERT((FxU32)gc->cmdTransportInfo.fifoRoom >= writeSize); \ + FIFO_ASSERT(); \ +} while(0) +#else +#error "GR_CHECK_FOR_ROOM not defined" +#endif + +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) + +#define GR_CHECK_FOR_ROOM(__n, __p) + +#endif /* GLIDE_PLATFORM & GLIDE_HW_?? */ + +#if GLIDE_SANITY_SIZE +#if USE_PACKET_FIFO + +#if GLIDE_USE_SHADOW_FIFO +#define GR_CHECK_SHADOW_FIFO \ + if ((gc != NULL) && (gc->cmdTransportInfo.fifoShadowPtr != NULL)) \ + ASSERT_FAULT_IMMED((((FxU32)gc->cmdTransportInfo.fifoPtr) & (kDebugFifoSize - 1)) == \ + (((FxU32)gc->cmdTransportInfo.fifoShadowPtr) & (kDebugFifoSize - 1))) +#else /* !GLIDE_USE_SHADOW_FIFO */ +#define GR_CHECK_SHADOW_FIFO +#endif /* !GLIDE_USE_SHADOW_FIFO */ + +#define GR_CHECK_FIFO_PTR() \ + if((FxU32)gc->cmdTransportInfo.fifoPtr != gc->checkPtr + gc->checkCounter) \ + GDBG_ERROR("GR_ASSERT_FIFO", "(%s : %d) : " \ + "fifoPtr should be 0x%X (0x%X : 0x%X) but is 0x%X\n", \ + __FILE__, __LINE__, \ + gc->checkPtr + gc->checkCounter, gc->checkPtr, gc->checkCounter, \ + gc->cmdTransportInfo.fifoPtr); \ + GR_CHECK_SHADOW_FIFO; \ + ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoPtr == gc->checkPtr + gc->checkCounter) +#define GR_SET_FIFO_PTR(__n, __p) \ + gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr; \ + gc->checkCounter = ((__n) + ((__p) << 2)) +#else +#define GR_CHECK_FIFO_PTR() +#define GR_SET_FIFO_PTR(__n, __p) +#endif + +#define GR_CHECK_SIZE() \ + if(gc->counter != gc->expected_counter) \ + GDBG_ERROR("GR_ASSERT_SIZE","byte counter should be %d but is %d\n", \ + gc->expected_counter,gc->counter); \ + GR_CHECK_FIFO_PTR(); \ + gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr; \ + gc->checkCounter = 0; \ + ASSERT(gc->counter == gc->expected_counter); \ + gc->counter = gc->expected_counter = 0 + +#define GR_SET_EXPECTED_SIZE(n,p) \ + ASSERT(gc->counter == 0); \ + ASSERT(gc->expected_counter == 0); \ + GR_CHECK_FOR_ROOM(n,p); \ + gc->expected_counter = n; \ + GR_SET_FIFO_PTR(n, p) + +#define GR_INC_SIZE(n) gc->counter += n +#else + /* define to do nothing */ + #define GR_CHECK_SIZE() + #define GR_SET_EXPECTED_SIZE(n,p) GR_CHECK_FOR_ROOM(n,p) + #define GR_INC_SIZE(n) +#endif + +#define GR_DCL_GC GrGC *gc = _GlideRoot.curGC +#define GR_DCL_HW SstRegs *hw = (SstRegs *)gc->reg_ptr + +#ifdef DEBUG_MODE +#define ASSERT(exp) GR_ASSERT(exp) + +#define GR_BEGIN_NOFIFOCHECK(name,level) \ + GR_DCL_GC; \ + GR_DCL_HW; \ + const FxI32 saveLevel = gc->myLevel; \ + static char myName[] = name; \ + GR_ASSERT(gc != NULL); \ + GR_ASSERT(hw != NULL); \ + gc->myLevel = level; \ + gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr; \ + GDBG_INFO(gc->myLevel,myName); \ + FXUNUSED(saveLevel); \ + FXUNUSED(hw) +#define GR_TRACE_EXIT(__n) \ + gc->myLevel = saveLevel; \ + GDBG_INFO(281, "%s --done---------------------------------------\n", __n) +#define GR_TRACE_RETURN(__l, __n, __v) \ + gc->myLevel = saveLevel; \ + GDBG_INFO((__l), "%s() => 0x%x---------------------\n", (__n), (__v), (__v)) +#else /* !DEBUG_MODE */ +#define ASSERT(exp) +#define GR_BEGIN_NOFIFOCHECK(name,level) \ + GR_DCL_GC; \ + GR_DCL_HW; \ + FXUNUSED(hw) +#define GR_TRACE_EXIT(__n) +#define GR_TRACE_RETURN(__l, __n, __v) +#endif /* !DEBUG_MODE */ + +#define GR_BEGIN(name,level,size, packetNum) \ + GR_BEGIN_NOFIFOCHECK(name,level); \ + GR_SET_EXPECTED_SIZE(size, packetNum) + +#define GR_END() {GR_CHECK_SIZE(); GR_TRACE_EXIT(myName);} + +#define GR_RETURN(val) \ + if (GDBG_GET_DEBUGLEVEL(gc->myLevel)) { \ + GR_CHECK_SIZE(); \ + } \ + else \ + GR_END(); \ + GR_TRACE_RETURN(gc->myLevel, myName, val); \ + return val + +#if defined(GLIDE_SANITY_ASSERT) +#define GR_ASSERT(exp) ((void)((!(exp)) ? (_grAssert(#exp, __FILE__, __LINE__),0) : 0xFFFFFFFF)) +#else +#define GR_ASSERT(exp) ((void)(0 && ((FxU32)(exp)))) +#endif + +#define INTERNAL_CHECK(__name, __cond, __msg, __fatalP) \ + if (__cond) _doGrErrorCallback(__name, __msg, __fatalP) + +#if defined(GLIDE_DEBUG) +#define GR_CHECK_F(name,condition,msg) INTERNAL_CHECK(name, condition, msg, FXTRUE) +#define GR_CHECK_W(name,condition,msg) INTERNAL_CHECK(name, condition, msg, FXFALSE) +#else +#define GR_CHECK_F(name,condition,msg) +#define GR_CHECK_W(name,condition,msg) +#endif + +#if GLIDE_CHECK_COMPATABILITY +#define GR_CHECK_COMPATABILITY(__name, __cond, __msg) INTERNAL_CHECK(__name, __cond, __msg, FXTRUE) +#else +#define GR_CHECK_COMPATABILITY(__name, __cond, __msg) GR_CHECK_F(__name, __cond, __msg) +#endif /* !GLIDE_CHECK_COMPATABILITY */ + +/* macro define some basic and common GLIDE debug checks */ +#define GR_CHECK_TMU(name,tmu) \ + GR_CHECK_COMPATABILITY(name, tmu < GR_TMU0 || tmu >= gc->num_tmu , "invalid TMU specified") + +void +_grAssert(char *, char *, int); + +#if USE_PACKET_FIFO +#ifdef GDBG_INFO_ON +void _grFifoWriteDebug(FxU32 addr, FxU32 val, FxU32 fifoPtr); +#define DEBUGFIFOWRITE(a,b,c) \ +_grFifoWriteDebug((FxU32) a, (FxU32) b, (FxU32) c) +void _grFifoFWriteDebug(FxU32 addr, float val, FxU32 fifoPtr); +#define DEBUGFIFOFWRITE(a,b,c) \ +_grFifoFWriteDebug((FxU32) a, (float) b, (FxU32) c) +#else /* ~GDBG_INFO_ON */ +#define DEBUGFIFOWRITE(a,b,c) +#define DEBUGFIFOFWRITE(a,b,c) +#endif /* !GDBG_INFO_ON */ +#endif /* USE_PACKET_FIFO */ + +#if USE_PACKET_FIFO && GLIDE_USE_SHADOW_FIFO + +#undef SET +#define SET(d, s) \ +do { \ + GR_DCL_GC; \ + GR_DCL_HW; \ + volatile FxU32* __u32P = (volatile FxU32*)&(d); \ + const FxU32 __u32Val = (s); \ + if ((__u32P != &hw->swapbufferCMD) && (gc->cmdTransportInfo.fifoShadowPtr != NULL)) { \ + *gc->cmdTransportInfo.fifoShadowPtr++ = __u32Val; \ + } \ + *__u32P = __u32Val; \ +} while(0) + +#undef SETF +#define SETF(d, s) \ +do { \ + volatile float* __floatP = (volatile float*)(&(d)); \ + const float __floatVal = (s); \ + GR_DCL_GC; \ + if (gc->cmdTransportInfo.fifoShadowPtr != NULL) { \ + *(float*)gc->cmdTransportInfo.fifoShadowPtr = __floatVal; \ + gc->cmdTransportInfo.fifoShadowPtr++; \ + } \ + *__floatP = __floatVal; \ +} while(0) + +#undef SET16 +#define SET16(d, s) SET(d, (FxU32)s) +#endif /* USE_PACKET_FIFO && GLIDE_USE_DEBUG_FIFO */ + +#if SET_BSWAP +#undef GET +#undef GET16 +#undef SET +#undef SET16 +#undef SETF + +#if __POWERPC__ && defined(__MWERKS__) +#define GET(s) __lwbrx( (void*)&(s), 0 ) +#define GET16(s) __lwbrx( (void*)&(s), 0 ) +#define SET(d, s) __stwbrx((s), (void*)&(d), 0) +#define SET16(d, s) __sthbrx((s), (void*)&(d), 0 ) +#define SETF(d, s) \ + { \ + const float temp = (s); \ + __stwbrx( *((FxU32*)&temp), (void*)&(d), 0 ); \ + } +#define SET_LINEAR(d, s) SET((d), (s)) +#define SET_LINEAR_16(d, s) SET((d), ((((FxU32)(s)) >> 16UL) | \ + (((FxU32)(s)) << 16UL))) +#define SET_LINEAR_8(d, s) ((d) = (s)) +#else /* !defined(__MWERKS__) && POWERPC */ +#error "Define byte swapped macros for GET/SET" +#endif /* !defined(__MWERKS__) && POWERPC */ +#endif /* SET_BSWAP */ + +#if GLIDE_USE_DEBUG_FIFO +#define kDebugFifoSize 0x1000UL +#endif /* GLIDE_USE_DEBUG_FIFO */ + +#ifndef SET_LINEAR +#define SET_LINEAR(__addr, __val) SET(__addr, __val) +#define SET_LINEAR_16(__addr, __val) SET(__addr, __val) +#define SET_LINEAR_8(__addr, __val) SET(__addr, __val) +#endif /* !defined(SET_LINEAR) */ + +/* Extract the fp exponent from a floating point value. + * NB: The value passed to this macro must be convertable + * into an l-value. + */ +#define kFPExpMask 0x7F800000UL +#define kFPZeroMask 0x80000000UL +#define kFPExpShift 0x17UL +#define FP_FLOAT_EXP(__fpVal) ((FxU32)(((*(const FxU32*)(&(__fpVal))) & kFPExpMask) >> kFPExpShift)) +#define FP_FLOAT_ZERO(__fpVal) (((*(const FxU32*)(&(__fpVal))) & ~kFPZeroMask) == 0x00) + +/* The two most commonly defined macros in the known universe */ +#define MIN(__x, __y) (((__x) < (__y)) ? (__x) : (__y)) +#define MAX(__x, __y) (((__x) < (__y)) ? (__y) : (__x)) + +/* Simple macro to make selecting a value against a boolean flag + * simpler w/o a conditional. + * + * NB: This requires that the boolean value being passed in be the + * result of one of the standard relational operators. + */ +#define MaskSelect(__b, __val) (~(((FxU32)(__b)) - 1UL) & (__val)) + +/* Chipfield ids that glide uses. */ +#define kChipFieldShift (8UL + 3UL) +typedef enum { + eChipBroadcast = 0x00UL, + eChipFBI = 0x01UL, + eChipTMU0 = 0x02UL, + eChipTMU1 = 0x04UL, + eChipTMU2 = 0x08UL, + eChipAltBroadcast = 0x0FUL, +} FifoChipField; + +#if GLIDE_CHIP_BROADCAST && (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define BROADCAST_ID eChipAltBroadcast +#else +#define BROADCAST_ID eChipBroadcast +#endif + +/* Although these are named reg_group_xxx they are generic options for + * grouping register writes and should be fine w/ and w/o the fifo + * being enabled. + */ +#if GDBG_INFO_ON +#define REG_GROUP_DCL(__regMask, __regBase, __groupNum, __checkP) \ +const FxBool _checkP = (__checkP); \ +const FxU32 _regMask = (__regMask); \ +const FxU32 _groupNum = (__groupNum); \ +FxU32 _regCheckMask = (__regMask); \ +FxU32 _regBase = offsetof(SstRegs, __regBase) + +#define REG_GROUP_ASSERT(__regAddr, __val, __floatP) \ +{ \ + const FxU32 curRegAddr = offsetof(SstRegs, __regAddr); \ + const FxU32 curRegIndex = (curRegAddr - _regBase) >> 2; \ + const FxU32 curRegBit = (0x01UL << curRegIndex); \ + const float floatVal = (const float)(__val); \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X : 0x%X) : 0x%X\n", \ + curRegIndex, curRegAddr, *(const FxU32*)&floatVal); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT((_regMask & curRegBit) == curRegBit); /* reg allocated in mask */ \ + if (curRegIndex > 0) \ + GR_ASSERT(((0xFFFFFFFFUL >> (32 - curRegIndex)) & _regCheckMask) == 0x00); /* All previous regs done */ \ + _regCheckMask ^= curRegBit; /* Mark current reg */ \ +} +#else /* !GDBG_INFO_ON */ +#define REG_GROUP_DCL(__regMask, __regBase, __groupNum, __checkP) +#define REG_GROUP_ASSERT(__regAddr, __val, __floatP) +#endif /* !GDBG_INFO_ON */ + +#if GLIDE_HW_TRI_SETUP +enum { + kSetupStrip = 0x00, + kSetupFan = 0x01, + kSetupCullDisable = 0x00, + kSetupCullEnable = 0x02, + kSetupCullPositive = 0x00, + kSetupCullNegative = 0x04, + kSetupPingPongNorm = 0x00, + kSetupPingPongDisable = 0x08 +}; +#endif /* GLIDE_HW_TRI_SETUP */ + +#if USE_PACKET_FIFO + +/* CVG has a problem when using the chipfield to address multiple + * tmu's and using the tsu which does not send things to different + * tmu's. We work around this by using broadcast 0xF rather than 0x0 + * in the chipfield. This macro should build a compile-time constant + * bit value that can be or-ed w/ any dynamic data. + */ +#define FIFO_REG(__chipField, __field) \ + ((((FxU32)offsetof(SstRegs, __field)) << 1) | \ + (((FxU32)(__chipField)) << kChipFieldShift)) + +/* The REG_GROUP_XXX macros do writes to a monotonically increasing + * set of registers. There are three flavors of the macros w/ + * different restrictions etc. + * + * NB: Care must be taken to order the REG_GROUP_SET macro uses to + * match the actual register order, otherwise all hell breaks loose. + */ + +/* Write to __groupNum registers (max 14) starting at __regBase under + * the control of __groupMask (lsb->msb). + */ +#define REG_GROUP_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, \ + __groupMask, (((__groupMask) << SSTCP_PKT4_MASK_SHIFT) | \ + FIFO_REG(__chipId, __regBase) | \ + SSTCP_PKT4), \ + FXTRUE) + +/* Same as the non-NO_CHECK variant, but GR_SET_EXPECTED_SIZE must + * have already been called to allocate space for this write. + */ +#define REG_GROUP_NO_CHECK_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_ASSERT(gc->expected_counter >= (FxI32)((__groupNum) * sizeof(FxU32))); \ +REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, \ + __groupMask, \ + (((__groupMask) << SSTCP_PKT4_MASK_SHIFT) | \ + FIFO_REG(__chipId, __regBase) | \ + SSTCP_PKT4), \ + FXFALSE) + +/* Register writes (<= 32) sequentially starting at __regBase */ +#define REG_GROUP_LONG_BEGIN(__chipId, __regBase, __groupNum) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 32)); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, \ + (0xFFFFFFFF >> (32 - (__groupNum))), \ + (((__groupNum) << SSTCP_PKT1_NWORDS_SHIFT) | \ + FIFO_REG(__chipId, __regBase) | \ + SSTCP_INC | \ + SSTCP_PKT1), \ + FXTRUE) + +#define REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, __groupMask, __pktHdr, __checkP) \ +{ \ + GR_DCL_GC; \ + volatile FxU32* _regGroupFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + REG_GROUP_DCL(__groupMask, __regBase, __groupNum, __checkP); \ + GR_ASSERT(((__pktHdr) & 0xE0000000UL) == 0x00UL); \ + FIFO_ASSERT(); \ + GDBG_INFO(120, "REG_GROUP_BEGIN: (0x%X : 0x%X) : (0x%X - 0x%X : 0x%X) : (0x%X : 0x%X)\n", \ + (__pktHdr), (__groupMask), \ + FIFO_REG(__chipId, __regBase), __chipId, offsetof(SstRegs, __regBase), \ + (FxU32)gc->cmdTransportInfo.fifoPtr, gc->cmdTransportInfo.fifoRoom); \ + SET(*_regGroupFifoPtr++, (__pktHdr)) + +#define REG_GROUP_SET(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXFALSE); \ + FXUNUSED(__regBase); \ + SET(*_regGroupFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define REG_GROUP_SETF(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXTRUE); \ + FXUNUSED(__regBase); \ + SETF(*(FxFloat*)_regGroupFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) + +#if GLIDE_FP_CLAMP +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ +do { \ + const FxU32 fpClampVal = FP_FLOAT_CLAMP(__val); \ + REG_GROUP_ASSERT(__regAddr, fpClampVal, FXTRUE); \ + FXUNUSED(__regBase); \ + SETF(*(FxFloat*)_regGroupFifoPtr++, fpClampVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) +#else +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ + REG_GROUP_SETF(__regBase, __regAddr, __val) +#endif + +#define REG_GROUP_NO_CHECK_END() \ + ASSERT(!_checkP); \ + ASSERT((((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) >> 2) == _groupNum + 1); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = (FxU32*)_regGroupFifoPtr; \ + FIFO_ASSERT(); \ +} + +#define REG_GROUP_END() \ + ASSERT(_checkP); \ + ASSERT((((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) >> 2) == _groupNum + 1); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = (FxU32*)_regGroupFifoPtr; \ + GDBG_INFO(gc->myLevel + 200, "\tGroupEnd: (0x%X : 0x%X) : (0x%X : 0x%X)\n", \ + _regGroupFifoPtr, gc->cmdTransportInfo.fifoRoom, \ + HW_FIFO_PTR(FXTRUE), gc->cmdTransportInfo.fifoPtr); \ + FIFO_ASSERT(); \ +} \ +GR_CHECK_SIZE() + +#if !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE +/* Send all of the triangle parameters in a single cmd fifo packet to + * the chip until the tsu is fixed. + */ +#define kNumTriParam 0x1FUL + +#define TRI_NO_TSU_BEGIN(__floatP) \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * kNumTriParam, 1); \ +{ \ + FxU32* noTsuFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + volatile FxU32* regBaseAddr = &hw->FvA.x; \ + FIFO_ASSERT(); \ + GR_ASSERT(__floatP); \ + SET(*noTsuFifoPtr++, ((kNumTriParam << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + SSTCP_INC | /* sequential writes */ \ + FIFO_REG(BROADCAST_ID, FvA.x) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + GDBG_INFO(gc->myLevel, "TRI_NO_TSU_BEGIN: (fbiRegs->%svA : 0x%X)\n", \ + ((__floatP) ? "F" : ""), (FxU32)noTsuFifoPtr) + +#define TRI_NO_TSU_SET(__addr, __val) \ +do { \ + const FxU32 hwWriteAddr = (FxU32)(__addr); \ + ASSERT(hwWriteAddr == (FxU32)regBaseAddr); \ + SET(*noTsuFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_SETF(__addr, __val) \ +do { \ + const FxU32 hwWriteAddr = (FxU32)(__addr); \ + const FxFloat hwFloatVal = __val; \ + ASSERT(hwWriteAddr == (FxU32)regBaseAddr); \ + GDBG_INFO(gc->myLevel + 200, FN_NAME": FloatVal 0x%X : (0x%X : %g)\n", \ + ((FxU32)hwWriteAddr - (FxU32)hw) >> 2, \ + *(const FxU32*)&hwFloatVal, hwFloatVal); \ + SETF(*noTsuFifoPtr++, hwFloatVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_END() \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)noTsuFifoPtr - \ + (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = noTsuFifoPtr; \ + FIFO_ASSERT(); \ +} +#endif /* !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE */ + +#define STORE_FIFO(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((SstRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG(__chipId, __field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SET(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STORE_FIFO_INDEX(__chipId, __base, __regIndex, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((FxU32*)(__base))[__regIndex], __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + ((__chipId) << kChipFieldShift) | /* chip[14:10] */ \ + ((__regIndex) << 3) | /* Reg Num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SET(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STOREF_FIFO_INDEX(__chipId, __base, __regIndex, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOFWRITE(&((FxU32*)(__base))[__regIndex], __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + ((__chipId) << kChipFieldShift) | /* chip[14:10] */ \ + ((__regIndex) << 3) | /* Reg Num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SETF(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STORE16_FIFO(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 temp32 = (((FxU32)(__val)) & 0x0000FFFF); \ + FXUNUSED(__base); \ + ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((SstRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG(__chipId, __field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SET(*curFifoPtr++, temp32); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STOREF_FIFO(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOFWRITE(&((SstRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG(__chipId, __field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SETF(*(FxFloat*)curFifoPtr, __val); \ + curFifoPtr++; \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +/* There are now three different flavors of the packet 3 macros for + * your coding pleasure. In increasing order of complexity and control + * they are TRI_BEGIN, TRI_STRIP_BEGIN, TRI_PACKET_BEGIN. + * + * NB: All of these macros must be terminated w/ a matching invocation of + * TRI_END otherwise all sorts of hell will break loose. + * + * TRI_BEGIN: + * The simplest form that draws a single indepependent triangle whose + * parameters and culling are all the glide defaults for grDrawTriangle. + * + * TRI_STRIP_BEGIN: + * setupMode: [kSetupStrip | kSetupFan]. Culling defaults to the current + * glide setting, w/ strips/fans defaulting to ping-pong culling + * nVertex: The number of vertices for the current packet (max 15). + * vertexSize: Size in bytes of the parameters for the vertices making up + * the current packet. + * cmd: [SSTCP_PKT3_BDDBDD (Independent) + * SSTCP_PKT3_BDDDDD (Start strip/fan) + * SSTCP_PKT3_DDDDDD (Continue strip)] + * + * TRI_PACKET_BEGIN: + * setupMode: The same as with TRI_STRIP_BEGIN, except that the caller + * needs to specify the culling bits kSetupCullXXX/kSetupPingPongXXX. + * params: Bits matching the descriptin of the sMode register describing + * which parameters are specified in the packet. + * nVertex: See TRI_STRIP_BEGIN. + * vertexSize: See TRI_STRIP_BEGIN. + * cmd: See TRI_STRIP_BEGIN. + */ +#define TRI_PACKET_BEGIN(__setupMode, __params, __nVertex, __vertexSize, __cmd) \ +{ \ + FxU32* tPackPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 packetVal = (((__setupMode) << SSTCP_PKT3_SMODE_SHIFT) | /* [27:22] */ \ + (__params) | /* pack[28] params[21:10] */ \ + ((__nVertex) << SSTCP_PKT3_NUMVERTEX_SHIFT) | /* [9:6] */ \ + (__cmd) | /* command [5:3] */ \ + SSTCP_PKT3); /* type [2:0] */ \ + TRI_ASSERT_DECL(__nVertex, __vertexSize, packetVal); \ + SET(*tPackPtr++, packetVal) + +#define TRI_STRIP_BEGIN(__setupMode, __nVertex, __vertexSize, __cmd) \ +{ \ + FxU32* tPackPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 packetVal = (((__setupMode) << SSTCP_PKT3_SMODE_SHIFT) | /* [27:22] */ \ + ((__nVertex) << SSTCP_PKT3_NUMVERTEX_SHIFT) | /* [9:6] */ \ + (__cmd) | /* command [5:3] */ \ + gc->cmdTransportInfo.cullStripHdr); \ + TRI_ASSERT_DECL(__nVertex, __vertexSize, packetVal); \ + SET(*tPackPtr++, packetVal) + +#define TRI_BEGIN() \ +{ \ + FxU32* tPackPtr = gc->cmdTransportInfo.fifoPtr; \ + TRI_ASSERT_DECL(3, _GlideRoot.curVertexSize, gc->cmdTransportInfo.triPacketHdr); \ + SET(*tPackPtr++, gc->cmdTransportInfo.triPacketHdr) + +#if GDBG_INFO_ON +extern void +_grCVGFifoDump_TriHdr(const FxU32 triPacketHdr); +extern void +_grCVGFifoDump_Linear(const FxU32* const linearPacketAddr); + +#define DEBUGFIFODUMP_TRI(__packetAddr) _grCVGFifoDump_TriHdr(__packetAddr) +#define DEBUGFIFODUMP_LINEAR(__packetAddr) _grCVGFifoDump_Linear(__packetAddr) + +#define TRI_ASSERT_DECL(__nVerts, __vertSize, __packetHdr) \ + const FxU32 nVertex = (__nVerts); \ + const FxU32 sVertex = (__vertSize); \ + FxU32 pCount = 0; \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT(((FxU32)(tPackPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_ASSERT((((__nVerts) * (__vertSize)) + sizeof(FxU32)) <= (FxU32)gc->cmdTransportInfo.fifoRoom); \ + GR_ASSERT((((FxU32)tPackPtr) + ((__nVerts) * (__vertSize)) + sizeof(FxU32)) < \ + (FxU32)gc->cmdTransportInfo.fifoEnd); \ + GR_ASSERT(nVertex < 0x10); \ + GR_ASSERT(nVertex > 0x00); \ + GR_ASSERT(((__packetHdr) & 0xE0000000UL) == 0x00UL); \ + FIFO_ASSERT(); \ + GDBG_INFO(120, "Triangle(0x%X): (0x%X : 0x%X)\n", (__packetHdr), __nVerts, __vertSize); \ + DEBUGFIFODUMP_TRI(__packetHdr) +#define CLAMP_DUMP(__val, __floatVal) \ + pCount++; \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X) : V#: 0x%X - P#: 0x%X - ParamVal: (%f : 0x%X)\n", \ + (FxU32)tPackPtr, \ + ((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) / sVertex, \ + (((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) % sVertex) >> 2, \ + (((__val) < 786432.875) ? (__val) : ((__val) - 786432.875)), \ + (__floatVal)) +#define SETF_DUMP(__val) \ + pCount++; \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X) : V#: 0x%X - P#: 0x%X - ParamVal: %f\n", \ + (FxU32)tPackPtr, \ + ((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) / sVertex, \ + (((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) % sVertex) >> 2, \ + (((__val) < 786432.875) ? (__val) : ((__val) - 786432.875))) +#define SET_DUMP(__val) \ + pCount++; \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X) : V#: 0x%X - P#: 0x%X - ParamVal: 0x%X\n", \ + (FxU32)tPackPtr, \ + ((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) / sVertex, \ + (((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) % sVertex) >> 2, \ + (__val)) +#define TRI_ASSERT() \ + GR_ASSERT(pCount == (nVertex * (sVertex >> 2))); \ + ASSERT(((FxU32)tPackPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) == (nVertex * sVertex) + sizeof(FxU32)) +#else /* !GDBG_INFO_ON */ +#define DEBUGFIFODUMP_TRI(__packetAddr) +#define DEBUGFIFODUMP_LINEAR(__packetAddr) + +#define CLAMP_DUMP(__val, __floatVal) +#define SETF_DUMP(__val) +#define SET_DUMP(__val) + +#define TRI_ASSERT_DECL(__nVerts, __vertSize, __packetHdr) +#define TRI_ASSERT() +#endif /* !GDBG_INFO_ON */ + +/* Get the integer representation of the color component. Currently, + * following in the 'Glide is not an API for kids' tradition we'll + * probably do something silly like wrap around zero. + */ +#if GLIDE_PACKED_RGB +#define RGBA_COMP(__fpVal, __fpBias, __fpShift, __fpMask) \ +((_GlideRoot.pool.ftemp1 = (float)((float)(__fpVal) + (float)(__fpBias))), \ + GR_ASSERT((__fpVal) >= 0.0f), \ + GR_ASSERT((__fpVal) < 256.0f), \ + (((*(const FxU32*)&_GlideRoot.pool.ftemp1) & (__fpMask)) << (__fpShift))) + +#define RGBA_COMP_CLAMP(__fpVal, __compToken) \ + RGBA_COMP(__fpVal, kPackBias##__compToken, kPackShift##__compToken, kPackMask##__compToken) +#endif /* GLIDE_PACKED_RGB */ + +/* First stage tsu-subtractor chec/fix. + * Mmm..... sequence operator. + */ +#if GLIDE_FP_CLAMP +#define kFPClampThreshold 0x20UL +#define FP_FLOAT_CLAMP(__fpVal) ((FP_FLOAT_EXP(__fpVal) < kFPClampThreshold) \ + ? (_GlideRoot.stats.tsuValClamp++, 0x00UL) \ + : *(const FxU32*)(&(__fpVal))) + +#define TRI_SETF_CLAMP(__val) \ +do { \ + const FxU32 floatCastVal = FP_FLOAT_CLAMP(__val); \ + CLAMP_DUMP(__val, floatCastVal); \ + SET(*tPackPtr++, floatCastVal); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) +#else +#define TRI_SETF_CLAMP(__val) \ + TRI_SETF(__val) +#endif + +#define TRI_SETF(__val) \ +do { \ + SETF_DUMP(__val); \ + SETF(*tPackPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) + +#define TRI_SET(__val) \ +do { \ + SET_DUMP(__val); \ + SET(*tPackPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define TRI_END \ + TRI_ASSERT(); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)tPackPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = tPackPtr; \ + GDBG_INFO(gc->myLevel + 200, "\tTriEnd: (0x%X : 0x%X)\n", tPackPtr, gc->cmdTransportInfo.fifoRoom); \ + FIFO_ASSERT(); \ +} + +#define FIFO_LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN, __f, __l) \ +{ \ + FxU32* packetPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 __writeSize = (__numWords); /* Add size of packet header */ \ + const FxU32 hdr1 = ((__type) | \ + (((FxU32)(__maskW2)) << SSTCP_PKT5_BYTEN_W2_SHIFT) | \ + (((FxU32)(__maskWN)) << SSTCP_PKT5_BYTEN_WN_SHIFT) | \ + (__writeSize << SSTCP_PKT5_NWORDS_SHIFT) | \ + SSTCP_PKT5); \ + const FxU32 hdr2 = ((FxU32)(__addr)) & SSTCP_PKT5_BASEADDR; \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT(((FxU32)(packetPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_ASSERT((__numWords) > 0); /* packet size */ \ + GR_ASSERT((__numWords) < ((0x01 << 19) - 2)); \ + GR_ASSERT((((__numWords) + 2) << 2) <= (FxU32)gc->cmdTransportInfo.fifoRoom); \ + GR_ASSERT(((FxU32)packetPtr + (((__numWords) + 2) << 2)) < \ + (FxU32)gc->cmdTransportInfo.fifoEnd); \ + GR_ASSERT((hdr2 & 0xE0000000UL) == 0x00UL); \ + GR_ASSERT((((FxU32)(__type)) >= ((FxU32)kLinearWriteLFB)) && /* packet type */ \ + (((FxU32)(__type)) <= ((FxU32)kLinearWriteTex))); \ + FIFO_ASSERT(); \ + GDBG_INFO(120, "LinearWrite(0x%X : 0x%X)\n", hdr1, hdr2); \ + GDBG_INFO(gc->myLevel + 200, "\tFile: %s - Line: %ld\n", __f, __l); \ + GDBG_INFO(gc->myLevel + 200, "\tType: 0x%X\n", (FxU32)(__type)); \ + GDBG_INFO(gc->myLevel + 200, "\tAddr: 0x%X\n", (FxU32)(__addr)); \ + GDBG_INFO(gc->myLevel + 200, "\tMaskW2: 0x%X\n", (FxU32)(__maskW2)); \ + GDBG_INFO(gc->myLevel + 200, "\tMaskWN: 0x%X\n", (FxU32)(__maskWN)); \ + GDBG_INFO(gc->myLevel + 200, "\twriteSize: 0x%X\n", __writeSize); \ + GDBG_INFO(gc->myLevel + 200, "\thdr 1: 0x%X\n", hdr1); \ + GDBG_INFO(gc->myLevel + 200, "\thdr 2: 0x%X\n", hdr2); \ + SET(*packetPtr++, hdr1); \ + SET(*packetPtr++, hdr2); \ + GR_INC_SIZE(sizeof(FxU32)) + +#define FIFO_LINEAR_WRITE_SET(__val) \ +do { \ + GDBG_INFO(gc->myLevel + 205, "\t0x%X : 0x%X\n", packetPtr, (__val)); \ + SET_LINEAR(*packetPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define FIFO_LINEAR_WRITE_SET_16(__val) \ +do { \ + GDBG_INFO(gc->myLevel + 205, "\t0x%X : 0x%X\n", packetPtr, (__val)); \ + SET_LINEAR_16(*packetPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define FIFO_LINEAR_WRITE_SET_8(__val) \ +do { \ + GDBG_INFO(gc->myLevel + 205, "\t0x%X : 0x%X\n", packetPtr, (__val)); \ + SET_LINEAR_8(*packetPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define FIFO_LINEAR_WRITE_END \ + DEBUGFIFODUMP_LINEAR(gc->cmdTransportInfo.fifoPtr); \ + GR_ASSERT((((FxU32)packetPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) >> 2) == __writeSize + 2); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)packetPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = packetPtr; \ + GDBG_INFO(gc->myLevel + 200, "\tLinearEnd: (0x%X : 0x%X)\n", \ + packetPtr, gc->cmdTransportInfo.fifoRoom); \ + FIFO_ASSERT(); \ +} + +# define GR_GET(s) GET(s) +# define GR_GET16(s) ((FxU16)GET16(s)) +# define GR_SET(c, h, f, s) STORE_FIFO(c, h, f, s) +# define GR_SET_INDEX(c, h, r, s) STORE_FIFO_INDEX(c, h, r, s) +# define GR_SET16(c, h, f, s) STORE16_FIFO(c, h, f, s) +# define GR_SETF(c, h, f, s) STOREF_FIFO(c, h, f, s) +# define GR_SETF_INDEX(c, h, r, s) STOREF_FIFO_INDEX(c, h, r, s) +#else /* !USE_PACKET_FIFO */ +# define GR_GET(s) GET(s) +# define GR_GET16(s) ((FxU16)GET16(s)) +# define GR_SET(c, h, f, s) do {SET((h)->f, s); GR_INC_SIZE(4);} while(0) +# define GR_SET_INDEX(c, h, r, s) do {SET(((FxU32*)(h))[r], s); GR_INC_SIZE(sizeof(FxU32));} while(0) +# define GR_SETF(c, h, f, s) do {SETF(h->f, s); GR_INC_SIZE(4);} while(0) +# define GR_SETF_INDEX(c, h, r, s) do {SETF(((FxU32*)(h))[r], s); GR_INC_SIZE(sizeof(FxU32));} while(0) +# define GR_SET16(c, h, f, s) do {SET16((h)->f, s); GR_INC_SIZE(2);} while(0) +#endif /* !USE_PACKET_FIFO */ + +/* Macros to do linear writes to lfb/tex memory. + * + * LINEAR_WRITE_BEGIN - Setup stuff for the linear write. + * + * numWords: The number of words to actually write to the destination + * address. This does *NOT* include the packet headers etc for any + * command fifos etc. + * + * type: One of the kLinearWriteXXX enum values above. This can + * control what the legal values for addr and maskXX are. + * + * addr: Base address to the start the write. + * + * maskXX: Control what bytes in a write are active, these are active + * low. W2 controls the masking of the first 32bit word written, and + * WN controls all of the other writes. + * + * LINEAR_WRITE_SET - Writes are done in 32-bit increments, and must + * be properly aligned etc. This can only be used inside of a + * LINEAR_WRITE_BEGIN/LINEAR_WRITE_END pair. + * + * LINEAR_WRITE_EDGE - Write to a 16-bit value to an address. The + * address must be aligned for at 16-bit access, and should not appear + * within a LINEAR_WRITE_BEGIN/LINEAR_WRITE_END pair. + * + * LINEAR_WRITE_END - Finish off any stuff for the linear write. + */ + +enum { + kLinearWriteLFB = SSTCP_PKT5_3DLFB, + kLinearWriteTex = SSTCP_PKT5_TEXPORT +}; + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define TEX_ROW_ADDR_INCR(__t, __lod) ((__t) << 9) +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) +#define TEX_ROW_ADDR_INCR(__t, __lod) ((__t) << 7) +#else +#error "Need to define TEX_ROW_ADDR_INCR for this hw." +#endif + +#if USE_PACKET_FIFO + +#define LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN) \ +{ \ + GR_SET_EXPECTED_SIZE(((FxU32)((__numWords) + 1UL) << 2UL), 1); \ + FIFO_LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN, __FILE__, __LINE__) +#define LINEAR_WRITE_SET(__addr, __val) \ + FIFO_LINEAR_WRITE_SET(__val) +#define LINEAR_WRITE_SET_16(__addr, __val) \ + FIFO_LINEAR_WRITE_SET_16(__val) +#define LINEAR_WRITE_SET_8(__addr, __val) \ + FIFO_LINEAR_WRITE_SET_8(__val) +#define LINEAR_WRITE_END() \ + FIFO_LINEAR_WRITE_END; \ + GR_CHECK_SIZE(); \ +} + +/* Macro to write the edge cases of a linear write, for example to the + * lfb w/ a 16-bit pixel value. We do some address manipulation here + * since the cmd fifo only addresses 32-bit quantities, but allows us + * to mask of crap for the actual write. + */ +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define FIFO_LINEAR_EDGE_MASK_ADJUST(__mask) ((~(__mask)) & 0x0FUL) +#define FIFO_LINEAR_EDGE_SET(__val) FIFO_LINEAR_WRITE_SET((((__val) & 0xFFFF0000UL) >> 16UL) | \ + (((__val) & 0x0000FFFFUL) << 16UL)) +#else +#define FIFO_LINEAR_EDGE_SET(__val) FIFO_LINEAR_WRITE_SET(__val) +#define FIFO_LINEAR_EDGE_MASK_ADJUST(__mask) (__mask) +#endif + +#define LINEAR_WRITE_EDGE(__type, __addr, __val, __valBytes) \ +do { \ + const FxU32 edgeAddr = (FxU32)(((FxU32)__addr) & 0x03UL); \ + GR_ASSERT((__valBytes) <= sizeof(FxU32)); \ + GR_ASSERT((((FxU32)(__addr)) + (__valBytes)) <= ((((FxU32)(__addr)) & ~0x03UL) + sizeof(FxU32))); \ + LINEAR_WRITE_BEGIN(1, __type, ((FxU32)__addr & ~0x03UL), \ + FIFO_LINEAR_EDGE_MASK_ADJUST((0xF0UL | (0x0FUL >> (__valBytes))) >> edgeAddr), \ + 0x00); \ + FIFO_LINEAR_EDGE_SET(((FxU32)(__val)) << (((sizeof(FxU32) - edgeAddr) << 3UL) - \ + ((__valBytes) << 3UL))); \ + LINEAR_WRITE_END(); \ +} while(0) +#else /* !USE_PACKET_FIFO */ +# define LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN) \ +{ \ + GR_SET_EXPECTED_SIZE(((__numWords) << 2), (__numWords)) +# define LINEAR_WRITE_SET(__addr, __val) \ +do { \ + FxU32* tempAddr = (FxU32*)(__addr); \ + SET_LINEAR(*tempAddr, __val); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define LINEAR_WRITE_SET_16(__addr, __val) \ +do { \ + FxU32* tempAddr = (FxU32*)(__addr); \ + SET_LINEAR_16(*tempAddr, __val); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define LINEAR_WRITE_SET_8(__addr, __val) \ +do { \ + FxU32* tempAddr = (FxU32*)(__addr); \ + SET_LINEAR_8(*tempAddr, __val); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +# define LINEAR_WRITE_EDGE(__type, __addr, __val, __isLeftP) \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1); \ +{ \ + FxU32* tempAddr = (FxU32*)(__addr); \ + SET16(*tempAddr, __val); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} \ +GR_CHECK_SIZE() +# define LINEAR_WRITE_END() \ + GR_CHECK_SIZE(); \ +} + +/* The REG_GROUP_XXX macros do writes to a monotonically increasing + * set of registers. There are three flavors of the macros w/ + * different restrictions etc. + * + * NB: Care must be taken to order the REG_GROUP_SET macro uses to + * match the actual register order, otherwise all hell breaks loose. + */ + +/* Write to __groupNum registers (max 14) starting at __regBase under + * the control of __groupMask (lsb->msb). + */ +#define REG_GROUP_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, __groupMask, FXTRUE) + +/* Same as the non-NO_CHECK variant, but GR_SET_EXPECTED_SIZE must + * have already been called to allocate space for this write. + */ +#define REG_GROUP_NO_CHECK_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_ASSERT(gc->expected_counter >= (FxI32)((__groupNum) * sizeof(FxU32))); \ +REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, __groupMask, FXFALSE) + +/* Register writes (<= 32) sequentially starting at __regBase */ +#define REG_GROUP_LONG_BEGIN(__chipId, __regBase, __groupNum) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 32)); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, (0xFFFFFFFF >> (32 - (__groupNum))), FXTRUE) + +#define REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, __groupMask, __checkP) \ +{ \ + GR_DCL_GC; \ + REG_GROUP_DCL(__groupMask, __regBase, __groupNum, __checkP); \ + GDBG_INFO(gc->myLevel + 100, "REG_GROUP_BEGIN: (0x%X : 0x%X)\n", \ + (__groupMask), offsetof(SstRegs, __regBase) >> 2) + +#define REG_GROUP_SET(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXFALSE); \ + SET(((SstRegs*)(__regBase))->__regAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define REG_GROUP_SETF(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXTRUE); \ + SETF(((SstRegs*)(__regBase))->__regAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) + +#if GLIDE_FP_CLAMP +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ +do { \ + const FxU32 fpClampVal = FP_FLOAT_CLAMP(__val); \ + REG_GROUP_ASSERT(__regAddr, fpClampVal, FXTRUE); \ + SET(((FxU32*)(__regBase))[offsetof(SstRegs, __regAddr) >> 2], fpClampVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) +#else +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ + REG_GROUP_SETF(__regBase, __regAddr, __val) +#endif + +#define REG_GROUP_NO_CHECK_END() \ + ASSERT(!_checkP); \ +} + +#define REG_GROUP_END() \ + ASSERT(_checkP); \ +} \ +GR_CHECK_SIZE() + +#if !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE +/* Send all of the triangle parameters in a single cmd fifo packet to + * the chip until the tsu is fixed. + */ +#define kNumTriParam 0x1FUL + +#define TRI_NO_TSU_BEGIN(__floatP) \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * kNumTriParam, 1); \ +{ \ + volatile FxU32* regBaseAddr = (volatile FxU32*)((__floatP) \ + ? &hw->FvA \ + : &hw->vA); \ + GDBG_INFO(gc->myLevel, "TRI_NO_TSU_BEGIN: fbiRegs->%svA\n", \ + ((__floatP) ? "F" : "")) + +#define TRI_NO_TSU_SET(__addr, __val) \ +do { \ + const FxU32* hwWriteAddr = (const FxU32*)(__addr); \ + ASSERT(hwWriteAddr == regBaseAddr); \ + SET(*hwWriteAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_SETF(__addr, __val) \ +do { \ + const FxU32* hwWriteAddr = (const FxU32*)(__addr); \ + const FxFloat hwFloatVal = __val; \ + ASSERT(hwWriteAddr == regBaseAddr); \ + GDBG_INFO(gc->myLevel + 200, FN_NAME": FloatVal 0x%X : (0x%X : %g)\n", \ + ((FxU32)hwWriteAddr - (FxU32)hw) >> 2, \ + *(const FxU32*)&hwFloatVal, hwFloatVal); \ + SETF(*hwWriteAddr, hwFloatVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_END() \ +} +#endif /* !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE */ + +#endif /* !USE_PACKET_FIFO */ + +/* Offsets to 'virtual' addresses in the hw */ +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define HW_REGISTER_OFFSET SST_3D_OFFSET +#define HW_FIFO_OFFSET 0x00200000UL +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) +#define HW_IO_REG_REMAP SST_IO_OFFSET +#define HW_CMD_AGP_OFFSET SST_CMDAGP_OFFSET +#define HW_2D_REG_OFFSET SST_2D_OFFSET +#define HW_3D_REG_OFFSET SST_3D_OFFSET +#define HW_REGISTER_OFFSET HW_3D_REG_OFFSET +#else +#error "Must define virtual address spaces for this hw" +#endif + +#define HW_FIFO_OFFSET 0x00200000UL +#define HW_LFB_OFFSET SST_LFB_OFFSET +#define HW_TEXTURE_OFFSET SST_TEX_OFFSET + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) || (GLIDE_PLATFORM & GLIDE_HW_H3) +#define HW_BASE_PTR(__b) (__b) +#else +#error "Need HW_BASE_PTR to convert hw address into board address." +#endif + +#define HW_REG_PTR(__b) ((FxU32*)(((FxU32)(__b)) + HW_REGISTER_OFFSET)) +#define HW_LFB_PTR(__b) ((FxU32*)(((FxU32)(__b)) + HW_LFB_OFFSET)) +#define HW_TEX_PTR(__b) ((FxU32*)(((FxU32)(__b)) + HW_TEXTURE_OFFSET)) + +/* access a floating point array with a byte index */ +#define FARRAY(p,i) (*(float *)((i)+(int)(p))) +#define ArraySize(__a) (sizeof(__a) / sizeof((__a)[0])) + +void rle_decode_line_asm(FxU16 *tlut,FxU8 *src,FxU16 *dest); + +extern FxU16 rle_line[256]; +extern FxU16 *rle_line_end; + +#define RLE_CODE 0xE0 +#define NOT_RLE_CODE 31 + +#ifdef __WATCOMC__ +#pragma aux rle_decode_line_asm parm [edx] [edi] [esi] value [edi] modify exact [eax ebx ecx edx esi edi] = \ +" next_pixel: " \ +" xor ecx,ecx " \ +" mov al,byte ptr[edi] " \ +" mov cl,byte ptr[edi] " \ +" inc edi " \ +" " \ +" and al,0xE0 " \ +" cmp al,0xE0 " \ +" jne unique " \ +" " \ +" and cl,0x1F " \ +" mov al,cl " \ +" jz done_rle " \ +" " \ +" mov cl,byte ptr[edi] " \ +" inc edi " \ +" mov bx,word ptr[edx+ecx*2] " \ +" " \ +" copy_block: " \ +" mov word ptr[esi],bx " \ +" add esi,0x2 " \ +" dec al " \ +" jz next_pixel " \ +" jmp copy_block " \ +" " \ +" unique: " \ +" mov bx,word ptr[edx+ecx*2] " \ +" mov word ptr[esi],bx " \ +" add esi,0x2 " \ +" jmp next_pixel " \ +" done_rle: "; +#endif /* __WATCOMC__ */ + +#if GDBG_INFO_ON +/* cvg.c */ +extern void +_grErrorCallback(const char* const procName, + const char* const format, + va_list args); +#endif + +extern FxU32 GR_CDECL +_cpu_detect_asm(void); + +extern void GR_CDECL +single_precision_asm(void); + +extern void GR_CDECL +double_precision_asm(void); + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +/* gglide.c */ +extern void +_grSliOriginClear(void); +#endif /* (GLIDE_PLATFORM & GLIDE_HW_CVG) */ + +#endif /* __FXGLIDE_H__ */ + diff --git a/glide2x/h3/glide/src/fxglide.h b/glide2x/h3/glide/src/fxglide.h new file mode 100644 index 0000000..aed7728 --- /dev/null +++ b/glide2x/h3/glide/src/fxglide.h @@ -0,0 +1,3384 @@ +/* +** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +** FULL TEXT OF THE NON-WARRANTY PROVISIONS. +** +** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +** THE UNITED STATES. +** +** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +** +** $Header$ +** $Log$ +** Revision 1.2 2003/06/28 19:10:36 guillemj +** Fixed preprocessor invalid tokens in newer gcc 3.x versions. +** +** Revision 1.1.1.1 1999/12/07 21:49:26 joseph +** Initial checkin into SourceForge. +** +** +** 3 3/17/99 6:16p Dow +** Phantom Menace and other fixes. +** +** 243 3/17/99 5:08p Peter +** removed whacky stuff now that the command fifo threshold stuff appears +** to make all happy (including the k7) +** +** 242 3/17/99 1:37p Atai +** use grHints to enable/disable uma hack +** +** 241 3/16/99 11:51a Atai +** Back door (set FX_GLIDE_ENABLE_UMA=1) to enable unified texture memory. +** TMUn memory size will the whole texture memory space. The offset for +** each TMU points to the start address of the memory pool. +** +** 240 3/15/99 10:51p Dow +** Vile Hack +** +** 239 3/14/99 1:42p Peter +** really invokve the ggggsoph +** +** 238 3/13/99 9:48p Dow +** +** 237 3/12/99 2:28p Dow +** Great-great-great grandson of packer workaround +** +** 236 3/10/99 10:40a Peter +** bump-n-grind workaround for katmai until the bug is better +** characterized +** +** 235 3/04/99 3:15p Atai +** mods for direct write +** +** 234 3/02/99 2:21p Peter +** wax is a chip id +** +** 233 2/19/99 5:54p Peter +** new splash screen +** +** 232 2/18/99 7:11p Kcd +** Added P6FENCE for MacOS +** +** 231 2/16/99 4:14p Peter +** made texture table declarations consistent +** +** 230 2/10/99 2:24p Peter +** corrected alignment textures within an alignment allocation unit +** +** 229 12/09/98 2:07p Peter +** More Norbert's stuff for the other 3DNow!(tm) partners +** +** 228 12/03/98 11:27p Dow +** Code 'cleanup' heç +** +** 227 12/02/98 2:53p Dow +** NT/9X Registry reading fix +** +** 226 11/18/98 7:57p Dow +** Added grxclk +** +** 225 11/12/98 2:50p Atai +** fixed register get +** +** 224 11/02/98 5:34p Atai +** merge direct i/o code +** +** 223 10/21/98 4:20p Atai +** gamma stuff +** +** 222 10/21/98 10:41a Atai +** +** 221 10/20/98 4:39p Atai +** update tramOffset and tramSize +** +** 220 10/19/98 2:11p Peter +** ctrisetup happiness +** +** 219 10/09/98 6:57p Peter +** dynamic 3DNow!(tm) mods +** +** 218 9/04/98 11:36a Peter +** re-open fix for nt (thanks to taco/rob/nt bob) +** +** 217 8/27/98 6:33p Atai +** added environment.tmuMemory +** +** 216 7/29/98 3:09p Dow +** SDRAM Fixes +** +** 215 7/24/98 2:03p Dow +** AGP Stuff +** +** 214 7/23/98 3:19p Dow +** Bump & Grind Fix +** +** 213 7/23/98 1:17a Dow +** Bump & Grind +** +** 212 7/14/98 2:48p Mikec +** Added Glide environment variable FX_GLIDE_EMUL_RUSH allow Banshee glide +** to report itself as Rush to the application. Set it to 1 to enable Rush +** reporting. By default Glide still reports itself as Voodoo Graphics. +** +** 211 7/09/98 12:00p Jdt +** +** 210 7/09/98 11:49a Jdt +** +** 209 7/09/98 11:33a Jdt +** fixed fencing for dos build +** +** 208 7/06/98 7:03p Jdt +** in-memory fifo test code, minor changes to init-time variables +** +** 207 7/02/98 12:12p Dow +** LFB Fixes +** +** 206 6/24/98 10:55a Peter +** gary's trilinear hell bug +** +** 205 6/19/98 2:33p Mikec +** Fixed my triple buffering effage when getting lfb buffers we need to +** re-allocate the size of the render buffer +** +** 204 6/16/98 6:12p Dow +** Rearranged texture memory +** +** 203 6/12/98 9:21a Peter +** lfb read for triple buffering +** +** 202 6/10/98 9:49a Peter +** lfb buffer addressing +** +** 201 5/28/98 1:46p Dow +** Swap Pending Workaround +** +** 200 5/21/98 4:47p Dow +** Direct Register Writes Work +** +** 199 5/18/98 3:20p Peter +** pts more resistant to changing rounding modes +** +** 198 5/13/98 11:42a Dow +** +** 197 5/12/98 2:42p Dow +** +** 196 5/12/98 1:36p Mc +** +** 195 5/06/98 5:34p Dow +** 2D FastFill Workaround +** +** 194 4/22/98 8:41a Dow +** AGP Workaround +** +** 193 4/14/98 6:41p Peter +** Merge w/ cvg glide cleanup +** +** 192 4/05/98 2:18p Dow +** DOS Glide Stuff +** +** 191 4/03/98 2:04p Dow +** Dos Glide Mods +** +** 190 3/28/98 12:31p Dow +** Added Fencing +** +** 189 3/28/98 11:24a Dow +** itwoç +** +** 184 2/17/98 12:50p Dow +** +** 183 2/08/98 3:08p Dow +** FIFO Works +** +** 182 2/03/98 8:45p Dow +** Prep for cmd fifo stuff +** +** 181 2/02/98 4:31p Dow +** IO w/o HAL now possible +** +** 180 2/01/98 7:52p Peter +** grLfbWriteRegion byte count problems +** +** 179 1/29/98 9:54p Dow +** This is Banshee +** +** 178 1/20/98 11:03a Peter +** env var to force triple buffering + * + * 176 1/16/98 7:03p Peter + * fixed volatile + * + * 175 1/16/98 10:47a Peter + * fixed idle effage + * + * 174 1/15/98 1:12p Peter + * dispatch w/o packing + * + * 173 1/13/98 12:42p Atai + * fixed grtexinfo, grVertexLayout, and draw triangle + * + * 172 1/10/98 4:01p Atai + * inititialize vertex layout, viewport, added defines + * + * 168 1/07/98 11:18a Atai + * remove GrMipMapInfo and GrGC.mm_table in glide3 + * + * 167 1/07/98 10:22a Peter + * lod dithering env var + * + * 166 1/06/98 6:47p Atai + * undo grSplash and remove gu routines + * + * 165 1/05/98 6:06p Atai + * glide extension stuff + * + * 164 12/18/97 10:52a Atai + * fixed grGet(GR_VIDEO_POS) + * + * 163 12/17/97 4:45p Peter + * groundwork for CrybabyGlide + * + * 162 12/17/97 4:05p Atai + * added grChromaRange(), grGammaCorrecionRGB(), grRest(), and grGet() + * functions + * + * 160 12/15/97 5:52p Atai + * disable obsolete glide2 api for glide3 + * + * 156 12/09/97 12:20p Peter + * mac glide port + * + * 155 12/09/97 10:28a Peter + * cleaned up some frofanity + * + * 154 12/09/97 9:46a Atai + * added viewport varibales + * + * 152 11/25/97 12:09p Peter + * nested calls to grLfbLock vs init code locking on v2 + * + * 151 11/21/97 6:05p Atai + * use one datalist (tsuDataList) in glide3 + * + * 150 11/21/97 3:20p Peter + * direct writes tsu registers + * + * 149 11/19/97 4:33p Atai + * #define GLIDE3_VERTEX_LAYOUT 1 + * + * 148 11/19/97 3:51p Dow + * Tex stuff for h3, def of GETENV when using fxHal + * + * 147 11/18/97 6:11p Peter + * fixed glide3 effage + * + * 146 11/18/97 4:36p Peter + * chipfield stuff cleanup and w/ direct writes + * + * 145 11/18/97 3:25p Atai + * redefine vData + * + * 144 11/17/97 4:55p Peter + * watcom warnings/chipfield stuff + * + * 143 11/15/97 7:43p Peter + * more comdex silliness + * + * 142 11/14/97 11:10p Peter + * open vs hw init confusion + * + * 141 11/14/97 5:02p Peter + * more comdex stuff + * + * 140 11/14/97 12:09a Peter + * comdex thing and some other stuff + * + * 139 11/12/97 2:35p Peter + * fixed braino + * + * 138 11/12/97 2:27p Peter + * + * 137 11/12/97 11:38a Dow + * + * 136 11/12/97 11:15a Peter + * fixed tri/strip param send and used cvgdef.h constant + * + * 135 11/12/97 9:21a Dow + * Changed offset defs to those in h3defs.h + * + * 134 11/07/97 11:22a Atai + * remove GR_*_SMOOTH. use GR_SMOOTH + * + * 133 11/06/97 3:46p Peter + * dos ovl build problem + * + * 132 11/06/97 3:38p Dow + * More banshee stuff + * + * 131 11/04/97 6:35p Atai + * 1. sync with data structure changes + * 2. break up aa triangle routine + * + * 130 11/04/97 5:04p Peter + * cataclysm part deux + * + * 129 11/04/97 4:00p Dow + * Banshee Mods + * + * 128 11/03/97 3:43p Peter + * h3/cvg cataclysm + * + * 127 10/29/97 2:45p Peter + * C version of Taco's packing code + * +** +*/ + +/* +** fxglide.h +** +** Internal declarations for use inside Glide. +** +** GLIDE_LIB: Defined if building the Glide Library. This macro +** should ONLY be defined by a makefile intended to build +** GLIDE.LIB or glide.a. +** +** GLIDE_NUM_TMU: Number of physical TMUs installed. Valid values are 1 +** and 2. If this macro is not defined by the application +** it is automatically set to the value 2. +** +*/ + +#ifndef __FXGLIDE_H__ +#define __FXGLIDE_H__ + +/* +** ----------------------------------------------------------------------- +** INCLUDE FILES +** ----------------------------------------------------------------------- +*/ +#include +#include +#include +#include +#include + +#include <3dfx.h> +#include +#include + +#include + +#if (GLIDE_PLATFORM & GLIDE_OS_WIN32) +#define WIN32_LEANER_AND_MEANER +#include +#include "fxsplash.h" +#endif /* (GLIDE_PLATFORM & GLIDE_OS_WIN32) */ + +/* Compilation hacks for h3 */ + +/* Reserved fbzMode bits */ +#define SST_DRAWBUFFER_SHIFT 14 +#define SST_DRAWBUFFER (0x3 << SST_DRAWBUFFER_SHIFT) +#define SST_DRAWBUFFER_FRONT (0 << SST_DRAWBUFFER_SHIFT) +#define SST_DRAWBUFFER_BACK (1 << SST_DRAWBUFFER_SHIFT) + +/* Reserved textureMode bits */ +#define SST_SEQ_8_DOWNLD BIT(31) + +/* hack for UMA via grHints */ +#define GR_HINT_ENABLE_UMA 0x10000000 + +#if GLIDE_INIT_HAL + +#include + +#ifdef GETENV +#undef GETENV +#endif +#ifdef __linux__ +/* We want to allow file based initialization */ +#define GETENV hwcGetenv +#endif + +/* dpc - 2 june 1997 + * Moved the fence check out to avoid empty if body warning w/ gcc. + * This only applies to systems that require the p6 fencing. + */ +#define P6FENCE_CHECK if (i & 2) P6FENCE + + +#else /* !defined(GLIDE_INIT_HAL) */ + +#include + +/* HACK HACK HACK */ +#define IDLE_HW(__hwPtr) (while (gc->ioRegs->status & (0x1f << 8))) + +#define HWC_BASE_ADDR_MASK 0x03UL + +#endif /* !GLIDE_INIT_HAL */ + +#if GLIDE_MULTIPLATFORM +#include "gcfuncs.h" +#endif + +/* isolate this 'hack' here so as to make the code look cleaner */ +#ifdef __WATCOMC__ +#define GR_CDECL __cdecl +#else +#define GR_CDECL +#endif + +#ifdef GLIDE3 + +#define GLIDE3_VERTEX_LAYOUT 1 +/* +** grGet defines +*/ +#define VOODOO2_FOG_TABLE_SIZE 80 +#define VOODOO_FOG_TABLE_SIZE 64 +#define VOODOO_GAMMA_TABLE_SIZE 32 +#define SST1_BITS_DEPTH 16 +#define SST1_ZDEPTHVALUE_NEAREST 0xFFFF +#define SST1_ZDEPTHVALUE_FARTHEST 0x0000 +#define SST1_WDEPTHVALUE_NEAREST 0x0000 +#define SST1_WDEPTHVALUE_FARTHEST 0xFFFF + +/* +** ----------------------------------------------------------------------- +** STUFF FOR STRIPS +** ----------------------------------------------------------------------- +*/ + +#define GR_COLOR_OFFSET_RED (0 << 2) +#define GR_COLOR_OFFSET_GREEN (1 << 2) +#define GR_COLOR_OFFSET_BLUE (2 << 2) +#define GR_COLOR_OFFSET_ALPHA (3 << 2) + +#define GR_VERTEX_OFFSET_X (0 << 2) +#define GR_VERTEX_OFFSET_Y (1 << 2) +#define GR_VERTEX_OFFSET_Z (2 << 2) +#define GR_VERTEX_OFFSET_WFBI (3 << 2) + +#define GR_TEXTURE_OFFSET_S (0 << 2) +#define GR_TEXTURE_OFFSET_T (1 << 2) +#define GR_TEXTURE_OFFSET_W (2 << 2) + +#define GR_DLIST_END 0x00 +#define GR_VTX_PTR 0x00 +#define GR_VTX_PTR_ARRAY 0x01 +#define GR_SCALE_OOW 0x00 +#define GR_SCALE_COLOR 0x01 +#define GR_SCALE_STW 0x02 + +typedef struct { + FxU32 + param, /* vertex, color, textureN */ + components, /* which ones? */ + type, /* data type */ + mode; /* enable / disable */ + FxI32 + offset; +} GrVParamInfo; + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +/* +** data structure for for oeminit dll +*/ +typedef struct { + FxU32 version; + FxU32 vendorID; + FxU32 deviceID; + FxU32 *linearAddress; + GrScreenResolution_t res; + GrScreenRefresh_t refresh; + FxU32 reserved[4]; +} OemInitInfo; +#endif + +/*============================================================ + ** State Monster Stuff: + **============================================================*/ +#define GR_FLUSH_STATE() \ +if (gc->state.invalid) _grValidateState() + + +/* Look in distate.c:grValidateState (NOTVALID macro) to see how these + are used I wanted to keep the mixed-case register names here, and + that's why they are mixed case */ +#define alphaModeBIT FXBIT(0) +#define fbzColorPathBIT FXBIT(1) +#define fbzModeBIT FXBIT(2) +#define chromaKeyBIT FXBIT(3) +#define clipRegsBIT FXBIT(4) +#define zaColorBIT FXBIT(5) +#define fogModeBIT FXBIT(6) +#define fogColorBIT FXBIT(7) +#define lfbModeBIT FXBIT(8) +#define c0c1BIT FXBIT(9) + +/*============================================================ + ** Video Stuff: + **============================================================*/ +#define VRETRACEMASK 0x00000fff +#define HRETRACEPOS 16 + +#else +/* Make sure GR_FLUSH_STATE is a noop if not Glide 3 */ +#define GR_FLUSH_STATE() +#endif /* GLIDE3 */ + + +/*==========================================================================*/ +/* +** GrState +** +** If something changes in here, then go into glide.h, and look for a +** declaration of the following form: +** +** #define GLIDE_STATE_PAD_SIZE N +** #ifndef GLIDE_LIB +** typedef struct { +** char pad[GLIDE_STATE_PAD_SIZE]; +** } GrState; +** #endif +** +** Then change N to sizeof(GrState) AS DECLARED IN THIS FILE! +** +*/ + +struct _GrState_s { + GrCullMode_t /* these go in front for cache hits */ + cull_mode; /* cull neg, cull pos, don't cull */ + + GrHint_t + paramHints; /* Tells us if we need to pointcast a + parameter to a specific chip */ + FxI32 + fifoFree; /* # free entries in FIFO */ + FxU32 + paramIndex, /* Index into array containing + parameter indeces to be sent ot the + triangle setup code */ + tmuMask; /* Tells the paramIndex updater which + TMUs need values */ + struct { + FxU32 fbzColorPath; + FxU32 fogMode; + FxU32 alphaMode; + FxU32 fbzMode; + FxU32 lfbMode; + FxU32 clipLeftRight; + FxU32 clipBottomTop; + + FxU32 fogColor; + FxU32 zaColor; + FxU32 chromaKey; + FxU32 chromaRange; + + FxU32 stipple; + FxU32 color0; + FxU32 color1; + } fbi_config; /* fbi register shadow */ + + struct tmu_config_t { + FxU32 textureMode; + FxU32 tLOD; + FxU32 tDetail; + FxU32 texBaseAddr; + FxU32 texBaseAddr_1; + FxU32 texBaseAddr_2; + FxU32 texBaseAddr_3_8; + GrMipMapMode_t mmMode; /* saved to allow MM en/dis */ + GrLOD_t smallLod, largeLod; /* saved to allow MM en/dis */ + FxU32 evenOdd; + GrNCCTable_t nccTable; + } tmu_config[GLIDE_NUM_TMU]; /* tmu register shadow */ + + FxBool /* Values needed to determine which */ + ac_requires_it_alpha, /* parameters need gradients computed */ + ac_requires_texture, /* when drawing triangles */ + cc_requires_it_rgb, + cc_requires_texture, + cc_delta0mode, /* Use constants for flat shading */ + allowLODdither, /* allow LOD dithering */ + checkFifo; /* Check fifo status as specified by hints */ + +#ifdef GLIDE3 + FxU16 +#else + FxU32 +#endif + lfb_constant_depth; /* Constant value for depth buffer (LFBs) */ + GrAlpha_t + lfb_constant_alpha; /* Constant value for alpha buffer (LFBs) */ + + FxU32 + num_buffers; /* 2 or 3 */ + + GrColorFormat_t + color_format; /* ARGB, RGBA, etc. */ + + GrOriginLocation_t /* lower left, upper left */ + origin; + + GrMipMapId_t + current_mm[GLIDE_NUM_TMU]; /* Which guTex** thing is the TMU set + up for? THIS NEEDS TO GO!!! */ + + float + clipwindowf_xmin, clipwindowf_ymin, /* Clipping info */ + clipwindowf_xmax, clipwindowf_ymax; + FxU32 + screen_width, screen_height; /* Screen width and height */ + float + a, r, g, b; /* Constant color values for Delta0 mode */ + +#ifdef GLIDE3 + /* viewport and clip space coordinate related stuff */ + + struct { + float + n, f; + FxFloat + ox, oy, oz; + FxFloat + hwidth, hheight, hdepth; + } Viewport; + +#endif + +#ifdef GLIDE3 + /* Strip Stuff */ +#if !GLIDE3_VERTEX_LAYOUT + struct { + GrVParamInfo + vertexInfo, /* Info about vertex data*/ + zInfo, + colorInfo, /* Info about color data */ + tex0Info, /* Info about tmu0 data */ + tex1Info; /* Info about tmu1 data */ + FxU32 + vSize, + vStride; + } vData; +#else /* GLIDE3_VERTEX_LAYOUT */ + struct { + GrVParamInfo + vertexInfo, /* xy */ + zInfo, /* z(ooz) */ + wInfo, /* w(oow) */ + aInfo, /* a float */ + rgbInfo, /* rgb float */ + pargbInfo, /* pargb byte */ + st0Info, /* st0 */ + st1Info, /* st1 */ + qInfo, /* q */ + q0Info, /* q0 */ + q1Info; /* q1 */ + FxU32 + vStride, /* vertex stride */ + vSize; /* vertex size */ + FxU32 + colorType; /* float or byte */ + } vData; +#endif /* GLIDE3_VERTEX_LAYOUT */ + + /*============================================================ + ** State Monster Stuff: + **============================================================*/ + /* + ** The following DWORD is used to determine what state (if any) needs to + ** be flushed when a rendering primative occurs. + */ + FxU32 + invalid; + /* invalid contains bits representing: + alphaMode register: + modified by grAlphaBlendFunction, grAlphaTestFunction, + grAlphaTestReferenceValue + + fbzColorPath register: + modified by grAlphaCombine, grAlphaControlsITRGBLighting, + grColorCombine + + fbzMode register: + modified by grChromaKeyMode, grDepthBufferFunction, + grDeptBufferMode, grDepthMask, grDitherMode, grRenderBuffer, + grSstOrigin, grColorMask + + chromaKey register: + modified by grChromaKeyValue + + clipLeftRight, clipBottomTop registers: + modified by grClipWindow + + zaColor register: + modified by grDepthBiasLevel + + fogMode register: + modified by grFogMode + + fogColor register: + modified by grFocColorValue + + lfbMode register: + modified by grLfbWriteColorFormat, grLfbWriteColorSwizzle + + c0 & c1 registers: + modified by grConstanColorValue + */ + + /* + ** Argument storage for State Monster: + ** + ** NOTE that the data structure element names are IDENTICAL to the function + ** argment names. This is very important, as there are macros in distate.c + ** that require that. + */ + struct { + struct { + GrAlphaBlendFnc_t rgb_sf; + GrAlphaBlendFnc_t rgb_df; + GrAlphaBlendFnc_t alpha_sf; + GrAlphaBlendFnc_t alpha_df; + } grAlphaBlendFunctionArgs; + struct { + GrCmpFnc_t fnc; + } grAlphaTestFunctionArgs; + struct { + GrAlpha_t value; + } grAlphaTestReferenceValueArgs; + struct { + GrCombineFunction_t function; + GrCombineFactor_t factor; + GrCombineLocal_t local; + GrCombineOther_t other; + FxBool invert; + } grAlphaCombineArgs; + struct { + FxBool enable; + } grAlphaControlsITRGBLightingArgs; + struct { + GrCombineFunction_t function; + GrCombineFactor_t factor; + GrCombineLocal_t local; + GrCombineOther_t other; + FxBool invert; + } grColorCombineArgs; + struct { + FxBool rgb; + FxBool alpha; + } grColorMaskArgs; + struct { + GrChromakeyMode_t mode; + } grChromakeyModeArgs; + struct { + GrColor_t color; + } grChromakeyValueArgs; +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) + struct { + GrColor_t range; + GrChromaRangeMode_t mode; + } grChromaRangeArgs; +#endif + struct { + FxBool enable; + } grDepthMaskArgs; + struct { + GrCmpFnc_t fnc; + } grDepthBufferFunctionArgs; + struct { + GrDepthBufferMode_t mode; + } grDepthBufferModeArgs; + struct { + GrDitherMode_t mode; + } grDitherModeArgs; + struct { + GrBuffer_t buffer; + } grRenderBufferArgs; + struct { + GrOriginLocation_t origin; + } grSstOriginArgs; + struct { + FxU32 minx; + FxU32 miny; + FxU32 maxx; + FxU32 maxy; + } grClipWindowArgs; + struct { + FxU32 level; + } grDepthBiasLevelArgs; + struct { + GrFogMode_t mode; + } grFogModeArgs; + struct { + GrColor_t color; + } grFogColorValueArgs; + struct { + GrColorFormat_t colorFormat; + } grLfbWriteColorFormatArgs; + struct { + FxBool swizzleBytes; + FxBool swapWords; + } grLfbWriteColorSwizzleArgs; + struct { + GrColor_t color; + } grConstantColorValueArgs; + } stateArgs; + struct{ + GrEnableMode_t primitive_smooth_mode; + GrEnableMode_t shameless_plug_mode; + GrEnableMode_t video_smooth_mode; + } grEnableArgs; + struct{ + GrCoordinateSpaceMode_t coordinate_space_mode; + } grCoordinateSpaceArgs; +#endif /* GLIDE3 end grenable mode*/ +}; + +#if GLIDE_DISPATCH_SETUP +/* gpci.c + * + * Set of procs for the current cpu type. These are selected out of + * the _archXXXX proc list that is selected at grGlideInit time. + * + * TriProc vector + * 0 - No Culling + * 1 - Culling (Postive/Negative) + * + * _GlideRoot.curTriProcs + * 0 - Generic dataList w/ all parameters + * 1 - Packed rgb (GLIDE_PACKED_RGB) + * 2 - Packed argb (GLIDE_PACKED_RGB) + */ + +#define NUM_TRI_PROC_LISTS 1 + +typedef FxI32 (FX_CALL* GrTriSetupProc)(const GrVertex*, const GrVertex*, const GrVertex*); +typedef GrTriSetupProc GrTriSetupProcVector[2]; +typedef GrTriSetupProcVector GrTriSetupProcArchVector[NUM_TRI_PROC_LISTS]; + +/* Decalrations of the dispatchable procs found in xdraw2.asm and + * xtexdl.c for teh triangle and texture download procs respectively. + */ +extern FxI32 FX_CALL _trisetup_Default_Default(const GrVertex*, const GrVertex*, const GrVertex*); +extern FxI32 FX_CALL _trisetup_Default_cull(const GrVertex*, const GrVertex*, const GrVertex*); + +#if GL_AMD3D +extern FxI32 FX_CALL _trisetup_3DNow_Default(const GrVertex*, const GrVertex*, const GrVertex*); +extern FxI32 FX_CALL _trisetup_3DNow_cull(const GrVertex*, const GrVertex*, const GrVertex*); +#endif /* GL_AMD3D */ +#endif /* GLIDE_DISPATCH_SETUP */ + +struct GrGC_s; + +/* _GlideRoot.curTexProcs is an array of (possibly specialized + * function pointers indexed by texture format size (8/16 bits) and + * texture line width (1/2/4/>4). + * + * xtexdl.c + */ +typedef void (FX_CALL* GrTexDownloadProc)(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +typedef GrTexDownloadProc GrTexDownloadProcVector[2][4]; + +extern void FX_CALL _grTexDownload_Default_8_1(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +extern void FX_CALL _grTexDownload_Default_8_2(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +extern void FX_CALL _grTexDownload_Default_8_4(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +extern void FX_CALL _grTexDownload_Default_8_WideS(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); + +extern void FX_CALL _grTexDownload_Default_16_1(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +extern void FX_CALL _grTexDownload_Default_16_2(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +extern void FX_CALL _grTexDownload_Default_16_4(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +extern void FX_CALL _grTexDownload_Default_16_WideS(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); + +#if GL_AMD3D +/* xtexdl.asm */ +extern void FX_CALL _grTexDownload_3DNow_MMX(struct GrGC_s* gc, const FxU32 tmuBaseAddr, + const FxI32 maxS, const FxI32 minT, const FxI32 maxT, + void* texData); +#endif /* GL_AMD3D */ + +typedef struct GrGC_s { + FxU32 + totBuffers, + strideInTiles, + heightInTiles, + bufferStride, + bufSizeInTiles, + bufSize, + fbOffset, + tramOffset[2], + tramSize[2], + *base_ptr, /* base address of SST */ + *reg_ptr, /* pointer to base of SST registers */ + *tex_ptr, /* texture memory address */ + *lfb_ptr, /* linear frame buffer address */ + *slave_ptr; /* Scanline Interleave Slave address */ + +#ifdef GLIDE_INIT_HWC + hwcBoardInfo + *bInfo; +#endif + +#if GLIDE_MULTIPLATFORM + GrGCFuncs + gcFuncs; +#endif + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) + void *oemInit; +#endif + + +#define kMaxVertexParam (20 + (12 * GLIDE_NUM_TMU) + 3) + struct dataList_s { + int i; + FxFloat* addr; + } regDataList[kMaxVertexParam]; + int tsuDataList[kMaxVertexParam]; + + struct { +#if GLIDE_DISPATCH_SETUP + /* Current triangle rendering proc specialized for culling/no + * culling and optionally for packed rgb at compile time. + */ + GrTriSetupProc triSetupProc; +#endif /* GLIDE_DISPATCH_SETUP */ + + /* Vector of texture download procs specialized by size + * and processor vendor type. + */ + GrTexDownloadProcVector* texDownloadProcs; + } archDispatchProcs; + +#ifdef GLIDE3 +#if 0 + /* scale factor for clip space and viewport code */ + int scaleDataList[kMaxVertexParam]; +#endif +#endif + + GrState + state; /* state of Glide/SST */ + + /* Here beginneth the Swap Pending Workaround (tm) */ +#define MAX_BUFF_PENDING 0x7 + FxU32 + swapsPending, /* swaps in unexecuted region of FIFO */ + lastSwapCheck, /* Position at last check */ + curSwap, /* Position in the array below */ + bufferSwaps[MAX_BUFF_PENDING];/* Position in FIFO of buffer swaps */ + /* Here endeth the Swap Pending Workaround */ + + struct cmdTransportInfo { + FxU32 triPacketHdr; /* Pre-computed packet header for + * independent triangles. + */ + + FxU32 cullStripHdr; /* Pre-computed packet header for generic + * case of packet 3 triangles. This needs + * command type and # of vertices to be complete. + */ + + FxU32 paramMask; /* Mask for specifying parameters of + * non-triangle packets. The parameter + * bits[21:10] mimic the packet3 header + * controlling which fields are sent, and + * pc[28] controls whether any color + * information is sent as packed. + */ + + /* Basic command fifo characteristics. These should be + * considered logically const after their initialization. + */ + FxU32* fifoStart; /* Virtual address of start of fifo */ + FxU32* fifoEnd; /* Virtual address of fba fifo */ + FxU32 fifoOffset; /* Offset from hw base to fifo start */ + FxU32 fifoSize; /* Size in bytes of the fifo */ + FxU32 fifoJmpHdr[2];/* Type0 packet for jmp to fifo start + only first DWORD is used for memory + fifo--both are used for AGP FIFO + */ + +#ifdef TACO_MEMORY_FIFO_HACK + FxU32 *vFifoStart; + FxU32 *vFifoEnd; +#endif + + FxU32* fifoPtr; /* Current write pointer into fifo */ + FxU32 fifoRead; /* Last known hw read ptr. + * This is the sli master, if enabled. + */ + +#if GLIDE_USE_DEBUG_FIFO + FxU32* fifoShadowBase; /* Buffer that shadows the hw fifo for debugging */ + FxU32* fifoShadowPtr; +#endif /* GLIDE_USE_DEBUG_FIFO */ + + /* Fifo checking information. In units of usuable bytes until + * the appropriate condition. + */ + FxI32 fifoRoom; /* Space until next fifo check */ + FxI32 roomToReadPtr;/* Bytes until last known hw ptr */ + FxI32 roomToEnd; /* # of bytes until last usable address before fifoEnd */ + + FxBool lfbLockCount; /* Have we done an lfb lock? Count of the locks. */ + FxBool + autoBump; /* Are we auto bumping (aka hole counting?) */ + FxU32 + *lastBump, /* Last ptr where we bumped. */ + *bumpPos; /* Nex place to bump */ + FxU32 + bumpSize; /* # of DWORDS per bump */ + + } cmdTransportInfo; + + + SstIORegs + *ioRegs; /* I/O remap regs */ + SstCRegs + *cRegs; /* AGP/Cmd xfer/misc regs */ + SstGRegs + *gRegs; /* 2D regs */ + SstRegs + *sstRegs; /* Graphics Regs (3D Regs) */ + FxU32 + *rawLfb, /* Poiinter to vAddr of baseAddress1 */ + nBuffers, + curBuffer, + frontBuffer, + backBuffer, + buffers[4], + lfbBuffers[4]; /* Tile relative addresses of the color/aux + * buffers for lfbReads. + */ + + FxU32 lockPtrs[2]; /* pointers to locked buffers */ + FxU32 fbStride; + + struct { + FxU32 freemem_base; + FxU32 total_mem; + FxU32 next_ncc_table; + GrMipMapId_t ncc_mmids[2]; + const GuNccTable *ncc_table[2]; + } tmu_state[GLIDE_NUM_TMU]; + + int + grSstRez, /* Video Resolution of board */ + grSstRefresh, /* Video Refresh of board */ + fbuf_size, /* in MB */ + num_tmu, /* number of TMUs attached */ + grColBuf, + grAuxBuf, + grHwnd; + + /* Overlay Hack: This flag indicates if the overlay hack is on. + * This is probably the wrong place for this kind of thing*/ + int desktopOverlay; + + FxBool + scanline_interleaved; + +#ifndef GLIDE3_ALPHA + struct { + GrMipMapInfo data[MAX_MIPMAPS_PER_SST]; + GrMipMapId_t free_mmid; + } mm_table; /* mip map table */ +#endif + + FxBool tmuLodDisable[GLIDE_NUM_TMU]; + + /* DEBUG and SANITY variables */ + FxI32 myLevel; /* debug level */ + FxI32 counter; /* counts bytes sent to HW */ + FxI32 expected_counter; /* the number of bytes expected to be sent */ + + FxU32 checkCounter; + FxU32 checkPtr; + + FxVideoTimingInfo* vidTimings;/* init code overrides */ + + FxU32 nColBuffers; + FxBool open; /* Has GC Been Opened? */ + FxBool hwInitP; /* Has the hw associated w/ GC been initted and + mapped? This is managed in + _grDetectResources:gpci.c the first time + that the board is detected, and in + grSstWinOpen:gsst.c if the hw has been + shutdown in a call to grSstWinClose. + */ + +#if (GLIDE_PLATFORM & GLIDE_OS_WIN32) + /* Splash screen/shameless plug crap */ + struct { + HMODULE + moduleHandle; + GrSplashInitProc + initProc; + GrSplashShutdownProc + shutdownProc; + GrSplashProc + splashProc; + GrSplashPlugProc + plugProc; + } pluginInfo; +#endif /* (GLIDE_PLATFORM & GLIDE_OS_WIN32) */ +} GrGC; + + +/* +** The Root Of All EVIL! +** +** The root of all Glide data, all global data is in here +** stuff near the top is accessed a lot +*/ +struct _GlideRoot_s { + /* NOTE!!!! p6Fencer this must be the very first structure element always */ + int p6Fencer; /* xchg to here to keep this in cache!!! */ + int current_sst; + FxU32 CPUType; + GrGC *curGC; /* point to the current GC */ + FxU32 packerFixAddress; /* address to write packer fix to */ + FxBool windowsInit; /* Is the Windows part of glide initialized? */ + + FxI32 curTriSize; /* the size in bytes of the current triangle */ +#if GLIDE_HW_TRI_SETUP + FxI32 curVertexSize; /* Size in bytes of a single vertex's parameters */ +#endif + +#if !GLIDE_HW_TRI_SETUP || !GLIDE_PACKET3_TRI_SETUP + FxU32 paramCount; + FxI32 curTriSizeNoGradient; /* special for _trisetup_nogradients */ +#endif /* !GLIDE_HW_TRI_SETUP || !GLIDE_PACKET3_TRI_SETUP */ + +#if GLIDE_MULTIPLATFORM + GrGCFuncs + curGCFuncs; /* Current dd Function pointer table */ +#endif + int initialized; + + struct { /* constant pool (minimizes cache misses) */ + float f0; + float fHalf; + float f1; + float f255; + float ftemp1, ftemp2; /* temps to convert floats to ints */ + +#if GLIDE_PACKED_RGB +#define kPackBiasA _GlideRoot.pool.fBiasHi +#define kPackBiasR _GlideRoot.pool.fBiasHi +#define kPackBiasG _GlideRoot.pool.fBiasHi +#define kPackBiasB _GlideRoot.pool.fBiasLo + +#define kPackShiftA 16UL +#define kPackShiftR 8UL +#define kPackShiftG 0UL +#define kPackShiftB 0UL + +#define kPackMaskA 0x00FF00UL +#define kPackMaskR 0x00FF00UL +#define kPackMaskG 0x00FF00UL +#define kPackMaskB 0x00FFUL + + float fBiasHi; + float fBiasLo; +#endif /* GLIDE_PACKED_RGB */ + } pool; + + struct { /* environment data */ + FxBool ignoreReopen; + FxBool triBoundsCheck; /* check triangle bounds */ + FxBool noSplash; /* don't draw it */ + FxBool shamelessPlug; /* translucent 3Dfx logo in lower right */ + FxI32 swapInterval; /* swapinterval override */ + FxI32 swFifoLWM; + FxU32 snapshot; /* register trace snapshot */ + FxBool disableDitherSub; /* Turn off dither subtraction? */ + FxBool texLodDither; /* Always do lod-dithering */ + FxI32 tmuMemory; /* tmuMemory */ + FxBool enUma; /* enable uma */ + float gammaR, gammaG, gammaB; /* Gamma settings */ + + /* Force alternate buffer strategy */ + FxI32 nColorBuffer; + FxI32 nAuxBuffer; + FxI32 emulRush; /* Banshee reports as Rush flag */ + FxI32 grxClk; + FxBool autoBump; /* Auto bump or do it manually? */ + FxU32 bumpSize; + } environment; + + struct { + FxU32 bufferSwaps; /* number of buffer swaps */ + FxU32 pointsDrawn; + FxU32 linesDrawn; + FxU32 trisProcessed; + FxU32 trisDrawn; + + FxU32 texDownloads; /* number of texDownload calls */ + FxU32 texBytes; /* number of texture bytes downloaded */ + + FxU32 palDownloads; /* number of palette download calls */ + FxU32 palBytes; /* number of palette bytes downloaded */ + + FxU32 nccDownloads; /* # of NCC palette download calls */ + FxU32 nccBytes; /* # of NCC palette bytes downloaded */ + +#if USE_PACKET_FIFO + FxU32 fifoWraps; + FxU32 fifoWrapDepth; + FxU32 fifoStalls; + FxU32 fifoStallDepth; +#endif /* USE_PACKET_FIFO */ + } stats; + + GrHwConfiguration hwConfig; + + GrGC GCs[MAX_NUM_SST]; /* one GC per board */ + +#if GLIDE_DISPATCH_SETUP +#define TRISETUP_NORGB (*_GlideRoot.curTriProcs + 0) +#if GLIDE_PACKED_RGB +#define TRISETUP_RGB (*_GlideRoot.curTriProcs + 1) +#define TRISETUP_ARGB (*_GlideRoot.curTriProcs + 2) +#else /* !GLIDE_PACKED_RGB */ +#define TRISETUP_RGB TRISETUP_NORGB +#define TRISETUP_ARGB TRISETUP_NORGB +#endif /* !GLIDE_PACKED_RGB */ +#define PROC_SELECT_TRISETUP(__procVector, __cullMode) (__procVector)[(__cullMode) != GR_CULL_DISABLE] + + GrTriSetupProcArchVector* curTriProcs; +#endif /* GLIDE_DISPATCH_SETUP */ + + GrTexDownloadProcVector* curTexProcs; +#define PROC_SELECT_TEXDOWNLOAD() _GlideRoot.curTexProcs + FxBool OSWin95; +}; + +extern struct _GlideRoot_s GR_CDECL _GlideRoot; +#if GLIDE_MULTIPLATFORM +extern GrGCFuncs _curGCFuncs; +#endif + +#if defined(__WATCOMC__) +/* + * P6 Fence + * + * Here's the stuff to do P6 Fencing. This is required for the + * certain things on the P6 + * + * dpc - 21 may 1997 - FixMe! + * This was yoinked from sst1/include/sst1init.h, and should be + * merged back into something if we decide that we need it later. + */ +extern FxU32 p6FenceVar; + +void +p6Fence(void); +#pragma aux p6Fence = \ +"xchg eax, p6FenceVar" \ +modify [eax]; + + +#define P6FENCE p6Fence() +#elif defined(__MSC__) +/* Turn off the no return value warning for the function definition. + * + * NB: The function returns a value so that we can use it in places + * that require a value via the comma operator w/o resorting to casts + * everywhere the macro is invoked. + * + * NB: I checked the compiled code to make sure that it was inlined + * everywhere that we would possibly care that it was inlines. + */ +# pragma warning(disable : 4035) + __inline FxU32 _grP6Fence(void) + { + __asm xchg eax, _GlideRoot.p6Fencer + } +# define P6FENCE _grP6Fence() +# pragma warning(default : 4035) +#elif defined(macintosh) && defined(__POWERPC__) && defined(__MWERKS__) +#define P6FENCE __eieio() +#elif defined(__GNUC__) && defined(__i386__) +#define P6FENCE asm("xchg %%eax, %0" : : "m" (_GlideRoot.p6Fencer) : "eax"); +#else +#error "P6 Fencing in-line assembler code needs to be added for this compiler" +#endif /* Compiler specific fence commands */ + +/*==========================================================================*/ +/* Macros for declaring functions */ +#define GR_DDFUNC(name, type, args) \ + type FX_CSTYLE name args + +#define GR_ENTRY(name, type, args) \ + FX_EXPORT type FX_CSTYLE name args + +#define GR_DIENTRY(name, type, args) \ + FX_EXPORT type FX_CSTYLE name args + +#ifdef GLIDE3 +#define GR_STATE_ENTRY(name, type, args) \ + type _##name## args +#else +#define GR_STATE_ENTRY(name, type, args) \ + GR_ENTRY(name, type, args) +#endif + +/*==========================================================================*/ + +#define STATE_REQUIRES_IT_DRGB FXBIT(0) +#define STATE_REQUIRES_IT_ALPHA FXBIT(1) +#define STATE_REQUIRES_OOZ FXBIT(2) +#define STATE_REQUIRES_OOW_FBI FXBIT(3) +#define STATE_REQUIRES_W_TMU0 FXBIT(4) +#define STATE_REQUIRES_ST_TMU0 FXBIT(5) +#define STATE_REQUIRES_W_TMU1 FXBIT(6) +#define STATE_REQUIRES_ST_TMU1 FXBIT(7) +#define STATE_REQUIRES_W_TMU2 FXBIT(8) +#define STATE_REQUIRES_ST_TMU2 FXBIT(9) + +#define GR_TMUMASK_TMU0 FXBIT(GR_TMU0) +#define GR_TMUMASK_TMU1 FXBIT(GR_TMU1) +#define GR_TMUMASK_TMU2 FXBIT(GR_TMU2) + +/* +** Parameter gradient offsets +** +** These are the offsets (in bytes)of the DPDX and DPDY registers from +** from the P register +*/ +#ifdef GLIDE_USE_ALT_REGMAP +#define DPDX_OFFSET 0x4 +#define DPDY_OFFSET 0x8 +#else +#define DPDX_OFFSET 0x20 +#define DPDY_OFFSET 0x40 +#endif + +#if (GLIDE_PLATFORM & GLIDE_HW_SST1) +#define GLIDE_DRIVER_NAME "Voodoo Graphics" +#elif (GLIDE_PLATFORM & GLIDE_HW_SST96) +#define GLIDE_DRIVER_NAME "Voodoo Rush" +#elif (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define GLIDE_DRIVER_NAME "Voodoo^2" +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) +#define GLIDE_DRIVER_NAME "Banshee" +#else +#define GLIDE_DRIVER_NAME "HOOPTI???" +#endif + +/*==========================================================================*/ +#ifndef FX_GLIDE_NO_FUNC_PROTO + +void _grMipMapInit(void); + +#if GLIDE_DISPATCH_SETUP +#define TRISETUP (*gc->archDispatchProcs.triSetupProc) +#else /* !GLIDE_DISPATCH_SETUP */ +FxI32 FX_CSTYLE +_trisetup_asm(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); +FxI32 FX_CSTYLE +_trisetup_nogradients(const GrVertex *va, const GrVertex *vb, const GrVertex *vc); + +/* GMT: BUG need to make this dynamically switchable + That is not a bug. It is an opinion! + */ +#if GLIDE_USE_C_TRISETUP +# if (GLIDE_PLATFORM & GLIDE_HW_CVG) && USE_PACKET_FIFO +# define TRISETUP _trisetup_nogradients +# else /* !((GLIDE_PLATFORM & GLIDE_HW_CVG) && USE_PACKET_FIFO) */ +# define TRISETUP _trisetup_nogradients +# endif /* !((GLIDE_PLATFORM & GLIDE_HW_CVG) && USE_PACKET_FIFO) */ +#else /* !GLIDE_USE_C_TRISETUP */ +# define TRISETUP _trisetup_asm +#endif /* !GLIDE_USE_C_TRISETUP */ +#endif /* !GLIDE_DISPATCH_SETUP */ + +#ifdef GLIDE3 +void +_grValidateState(); + +void FX_CSTYLE +_grDrawVertexList(FxU32 listType, FxI32 mode, FxI32 count, void *pointers); + +void +_grAlphaBlendFunction( + GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, + GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df + ); +void +_grAlphaTestFunction( GrCmpFnc_t function ); + +void +_grAlphaTestReferenceValue( GrAlpha_t value ); + +void +_grAlphaCombine( + GrCombineFunction_t function, GrCombineFactor_t factor, + GrCombineLocal_t local, GrCombineOther_t other, + FxBool invert + ); + +void +_grAlphaControlsITRGBLighting( FxBool enable ); + +void +_grColorCombine( + GrCombineFunction_t function, GrCombineFactor_t factor, + GrCombineLocal_t local, GrCombineOther_t other, + FxBool invert ); + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +void +_grChromaModeExt(GrChromakeyMode_t mode); +void +_grChromaRangeExt( GrColor_t min, GrColor_t max , GrChromaRangeMode_t mode); +void +_grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode); +void +_grTexChromaRangeExt(GrChipID_t tmu, GrColor_t min, GrColor_t max); +#else +void +_grChromakeyValue( GrColor_t value ); +#endif + +void +_grChromakeyMode( GrChromakeyMode_t mode ); + +void +_grDepthMask( FxBool mask ); + +void +_grDepthBufferFunction( GrCmpFnc_t function ); + +void +_grDepthBufferMode( GrDepthBufferMode_t mode ); + +void +_grDitherMode( GrDitherMode_t mode ); + +void +_grRenderBuffer( GrBuffer_t buffer ); + +void +_grColorMask( FxBool rgb, FxBool a ); + +void +_grSstOrigin(GrOriginLocation_t origin); + +void +_grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy ); + +void +_grDepthBiasLevel( FxI16 level ); + +void +_grFogMode( GrFogMode_t mode ); + +void +_grFogColorValue( GrColor_t fogcolor ); + +void +_grLfbWriteColorFormat(GrColorFormat_t colorFormat); + +void +_grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords); + +void +_grConstantColorValue( GrColor_t value ); + +#endif + +#ifdef GLIDE3 /* glide 3 m point, m aa point, m line, m aa line routine */ + +void FX_CSTYLE +_grDrawPoints(FxI32 mode, FxI32 count, void *pointers); + +void FX_CSTYLE +_grDrawLineStrip(FxI32 mode, FxI32 count, FxI32 ltype, void *pointers); + +void FX_CSTYLE +_grDrawTriangles(FxI32 mode, FxI32 count, void *pointers); + +void FX_CSTYLE +_grAADrawPoints(FxI32 mode, FxI32 count, void *pointers); + +void FX_CSTYLE +_grAADrawLineStrip(FxI32 mode, FxI32 ltype, FxI32 count, void *pointers); + +void FX_CSTYLE +_grAADrawLines(FxI32 mode, FxI32 count, void *pointers); + +void FX_CSTYLE +_grAADrawTriangles(FxI32 mode, FxI32 ttype, FxI32 count, void *pointers); + +void FX_CSTYLE +_grAAVpDrawTriangles(FxI32 mode, FxI32 ttype, FxI32 count, void *pointers); + +void FX_CSTYLE +_grAADrawVertexList(FxU32 type, FxI32 mode, FxI32 count, void *pointers); + +#endif + +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +void FX_CSTYLE +_guTexMemReset(void); + +int FX_CSTYLE +_grBufferNumPending(void); + +FxBool FX_CSTYLE +_grSstIsBusy(void); + +void FX_CSTYLE +_grSstResetPerfStats(void); + +void FX_CSTYLE +_grResetTriStats(void); + +FxU32 FX_CSTYLE +_grSstStatus(void); + +FxU32 FX_CSTYLE +_grSstVideoLine(void); + +FxBool FX_CSTYLE +_grSstVRetraceOn(void); + +#endif + +#endif /* FX_GLIDE_NO_FUNC_PROTO */ + +/*==========================================================================*/ +/* +** Function Prototypes +*/ +void +_grClipNormalizeAndGenerateRegValues(FxU32 minx, FxU32 miny, FxU32 maxx, + FxU32 maxy, FxU32 *clipLeftRight, + FxU32 *clipBottomTop); + +void +_grSwizzleColor(GrColor_t *color); + +void +_grDisplayStats(void); + +void +_GlideInitEnvironment(void); + +void FX_CSTYLE +_grColorCombineDelta0Mode(FxBool delta0Mode); + +void +_doGrErrorCallback(const char *name, const char *msg, FxBool fatal); + +void _grErrorDefaultCallback(const char *s, FxBool fatal); + +#ifdef __WIN32__ +void _grErrorWindowsCallback(const char *s, FxBool fatal); +#endif /* __WIN32__ */ + +extern void +(*GrErrorCallback)(const char *string, FxBool fatal); + +void GR_CDECL +_grFence(void); + +int +_guHeapCheck(void); + +void FX_CSTYLE +_grRebuildDataList(void); + +void +_grReCacheFifo(FxI32 n); + +FxI32 GR_CDECL +_grSpinFifo(FxI32 n); + +void +_grShamelessPlug(void); + +FxBool +_grSstDetectResources(void); + +FxU16 +_grTexFloatLODToFixedLOD(float value); + +void FX_CSTYLE +_grTexDetailControl(GrChipID_t tmu, FxU32 detail); + +void FX_CSTYLE +_grTexDownloadNccTable(GrChipID_t tmu, FxU32 which, + const GuNccTable *ncc_table, + int start, int end); + +void FX_CSTYLE +_grTexDownloadPalette(GrChipID_t tmu, + GuTexPalette *pal, + int start, int end); + +FxU32 +_grTexCalcBaseAddress(FxU32 start_address, GrLOD_t largeLod, + GrAspectRatio_t aspect, GrTextureFormat_t fmt, + FxU32 odd_even_mask); + +void +_grTexForceLod(GrChipID_t tmu, int value); + +FxU32 +_grTexTextureMemRequired(GrLOD_t small_lod, GrLOD_t large_lod, + GrAspectRatio_t aspect, GrTextureFormat_t format, + FxU32 evenOdd, + FxBool roundP); +void FX_CSTYLE +_grUpdateParamIndex(void); + +/* ddgump.c */ +void FX_CSTYLE +_gumpTexCombineFunction(int virtual_tmu); + +/* disst.c - this is an un-documented external for arcade developers */ +extern FX_ENTRY void FX_CALL +grSstVidMode(FxU32 whichSst, FxVideoTimingInfo* vidTimings); + +/* glfb.c */ +extern FxBool +_grLfbWriteRegion(FxBool pixPipelineP, + GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y, + GrLfbSrcFmt_t src_format, + FxU32 src_width, FxU32 src_height, + FxI32 src_stride, + const void *src_data); + +/* gglide.c - Flushes the current state in gc->state.fbi_config to the hw. + */ +extern void +_grFlushCommonStateRegs(void); + +#if USE_PACKET_FIFO +/* cvg.c */ +extern void +_grSet32(volatile FxU32* const sstAddr, const FxU32 val); + +extern FxU32 +_grGet32(volatile FxU32* const sstAddr); +#endif /* USE_PACKET_FIFO */ + +/*==========================================================================*/ +/* GMT: have to figure out when to include this and when not to +*/ +#if defined(GLIDE_DEBUG) || defined(GLIDE_ASSERT) || defined(GLIDE_SANITY_ASSERT) || defined(GLIDE_SANITY_SIZE) + #define DEBUG_MODE 1 + #include +#endif + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) || (GLIDE_PLATFORM & GLIDE_HW_H3) + +#if ASSERT_FAULT +#define ASSERT_FAULT_IMMED(__x) if (!(__x)) { \ + *(FxU32*)NULL = 0; \ + _grAssert(#__x, __FILE__, __LINE__); \ + } +#else +#define ASSERT_FAULT_IMMED(__x) GR_ASSERT(__x) +#endif + +#if !USE_PACKET_FIFO +/* NOTE: fifoFree is the number of entries, each is 8 bytes */ +#define GR_CHECK_FOR_ROOM(n,p) \ +{ \ + FxI32 fifoFree = gc->state.fifoFree - (n); \ + if (fifoFree < 0) \ + fifoFree = _grSpinFifo(n); \ + gc->state.fifoFree = fifoFree;\ +} +#elif USE_PACKET_FIFO +/* Stuff to manage the command fifo on cvg + * + * NB: All of the addresses are in 'virtual' address space, and the + * sizes are in bytes. + */ + +/* The Voodoo^2 fifo is 4 byte aligned */ +#define FIFO_ALIGN_MASK 0x03 + +/* We claim space at the end of the fifo for: + * 1 nop (2 32-bit words) + * 1 jmp (1 32-bit word) + * 1 pad word + */ +#define FIFO_END_ADJUST (sizeof(FxU32) << 2) + +/* NB: This should be used sparingly because it does a 'real' hw read + * which is *SLOW*. + * + * NB: This address is always in sli master relative coordinates. + */ +FxU32 _grHwFifoPtr(FxBool); +#define HW_FIFO_PTR(a) _grHwFifoPtr(a) + +#if FIFO_ASSERT_FULL +extern const FxU32 kFifoCheckMask; +extern FxU32 gFifoCheckCount; + +#define FIFO_ASSERT() \ +if ((gFifoCheckCount++ & kFifoCheckMask) == 0) { \ + const FxU32 cmdFifoDepth = GR_GET(((SstRegs*)(gc->reg_ptr))->cmdFifoDepth); \ + const FxU32 maxFifoDepth = ((gc->cmdTransportInfo.fifoSize - FIFO_END_ADJUST) >> 2); \ + if(cmdFifoDepth > maxFifoDepth) { \ + gdbg_printf("cmdFifoDepth > size: 0x%X : 0x%X\n", \ + cmdFifoDepth, maxFifoDepth); \ + ASSERT_FAULT_IMMED(cmdFifoDepth <= maxFifoDepth); \ + } else if (cmdFifoDepth + (gc->cmdTransportInfo.fifoRoom >> 2) > maxFifoDepth) { \ + gdbg_printf("cmdFifoDepth + fifoRoom > size: (0x%X : 0x%X) : 0x%X\n", \ + cmdFifoDepth, (gc->cmdTransportInfo.fifoRoom >> 2), maxFifoDepth); \ + ASSERT_FAULT_IMMED(cmdFifoDepth + (gc->cmdTransportInfo.fifoRoom >> 2) <= maxFifoDepth); \ + } \ +} \ +ASSERT_FAULT_IMMED(HW_FIFO_PTR(FXTRUE) >= (FxU32)gc->cmdTransportInfo.fifoStart); \ +ASSERT_FAULT_IMMED(HW_FIFO_PTR(FXTRUE) < (FxU32)gc->cmdTransportInfo.fifoEnd); \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoRoom < gc->cmdTransportInfo.fifoSize); \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoPtr < (FxU32)gc->cmdTransportInfo.fifoEnd) +#else /* !FIFO_ASSERT_FULL */ +#define FIFO_ASSERT() \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoRoom < gc->cmdTransportInfo.fifoSize); \ +ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoPtr < (FxU32)gc->cmdTransportInfo.fifoEnd) +#endif /* !FIFO_ASSERT_FULL */ + +void GR_CDECL +_FifoMakeRoom(const FxI32 blockSize, const char* fName, const int fLine); + +#if defined( TACO_MEMORY_FIFO_HACK ) +extern void _FifoFlush( void ); +#endif + +#ifndef GLIDE_DEBUG +#define GR_BUMP_N_GRIND \ +do { \ + P6FENCE; \ + GR_CAGP_SET(bump, gc->cmdTransportInfo.fifoPtr - gc->cmdTransportInfo.lastBump); \ + gc->cmdTransportInfo.lastBump = gc->cmdTransportInfo.fifoPtr; \ + gc->cmdTransportInfo.bumpPos = gc->cmdTransportInfo.fifoPtr + (gc->cmdTransportInfo.bumpSize); \ + if (gc->cmdTransportInfo.bumpPos > gc->cmdTransportInfo.fifoEnd) \ + gc->cmdTransportInfo.bumpPos = gc->cmdTransportInfo.fifoEnd; \ +} while(0) +#else +/* fifo.c */ +void _grBumpNGrind(void); +#define GR_BUMP_N_GRIND _grBumpNGrind() +#endif + +#define CHECK_FOR_BUMP(__writeSize) \ +if (!gc->cmdTransportInfo.autoBump && \ + ((gc->cmdTransportInfo.fifoPtr + __writeSize) > gc->cmdTransportInfo.bumpPos)) \ + GR_BUMP_N_GRIND; + +#define GR_CHECK_FOR_ROOM(__n, __p) \ +do { \ + const FxU32 writeSize = (__n) + ((__p) * sizeof(FxU32)); /* Adjust for size of hdrs */ \ + ASSERT(((FxU32)(gc->cmdTransportInfo.fifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + ASSERT(writeSize < gc->cmdTransportInfo.fifoSize - sizeof(FxU32)); \ + /* CHECK_FOR_BUMP(writeSize); */ /* now done in _FifoMakeRoom */ \ + FIFO_ASSERT(); \ + if (gc->cmdTransportInfo.fifoRoom < (FxI32)writeSize) { \ + GDBG_INFO(280, "Fifo Addr Check: (0x%X : 0x%X)\n", \ + gc->cmdTransportInfo.fifoRoom, writeSize); \ + _FifoMakeRoom(writeSize, __FILE__, __LINE__); \ + } \ + ASSERT((FxU32)gc->cmdTransportInfo.fifoRoom >= writeSize); \ + FIFO_ASSERT(); \ +} while(0) +#else +#error "GR_CHECK_FOR_ROOM not defined" +#endif + +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) + +#define GR_CHECK_FOR_ROOM(__n, __p) + +#endif /* GLIDE_PLATFORM & GLIDE_HW_?? */ + +#ifdef GLIDE_SANITY_SIZE +#if USE_PACKET_FIFO +#define GR_CHECK_FIFO_PTR() \ +if (gc->cmdTransportInfo.autoBump) {\ + if((FxU32)gc->cmdTransportInfo.fifoPtr != gc->checkPtr + gc->checkCounter)\ + GDBG_ERROR("GR_ASSERT_FIFO", "(%s : %d) : " \ + "fifoPtr should be 0x%X (0x%X : 0x%X) but is 0x%X\n", \ + __FILE__, __LINE__, gc->checkPtr + gc->checkCounter, \ + gc->checkPtr, gc->checkCounter, gc->cmdTransportInfo.fifoPtr);\ + ASSERT_FAULT_IMMED((FxU32)gc->cmdTransportInfo.fifoPtr == gc->checkPtr + gc->checkCounter);\ +} + +#define GR_SET_FIFO_PTR(__n, __p) \ + gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr; \ + gc->checkCounter = ((__n) + ((__p) << 2)) +#else +#define GR_CHECK_FIFO_PTR() +#define GR_SET_FIFO_PTR(__n, __p) +#endif + +# define GR_CHECK_SIZE() \ + if(gc->counter != gc->expected_counter) \ + GDBG_ERROR("GR_ASSERT_SIZE","byte counter should be %d but is %d\n", \ + gc->expected_counter,gc->counter); \ + GR_CHECK_FIFO_PTR(); \ + gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr; \ + gc->checkCounter = 0; \ + ASSERT(gc->counter == gc->expected_counter); \ + gc->counter = gc->expected_counter = 0 + +# define GR_CHECK_SIZE_DIRECT() \ + if(gc->counter != gc->expected_counter) \ + GDBG_ERROR("GR_ASSERT_SIZE","byte counter should be %d but is %d\n", \ + gc->expected_counter,gc->counter); \ + gc->checkCounter = 0; \ + ASSERT(gc->counter == gc->expected_counter); \ + gc->counter = gc->expected_counter = 0 + + + +# define GR_SET_EXPECTED_SIZE(n,p) \ + ASSERT(gc->counter == 0); \ + ASSERT(gc->expected_counter == 0); \ + GR_CHECK_FOR_ROOM(n,p); \ + gc->expected_counter = n; \ + GR_SET_FIFO_PTR(n, p) + +# define GR_INC_SIZE(n) gc->counter += n +#else + /* define to do nothing */ +# define GR_CHECK_SIZE() +# define GR_CHECK_SIZE_DIRECT() +# define GR_SET_EXPECTED_SIZE(n,p) GR_CHECK_FOR_ROOM(n,p) +# define GR_INC_SIZE(n) +#endif + +#define GR_DCL_GC GrGC *gc = _GlideRoot.curGC +#if GLIDE_INIT_HAL +#define GR_DCL_HW SstRegs *hw = (SstRegs *)gc->sstRegs +#else +#define GR_DCL_HW SstRegs *hw = (SstRegs *)gc->sstRegs +#endif +#ifdef DEBUG_MODE +#define ASSERT(exp) GR_ASSERT(exp) + +#define GR_BEGIN_NOFIFOCHECK(name,level) \ + GR_DCL_GC; \ + GR_DCL_HW; \ + const FxI32 saveLevel = gc->myLevel; \ + static char myName[] = name; \ + GR_ASSERT(gc != NULL); \ + GR_ASSERT(hw != NULL); \ + gc->myLevel = level; \ + gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr; \ + GDBG_INFO(gc->myLevel,myName); \ + FXUNUSED(saveLevel); \ + FXUNUSED(hw) +#define GR_TRACE_EXIT(__n) \ + gc->myLevel = saveLevel; \ + GDBG_INFO(281, "%s --done---------------------------------------\n", __n) +#define GR_TRACE_RETURN(__l, __n, __v) \ + gc->myLevel = saveLevel; \ + GDBG_INFO((__l), "%s() => 0x%x---------------------\n", (__n), (__v), (__v)) +#else /* !DEBUG_MODE */ +#define ASSERT(exp) +#define GR_BEGIN_NOFIFOCHECK(name,level) \ + GR_DCL_GC; \ + GR_DCL_HW; \ + FXUNUSED(hw) +#define GR_TRACE_EXIT(__n) +#define GR_TRACE_RETURN(__l, __n, __v) +#endif /* !DEBUG_MODE */ + +#define GR_BEGIN(name,level,size, packetNum) \ + GR_BEGIN_NOFIFOCHECK(name,level); \ + GR_SET_EXPECTED_SIZE(size, packetNum) + +#define GR_END() {GR_CHECK_SIZE(); GR_TRACE_EXIT(myName);} + +#define GR_RETURN(val) \ + if (GDBG_GET_DEBUGLEVEL(gc->myLevel)) { \ + GR_CHECK_SIZE(); \ + } \ + else \ + GR_END(); \ + GR_TRACE_RETURN(gc->myLevel, myName, val); \ + return val + +#if defined(GLIDE_SANITY_ASSERT) +#define GR_ASSERT(exp) ((void)((!(exp)) ? (_grAssert(#exp, __FILE__, __LINE__),0) : 0xFFFFFFFF)) +#else +#define GR_ASSERT(exp) ((void)(0 && ((FxU32)(exp)))) +#endif + +#define INTERNAL_CHECK(__name, __cond, __msg, __fatalP) \ + if (__cond) _doGrErrorCallback(__name, __msg, __fatalP) + +#if defined(GLIDE_DEBUG) +#define GR_CHECK_F(name,condition,msg) INTERNAL_CHECK(name, condition, msg, FXTRUE) +#define GR_CHECK_W(name,condition,msg) INTERNAL_CHECK(name, condition, msg, FXFALSE) +#else +#define GR_CHECK_F(name,condition,msg) +#define GR_CHECK_W(name,condition,msg) +#endif + +#if GLIDE_CHECK_COMPATABILITY +#define GR_CHECK_COMPATABILITY(__name, __cond, __msg) INTERNAL_CHECK(__name, __cond, __msg, FXTRUE) +#else +#define GR_CHECK_COMPATABILITY(__name, __cond, __msg) GR_CHECK_F(__name, __cond, __msg) +#endif /* !GLIDE_CHECK_COMPATABILITY */ + +/* macro define some basic and common GLIDE debug checks */ +#define GR_CHECK_TMU(name,tmu) \ + GR_CHECK_COMPATABILITY(name, tmu < GR_TMU0 || tmu >= gc->num_tmu , "invalid TMU specified") + +void +_grAssert(char *, char *, int); + +#if USE_PACKET_FIFO +#ifdef GDBG_INFO_ON +void _grFifoWriteDebug(FxU32 addr, FxU32 val, FxU32 fifoPtr); +#define DEBUGFIFOWRITE(a,b,c) \ +_grFifoWriteDebug((FxU32) a, (FxU32) b, (FxU32) c) +void _grFifoFWriteDebug(FxU32 addr, float val, FxU32 fifoPtr); +#define DEBUGFIFOFWRITE(a,b,c) \ +_grFifoFWriteDebug((FxU32) a, (float) b, (FxU32) c) +#else /* ~GDBG_INFO_ON */ +#define DEBUGFIFOWRITE(a,b,c) +#define DEBUGFIFOFWRITE(a,b,c) +#endif /* !GDBG_INFO_ON */ +#endif /* USE_PACKET_FIFO */ + +/* HW Setting macros. We redefine the default macros to: + * - add extra tracing + * - work around hw bugs + * - do platform specific whacky things. + */ +# if SET_BSWAP +# undef GET +# undef GET16 +# undef SET +# undef SET16 +# undef SETF + +# if __POWERPC__ && defined(__MWERKS__) +# define GET(s) __lwbrx( (void*)&(s), 0 ) +# define GET16(s) __lwbrx( (void*)&(s), 0 ) +# define SET(d, s) __stwbrx((s), (void*)&(d), 0) +# define SET16(d, s) __sthbrx((s), (void*)&(d), 0 ) +# define SETF(d, s) { \ + const float temp = (s); \ + __stwbrx( *((FxU32*)&temp), (void*)&(d), 0 ); \ + } +# define SET_LINEAR(d, s) SET((d), (s)) +# define SET_LINEAR_16(d, s) SET((d), ((((FxU32)(s)) >> 16UL) | \ + (((FxU32)(s)) << 16UL))) +# define SET_LINEAR_8(d, s) ((d) = (s)) +# else /* !defined(__MWERKS__) && POWERPC */ +# error "Define byte swapped macros for GET/SET" +# endif /* !defined(__MWERKS__) && POWERPC */ +# else /* !SET_BSWAP */ +# undef GET +# undef GET16 + +# define GET(s) s +# define GET16(s) s +# endif /* !SET_BSWAP */ + + +#if GLIDE_USE_DEBUG_FIFO +#define kDebugFifoSize 0x1000UL +#endif /* GLIDE_USE_DEBUG_FIFO */ + +#ifndef SET_LINEAR +#define SET_LINEAR(__addr, __val) SET(__addr, __val) +#define SET_LINEAR_16(__addr, __val) SET(__addr, __val) +#define SET_LINEAR_8(__addr, __val) SET(__addr, __val) +#endif /* !defined(SET_LINEAR) */ + +/* Extract the fp exponent from a floating point value. + * NB: The value passed to this macro must be convertable + * into an l-value. + */ +#define kFPExpMask 0x7F800000UL +#define kFPZeroMask 0x80000000UL +#define kFPExpShift 0x17UL +#define FP_FLOAT_EXP(__fpVal) ((FxU32)(((*(const FxU32*)(&(__fpVal))) & kFPExpMask) >> kFPExpShift)) +#define FP_FLOAT_ZERO(__fpVal) (((*(const FxU32*)(&(__fpVal))) & ~kFPZeroMask) == 0x00) + +/* The two most commonly defined macros in the known universe */ +#define MIN(__x, __y) (((__x) < (__y)) ? (__x) : (__y)) +#define MAX(__x, __y) (((__x) < (__y)) ? (__y) : (__x)) + +/* Simple macro to make selecting a value against a boolean flag + * simpler w/o a conditional. + * + * NB: This requires that the boolean value being passed in be the + * result of one of the standard relational operators. + */ +#define MaskSelect(__b, __val) (~(((FxU32)(__b)) - 1UL) & (__val)) + +/* Chipfield ids that glide uses. */ +#define kChipFieldShift (8UL + 3UL) +typedef enum { + eChipBroadcast = 0x00UL, + eChipFBI = 0x01UL, + eChipTMU0 = 0x02UL, + eChipTMU1 = 0x04UL, + eChipTMU2 = 0x08UL, + eChipAltBroadcast = 0x0FUL, +} FifoChipField; + +#define BROADCAST_ID eChipBroadcast + +#define WAX_ID FX_BIT(14) + +/* Although these are named reg_group_xxx they are generic options for + * grouping register writes and should be fine w/ and w/o the fifo + * being enabled. + */ +#if GDBG_INFO_ON +#define REG_GROUP_DCL(__regMask, __regBase, __groupNum, __checkP) \ +const FxBool _checkP = (__checkP); \ +const FxU32 _groupNum = (__groupNum);\ +const FxU32 _regMask = (__regMask); \ +FxU32 _regCheckMask = (__regMask); \ +FxU32 _regBase = offsetof(SstRegs, __regBase) + +#define REG_GROUP_DCL_WAX(__regMask, __regBase, __groupNum, __checkP) \ +const FxBool _checkP = (__checkP); \ +const FxU32 _groupNum = (__groupNum);\ +const FxU32 _regMask = (__regMask); \ +FxU32 _regCheckMask = (__regMask); \ +FxU32 _regBase = offsetof(SstGRegs, __regBase) + + +#define REG_GROUP_ASSERT(__regAddr, __val, __floatP) \ +{ \ + const FxU32 curRegAddr = offsetof(SstRegs, __regAddr); \ + const FxU32 curRegIndex = (curRegAddr - _regBase) >> 2; \ + const FxU32 curRegBit = (0x01UL << curRegIndex); \ + const float floatVal = (const float)(__val); \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X : 0x%X) : 0x%X\n", \ + curRegIndex, curRegAddr, *(const FxU32*)&floatVal); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT((_regMask & curRegBit) == curRegBit); /* reg allocated in mask */ \ + if (curRegIndex > 0) \ + GR_ASSERT(((0xFFFFFFFFUL >> (32 - curRegIndex)) & _regCheckMask) == 0x00); /* All previous regs done */ \ + _regCheckMask ^= curRegBit; /* Mark current reg */ \ +} + +#define REG_GROUP_ASSERT_WAX(__regAddr, __val, __floatP) \ +{ \ + const FxU32 curRegAddr = offsetof(SstGRegs, __regAddr); \ + const FxU32 curRegIndex = (curRegAddr - _regBase) >> 2; \ + const FxU32 curRegBit = (0x01UL << curRegIndex); \ + const float floatVal = (const float)(__val); \ + GDBG_INFO(220, "\t(0x%X : 0x%X) : 0x%X\n", \ + curRegIndex, curRegAddr, *(const FxU32*)&floatVal); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT((_regMask & curRegBit) == curRegBit); /* reg allocated in mask */ \ + if (curRegIndex > 0) \ + GR_ASSERT(((0xFFFFFFFFUL >> (32 - curRegIndex)) & _regCheckMask) == 0x00); /* All previous regs done */ \ + _regCheckMask ^= curRegBit; /* Mark current reg */ \ +} + +#else /* !GDBG_INFO_ON */ +#define REG_GROUP_DCL(__regMask, __regBase, __groupNum, __checkP) +#define REG_GROUP_DCL_WAX(__regMask, __regBase, __groupNum, __checkP) +#define REG_GROUP_ASSERT(__regAddr, __val, __floatP) +#define REG_GROUP_ASSERT_WAX(__regAddr, __val, __floatP) +#endif /* !GDBG_INFO_ON */ + +#if GLIDE_HW_TRI_SETUP +enum { + kSetupStrip = 0x00, + kSetupFan = 0x01, + kSetupCullDisable = 0x00, + kSetupCullEnable = 0x02, + kSetupCullPositive = 0x00, + kSetupCullNegative = 0x04, + kSetupPingPongNorm = 0x00, + kSetupPingPongDisable = 0x08 +}; +#endif /* GLIDE_HW_TRI_SETUP */ + +#define REGNUM(__reg) (offsetof(SstRegs, __reg) >> 2) +#define REGNUM_WAX(_reg) (offsetof(SstGRegs, __reg) >> 2) + +#define PACKET_HEADER_ADD(__start, __reg, __header) \ +do {\ + GDBG_PRINTF("%x, %x\n", REGNUM(__reg), REGNUM(__start));\ + GR_ASSERT((REGNUM(__reg) - REGNUM(__start)) <= 14);\ + __header |= ((1 << (REGNUM(__reg) - REGNUM(__start))) << 15);\ +} while (0) + + +#if USE_PACKET_FIFO + +#define REGNUM(__reg) (offsetof(SstRegs, __reg) >> 2) +#define REGNUM_WAX(_reg) (offsetof(SstGRegs, __reg) >> 2) + +/* The shift below is a bit tricky. Watch out! */ +#define FIFO_REG(__chipField, __field) \ + (GR_ASSERT(((FxU32)(__chipField)) < 0x10UL), \ + ((((FxU32)offsetof(SstRegs, __field)) << 1) | (((FxU32)(__chipField)) << kChipFieldShift))) + +/* And here's the WAX version */ +/* The shift below is a bit tricky. Watch out! */ +#define FIFO_REG_WAX(__field) ((((FxU32)offsetof(SstGRegs, __field)) << 1) | FXBIT(14)) + +/* The REG_GROUP_XXX macros do writes to a monotonically increasing + * set of registers. There are three flavors of the macros w/ + * different restrictions etc. + * + * NB: Care must be taken to order the REG_GROUP_SET macro uses to + * match the actual register order, otherwise all hell breaks loose. + */ + +/* Write to __groupNum registers (max 14) starting at __regBase under + * the control of __groupMask (lsb->msb). + */ +#define REG_GROUP_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, \ + __groupMask, (((__groupMask) << SSTCP_PKT4_MASK_SHIFT) | \ + FIFO_REG(__chipId, __regBase) | \ + SSTCP_PKT4), \ + FXTRUE) + +#define REG_GROUP_BEGIN_WAX(__regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL_WAX(__regBase, __groupNum, __groupMask, \ +(((__groupMask) << SSTCP_PKT4_MASK_SHIFT) | FIFO_REG_WAX(__regBase) | \ +SSTCP_PKT4), FXTRUE) + +/* Same as the non-NO_CHECK variant, but GR_SET_EXPECTED_SIZE must + * have already been called to allocate space for this write. + */ +#define REG_GROUP_NO_CHECK_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_ASSERT(gc->expected_counter >= (FxI32)((__groupNum) * sizeof(FxU32))); \ +REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, \ + __groupMask, \ + (((__groupMask) << SSTCP_PKT4_MASK_SHIFT) | \ + FIFO_REG(__chipId, __regBase) | \ + SSTCP_PKT4), \ + FXFALSE) + +/* Register writes (<= 32) sequentially starting at __regBase */ +#define REG_GROUP_LONG_BEGIN(__chipId, __regBase, __groupNum) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 32)); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, \ + (0xFFFFFFFF >> (32 - (__groupNum))), \ + (((__groupNum) << SSTCP_PKT1_NWORDS_SHIFT) | \ + FIFO_REG(__chipId, __regBase) | \ + SSTCP_INC | \ + SSTCP_PKT1), \ + FXTRUE) + +#define GETREG(reg) (reg) + +#define REG_GROUP_BEGIN_INTERNAL(__chipId, __regBase, __groupNum, __groupMask, __pktHdr, __checkP) \ +{ \ + GR_DCL_GC; \ + volatile FxU32* _regGroupFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + REG_GROUP_DCL(__groupMask, __regBase, __groupNum, __checkP); \ + GR_ASSERT(((__pktHdr) & 0xE0000000UL) == 0x00UL); \ + FIFO_ASSERT(); \ + GR_ASSERT(GETREG(gc->cRegs->cmdFifo0.readPtrL) >= gc->cmdTransportInfo.fifoOffset);\ + GR_ASSERT(GETREG(gc->cRegs->cmdFifo0.readPtrL) < (gc->cmdTransportInfo.fifoOffset + gc->cmdTransportInfo.fifoSize));\ + GDBG_INFO(120, "REG_GROUP_BEGIN:\n");\ + GDBG_INFO(120, "\tFile: %s Line %d\n", __FILE__, __LINE__);\ + GDBG_INFO(120, "\t_regGroupFifoPtr: 0x%x\n", (FxU32)_regGroupFifoPtr - (FxU32)gc->rawLfb);\ + GDBG_INFO(120, "\t__pktHdr: 0x%x\n", __pktHdr);\ + GDBG_INFO(120, "\t__groupNum: 0x%x\n", __groupNum);\ + GDBG_INFO(120, "\t__groupMask: 0x%x\n", (__groupMask));\ + GDBG_INFO(120, "\t__chipId: 0x%x\n", __chipId);\ + GDBG_INFO(120, "\t__regBase: 0x%x\n", offsetof(SstRegs, __regBase));\ + GDBG_INFO(120, "\tfifoPtr: 0x%x\n", (FxU32)gc->cmdTransportInfo.fifoPtr - (FxU32)gc->cmdTransportInfo.fifoStart - (FxU32)gc->rawLfb); \ + GDBG_INFO(120, "\tfifoRoom: 0x%x\n", gc->cmdTransportInfo.fifoRoom);\ + GDBG_INFO(120, "\treadPtrL: 0x%x\n", GETREG(gc->cRegs->cmdFifo0.readPtrL));\ + SET(*_regGroupFifoPtr++, (__pktHdr)) + +#define REG_GROUP_BEGIN_INTERNAL_WAX(__regBase, __groupNum, __groupMask, __pktHdr, __checkP) \ +{ \ + GR_DCL_GC; \ + volatile FxU32* _regGroupFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + REG_GROUP_DCL_WAX(__groupMask, __regBase, __groupNum, __checkP); \ + GR_ASSERT(((__pktHdr) & 0xE0000000UL) == 0x00UL); \ + FIFO_ASSERT(); \ + GR_ASSERT(gc->cRegs->cmdFifo0.readPtrL >= gc->cmdTransportInfo.fifoOffset);\ + GR_ASSERT(gc->cRegs->cmdFifo0.readPtrL < (gc->cmdTransportInfo.fifoOffset + gc->cmdTransportInfo.fifoSize));\ + GDBG_INFO(220, "REG_GROUP_BEGIN_WAX:\n");\ + GDBG_INFO(220, "\tFile: %s Line %d\n", __FILE__, __LINE__);\ + GDBG_INFO(220, "\t_regGroupFifoPtr: 0x%x\n", (FxU32)_regGroupFifoPtr - (FxU32)gc->rawLfb);\ + GDBG_INFO(220, "\t__pktHdr: 0x%x\n", __pktHdr);\ + GDBG_INFO(220, "\t__groupNum: 0x%x\n", __groupNum);\ + GDBG_INFO(220, "\t__groupMask: 0x%x\n", (__groupMask));\ + GDBG_INFO(220, "\t__regBase: 0x%x\n", offsetof(SstGRegs, __regBase));\ + GDBG_INFO(220, "\tfifoPtr: 0x%x\n", (FxU32)gc->cmdTransportInfo.fifoPtr - (FxU32)gc->cmdTransportInfo.fifoStart - (FxU32)gc->rawLfb); \ + GDBG_INFO(220, "\tfifoRoom: 0x%x\n", gc->cmdTransportInfo.fifoRoom);\ + GDBG_INFO(220, "\treadPtrL: 0x%x\n", gc->cRegs->cmdFifo0.readPtrL);\ + GDBG_INFO(220, "\tStart Reg: 0x%x\n", (__pktHdr & 0x7fff) >> 3);\ + GDBG_INFO(220, "\tReg Mask: 0x%x\n", (__pktHdr >> 15) & 0x3fff);\ + GDBG_INFO(220, "\tReg Type: %s\n", ((__pktHdr >> 14) & 1) ? "2D" : "3D");\ + SET(*_regGroupFifoPtr++, (__pktHdr)) + + +#define REG_GROUP_SET(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXFALSE); \ + FXUNUSED(__regBase); \ + GDBG_INFO(120, "fifoReadPtr(HW): 0x%x\n", GETREG(gc->cRegs->cmdFifo0.readPtrL));\ + GR_ASSERT(GETREG(gc->cRegs->cmdFifo0.readPtrL) >= gc->cmdTransportInfo.fifoOffset);\ + GR_ASSERT(GETREG(gc->cRegs->cmdFifo0.readPtrL) < (gc->cmdTransportInfo.fifoOffset + gc->cmdTransportInfo.fifoSize));\ + GDBG_INFO(120, "REG_GROUP_SET:\n");\ + GDBG_INFO(120, "\tFile: %s Line %d\n", __FILE__, __LINE__);\ + GDBG_INFO(120, "\tfifoPtr: 0x%x, Val: 0x%x\n", (FxU32) _regGroupFifoPtr - (FxU32)gc->rawLfb, __val);\ + SET(*_regGroupFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define REG_GROUP_SET_WAX(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT_WAX(__regAddr, __val, FXFALSE); \ + FXUNUSED(__regBase); \ + GDBG_INFO(220, "fifoReadPtr(HW): 0x%x\n", gc->cRegs->cmdFifo0.readPtrL);\ + GR_ASSERT(gc->cRegs->cmdFifo0.readPtrL >= gc->cmdTransportInfo.fifoOffset);\ + GR_ASSERT(gc->cRegs->cmdFifo0.readPtrL < (gc->cmdTransportInfo.fifoOffset + gc->cmdTransportInfo.fifoSize));\ + GDBG_INFO(220, "REG_GROUP_SET_WAX:\n");\ + GDBG_INFO(220, "\tFile: %s Line %d\n", __FILE__, __LINE__);\ + GDBG_INFO(220, "\tfifoPtr: 0x%x, Val: 0x%x\n", (FxU32) _regGroupFifoPtr - (FxU32)gc->rawLfb, __val);\ + SET(*_regGroupFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define REG_GROUP_SETF(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXTRUE); \ + FXUNUSED(__regBase); \ + SETF(*(FxFloat*)_regGroupFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) + +#if GLIDE_FP_CLAMP +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ +do { \ + const FxU32 fpClampVal = FP_FLOAT_CLAMP(__val); \ + REG_GROUP_ASSERT(__regAddr, fpClampVal, FXTRUE); \ + FXUNUSED(__regBase); \ + SETF(*(FxFloat*)_regGroupFifoPtr++, fpClampVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) +#else +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ + REG_GROUP_SETF(__regBase, __regAddr, __val) +#endif + +#define REG_GROUP_NO_CHECK_END() \ + ASSERT(!_checkP); \ + ASSERT((((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) >> 2) == _groupNum + 1); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = (FxU32*)_regGroupFifoPtr; \ + FIFO_ASSERT(); \ +} + +#define REG_GROUP_END() \ + ASSERT(_checkP); \ + ASSERT((((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) >> 2) == _groupNum + 1); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)_regGroupFifoPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = (FxU32*)_regGroupFifoPtr; \ + GDBG_INFO(gc->myLevel + 200, "\tGroupEnd: (0x%X : 0x%X) : (0x%X : 0x%X)\n", \ + _regGroupFifoPtr, gc->cmdTransportInfo.fifoRoom, \ + HW_FIFO_PTR(FXTRUE), gc->cmdTransportInfo.fifoPtr); \ + FIFO_ASSERT(); \ +} \ +GR_CHECK_SIZE() + + +#if !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE +/* Send all of the triangle parameters in a single cmd fifo packet to + * the chip until the tsu is fixed. + */ +#define kNumTriParam 0x1FUL + +#define TRI_NO_TSU_BEGIN(__floatP) \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * kNumTriParam, 1); \ +{ \ + FxU32* noTsuFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + volatile FxU32* regBaseAddr = &hw->FvA.x; \ + FIFO_ASSERT(); \ + GR_ASSERT(__floatP); \ + SET(*noTsuFifoPtr++, ((kNumTriParam << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + SSTCP_INC | /* sequential writes */ \ + FIFO_REG(BROADCAST_ID, FvA.x) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + GDBG_INFO(gc->myLevel, "TRI_NO_TSU_BEGIN: (fbiRegs->%svA : 0x%X)\n", \ + ((__floatP) ? "F" : ""), (FxU32)noTsuFifoPtr) + +#define TRI_NO_TSU_SET(__addr, __val) \ +do { \ + const FxU32 hwWriteAddr = (FxU32)(__addr); \ + ASSERT(hwWriteAddr == (FxU32)regBaseAddr); \ + SET(*noTsuFifoPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_SETF(__addr, __val) \ +do { \ + const FxU32 hwWriteAddr = (FxU32)(__addr); \ + const FxFloat hwFloatVal = __val; \ + ASSERT(hwWriteAddr == (FxU32)regBaseAddr); \ + GDBG_INFO(gc->myLevel + 200, FN_NAME": FloatVal 0x%X : (0x%X : %g)\n", \ + ((FxU32)hwWriteAddr - (FxU32)hw) >> 2, \ + *(const FxU32*)&hwFloatVal, hwFloatVal); \ + SETF(*noTsuFifoPtr++, hwFloatVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_END() \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)noTsuFifoPtr - \ + (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = noTsuFifoPtr; \ + FIFO_ASSERT(); \ +} +#endif /* !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE */ + +#define STORE_FIFO(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((SstRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG(__chipId, __field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SET(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STORE_FIFO_WAX(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((SstGRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++,\ + ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG_WAX(__field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1 | FXBIT(14))); /* type (1) */ \ + SET(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + + +#define STORE_FIFO_INDEX(__chipId, __base, __regIndex, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((FxU32*)(__base))[__regIndex], __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + ((__chipId) << kChipFieldShift) | /* chip[14:10] */ \ + ((__regIndex) << 3) | /* Reg Num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SET(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STOREF_FIFO_INDEX(__chipId, __base, __regIndex, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + GR_ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOFWRITE(&((FxU32*)(__base))[__regIndex], __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + ((__chipId) << kChipFieldShift) | /* chip[14:10] */ \ + ((__regIndex) << 3) | /* Reg Num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SETF(*curFifoPtr++, __val); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STORE16_FIFO(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 temp32 = (((FxU32)(__val)) & 0x0000FFFF); \ + FXUNUSED(__base); \ + ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOWRITE(&((SstRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG(__chipId, __field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SET(*curFifoPtr++, temp32); \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +#define STOREF_FIFO(__chipId, __base, __field, __val) \ +do { \ + FxU32* curFifoPtr = gc->cmdTransportInfo.fifoPtr; \ + FXUNUSED(__base); \ + ASSERT(((FxU32)(curFifoPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + DEBUGFIFOFWRITE(&((SstRegs*)(__base))->__field, __val, curFifoPtr); \ + SET(*curFifoPtr++, ((0x01 << SSTCP_PKT1_NWORDS_SHIFT) | /* size (32bit words) */ \ + FIFO_REG(__chipId, __field) | /* chip[14:10] num[9:3] */ \ + SSTCP_PKT1)); /* type (1) */ \ + SETF(*(FxFloat*)curFifoPtr, __val); \ + curFifoPtr++; \ + gc->cmdTransportInfo.fifoPtr += 2; \ + gc->cmdTransportInfo.fifoRoom -= (sizeof(FxU32) << 1); \ + FIFO_ASSERT(); \ + GR_INC_SIZE(sizeof(FxU32)); /* Size of actual write not including header */ \ +} while(0) + +/* There are now three different flavors of the packet 3 macros for + * your coding pleasure. In increasing order of complexity and control + * they are TRI_BEGIN, TRI_STRIP_BEGIN, TRI_PACKET_BEGIN. + * + * NB: All of these macros must be terminated w/ a matching invocation of + * TRI_END otherwise all sorts of hell will break loose. + * + * TRI_BEGIN: + * The simplest form that draws a single indepependent triangle whose + * parameters and culling are all the glide defaults for grDrawTriangle. + * + * TRI_STRIP_BEGIN: + * setupMode: [kSetupStrip | kSetupFan]. Culling defaults to the current + * glide setting, w/ strips/fans defaulting to ping-pong culling + * nVertex: The number of vertices for the current packet (max 15). + * vertexSize: Size in bytes of the parameters for the vertices making up + * the current packet. + * cmd: [SSTCP_PKT3_BDDBDD (Independent) + * SSTCP_PKT3_BDDDDD (Start strip/fan) + * SSTCP_PKT3_DDDDDD (Continue strip)] + * + * TRI_PACKET_BEGIN: + * setupMode: The same as with TRI_STRIP_BEGIN, except that the caller + * needs to specify the culling bits kSetupCullXXX/kSetupPingPongXXX. + * params: Bits matching the descriptin of the sMode register describing + * which parameters are specified in the packet. + * nVertex: See TRI_STRIP_BEGIN. + * vertexSize: See TRI_STRIP_BEGIN. + * cmd: See TRI_STRIP_BEGIN. + */ +#define TRI_PACKET_BEGIN(__setupMode, __params, __nVertex, __vertexSize, __cmd) \ +{ \ + FxU32* tPackPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 packetVal = (((__setupMode) << SSTCP_PKT3_SMODE_SHIFT) | /* [27:22] */ \ + (__params) | /* pack[28] params[21:10] */ \ + ((__nVertex) << SSTCP_PKT3_NUMVERTEX_SHIFT) | /* [9:6] */ \ + (__cmd) | /* command [5:3] */ \ + SSTCP_PKT3); /* type [2:0] */ \ + TRI_ASSERT_DECL(__nVertex, __vertexSize, packetVal); \ + SET(*tPackPtr++, packetVal) + +#define TRI_STRIP_BEGIN(__setupMode, __nVertex, __vertexSize, __cmd) \ +{ \ + FxU32* tPackPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 packetVal = (((__setupMode) << SSTCP_PKT3_SMODE_SHIFT) | /* [27:22] */ \ + ((__nVertex) << SSTCP_PKT3_NUMVERTEX_SHIFT) | /* [9:6] */ \ + (__cmd) | /* command [5:3] */ \ + gc->cmdTransportInfo.cullStripHdr); \ + TRI_ASSERT_DECL(__nVertex, __vertexSize, packetVal); \ + SET(*tPackPtr++, packetVal) + +#define TRI_BEGIN() \ +{ \ + FxU32* tPackPtr = gc->cmdTransportInfo.fifoPtr; \ + TRI_ASSERT_DECL(3, _GlideRoot.curVertexSize, gc->cmdTransportInfo.triPacketHdr); \ + SET(*tPackPtr++, gc->cmdTransportInfo.triPacketHdr) + +#if GDBG_INFO_ON +extern void +_grH3FifoDump_TriHdr(const FxU32 triPacketHdr); +extern void +_grH3FifoDump_Linear(const FxU32* const linearPacketAddr); + +#define DEBUGFIFODUMP_TRI(__packetAddr) _grH3FifoDump_TriHdr(__packetAddr) +#define DEBUGFIFODUMP_LINEAR(__packetAddr) _grH3FifoDump_Linear(__packetAddr) + +#define TRI_ASSERT_DECL(__nVerts, __vertSize, __packetHdr) \ + const FxU32 nVertex = (__nVerts); \ + const FxU32 sVertex = (__vertSize); \ + FxU32 pCount = 0; \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT(((FxU32)(tPackPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_ASSERT((((__nVerts) * (__vertSize)) + sizeof(FxU32)) <= (FxU32)gc->cmdTransportInfo.fifoRoom); \ + GR_ASSERT((((FxU32)tPackPtr) + ((__nVerts) * (__vertSize)) + sizeof(FxU32)) < \ + (FxU32)gc->cmdTransportInfo.fifoEnd); \ + GR_ASSERT(nVertex < 0x10); \ + GR_ASSERT(nVertex > 0x00); \ + GR_ASSERT(((__packetHdr) & 0xE0000000UL) == 0x00UL); \ + FIFO_ASSERT(); \ + GDBG_INFO(120, "Triangle(0x%X): (0x%X : 0x%X)\n", (__packetHdr), __nVerts, __vertSize); \ + DEBUGFIFODUMP_TRI(__packetHdr) +#define CLAMP_DUMP(__val, __floatVal) \ + pCount++; \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X) : V#: 0x%X - P#: 0x%X - ParamVal: (%f : 0x%X)\n", \ + (FxU32)tPackPtr, \ + ((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) / sVertex, \ + (((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) % sVertex) >> 2, \ + (((__val) < 786432.875) ? (__val) : ((__val) - 786432.875)), \ + (__floatVal)) +#define SETF_DUMP(__val) \ + pCount++; \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X) : V#: 0x%X - P#: 0x%X - ParamVal: %f\n", \ + (FxU32)tPackPtr, \ + ((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) / sVertex, \ + (((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) % sVertex) >> 2, \ + (((__val) < 786432.875) ? (__val) : ((__val) - 786432.875))) +#define SET_DUMP(__val) \ + pCount++; \ + GDBG_INFO(gc->myLevel + 200, "\t(0x%X) : V#: 0x%X - P#: 0x%X - ParamVal: 0x%X\n", \ + (FxU32)tPackPtr, \ + ((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) / sVertex, \ + (((FxU32)tPackPtr - ((FxU32)gc->cmdTransportInfo.fifoPtr + sizeof(FxU32))) % sVertex) >> 2, \ + (__val)) +#define TRI_ASSERT() \ + GR_ASSERT(pCount == (nVertex * (sVertex >> 2))); \ + ASSERT(((FxU32)tPackPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) == (nVertex * sVertex) + sizeof(FxU32)) +#else /* !GDBG_INFO_ON */ +#define DEBUGFIFODUMP_TRI(__packetAddr) +#define DEBUGFIFODUMP_LINEAR(__packetAddr) + +#define CLAMP_DUMP(__val, __floatVal) +#define SETF_DUMP(__val) +#define SET_DUMP(__val) + +#define TRI_ASSERT_DECL(__nVerts, __vertSize, __packetHdr) +#define TRI_ASSERT() +#endif /* !GDBG_INFO_ON */ + +/* Get the integer representation of the color component. Currently, + * following in the 'Glide is not an API for kids' tradition we'll + * probably do something silly like wrap around zero. + */ +#if GLIDE_PACKED_RGB +#define RGBA_COMP(__fpVal, __fpBias, __fpShift, __fpMask) \ +((_GlideRoot.pool.ftemp1 = (float)((float)(__fpVal) + (float)(__fpBias))), \ + GR_ASSERT((__fpVal) >= 0.0f), \ + GR_ASSERT((__fpVal) < 256.0f), \ + (((*(const FxU32*)&_GlideRoot.pool.ftemp1) & (__fpMask)) << (__fpShift))) + +#define RGBA_COMP_CLAMP(__fpVal, __compToken) \ + RGBA_COMP(__fpVal, kPackBias##__compToken, kPackShift##__compToken, kPackMask##__compToken) +#endif /* GLIDE_PACKED_RGB */ + +/* First stage tsu-subtractor chec/fix. + * Mmm..... sequence operator. + */ +#if GLIDE_FP_CLAMP +#define kFPClampThreshold 0x20UL +#define FP_FLOAT_CLAMP(__fpVal) ((FP_FLOAT_EXP(__fpVal) < kFPClampThreshold) \ + ? (_GlideRoot.stats.tsuValClamp++, 0x00UL) \ + : *(const FxU32*)(&(__fpVal))) + +#define TRI_SETF_CLAMP(__val) \ +do { \ + const FxU32 floatCastVal = FP_FLOAT_CLAMP(__val); \ + CLAMP_DUMP(__val, floatCastVal); \ + SET(*tPackPtr++, floatCastVal); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) +#else +#define TRI_SETF_CLAMP(__val) \ + TRI_SETF(__val) +#endif + +#define TRI_SETF(__val) \ +do { \ + SETF_DUMP(__val); \ + SETF(*tPackPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) + +#define TRI_SET(__val) \ +do { \ + SET_DUMP(__val); \ + SET(*tPackPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define TRI_END \ + TRI_ASSERT(); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)tPackPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = tPackPtr; \ + GDBG_INFO(gc->myLevel + 200, "\tTriEnd: (0x%X : 0x%X)\n", tPackPtr, gc->cmdTransportInfo.fifoRoom); \ + FIFO_ASSERT(); \ +} + +#define FIFO_LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN, __f, __l) \ +{ \ + FxU32* packetPtr = gc->cmdTransportInfo.fifoPtr; \ + const FxU32 writeSize = (__numWords); /* Add size of packet header */ \ + const FxU32 hdr1 = ((__type) | \ + (((FxU32)(__maskW2)) << SSTCP_PKT5_BYTEN_W2_SHIFT) | \ + (((FxU32)(__maskWN)) << SSTCP_PKT5_BYTEN_WN_SHIFT) | \ + (writeSize << SSTCP_PKT5_NWORDS_SHIFT) | \ + SSTCP_PKT5); \ + const FxU32 hdr2 = ((FxU32)(__addr)) & SSTCP_PKT5_BASEADDR; \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ + GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ + GR_ASSERT(((FxU32)(packetPtr) & FIFO_ALIGN_MASK) == 0); /* alignment */ \ + GR_ASSERT((__numWords) > 0); /* packet size */ \ + GR_ASSERT((__numWords) < ((0x01 << 19) - 2)); \ + GR_ASSERT((((FxU32)(__numWords) + 2) << 2) <= (FxU32)gc->cmdTransportInfo.fifoRoom); \ + GR_ASSERT(((FxU32)packetPtr + (((FxU32)(__numWords) + 2) << 2)) < \ + (FxU32)gc->cmdTransportInfo.fifoEnd); \ + GR_ASSERT((hdr2 & 0xE0000000UL) == 0x00UL); \ + GR_ASSERT(1 /* (((FxU32)(__type)) >= ((FxU32)SSTCP_PKT5_3DLFB)) && \ + (((FxU32)(__type)) <= ((FxU32)SSTCP_PKT5_TEXPORT))*/); \ + FIFO_ASSERT(); \ + GDBG_INFO(120, "LinearWrite(0x%X : 0x%X)\n", hdr1, hdr2); \ + GDBG_INFO(gc->myLevel + 200, "\tFile: %s - Line: %ld\n", __f, __l); \ + GDBG_INFO(gc->myLevel + 200, "\tType: 0x%X\n", (FxU32)(__type)); \ + GDBG_INFO(gc->myLevel + 200, "\tAddr: 0x%X\n", (FxU32)(__addr)); \ + GDBG_INFO(gc->myLevel + 200, "\tMaskW2: 0x%X\n", (FxU32)(__maskW2)); \ + GDBG_INFO(gc->myLevel + 200, "\tMaskWN: 0x%X\n", (FxU32)(__maskWN)); \ + GDBG_INFO(gc->myLevel + 200, "\twriteSize: 0x%X\n", writeSize); \ + GDBG_INFO(gc->myLevel + 200, "\thdr 1: 0x%X\n", hdr1); \ + GDBG_INFO(gc->myLevel + 200, "\thdr 2: 0x%X\n", hdr2); \ + SET(*packetPtr++, hdr1); \ + SET(*packetPtr++, hdr2); \ + GR_INC_SIZE(sizeof(FxU32)) + +#define FIFO_LINEAR_WRITE_SET(__val) \ +do { \ + GDBG_INFO(gc->myLevel + 205, "\t0x%X : 0x%X\n", packetPtr, (__val)); \ + GDBG_INFO(gc->myLevel + 205, "fifPtr: 0x%x, val: 0x%x\n\n", packetPtr, __val);\ + GR_ASSERT(GETREG(gc->cRegs->cmdFifo0.readPtrL) >= gc->cmdTransportInfo.fifoOffset);\ + GR_ASSERT(GETREG(gc->cRegs->cmdFifo0.readPtrL) < (gc->cmdTransportInfo.fifoOffset + gc->cmdTransportInfo.fifoSize));\ + SET_LINEAR(*packetPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define FIFO_LINEAR_WRITE_SET_16(__val) \ +do { \ + GDBG_INFO(gc->myLevel + 205, "\t0x%X : 0x%X\n", packetPtr, (__val)); \ + SET_LINEAR_16(*packetPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define FIFO_LINEAR_WRITE_SET_8(__val) \ +do { \ + GDBG_INFO(gc->myLevel + 205, "\t0x%X : 0x%X\n", packetPtr, (__val)); \ + SET_LINEAR_8(*packetPtr++, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define FIFO_LINEAR_WRITE_END \ + DEBUGFIFODUMP_LINEAR(gc->cmdTransportInfo.fifoPtr); \ + GR_ASSERT((((FxU32)packetPtr - (FxU32)gc->cmdTransportInfo.fifoPtr) >> 2) == writeSize + 2); \ + gc->cmdTransportInfo.fifoRoom -= ((FxU32)packetPtr - (FxU32)gc->cmdTransportInfo.fifoPtr); \ + gc->cmdTransportInfo.fifoPtr = packetPtr; \ + GDBG_INFO(gc->myLevel + 200, "\tLinearEnd: (0x%X : 0x%X)\n", \ + packetPtr, gc->cmdTransportInfo.fifoRoom); \ + FIFO_ASSERT(); \ +} + +# define GR_GET(s) GET(s) +# define GR_CAGP_GET(__reg) GET(gc->cRegs->cmdFifo0.__reg) +# define GR_CAGP_SET(__reg, __val) SET(gc->cRegs->cmdFifo0.__reg, __val) +# define GR_GET16(s) ((FxU16)GET16(s)) +# define GR_SET(c, h, f, s) STORE_FIFO(c, h, f, s) +# define GR_SET_WAX(c, h, f, s) STORE_FIFO_WAX(c, h, f, s) +# define GR_SET_INDEX(c, h, r, s) STORE_FIFO_INDEX(c, h, r, s) +# define GR_SET16(c, h, f, s) STORE16_FIFO(c, h, f, s) +# define GR_SETF(c, h, f, s) STOREF_FIFO(c, h, f, s) +# define GR_SETF_INDEX(c, h, r, s) STOREF_FIFO_INDEX(c, h, r, s) +# define GR_SET_DIRECT(__bc, __hw, __reg, __val) gc->sstRegs->__reg = __val;GR_INC_SIZE(sizeof(__val)) +# define GR_SET_IO(c, h, f, s) (gc->ioRegs)->f = s +#else /* !USE_PACKET_FIFO */ +# ifndef DIRECT_IO +# define GR_GET(s) GET(s) +# define GR_CAGP_GET(__reg) GET(gc->cRegs->cmdFifo0__reg) +# define GR_GET16(s) ((FxU16)GET16(s)) +# define GR_SET(c, h, f, s) do {SET((h)->f, s); GR_INC_SIZE(4);} while(0) +# define GR_SET_INDEX(c, h, r, s) do {SET(((FxU32*)(h))[r], s); GR_INC_SIZE(sizeof(FxU32));} while(0) +# define GR_SETF(c, h, f, s) do {SETF(h->f, s); GR_INC_SIZE(4);} while(0) +# define GR_SETF_INDEX(c, h, r, s) do {SETF(((FxU32*)(h))[r], s); GR_INC_SIZE(sizeof(FxU32));} while(0) +# define GR_SET16(c, h, f, s) do {SET16((h)->f, s); GR_INC_SIZE(2);} while(0) +# define GR_SET_IO(c,h,f,s) GR_SET(c, h, f, s) +# define GR_SET_DIRECT(c,h,f,s) GR_SET(c, h, f, s) +# else +# define GR_GET(s) GET(s) +# define GR_CAGP_GET(__reg) gc->cRegs->cmdFifo0.reg +# define GR_GET16(s) ((FxU16)GET16(s)) +# define GR_SET(c, h, f, s) {(gc->sstRegs)->f = s; GR_INC_SIZE(4);} +# define GR_SETF(c, h, f, s) {((volatile float) (gc->sstRegs)->f) = (float) (s); GR_INC_SIZE(4);} +# define GR_SET_INDEX(c, h, r, s) {((FxU32 *)(gc->sstRegs))[r] = s; GR_INC_SIZE(4);} +# define GR_SETF_INDEX(c, h, r, s) {((volatile float *)(gc->sstRegs))[r] = (float) (s); GR_INC_SIZE(4);} +# define GR_SET16(c, h, f, s) {*((FxU16 *)((gc->sstRegs)->f)) = s; GR_INC_SIZE(4);} +# define GR_SET_DIRECT(__b, __ptr, __reg, __val) \ +{\ + __ptr->__reg = __val;\ + GR_INC_SIZE(4);\ +} +# define GR_SET_IO(c, h, f, s) (gc->ioRegs)->f = s +# endif +#endif /* !USE_PACKET_FIFO */ + +/* Macros to do linear writes to lfb/tex memory. + * + * LINEAR_WRITE_BEGIN - Setup stuff for the linear write. + * + * numWords: The number of words to actually write to the destination + * address. This does *NOT* include the packet headers etc for any + * command fifos etc. + * + * type: One of the kLinearWriteXXX enum values above. This can + * control what the legal values for addr and maskXX are. + * + * addr: Base address to the start the write. + * + * maskXX: Control what bytes in a write are active, these are active + * low. W2 controls the masking of the first 32bit word written, and + * WN controls all of the other writes. + * + * LINEAR_WRITE_SET - Writes are done in 32-bit increments, and must + * be properly aligned etc. This can only be used inside of a + * LINEAR_WRITE_BEGIN/LINEAR_WRITE_END pair. + * + * LINEAR_WRITE_EDGE - Write to a 16-bit value to an address. The + * address must be aligned for at 16-bit access, and should not appear + * within a LINEAR_WRITE_BEGIN/LINEAR_WRITE_END pair. + * + * LINEAR_WRITE_END - Finish off any stuff for the linear write. + */ + +#if USE_PACKET_FIFO +#define LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN) \ +{ \ + GR_SET_EXPECTED_SIZE(((FxU32)((__numWords) + 1) << 2), 1); \ + FIFO_LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN, __FILE__, __LINE__) +#define LINEAR_WRITE_SET(__addr, __val) \ + FIFO_LINEAR_WRITE_SET(__val) +#define LINEAR_WRITE_SET_16(__addr, __val) \ + FIFO_LINEAR_WRITE_SET_16(__val) +#define LINEAR_WRITE_SET_8(__addr, __val) \ + FIFO_LINEAR_WRITE_SET_8(__val) +#define LINEAR_WRITE_END() \ + FIFO_LINEAR_WRITE_END; \ + GR_CHECK_SIZE(); \ +} + +/* Macro to write the edge cases of a linear write, for example to the + * lfb w/ a 16-bit pixel value. We do some address manipulation here + * since the cmd fifo only addresses 32-bit quantities, but allows us + * to mask of crap for the actual write. + * + */ +#if (GLIDE_PLATFORM & GLIDE_ENDIAN_LITTLE) +#define kWordMask 0x0CUL +#define kWordShift 0 +#elif (GLIDE_PLATFORM & GLIDE_ENDIAN_BIG) +#define kWordMask 0x03UL +#define kWordShift 16 +#else +#error "Must define processor endian-ness for LINEAR_WRITE_EDGE" +#endif /* Endian-ness check */ + +#define LINEAR_WRITE_EDGE(__type, __addr, __val, __alignedP) \ +do { \ + LINEAR_WRITE_BEGIN(1, __type, \ + ((FxU32)__addr & ~0x03UL), \ + ((__alignedP) ? kWordMask : (0x0F & (~kWordMask))), 0x00); \ + FIFO_LINEAR_WRITE_SET(((FxU32)(__val)) << ((__alignedP) ? kWordShift : (16 - kWordShift))); \ + LINEAR_WRITE_END(); \ +} while(0) +#else /* !USE_PACKET_FIFO */ +# define LINEAR_WRITE_BEGIN(__numWords, __type, __addr, __maskW2, __maskWN) \ +{ \ + GR_SET_EXPECTED_SIZE(((__numWords) << 2), (__numWords)) +# define LINEAR_WRITE_SET(__addr, __val) \ +do { \ + FxU32* tempAddr = (FxU32*)(__addr); \ + SET(*tempAddr, __val); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +# define LINEAR_WRITE_SET_16(__addr, __val)\ + LINEAR_WRITE_SET(__addr, (FxU32) __val) +# define LINEAR_WRITE_SET_8(__addr, __val) \ + LINEAR_WRITE_SET(__addr, (FxU32) __val) + +# define LINEAR_WRITE_EDGE(__type, __addr, __val, __alignedP) \ +do { \ + FxU32* tempAddr = (FxU32*)(__addr); \ + SET16(*tempAddr, __val); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) +# define LINEAR_WRITE_END() \ + GR_CHECK_SIZE(); \ +} + +/* The REG_GROUP_XXX macros do writes to a monotonically increasing + * set of registers. There are three flavors of the macros w/ + * different restrictions etc. + * + * NB: Care must be taken to order the REG_GROUP_SET macro uses to + * match the actual register order, otherwise all hell breaks loose. + */ + +/* Write to __groupNum registers (max 14) starting at __regBase under + * the control of __groupMask (lsb->msb). + */ +#define REG_GROUP_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, __groupMask, FXTRUE) + +#define REG_GROUP_BEGIN_WAX( __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL_WAX(__regBase, __groupNum, __groupMask, FXTRUE) + +/* Same as the non-NO_CHECK variant, but GR_SET_EXPECTED_SIZE must + * have already been called to allocate space for this write. + */ +#define REG_GROUP_NO_CHECK_BEGIN(__chipId, __regBase, __groupNum, __groupMask) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 21)); \ +GR_ASSERT(((__groupMask) & (SSTCP_PKT4_MASK >> SSTCP_PKT4_MASK_SHIFT)) != 0x00); \ +GR_ASSERT(gc->expected_counter >= (FxI32)((__groupNum) * sizeof(FxU32))); \ +REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, __groupMask, FXFALSE) + +/* Register writes (<= 32) sequentially starting at __regBase */ +#define REG_GROUP_LONG_BEGIN(__chipId, __regBase, __groupNum) \ +GR_ASSERT(((__groupNum) >= 1) && ((__groupNum) <= 32)); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * (__groupNum), 1); \ +REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, (0xFFFFFFFF >> (32 - (__groupNum))), FXTRUE) + +#define REG_GROUP_BEGIN_INTERNAL(__regBase, __groupNum, __groupMask, __checkP) \ +{ \ + GR_DCL_GC; \ + REG_GROUP_DCL(__groupMask, __regBase, __groupNum, __checkP); \ + GDBG_INFO(gc->myLevel + 100, "REG_GROUP_BEGIN: (0x%X : 0x%X)\n", \ + (__groupMask), offsetof(SstRegs, __regBase) >> 2) + +#define REG_GROUP_BEGIN_INTERNAL_WAX(__regBase, __groupNum, __groupMask, __checkP) \ +{ \ + GR_DCL_GC; \ + REG_GROUP_DCL_WAX(__groupMask, __regBase, __groupNum, __checkP); \ + GDBG_INFO(220, "REG_GROUP_BEGIN_WAX: (0x%X : 0x%X)\n", \ + (__groupMask), offsetof(SstGRegs, __regBase) >> 2) + + +#define REG_GROUP_SET(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXFALSE); \ + SET(((SstRegs*)(__regBase))->__regAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + +#define REG_GROUP_SET_WAX(__regBase, __regAddr, __val) \ +do { \ + SET(((SstGRegs*)((FxU32) __regBase + SST_2D_OFFSET))->__regAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) + + +#define REG_GROUP_SETF(__regBase, __regAddr, __val) \ +do { \ + REG_GROUP_ASSERT(__regAddr, __val, FXTRUE); \ + SETF(((SstRegs*)(__regBase))->__regAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxFloat)); \ +} while(0) + +#if GLIDE_FP_CLAMP +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ +do { \ + const FxU32 fpClampVal = FP_FLOAT_CLAMP(__val); \ + REG_GROUP_ASSERT(__regAddr, fpClampVal, FXTRUE); \ + SET(((FxU32*)(__regBase))[offsetof(SstRegs, __regAddr) >> 2], fpClampVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ +} while(0) +#else +#define REG_GROUP_SETF_CLAMP(__regBase, __regAddr, __val) \ + REG_GROUP_SETF(__regBase, __regAddr, __val) +#endif + +#define REG_GROUP_NO_CHECK_END() \ + ASSERT(!_checkP); \ +} + +#define REG_GROUP_END() \ + ASSERT(_checkP); \ +} \ +GR_CHECK_SIZE() + +#if !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE +/* Send all of the triangle parameters in a single cmd fifo packet to + * the chip until the tsu is fixed. + */ +#define kNumTriParam 0x1FUL + +#define TRI_NO_TSU_BEGIN(__floatP) \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + !gc->open, \ + "Called before grSstWinOpen()"); \ +GR_CHECK_COMPATABILITY(FN_NAME, \ + (gc->cmdTransportInfo.lfbLockCount != 0), \ + "Called within grLfbLock/grLfbUnlockPair"); \ +GR_SET_EXPECTED_SIZE(sizeof(FxU32) * kNumTriParam, 1); \ +{ \ + volatile FxU32* regBaseAddr = (volatile FxU32*)((__floatP) \ + ? &hw->FvA \ + : &hw->vA); \ + GDBG_INFO(gc->myLevel, "TRI_NO_TSU_BEGIN: fbiRegs->%svA\n", \ + ((__floatP) ? "F" : "")) + +#define TRI_NO_TSU_SET(__addr, __val) \ +do { \ + const FxU32* hwWriteAddr = (const FxU32*)(__addr); \ + ASSERT(hwWriteAddr == regBaseAddr); \ + SET(*hwWriteAddr, (__val)); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_SETF(__addr, __val) \ +do { \ + const FxU32* hwWriteAddr = (const FxU32*)(__addr); \ + const FxFloat hwFloatVal = __val; \ + ASSERT(hwWriteAddr == regBaseAddr); \ + GDBG_INFO(gc->myLevel + 200, FN_NAME": FloatVal 0x%X : (0x%X : %g)\n", \ + ((FxU32)hwWriteAddr - (FxU32)hw) >> 2, \ + *(const FxU32*)&hwFloatVal, hwFloatVal); \ + SETF(*hwWriteAddr, hwFloatVal); \ + GR_INC_SIZE(sizeof(FxU32)); \ + regBaseAddr++; \ +} while(0) + +#define TRI_NO_TSU_END() \ +} +#endif /* !GLIDE_HW_TRI_SETUP || HOOPTI_TRI_SETUP_COMPARE */ + +#endif /* !USE_PACKET_FIFO */ + +/* Offsets to 'virtual' addresses in the hw */ +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) +#define HW_REGISTER_OFFSET SST_3D_OFFSET +#define HW_FIFO_OFFSET 0x00200000UL +#elif (GLIDE_PLATFORM & GLIDE_HW_H3) +#define HW_IO_REG_REMAP SST_IO_OFFSET +#define HW_CMD_AGP_OFFSET SST_CMDAGP_OFFSET +#define HW_2D_REG_OFFSET SST_2D_OFFSET +#define HW_3D_REG_OFFSET SST_3D_OFFSET +#define HW_REGISTER_OFFSET HW_3D_REG_OFFSET +#else +#error "Must define virtual address spaces for this hw" +#endif + +#define HW_FIFO_OFFSET 0x00200000UL +#define HW_LFB_OFFSET SST_LFB_OFFSET +#define HW_TEXTURE_OFFSET SST_TEX_OFFSET + +/* This is the alignmnet requirement for texBaseAddr. Actually, + * nothing bad is going to happen, but when the hw lops bits off of + * the address the wrong texels are going to appear. + */ +#define SST_TEXTURE_ALIGN 0x10UL +#define SST_TEXTURE_ALIGN_MASK (SST_TEXTURE_ALIGN - 0x01UL) + +#if (GLIDE_PLATFORM & GLIDE_HW_CVG) || (GLIDE_PLATFORM & GLIDE_HW_H3) +#define HW_BASE_PTR(__b) (__b) +#else +#error "Need HW_BASE_PTR to convert hw address into board address." +#endif + +#define HW_REG_PTR(__b) ((FxU32*)(((FxU32)(__b)) + HW_REGISTER_OFFSET)) +#define HW_LFB_PTR(__b) ((FxU32*)(((FxU32)(__b)) + HW_LFB_OFFSET)) +#define HW_TEX_PTR(__b) ((FxU32*)(((FxU32)(__b)) + HW_TEXTURE_OFFSET)) + +/* access a floating point array with a byte index */ +#define FARRAY(p,i) (*(float *)((i)+(int)(p))) +#define ArraySize(__a) (sizeof(__a) / sizeof((__a)[0])) + +void rle_decode_line_asm(FxU16 *tlut,FxU8 *src,FxU16 *dest); + +extern FxU16 rle_line[256]; +extern FxU16 *rle_line_end; + +#define RLE_CODE 0xE0 +#define NOT_RLE_CODE 31 + +#ifdef __WATCOMC__ +#pragma aux rle_decode_line_asm parm [edx] [edi] [esi] value [edi] modify exact [eax ebx ecx edx esi edi] = \ +" next_pixel: " \ +" xor ecx,ecx " \ +" mov al,byte ptr[edi] " \ +" mov cl,byte ptr[edi] " \ +" inc edi " \ +" " \ +" and al,0xE0 " \ +" cmp al,0xE0 " \ +" jne unique " \ +" " \ +" and cl,0x1F " \ +" mov al,cl " \ +" jz done_rle " \ +" " \ +" mov cl,byte ptr[edi] " \ +" inc edi " \ +" mov bx,word ptr[edx+ecx*2] " \ +" " \ +" copy_block: " \ +" mov word ptr[esi],bx " \ +" add esi,0x2 " \ +" dec al " \ +" jz next_pixel " \ +" jmp copy_block " \ +" " \ +" unique: " \ +" mov bx,word ptr[edx+ecx*2] " \ +" mov word ptr[esi],bx " \ +" add esi,0x2 " \ +" jmp next_pixel " \ +" done_rle: "; +#endif /* __WATCOMC__ */ + +#if GDBG_INFO_ON +/* cvg.c */ +extern void +_grErrorCallback(const char* const procName, + const char* const format, + va_list args); +#endif + +/* Returns 16:16 pair indicating the cpu's manufacturer and its + * capabilities. Non-Intel processors should have a vendor id w/ the + * high bit set so that it appears to be a negative #. The value of + * the capability field is assumed to be a monotonically increasing + * inclusive set. + * + * Unknown: + * 0xFFFF:0xFFFF + * + * Intel: 0x0000 + * 4: 486 and lower + * 5: Pentium + * 6: P6 Core w/ MTRR's + * 7: P6 Core w/ KNI + * + * AMD: 0x8001 + * 1: MMX + * 2: 3DNow!(tm) + * 4: K6-type MTRRs + * 8: P2-type MTRRs + * + * Cyrix: 0x8002 + * 1: MMX + * 2: 3DNow!(tm) + * + * IDT: 0x8003 + * 1: MMX + * 2: 3DNow!(tm) + * + */ + +enum { + kCPUVendorIntel = 0x0000, + kCPUVendorAMD = 0x8001, + kCPUVendorCyrix = 0x8002, + kCPUVendorIDT = 0x8003, + kCPUVendorUnknown = 0xFFFF +}; +extern FxI32 GR_CDECL +_cpu_detect_asm(void); + +extern void GR_CDECL +single_precision_asm(void); + +extern void GR_CDECL +double_precision_asm(void); + +#ifdef GLIDE3 +/* +** Macro to handle clip space and viewport stuff +*/ +#define TRI_SETF_SCALE_ADVANCE(_ptr,_scaler) \ + TRI_SETF(FARRAY(_ptr, i)*_scaler); dataElem++; i = gc->tsuDataList[dataElem] + +#define DA_SETF_SCALE_ADVANCE(_ptr,_scaler) \ + DA_SETF(FARRAY(_ptr, i)*_scaler); dataElem++; i = gc->tsuDataList[dataElem] + +#define DA_VP_SETFS(_s,_oow) \ +{ \ + FxI32 i, dataElem=0; \ + i = gc->tsuDataList[dataElem]; \ + if (gc->state.paramIndex & (STATE_REQUIRES_IT_DRGB | STATE_REQUIRES_IT_ALPHA)) { \ + if (gc->state.vData.colorType == GR_FLOAT) { \ + if (gc->state.paramIndex & STATE_REQUIRES_IT_DRGB) { \ + DA_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + DA_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + DA_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_IT_ALPHA) { \ + DA_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + } \ + } \ + else { \ + DA_SETF(FARRAY(_s, i)); \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_OOZ) { \ + DA_SETF(FARRAY(_s, i)*_oow*gc->state.Viewport.hdepth + gc->state.Viewport.oz); \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_OOW_FBI) { \ + if (gc->state.vData.qInfo.offset) { \ + DA_SETF(FARRAY(_s, gc->state.vData.qInfo.offset)*_oow); \ + } else { \ + DA_SETF(_oow); \ + } \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + while (i != GR_DLIST_END) { \ + DA_SETF_SCALE_ADVANCE(_s,_oow*_GlideRoot.pool.f255); \ + } \ +} + +#define TRI_VP_SETFS(_s,_oow) \ +{ \ + FxI32 i, dataElem=0; \ + i = gc->tsuDataList[dataElem]; \ + if (gc->state.paramIndex & (STATE_REQUIRES_IT_DRGB | STATE_REQUIRES_IT_ALPHA)) { \ + if (gc->state.vData.colorType == GR_FLOAT) { \ + if (gc->state.paramIndex & STATE_REQUIRES_IT_DRGB) { \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_IT_ALPHA) { \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + } \ + } \ + else { \ + TRI_SETF(FARRAY(_s, i)); \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_OOZ) { \ + TRI_SETF(FARRAY(_s, i)*_oow*gc->state.Viewport.hdepth+gc->state.Viewport.oz); \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_OOW_FBI) { \ + if (gc->state.vData.qInfo.offset) { \ + TRI_SETF(FARRAY(_s, gc->state.vData.qInfo.offset)*_oow); \ + } else { \ + TRI_SETF(_oow); \ + } \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + while (i != GR_DLIST_END) { \ + TRI_SETF_SCALE_ADVANCE(_s,_oow*_GlideRoot.pool.f255); \ + } \ +} + +#define AA_TRI_VP_SETFS(_s,_oow) \ +{ \ + FxI32 i, dataElem=0; \ + i = gc->tsuDataList[dataElem]; \ + if (gc->state.paramIndex & (STATE_REQUIRES_IT_DRGB | STATE_REQUIRES_IT_ALPHA)) { \ + if (gc->state.vData.colorType == GR_FLOAT) { \ + if (gc->state.paramIndex & STATE_REQUIRES_IT_DRGB) { \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + TRI_SETF_SCALE_ADVANCE(_s,_GlideRoot.pool.f255); \ + } \ + TRI_SETF(0.0f); \ + } \ + else { \ + FxU32 argb; \ + argb = *((FxU32 *)((int)_s + i)) & 0x00ffffff; \ + TRI_SETF(*((float *)&argb)); \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_OOZ) { \ + TRI_SETF(FARRAY(_s, i)*_oow*gc->state.Viewport.hdepth + gc->state.Viewport.oz); \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + if (gc->state.paramIndex & STATE_REQUIRES_OOW_FBI) { \ + if (gc->state.vData.qInfo.offset) { \ + TRI_SETF(FARRAY(_s, gc->state.vData.qInfo.offset)*_oow); \ + } else { \ + TRI_SETF(_oow); \ + } \ + dataElem++; \ + i = gc->tsuDataList[dataElem]; \ + } \ + while (i != GR_DLIST_END) { \ + TRI_SETF_SCALE_ADVANCE(_s,_oow*_GlideRoot.pool.f255); \ + } \ +} + +#endif + +/* +** The lod and aspect ratio changes will be done after we split the tree. +** Currently, we change the definition but patch it back to the original value +** so it is the same glide2. +** To smooth the transition from glide2 defs to glide3 defs, we introduce the +** translation layer. +*/ +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) +#ifndef GLIDE3_DEBUG +//#define GLIDE3_DEBUG 1 +#endif +#ifdef GLIDE3_DEBUG +#define TEX_INFO(ptr,field) ptr.field +#define G3_LOD_TRANSLATE(lod) (lod) +#define G3_ASPECT_TRANSLATE(aspect) (aspect) +#else +#define TEX_INFO(ptr,field) ptr.field ## Log2 +#define G3_LOD_TRANSLATE(lod) (0x8-lod) +#define G3_ASPECT_TRANSLATE(aspect) (0x3-(aspect)) +#endif /* GLIDE3_DEBUG */ +#else +#define TEX_INFO(ptr,field) ptr.field +#define G3_LOD_TRANSLATE(lod) (lod) +#define G3_ASPECT_TRANSLATE(aspect) (aspect) +#endif + +/* externals from ditex.c */ +extern const FxU32 _grMipMapHostSize[4][9]; +extern const int _grMipMapHostWH[GR_ASPECT_1x8 + 1][GR_LOD_1 + 1][2]; +extern const FxU32 _gr_aspect_index_table[]; +extern const FxU32 _gr_aspect_xlate_table[]; +extern const FxU32 _gr_evenOdd_xlate_table[]; + +#endif /* __FXGLIDE_H__ */ + diff --git a/glide2x/h3/glide/src/gsplash.c b/glide2x/h3/glide/src/gsplash.c new file mode 100644 index 0000000..e9087d7 --- /dev/null +++ b/glide2x/h3/glide/src/gsplash.c @@ -0,0 +1,1015 @@ +/* + ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY + ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT + ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX + ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE + ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). + ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A + ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. + ** + ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN + ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + ** THE UNITED STATES. + ** + ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED + ** + ** $Header$ + ** $Log$ + ** Revision 1.1.1.1 1999/12/07 21:49:28 joseph + ** Initial checkin into SourceForge. + ** +** +** 3 3/17/99 6:16p Dow +** Phantom Menace and other fixes. +** +** 30 2/19/99 5:54p Peter +** new splash screen +** +** 29 12/03/98 11:27p Dow +** Code 'cleanup' heç +** +** 28 12/03/98 4:45p Atai +** exit grSplash if aux buffer equals zero +** +** 27 8/01/98 3:34p Jeske +** made a special grSplashCb() for Banshee diags, only avail with +** -DDIAG_BUILD +** +** 26 1/30/98 2:07p Peter +** fixed effage +** +** 25 1/28/98 1:13p Peter +** Stupid swap state form gratuitous splash screen + * + * 23 1/09/98 6:48p Atai + * grTexInfo, GR_LOD_* and GR_ASPECT_* + * + * 21 1/06/98 6:47p Atai + * undo grSplash and remove gu routines + * + * 20 12/18/97 2:13p Peter + * fogTable cataclysm + * + * 19 12/15/97 5:52p Atai + * disable obsolete glide2 api for glide3 + * + * 18 12/09/97 10:20a Peter + * removed extraneous cruft + * + * 17 11/14/97 5:03p Peter + * picking up the torch... removed #!@#$% c++ comments + * + * 16 10/23/97 5:30p Peter + * packed rgb happiness + * + * 15 7/31/97 11:14a Peter + * merge w/ sst1 glide tree, hopefully + * + * 13 7/07/97 3:05p Dow + * Moved fouled clears + * + * 12 3/18/97 9:07p Dow + * Got rid of #$#%#$ // comments + * + * 11 3/16/97 12:42a Jdt + * Removed watcom warning + * + * 10 3/13/97 10:53p Jdt + * Rewrote with simple optimizations. Changed prototype for + * multi-resolution, and running as a better shameless plug. + * + * 9 3/13/97 2:52a Jdt + * Added arguments to splash. + * + * 8 3/09/97 10:31a Dow + * Added GR_DIENTRY for di glide functions + * + * 7 3/01/97 6:24p Jdt + * Made splash force yorigin. + * + * 6 1/02/97 1:06p Dow + * Fixed state bug + * + * 3 11/17/96 11:16p Garymct + * Updated grSplash code to set all of the necessary state itself rather + * than expecting the caller to do so. + */ +#include + +#include <3dfx.h> +#define FX_DLL_DEFINITION +#include +#include + +#include "fxglide.h" +#include "fxinline.h" + +#if defined( DIAG_BUILD ) || defined( __linux__ ) + +/*----------------------------- + Constants + -----------------------------*/ +#define MAX_NUM_VERTS 2556 + +#define FADEIN_END_PERCENT (0.3f) +#define FADEOUT_BEGIN_PERCENT (0.8f) + +#define SPIN_FRAMES 25 +#define SPIN_START 26 + +#define NO_TABLE ((GrTexTable_t)(~0)) + +/*----------------------------- + Macros + -----------------------------*/ +#define SNAP_BIAS ((float)(3<<18)) +#define SNAP_COORD(X) ((X)+SNAP_BIAS) + +/*----------------------------- + Types + -----------------------------*/ +typedef struct { + float x, y, z; /* object space coordinates */ + float nx, ny, nz; /* object space vertex normal for lighting */ + float s, t; /* pre-glide-ified texture coordinates */ +} Vert; + +typedef struct { + int v[3]; /* vertex indices into array of vertes for face */ + int mat_index; /* material index */ + int aa_edge_flags; +} Face; + +typedef float Vector[3]; +typedef float Matrix[16]; + +typedef FxU32 Palette[256]; +typedef struct { + FxU8 yRGB[16]; + FxI16 iRGB[4][3]; + FxI16 qRGB[4][3]; + FxU32 packed_data[12]; +} NCCTable; +typedef union { + Palette palette; + NCCTable nccTable; +} TextureTable; + +/*----------------------------- + Globals + -----------------------------*/ +/* xScale, xOffset, yScale, yOffset */ +static float viewPort[4] = { + 480.0f, 320.0f, + 480.0f, 240.0f +}; + +typedef struct { + GrTexInfo info; + FxU32 addr; + GrTexTable_t tableType; + TextureTable tableData; +} Texture; + +static int do_phong = 0; +static int pass; +static int fog; +static int useTextures; +static Vector light = { -0.57735f, -0.57735f, -0.57735f }; +static Vector transformed_verts[MAX_NUM_VERTS]; +static Vector transformed_norms[MAX_NUM_VERTS]; + +#include "splshdat.c" + +static Texture textImage; +static Texture hiliteImage; +static Texture shadowImage; + +static FxU32 nextFreeBase; + +/*----------------------------- + Privates + -----------------------------*/ +static void +sourceTexture(Texture *texture) +{ + static Texture *lastTexture; + + if (texture != lastTexture && useTextures) { + grTexSource(GR_TMU0, + texture->addr, + GR_MIPMAPLEVELMASK_BOTH, + &texture->info); + if (texture->tableType != NO_TABLE) { +#if defined(GLIDE3) && defined(GLIDE3_ALPHA) + grTexDownloadTable(texture->tableType, + &texture->tableData); +#else + grTexDownloadTable(GR_TMU0, + texture->tableType, + &texture->tableData); +#endif + } + lastTexture = texture; + } +} + +static GrTexTable_t +texTableType(GrTextureFormat_t format) +{ + GrTexTable_t rv = (GrTexTable_t)NO_TABLE; + + switch(format) { + case GR_TEXFMT_YIQ_422: + case GR_TEXFMT_AYIQ_8422: + rv = GR_TEXTABLE_NCC0; + break; + + case GR_TEXFMT_P_8: + case GR_TEXFMT_AP_88: + rv = GR_TEXTABLE_PALETTE; + break; + } + + return rv; +} + +static void +downloadTexture(Texture *texture, Gu3dfInfo *info) +{ + texture->info.data = info->data; + TEX_INFO(texture->info,smallLod) = info->header.small_lod; + TEX_INFO(texture->info,largeLod) = info->header.large_lod; + TEX_INFO(texture->info,aspectRatio) = info->header.aspect_ratio; + texture->info.format = info->header.format; + + texture->addr = nextFreeBase; + nextFreeBase += grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, + &texture->info); + grTexDownloadMipMap(GR_TMU0, + texture->addr, + GR_MIPMAPLEVELMASK_BOTH, + &texture->info); + + texture->tableType = texTableType(info->header.format); + switch(texture->tableType) { + case GR_TEXTABLE_NCC0: + case GR_TEXTABLE_NCC1: + case GR_TEXTABLE_PALETTE: + texture->tableData = *(TextureTable*)(&info->table); + break; + default: + break; + } +} + +static void +createTextures(void) +{ + Gu3dfInfo *info; + + /* Download the texture for the "3D" part of the model. */ + info = (Gu3dfInfo*)&text_3dfinfo; + info->data = (void *)text_3dfinfo_image; + + downloadTexture(&textImage, info); + + /* Download the texture for the specular highlight. */ + info = (Gu3dfInfo *)&hilite_3dfinfo; + info->data = (void *)hilite_3dfinfo_image; + downloadTexture(&hiliteImage, info); + + /* Download the texture for the shadow. */ + info = (Gu3dfInfo *)&shadow_3dfinfo; + info->data = (void *)shadow_3dfinfo_image; + downloadTexture(&shadowImage, info); +} + +static void +vecMatMult(float *dstVec, float *srcVec, float *matrix) +{ + dstVec[0] = (srcVec[0] * matrix[0] + + srcVec[1] * matrix[4] + + srcVec[2] * matrix[8] + + matrix[12]); + + dstVec[1] = (srcVec[0] * matrix[1] + + srcVec[1] * matrix[5] + + srcVec[2] * matrix[9] + + matrix[13]); + + dstVec[2] = (srcVec[0] * matrix[2] + + srcVec[1] * matrix[6] + + srcVec[2] * matrix[10] + + matrix[14]); +} + +static void +normMatMult(float *dstVec, float *srcVec, float *matrix) +{ + dstVec[0] = (srcVec[0] * matrix[0] + + srcVec[1] * matrix[4] + + srcVec[2] * matrix[8]); + + dstVec[1] = (srcVec[0] * matrix[1] + + srcVec[1] * matrix[5] + + srcVec[2] * matrix[9]); + + dstVec[2] = (srcVec[0] * matrix[2] + + srcVec[1] * matrix[6] + + srcVec[2] * matrix[10]); +} + +static void +xfAndProj(int frame, int obj) +{ + int vertex; + float *matrix; + + matrix = &mat[frame][obj][0]; + + for(vertex = 0; vertex < num_verts[obj]; vertex++) { + float *srcVec; + float *dstVec; + float oow; + + /* transform point */ + srcVec = (float*)&(vert[obj][vertex].x); + dstVec = (float*)transformed_verts[vertex]; + vecMatMult(dstVec, srcVec, matrix); + + /* project point */ + oow = 1.0f / dstVec[2]; + dstVec[0] = dstVec[0] * oow * viewPort[0] + viewPort[1] + SNAP_BIAS; + dstVec[1] = dstVec[1] * oow * viewPort[2] + viewPort[3] + SNAP_BIAS; + + /* transform normal */ + srcVec = (float*)&(vert[obj][vertex].nx); + dstVec = (float*)transformed_norms[vertex]; + normMatMult(dstVec, srcVec, matrix); + } +} + +static void +setupMaterial(int material_index) +{ + switch(material_index) { + case 0: /* 3d */ + if(pass == 1) { + sourceTexture(&textImage); + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + do_phong = 1; + } else if (pass == 0xbeef) { + /* Pantone 320C - 3D Green */ + grConstantColorValue(0x00989100); + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_ITERATED, + FXFALSE); + } else { + sourceTexture(&hiliteImage); + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + } + break; + case 1: /* fx */ + if (pass == 0xbeef) { + /* Black - fx */ + grConstantColorValue(0x00); + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_CONSTANT, + GR_COMBINE_OTHER_ITERATED, + FXFALSE); + do_phong = 1; + } else { + sourceTexture(&hiliteImage); + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + do_phong = 1; + } + break; + case 2: + case 3: + case 4: + grColorCombine(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_NONE, + FXFALSE); + do_phong = 0; + break; + } +} + +static void +calculateIntensity(int material_index, + Vector intensity_factor, + int frame) +{ + switch(material_index) { + case 0: + /* 3d */ + intensity_factor[0] = 1.0f; + intensity_factor[1] = 1.0f; + intensity_factor[2] = 1.0f; + break; + case 1: + /* fx */ + intensity_factor[0] = 0.125f; + intensity_factor[1] = 0.125f; + intensity_factor[2] = 0.125f; + break; + case 2: + /* cyan */ + intensity_factor[0] = (10.0f / 255.0f); + intensity_factor[1] = (75.0f / 255.0f); + intensity_factor[2] = (120.0f / 255.0f); + break; + case 3: + /* white */ + intensity_factor[0] = 1.0f; + intensity_factor[1] = 1.0f; + intensity_factor[2] = 1.0f; + break; + case 4: + /* yellow */ + intensity_factor[0] = (248.0f / 255.0f); + intensity_factor[1] = (204.0f / 255.0f); + intensity_factor[2] = 0.0f; + break; + } +} + +static void +drawFaces(int frame, int objnum) +{ + int facenum; + int material_index; + float intensity_factor[3]; + GrVertex gvert[3]; + static int prev_mat_index = 0xffff; + int i; + FxBool aa_a, aa_b, aa_c; + + for(facenum = 0; facenum < num_faces[objnum]; facenum++) { + material_index = face[objnum][facenum].mat_index; + if(material_index != prev_mat_index) { + setupMaterial(material_index); + calculateIntensity(material_index, + intensity_factor, frame); + prev_mat_index = material_index; + } + + if((material_index != 0) && (pass == 2)) + continue; + + aa_a = aa_b = aa_c = FXFALSE; + if(face[objnum][facenum].aa_edge_flags & 4) + aa_a = FXTRUE; + if(face[objnum][facenum].aa_edge_flags & 2) + aa_b = FXTRUE; + if(face[objnum][facenum].aa_edge_flags & 1) + aa_c = FXTRUE; + + for(i = 0; i < 3; i++) { + float *transformed_vert, *transformed_norm; + Vert *v; + int vertnum; + float factor; + + vertnum = face[objnum][facenum].v[i]; + transformed_vert = transformed_verts[vertnum]; + transformed_norm = transformed_norms[vertnum]; + v = &vert[objnum][vertnum]; + + gvert[i].x = transformed_vert[0]; + gvert[i].y = transformed_vert[1]; + gvert[i].oow = 1.0f / transformed_vert[2]; + gvert[i].tmuvtx[0].oow = gvert[i].oow; + gvert[i].tmuvtx[0].sow = v->s * gvert[i].oow; + gvert[i].tmuvtx[0].tow = v->t * gvert[i].oow; + + factor = ((light[0] * transformed_norm[0] + + light[1] * transformed_norm[1] + + light[2] * transformed_norm[2])+ 1.0f) * 127.5f; + + gvert[i].r = factor * intensity_factor[0]; + gvert[i].g = factor * intensity_factor[1]; + gvert[i].b = factor * intensity_factor[2]; + gvert[i].a = 255.0f; + } + + if(pass == 2) { + for(i = 0; i < 3; i++) { + float *transformed_norm; + + transformed_norm = + transformed_norms[face[objnum][facenum].v[i]]; + + gvert[i].tmuvtx[0].sow = gvert[i].oow * + (128.0f + transformed_norm[0] * 128.0f); + gvert[i].tmuvtx[0].tow = gvert[i].oow * + (128.0f + transformed_norm[1] * 128.0f); + + gvert[i].r = intensity_factor[0] * 255.0f; + gvert[i].g = intensity_factor[1] * 255.0f; + gvert[i].b = intensity_factor[2] * 255.0f; + } + + grDrawTriangle(&gvert[0], &gvert[1], &gvert[2]); + + continue; + } + + grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, + GR_BLEND_ONE, GR_BLEND_ZERO); + /* Do this if 3D. */ + if(material_index == 0) { + /* + * Draw the textured 3D without specular. + */ + sourceTexture(&textImage); +#if 0 + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_LOCAL, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); +#endif + grAADrawTriangle(&gvert[0], &gvert[1], &gvert[2], + aa_a, aa_b, aa_c); + } else if(material_index != 1) { + /* + * Just go ahead and draw for things that don't + * have specular highlights. + */ + grAADrawTriangle(&gvert[0], &gvert[1], &gvert[2], + aa_a, aa_b, aa_c); + } + + if(do_phong && (material_index != 0)) { + /* + * figure out texture coords in [0..255.0f] based on the normal + * the specular highlight. + */ + for(i = 0; i < 3; i++) { + float *transformed_norm; + + transformed_norm = + transformed_norms[face[objnum][facenum].v[i]]; + + gvert[i].tmuvtx[0].sow = gvert[i].oow * + (128.0f + transformed_norm[0] * 128.0f); + gvert[i].tmuvtx[0].tow = gvert[i].oow * + (128.0f + transformed_norm[1] * 128.0f); + + gvert[i].r = intensity_factor[0] * 255.0f; + gvert[i].g = intensity_factor[1] * 255.0f; + gvert[i].b = intensity_factor[2] * 255.0f; + } + + grAADrawTriangle(&gvert[0], &gvert[1], &gvert[2], + aa_a, aa_b, aa_c); + } + } +} + +static void +intersectLineWithZPlane(Vector result, Vector p1, + Vector p2, float z) +{ + float t; + + t = (z - p1[2]) / (p2[2] - p1[2]); + result[0] = p1[0] + (p2[0] - p1[0]) * t; + result[1] = p1[1] + (p2[1] - p1[1]) * t; + result[2] = z; +} + +static float +vectorMag(float *v) +{ + return (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +static void +drawShadow(int frame, int shadow_object_index, + int receiver_object_index, Vector light_position) +{ + float *shadow_object_matrix; + float *receiver_object_matrix; + Vector view_verts[4]; + Vector projected_view_verts[4]; + int i; + + Vector local_verts[4] = { + { -280.0f, 0.0f, -160.0f }, + { -280.0f, 0.0f, 150.0f }, + { 280.0f, 0.0f, 150.0f }, + { 280.0f, 0.0f, -160.0f } + }; + + float texcoords[4][2] = { + { 10.5f, 127.5f }, + { 10.5f, 0.5f }, + { 255.0f, 0.5f }, + { 255.0f, 127.5f } + }; + + GrVertex gvert[4]; + GrVertex projected_gvert[4]; + GrVertex light_gvert; + + /* + * The point relative to the back part of the shield that + * the shadow is going to be projected onto. + */ + Vector shadow_light; + + shadow_light[0] = light_position[0]; + shadow_light[1] = light_position[1]; + shadow_light[2] = light_position[2]; + + shadow_object_matrix = &mat[frame][shadow_object_index][0]; + receiver_object_matrix = &mat[frame][receiver_object_index][0]; + + /* + * Offset the light by the Z position of + * the backplane that we are projected + * onto. + */ + shadow_light[2] += receiver_object_matrix[14]; + + for(i = 0; i < 4; i++) { + vecMatMult(view_verts[i], local_verts[i], shadow_object_matrix); + + /* + * project . . . + */ + gvert[i].oow = 1.0f / view_verts[i][2]; + gvert[i].x = + view_verts[i][0] * gvert[i].oow * viewPort[0] + + viewPort[1] + SNAP_BIAS; + gvert[i].y = + view_verts[i][1] * gvert[i].oow * viewPort[2] + + viewPort[3] + SNAP_BIAS; + + /* + * Set up texture coordinates. + */ + gvert[i].tmuvtx[0].sow = texcoords[i][0] * gvert[i].oow; + gvert[i].tmuvtx[0].tow = texcoords[i][1] * gvert[i].oow; + } + + + /* + * Intersect each line formed by the light source and a + * particular corner of the shadow object with the + * plane which the texture is to be projected onto. + */ + for(i = 0; i < 4; i++) { + Vector tmpvect; + float q; + +#if GLIDE_PACKED_RGB + /* dpc - 22 oct 1997 - FixMe! + * These are left uninitialized, yet they are being sent to the + * hw, probably because some other state is not being correctly + * setup. This doesn't seem to affect the 'correctness' of the + * splash screen so I'm not investigating it any more. + */ + projected_gvert[i].r = + projected_gvert[i].g = + projected_gvert[i].b = + projected_gvert[i].a = 0.0f; +#endif /* GLIDE_PACKED_RGB */ + + intersectLineWithZPlane(projected_view_verts[i], + shadow_light, + view_verts[i], + receiver_object_matrix[14] - 26.0f); + projected_gvert[i].oow = 1.0f / projected_view_verts[i][2]; + projected_gvert[i].x = (projected_view_verts[i][0] * projected_gvert[i].oow * viewPort[0] + + viewPort[1] + SNAP_BIAS); + projected_gvert[i].y = (projected_view_verts[i][1] * projected_gvert[i].oow * viewPort[2] + + viewPort[3] + SNAP_BIAS); + + tmpvect[0] = projected_view_verts[i][0] - shadow_light[0]; + tmpvect[1] = projected_view_verts[i][1] - shadow_light[1]; + tmpvect[2] = projected_view_verts[i][2] - shadow_light[2]; + q = vectorMag(tmpvect); + + /* + * Set up texture coordinates. + */ + projected_gvert[i].tmuvtx[0].oow = projected_gvert[i].oow * q; + projected_gvert[i].tmuvtx[0].sow = texcoords[i][0] * projected_gvert[i].oow; + projected_gvert[i].tmuvtx[0].tow = texcoords[i][1] * projected_gvert[i].oow; + } + + light_gvert.oow = 1.0f / shadow_light[2]; + light_gvert.x = shadow_light[0] * light_gvert.oow * viewPort[0] + viewPort[1] + SNAP_BIAS; + light_gvert.y = shadow_light[1] * light_gvert.oow * viewPort[2] + viewPort[3] + SNAP_BIAS; + + /* + * Draw a segment between the light and the point which hits + * the surface that the light is being projected onto. + */ + grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, + GR_COMBINE_FACTOR_ONE, + GR_COMBINE_LOCAL_NONE, + GR_COMBINE_OTHER_TEXTURE, + FXFALSE); + sourceTexture(&shadowImage); + + grAlphaBlendFunction(GR_BLEND_DST_COLOR, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO); + + grDrawTriangle(&projected_gvert[0], + &projected_gvert[1], + &projected_gvert[2]); + grDrawTriangle(&projected_gvert[0], + &projected_gvert[2], + &projected_gvert[3]); + grDrawTriangle(&projected_gvert[0], + &projected_gvert[2], + &projected_gvert[1]); + grDrawTriangle(&projected_gvert[0], + &projected_gvert[3], + &projected_gvert[2]); + + grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO); + +} + +#ifdef __linux__ +FX_ENTRY void FX_CALL +grSplashCb(float x, float y, float width, float height, FxU32 frame, + void (*fn)(int)); +#endif + + +/*------------------------------------------------------------------- + Function: grSplash + Date: 3/13 + Implementor(s): GaryMcT + Library: Glide + Description: + Render the opening splash screen animation, or render + a single frame of the splash screen. + Arguments: + x, y - upper left hand coord of window + w, h - width and height of window to render + _frame - frame number to render (~0 to render all frames) + Return: + none + -------------------------------------------------------------------*/ + +GR_DIENTRY(grSplash,void,(float x,float y,float w,float h,FxU32 _frame)) +{ + grSplashCb(x,y,w,h,_frame,NULL); +} + +GR_DIENTRY(grSplashCb,void,(float x,float y,float w,float h,FxU32 _frame, + void (*callback)(int frame))) +{ + GR_BEGIN_NOFIFOCHECK("grSplash", 85); + GDBG_INFO_MORE(gc->myLevel,"(%f,%f,%f,%f,%d)\n", + x, y, w, h, _frame); + + { + GrState oldState; + int frame; + Vector lights[] = { + { 5.0f, 300.0f, -1500.0f }, + { 5.0f, 150.0f, -1000.0f }, + { -30.0f, 150.0f, -1000.0f }, + { -30.0f, 100.0f, -1000.0f }, + { 30.0f, 70.0f, -1000.0f }, + }; + GrFog_t fogTable[kInternalFogTableEntryCount]; + int fadeInFrames, fadeOutFrames; + + /* Check Screen Dimensions and Check Avail of Depth Buffer */ + if ((x > gc->state.screen_width) || + ((x+w) > gc->state.screen_width) || + (y > gc->state.screen_height) || + ((y+h) > gc->state.screen_height)) + return; + + if (gc->state.screen_height == 640) { + if (gc->fbuf_size == 1) { + return; + } + } else if (gc->state.screen_width == 800) { + if ((gc->fbuf_size == 1) || + (gc->fbuf_size == 2)) { + return; + } + } + + if (gc->grAuxBuf == 0) return; + + if (!(gc->state.fbi_config.fbzMode & SST_YORIGIN)) { + y = ((gc->state.screen_height - 1.0f) - (h-1.0f)) - y; + } + + viewPort[0] = w * (480.0f / 640.0f); + viewPort[1] = x + (w / 2.0f); + viewPort[2] = h; + viewPort[3] = y + (h / 2.0f); + + grGlideGetState(&oldState); + + grSstOrigin(GR_ORIGIN_LOWER_LEFT); + + if (_frame == 0) { + createTextures(); + useTextures = 1; + } else { + useTextures = 0; + } + + grAlphaTestFunction(GR_CMP_ALWAYS); + grChromakeyMode(GR_CHROMAKEY_DISABLE); + grConstantColorValue(0xffffffff); + grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER); + grDepthMask(FXTRUE); + grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, + GR_COMBINE_FACTOR_NONE, + GR_COMBINE_LOCAL_ITERATED, + GR_COMBINE_OTHER_NONE, + FXFALSE); + grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO); + if (useTextures) + grTexCombine(GR_TMU0, + GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, + FXFALSE, FXFALSE); + else + grTexCombine(GR_TMU0, + GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, + GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, + FXTRUE, FXFALSE); + grTexMipMapMode(GR_TMU0, + GR_MIPMAP_NEAREST, + FXFALSE); + grTexFilterMode(GR_TMU0, + GR_TEXTUREFILTER_BILINEAR, + GR_TEXTUREFILTER_BILINEAR); + grDepthBufferFunction(GR_CMP_LEQUAL); + grCullMode(GR_CULL_NEGATIVE); + /* grClipWindow((int)x, (int)y, (int)(x+w), (int)(y+h)); */ + grFogColorValue(0x0); + + fadeInFrames = (int)(((float)total_num_frames) * FADEIN_END_PERCENT); + fadeOutFrames = (int)(((float)total_num_frames) * + (1.0f - FADEOUT_BEGIN_PERCENT)); + + if (_frame == 0) { /* Render Whole Animation */ + for(frame = 1; frame < total_num_frames; frame++) { + int i; + + /* Set Fog Value For This Frame */ + if(frame < fadeInFrames) { + unsigned char fval = (((unsigned char)0xFF) - + ((unsigned char)(255.0f * (float)(frame + 1) / (float)fadeInFrames))); + for(i = 0; i < kInternalFogTableEntryCount; i++) fogTable[i] = fval; + grFogMode(GR_FOG_WITH_TABLE); + grFogTable(fogTable); + fog = 1; + } else if(frame > total_num_frames-fadeOutFrames) { + unsigned char fval = (((unsigned char)0xFF) - + (unsigned char)(255.0f* ((float)(total_num_frames - frame))/ + ((float)fadeOutFrames))); + for(i = 0; i < kInternalFogTableEntryCount; i++) + fogTable[i] = fval; + grFogMode(GR_FOG_WITH_TABLE); + grFogTable(fogTable); + fog = 1; + } else { + grFogMode(GR_FOG_DISABLE); + fog = 0; + } + + grBufferClear(0x00000000, 0, GR_WDEPTHVALUE_FARTHEST); + + pass = 1; + + /* + * Avoid Z-aliasing between the shield and the 3dfx by + * not writing Z for the shield. + */ + + grDepthMask(FXFALSE); + /* cyan part of shield */ + xfAndProj(frame, 2); + drawFaces(frame, 2); + + /* yellow and white part of shield. */ + xfAndProj(frame, 0); + drawFaces(frame, 0); + + /* + * Reanable writes to the depth-buffer. + */ + grDepthMask(FXTRUE); + + /* + * Draw the shadow projected from the 3Dfx logo onto + * the rest of the powershield. + */ + grDepthBufferFunction(GR_CMP_ALWAYS); + grFogMode(GR_FOG_DISABLE); + drawShadow(frame, 1, 0, lights[0]); + if (fog) grFogMode(GR_FOG_WITH_TABLE); /* hack around mp fog */ + grDepthBufferFunction(GR_CMP_LEQUAL); + + /* 3Dfx logo */ + xfAndProj(frame, 1); + drawFaces(frame, 1); + grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ONE, + GR_BLEND_ONE, GR_BLEND_ZERO); + + pass = 2; + drawFaces(frame, 1); + pass = 1; + grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, + GR_BLEND_ONE, GR_BLEND_ZERO); + + grBufferSwap(2); + if (callback) callback(frame); + } + } else { /* Render One Frame */ + frame = ((_frame>>1) % SPIN_FRAMES)+SPIN_START; + + grColorMask(FXFALSE, FXFALSE); + grBufferClear(0x00000000, 0, GR_WDEPTHVALUE_FARTHEST); + grColorMask(FXTRUE, FXFALSE); + + pass = 0xbeef; + + /* 3Dfx logo */ + xfAndProj(frame, 1); + drawFaces(frame, 1); + } + + /* Get rid of the remnants on teh screen just in case + * the app doesn't do it itself yet + * assumes that the screen is clear. + */ + if (_frame == 0) { + int i; + + for(i = 0; i < gc->grColBuf; i++) { + grBufferClear(0x00000000, 0, GR_WDEPTHVALUE_FARTHEST); + grBufferSwap(0); + } + } + + /* + * Clean up after yourself! + */ + grGlideSetState(&oldState); + } + + GR_END(); +} +#else /* !DIAG_BUILD */ +GR_DIENTRY(grSplash,void,(float x, float y, + float w, float h, + FxU32 frameNumber)) +{ + GR_BEGIN_NOFIFOCHECK("grSplash", 85); + GDBG_INFO_MORE(gc->myLevel,"(%f,%f,%f,%f,%d)\n", + x, y, w, h, frameNumber); + +#if (GLIDE_PLATFORM & GLIDE_OS_WIN32) + if (gc->pluginInfo.splashProc != NULL) (*gc->pluginInfo.splashProc)(x, y, + w, h, + frameNumber); +#endif /* (GLIDE_PLATFORM & GLIDE_OS_WIN32) */ + + GR_END(); +} +#endif /* !DIAG_BUILD */ + + diff --git a/glide2x/h3/glide/src/xdraw2.S b/glide2x/h3/glide/src/xdraw2.S new file mode 100644 index 0000000..d668960 --- /dev/null +++ b/glide2x/h3/glide/src/xdraw2.S @@ -0,0 +1,258 @@ +/* + * THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY + * PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT + * TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX + * INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE + * DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). + * THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A + * FULL TEXT OF THE NON-WARRANTY PROVISIONS. + * + * USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO + * RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN + * TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, + * AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR + * SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF + * THE UNITED STATES. + * + * COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED + */ + +/* $Header$ */ +/* $Revision$ */ +/* $Log$ +/* Revision 1.1.1.1 1999/12/07 21:49:30 joseph +/* Initial checkin into SourceForge. +/* */ +/* */ +/* 11 10/05/98 7:43p Peter */ +/* 3DNow!(tm) happiness everywhere */ +/* */ +/* 10 10/03/98 3:35p Peter */ +/* First pass at dynamic detection of 3DNow!(tm) */ +/* */ +/* 9 9/21/98 5:42p Dow */ +/* 3DNow! (tm) mods */ +/* */ +/* 8 7/24/98 1:40p Hohn */ +/* */ +/* 7 5/18/98 12:16p Peter */ +/* culling enabling */ +/* */ +/* 6 1/15/98 1:12p Peter */ +/* dispatch w/o packing */ +/* */ +/* 5 11/06/97 3:47p Peter */ +/* */ +/* 4 11/04/97 5:04p Peter */ +/* cataclysm part deux */ +/* */ +/* 3 11/01/97 10:01a Peter */ +/* tri dispatch stuff */ +/* */ +/* 2 10/30/97 6:53p Peter */ +/* first real cut at tri asm */ +/* */ +/* 1 10/30/97 4:29p Peter */ +/* asm tri code */ +/* */ +/* 2 7/07/97 2:14p Jdt */ +/* assembly now on par with C code. */ +/* */ +/* 1 7/07/97 8:37a Jdt */ +/* B4 Chip field fix. */ + + +.file "xdraw2.asm" + + + +.data + .type One,@object + .size One,4 +One: .int 0x03f800000 + .type Area,@object + .size Area,4 +Area: .int 0 + +#if GLIDE_PACKED_RGB + .type bias0,@object + .size bias0,4 +bias0: .int 0 + .type bias1,@object + .size bias1,4 +bias1: .int 0 +#endif + +/* Ugly, but seems to workaround the problem with locally defined */ +/* data segment globals not getting relocated properly when using */ +/* djgpp. */ + +#define zArea One+0x04 + +/* Definitions of cvg regs and glide root structures. */ +#include "fxgasm.h" + +/* Arguments (STKOFF = 16 from 4 pushes) */ +#define STKOFF 16 +#define _va 4 + STKOFF +#define _vb 8 + STKOFF +#define _vc 12 + STKOFF + +#ifdef GL_AMD3D +#define PROC_TYPE(arg) _trisetup_3DNow_##arg +#define END_PROC_TYPE(arg) .L_END_trisetup_3Dnow_##arg +#else +#define PROC_TYPE(arg) _trisetup_Default_##arg +#define END_PROC_TYPE(arg) .L_END_Default_3Dnow_##arg +#endif + +/* -------------------------------------------------------------------------- */ +.text + + +.align 32 + +.globl PROC_TYPE(cull) +.type PROC_TYPE(cull),@function +PROC_TYPE(cull): + +#define LOCAL(arg) .L_cull_##arg + +#define GLIDE_CULLING 1 +#define GLIDE_PACK_RGB 0 +#define GLIDE_PACK_ALPHA 0 +#define GLIDE_GENERIC_SETUP 0 +#include "xdraw2.inc.S" +#undef cull +#undef GLIDE_GENERIC_SETUP +#undef GLIDE_PACK_ALPHA +#undef GLIDE_PACK_RGB +#undef GLIDE_CULLING + +#undef LOCAL + +END_PROC_TYPE(cull): +.size PROC_TYPE(cull),END_PROC_TYPE(cull)-PROC_TYPE(cull) + +.align 32 + +#if GLIDE_PACKED_RGB +.globl PROC_TYPE(cull_rgb) +.type PROC_TYPE(cull_rgb),@function +PROC_TYPE(cull_rgb): + +#define LOCAL(arg) .L_cull_rgb_##arg + +#define GLIDE_CULLING 1 +#define GLIDE_PACK_RGB 1 +#define GLIDE_PACK_ALPHA 0 +#define GLIDE_GENERIC_SETUP 0 +#include "xdraw2.inc.S" +#undef GLIDE_GENERIC_SETUP +#undef GLIDE_PACK_ALPHA +#undef GLIDE_PACK_RGB +#undef GLIDE_CULLING + +#undef LOCAL + +END_PROC_TYPE(cull_rgb): +.size PROC_TYPE(cull_rgb),END_PROC_TYPE(cull_rgb)-PROC_TYPE(cull_rgb) + +.align 32 + +.globl PROC_TYPE(cull_argb) +.type PROC_TYPE(cull_argb),@function +PROC_TYPE(cull_argb): + +#define LOCAL(arg) .L_cull_argb_##arg + +#define GLIDE_CULLING 1 +#define GLIDE_PACK_RGB 1 +#define GLIDE_PACK_ALPHA 1 +#define GLIDE_GENERIC_SETUP 0 +#include "xdraw2.inc.S" +#undef GLIDE_GENERIC_SETUP +#undef GLIDE_PACK_ALPHA +#undef GLIDE_PACK_RGB +#undef GLIDE_CULLING + +END_PROC_TYPE(cull_argb): +.size PROC_TYPE(cull_argb),END_PROC_TYPE(cull_argb)-PROC_TYPE(cull_argb) +#endif /* GLIDE_PACKED_RGB */ + +.align 32 + +.globl PROC_TYPE(Default) +.type PROC_TYPE(Default),@function +PROC_TYPE(Default): + +#define LOCAL(arg) .L_Default_##arg + +#define GLIDE_CULLING 0 +#define GLIDE_PACK_RGB 0 +#define GLIDE_PACK_ALPHA 0 +#define GLIDE_GENERIC_SETUP 0 +#include "xdraw2.inc.S" +#undef GLIDE_GENERIC_SETUP +#undef GLIDE_PACK_ALPHA +#undef GLIDE_PACK_RGB +#undef GLIDE_CULLING + +#undef LOCAL + +END_PROC_TYPE(Default): +.size PROC_TYPE(Default),END_PROC_TYPE(Default)-PROC_TYPE(Default) + +.align 32 + +#if GLIDE_PACKED_RGB +.globl PROC_TYPE(rgb) +.type PROC_TYPE(rgb),@function +PROC_TYPE(rgb): + +#define LOCAL(arg) .L_rgb_##arg + +#define GLIDE_CULLING 0 +#define GLIDE_PACK_RGB 1 +#define GLIDE_PACK_ALPHA 0 +#define GLIDE_GENERIC_SETUP 0 +#include "xdraw2.inc.S" +#undef GLIDE_GENERIC_SETUP +#undef GLIDE_PACK_ALPHA +#undef GLIDE_PACK_RGB +#undef GLIDE_CULLING + +#undef LOCAL + +END_PROC_TYPE(rgb): +.size PROC_TYPE(rgb),END_PROC_TYPE(rgb)-PROC_TYPE(rgb) + +.align 32 + +.globl PROC_TYPE(argb) +.type PROC_TYPE(argb),@function +PROC_TYPE(argb): + +#define LOCAL(arg) .L_argb_##arg + +#define GLIDE_CULLING 0 +#define GLIDE_PACK_RGB 1 +#define GLIDE_PACK_ALPHA 1 +#define GLIDE_GENERIC_SETUP 0 +#include "xdraw2.inc.S" +#undef GLIDE_GENERIC_SETUP +#undef GLIDE_PACK_ALPHA +#undef GLIDE_PACK_RGB +#undef GLIDE_CULLING + +#undef LOCAL + +END_PROC_TYPE(argb): +.size PROC_TYPE(argb),END_PROC_TYPE(argb)-PROC_TYPE(argb) +#endif /* GLIDE_PACKED_RGB */ + + + +.END + diff --git a/glide2x/h3/minihwc/fxhwc.h b/glide2x/h3/minihwc/fxhwc.h new file mode 100644 index 0000000..41fe6f4 --- /dev/null +++ b/glide2x/h3/minihwc/fxhwc.h @@ -0,0 +1,49 @@ +/* +** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +** FULL TEXT OF THE NON-WARRANTY PROVISIONS. +** +** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +** THE UNITED STATES. +** +** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +** +** $Header$ +** $Log$ +** Revision 1.2 2000/10/03 18:29:57 mercury +** 003-clean_up_h3-000, h3 tree cleanup. +** +** Revision 1.1.1.1 1999/12/07 21:49:43 joseph +** Initial checkin into SourceForge. +** +** +** 3 3/17/99 6:14p Dow +** Fixes Phantom Menace, OGL, and others. +** +** 1 3/04/98 4:13p Dow +** +*/ +#ifndef FXHWC_H +#define FXHWC_H + + + +/* +** I/O Macros +*/ +#warning Here! +#define HWC_IO_LOAD(regInfo, reg, val) \ +GDBG_INFO(120, "%s: Storing 0x%x to IO Register %s\n", \ +((SstIORegs *) regInfo.ioMemBase)-> + + +#endif /* FXHWC_H not defined */ diff --git a/glide2x/makefile.linux b/glide2x/makefile.linux new file mode 100644 index 0000000..46c836a --- /dev/null +++ b/glide2x/makefile.linux @@ -0,0 +1,62 @@ +# +# THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY +# PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT +# TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX +# INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE +# DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). +# THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A +# FULL TEXT OF THE NON-WARRANTY PROVISIONS. +# +# USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO +# RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN +# TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, +# AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR +# SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF +# THE UNITED STATES. +# +# COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED +# +# $Revision$ +# $Date$ +# + +export TOPDIR := $(shell pwd) + +THISDIR = devel +SUBDIRS = swlibs + +# We branched glide starting w/ Voodoo2(aka CVG) so +# make sure that the right thing happens. If this sort +# of branching happens again then add it to the list below. +ifeq ($(FX_GLIDE_HW),sst1) + SUBDIRS += sst1 +else + ifeq ($(FX_GLIDE_HW),sst96) + SUBDIRS += sst1 + else + ifeq ($(FX_GLIDE_HW),cvg) + SUBDIRS += cvg + else + ifeq ($(FX_GLIDE_HW),h3) + SUBDIRS += h3 + else + FX_GLIDE_HW = h3 + SUBDIRS += h3 + endif + endif + endif +endif + +# +# Other variables we need to set +# +export FX_HW_PROJECTS=glide +ifeq ($(HAL_HW),) + export HAL_HW=1 +endif +export FX_NO_GET_BOF=1 +export FX_GLIDE_HW +export SCRIPTDIR=$(TOPDIR)/swlibs/include/make + +include swlibs/include/make/3dfx.mak