From b72bb023fe0813b9c3e44325ee8554199a2a0629 Mon Sep 17 00:00:00 2001 From: Jakub Vesely <1251980+tinix0@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:36:15 +0200 Subject: [PATCH 1/4] Translate the VQ block decoders to C++ No documentation update: tests/unvqdec checks the C++ decoders against golden vectors recorded from the original assembly, so documented behavior is unchanged. --- code/unvq_asm.asm | 1906 ---------------------------------- code/unvqdec.cpp | 428 ++++++++ tests/CMakeLists.txt | 1 + tests/unvqdec/CMakeLists.txt | 30 + tests/unvqdec/unvqgolden.h | 174 ++++ tests/unvqdec/unvqparity.cpp | 172 +++ 6 files changed, 805 insertions(+), 1906 deletions(-) delete mode 100644 code/unvq_asm.asm create mode 100644 code/unvqdec.cpp create mode 100644 tests/unvqdec/CMakeLists.txt create mode 100644 tests/unvqdec/unvqgolden.h create mode 100644 tests/unvqdec/unvqparity.cpp diff --git a/code/unvq_asm.asm b/code/unvq_asm.asm deleted file mode 100644 index 08f61d2db..000000000 --- a/code/unvq_asm.asm +++ /dev/null @@ -1,1906 +0,0 @@ -;****************************************************************************** -;* O P E N T S -;****************************************************************************** -;* SPDX-License-Identifier: GPL-3.0-or-later -;* Copyright 2025 Electronic Arts Inc. -;* Copyright 2026 OpenTS contributors -;* -;* Contains material derived from Electronic Arts source code. -;* Modified by OpenTS contributors, 2026. -;* EA's GPLv3 Section 7 additional terms and supplemental warranty -;* disclaimers apply; see LICENSE.md. -;****************************************************************************** - -.386 -.model flat, C - -PHARLAP_TNT equ 0 -VQABLOCK_4X2 EQU 1 ;4x2 block decode enable/disable -VQABLOCK_4X4 EQU 1 ;4x4 block decode enable/disable - -;---------------------------------------------------------------------------- -; -; These are VQA UnVQ1 full-frame decoders -- assembly-optimized routines -; for drawing VQ-compressed video frames into a pixel buffer. -; -; Naming convention from VQALib: -; UnVQ1 = full-frame decoder (processes every pointer) -; C0 = ColorMode 0 (8-bit palette, 1 byte/pixel) -; C1 = ColorMode 1 (15-bit hicolor via HicolorTable lookup) -; TABLE = uses HicolorTable for single-color block fill -; HALF = half-resolution output (samples every-other pixel) -; -; Function map (10 functions, all share the same signature): -; -; Name | Block | ColorMode | 1-Color Source | Block Type Check -; ASM_UnVQ1_C1_TABLE | 4x4 | C1 table | HicolorTable[idx] | test bh, 80h -; ASM_UnVQ1_C1_TABLE_ALT | 4x2 | C1 table | HicolorTable[idx] | test bh, 80h -; ASM_UnVQ_4x2 | 4x2 | C0 (8bit) | byte duplication | cmp bh, 0FFh -; ASM_UnVQ_4x4 | 4x4 | C0 (8bit) | byte duplication | cmp bh, 0FFh -; ASM_UnVQ_4x4_HALF | 4x4>2 | C0 half | byte duplication | cmp bh, 0FFh -; ASM_UnVQ_6 | 4x2>2 | C0 half | byte duplication | cmp bh, 0FFh -; ASM_UnVQ1_C1_4x4 | 4x4 | C1 direct | value & 0x7FFF | test bh, 80h -; ASM_UnVQ_8 | 4x2 | C1 direct | value & 0x7FFF | test bh, 80h -; ASM_UnVQ_9 | 4x8 | C0 (8bit) | byte duplication | cmp bh, 0FFh -; ASM_UnVQ_10 | 4x4w | C0 (8bit) | byte duplication | cmp bh, 0FFh -; -; Paired functions (same logic, different color source): -; ASM_UnVQ1_C1_TABLE <-> ASM_UnVQ1_C1_4x4 (4x4, table vs direct) -; ASM_UnVQ1_C1_TABLE_ALT <-> ASM_UnVQ_8 (4x2, table vs direct) -; ASM_UnVQ_4x2 <-> ASM_UnVQ_6 (4x2 full vs half-res) -; ASM_UnVQ_4x4 <-> ASM_UnVQ_4x4_HALF (4x4 full vs half-res) -; ASM_UnVQ_9 <-> ASM_UnVQ_10 (large: 4x8 vs 4x4-wide) -; -; HicolorTable (global): 15-bit RGB to 16-bit pixel lookup table. -; Initialized by Hicolor_Init_Table() in unvqtblc.cpp. -;---------------------------------------------------------------------------- - -externdef C ASM_UnVQ1_C1_TABLE:NEAR -externdef C ASM_UnVQ1_C1_TABLE_ALT:NEAR -externdef C ASM_UnVQ_4x2:NEAR -externdef C ASM_UnVQ_4x4:NEAR -externdef C ASM_UnVQ_4x4_HALF:NEAR -externdef C ASM_UnVQ_6:NEAR -externdef C ASM_UnVQ1_C1_4x4:NEAR -externdef C ASM_UnVQ_8:NEAR -externdef C ASM_UnVQ_9:NEAR -externdef C ASM_UnVQ_10:NEAR -EXTERN C HicolorTable:DWORD ; USHORT * [65535-1]; - -.CODE - -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ1_C1_TABLE - Draw XxX block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ1_C1_TABLE(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ1_C1_TABLE(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ1_C1_TABLE - ASM_UnVQ1_C1_TABLE PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL unknown:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - shl [bufwidth],1 - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,2 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - mov edi,[buffer] - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - test bh,080h ;Is it a one color block? - js short ??One_color - -; Draw multi-color block - - shl ebx,5 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] ;Read 1st row of codeword - mov edx,[ebx+4] ;Read 2nd row of codeword - - mov [edi],eax - mov [edi+4],edx - - mov eax,[ebx+8] - mov edx,[ebx+12] - mov [unknown],ebx - mov ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - mov ebx,[unknown] - mov eax,[ebx+16] - mov edx,[ebx+20] - mov ebx,[bufwidth] - shl ebx,1 - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - mov ebx,[unknown] - mov eax,[ebx+24] - mov edx,[ebx+28] - mov ebx,[bufwidth] - shl ebx,1 - add ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - and ebx,07FFFh - shl ebx,1 - mov edx,[HicolorTable] - mov ax,[edx+ebx] - mov bx,ax - shl eax,16 - mov ax,bx - - mov [edi],eax - mov [edi+4],eax - - mov ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add edi,8 ;Next dest block positionw - dec ecx ;More blocks for this row? - jnz ??Not_finished_a_line ;jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ1_C1_TABLE ENDP - - -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ1_C1_TABLE_ALT - Draw XxX block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ1_C1_TABLE_ALT(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ1_C1_TABLE_ALT(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ1_C1_TABLE_ALT - ASM_UnVQ1_C1_TABLE_ALT PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL unknown:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - shl [bufwidth],1 - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,2 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - mov edi,[buffer] - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - test bh,080h ;Is it a one color block? - js short ??One_color - -; Draw multi-color block - - shl ebx,5 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] ;Read 1st row of codeword - mov edx,[ebx+4] ;Read 2nd row of codeword - mov [edi],eax - mov [edi+4],edx - mov eax,[ebx+16] - mov edx,[ebx+20] - mov ebx,[bufwidth] - shl ebx,1 - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - and ebx,07FFFh - shl ebx,1 - mov edx,[HicolorTable] - mov ax,[edx+ebx] - mov bx,ax - shl eax,16 - mov ax,bx - - mov [edi],eax - mov [edi+4],eax - - mov ebx,[bufwidth] - add ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add edi,8 ;Next dest block positionw - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ1_C1_TABLE_ALT ENDP - - - IF VQABLOCK_4X2 -;**************************************************************************** -;* -;* NAME -;* UnVQ_4x2 - Draw 4x2 block VQ frame to a buffer. -;* -;* SYNOPSIS -;* UnVQ_4x2(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void UnVQ_4x2(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_4x2 - ASM_UnVQ_4x2 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,1 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - mov edi,[buffer] - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - cmp bh,0FFh ;Is it a one color block? - je short ??One_color - -; Draw multi-color block - - shl ebx,3 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] ;Read 1st row of codeword - mov edx,[ebx+4] ;Read 2nd row of codeword - mov ebx,[bufwidth] - mov [edi],eax ;Write 1st row to dest - mov [edi+ebx],edx ;Write 2nd row to dest - - add edi,4 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - mov bh,bl ;Duplicate color through the - mov ax,bx ; entire dword register. - rol eax,16 - mov ax,bx - mov ebx,[bufwidth] - mov [edi],eax ;Write 1st row to dest - mov [edi+ebx],eax ;Write 2nd row to dest - - add edi,4 ;Next dest block positionw - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ_4x2 ENDP - ENDIF ;VQABLOCK_4X2 - - - IF VQABLOCK_4X4 -;**************************************************************************** -;* -;* NAME -;* UnVQ_4x4 - Draw 4x4 block VQ frame to a buffer. -;* -;* SYNOPSIS -;* UnVQ_4x4(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void UnVQ_4x4(unsigned char *, unsigned char *, unsigned char *, -;* unsigned short, unsigned short, unsigned short); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_4x4 - ASM_UnVQ_4x4 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,2 ; row of blocks - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - IF PHARLAP_TNT - push es - les edi,[FWORD buffer] ;KLUDGE - bcc32 pads FARPTR - ELSE - mov edi,[buffer] - ENDIF - - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - cmp bh,0FFh ;Is it a one color block? - je short ??One_color - -; Draw multi-color block - - shl ebx,4 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] ;Read 1st row of codeword - mov edx,[ebx+4] ;Read 2nd row of codeword - - IF PHARLAP_TNT - mov [es:edi],eax ;Write 1st row to dest - ELSE - mov [edi],eax ;Write 1st row to dest - ENDIF - - mov eax,ebx - mov ebx,[bufwidth] - - IF PHARLAP_TNT - mov [es:edi+ebx],edx ;Write 2nd row to dest - ELSE - mov [edi+ebx],edx ;Write 2nd row to dest - ENDIF - - mov ebx,eax - mov eax,[ebx+8] - mov edx,[ebx+12] - mov ebx,[bufwidth] - shl ebx,1 - - IF PHARLAP_TNT - mov [es:edi+ebx],eax ;Write 2nd row to dest - ELSE - mov [edi+ebx],eax ;Write 2nd row to dest - ENDIF - - add ebx,[bufwidth] - - IF PHARLAP_TNT - mov [es:edi+ebx],edx ;Write 2nd row to dest - ELSE - mov [edi+ebx],edx ;Write 2nd row to dest - ENDIF - - add edi,4 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - mov bh,bl ;Duplicate color through the - mov ax,bx ; entire dword register. - rol eax,16 - mov ax,bx - - IF PHARLAP_TNT - mov [es:edi],eax ;Write 1st row to dest - mov ebx,[bufwidth] - mov [es:edi+ebx],eax ;Write 2nd row to dest - ELSE - mov [edi],eax ;Write 1st row to dest - mov ebx,[bufwidth] - mov [edi+ebx],eax ;Write 2nd row to dest - ENDIF - - add ebx,[bufwidth] - - IF PHARLAP_TNT - mov [es:edi+ebx],eax ;Write 3rd row to dest - ELSE - mov [edi+ebx],eax ;Write 3rd row to dest - ENDIF - - add ebx,[bufwidth] - - IF PHARLAP_TNT - mov [es:edi+ebx],eax ;Write 4th row to dest - ELSE - mov [edi+ebx],eax ;Write 4th row to dest - ENDIF - - add edi,4 ;Next dest block positionw - dec ecx ;More blocks for this row? - jnz ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - IF PHARLAP_TNT - pop es - ENDIF - - ret - - ASM_UnVQ_4x4 ENDP - ENDIF ;VQABLOCK_4X4 - - -;;;; this is very close to UnVQ_2x2 in unvqbuff.asm ;;;; -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ_4x4_HALF - Draw 4x4 block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ_4x4_HALF(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ_4x4_HALF(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_4x4_HALF - ASM_UnVQ_4x4_HALF PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,1 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - IF PHARLAP_TNT - push es - les edi,[FWORD buffer] ;KLUDGE - bcc32 pads FARPTR - ELSE - mov edi,[buffer] - ENDIF - - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - cmp bh,0FFh ;Is it a one color block? - je short ??One_color - -; Draw multi-color block - - shl ebx,4 - add ebx,[codebook] ;Codeword address - mov al,[ebx] - mov ah,[ebx+2] - - IF PHARLAP_TNT - mov [es:edi],ax ;Write 1st row to dest - ELSE - mov [edi],ax ;Write 1st row to dest - ENDIF - - mov al,[ebx+8] - mov ah,[ebx+10] - mov ebx,[bufwidth] - - IF PHARLAP_TNT - mov [es:edi+ebx],ax ;Write 2nd row to dest - ELSE - mov [edi+ebx],ax ;Write 2nd row to dest - ENDIF - - - add edi,2 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - mov bh,bl ;Duplicate color through the - mov ax,bx ; entire dword register. - - IF PHARLAP_TNT - mov [es:edi],ax ;Write 1st row to dest - mov ebx,[bufwidth] - mov [es:edi+ebx],ax ;Write 2nd row to dest - ELSE - mov [edi],ax ;Write 1st row to dest - mov ebx,[bufwidth] - mov [edi+ebx],ax ;Write 2nd row to dest - ENDIF - - add edi,2 ;Next dest block positionw - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - IF PHARLAP_TNT - pop es - ENDIF - - ret - - ASM_UnVQ_4x4_HALF ENDP - - -;;;; this is very close to UnVQ_2x2 in unvqbuff.asm ;;;; -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ_6 - Draw XxX block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ_6(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ_6(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_6 - ASM_UnVQ_6 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,1 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - IF PHARLAP_TNT - push es - les edi,[FWORD buffer] ;KLUDGE - bcc32 pads FARPTR - ELSE - mov edi,[buffer] - ENDIF - - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - cmp bh,0FFh ;Is it a one color block? - je short ??One_color - -; Draw multi-color block - - shl ebx,3 - add ebx,[codebook] ;Codeword address - mov al,[ebx] - mov ah,[ebx+2] - - IF PHARLAP_TNT - mov [es:edi],ax ;Write 1st row to dest - ELSE - mov [edi],ax ;Write 1st row to dest - ENDIF - - mov al,[ebx+8] - mov ah,[ebx+10] - - IF PHARLAP_TNT - mov ebx,[bufwidth] - mov [es:edi+ebx],ax ;Write 2nd row to dest - ELSE - mov ebx,[bufwidth] - mov [edi+ebx],ax ;Write 2nd row to dest - ENDIF - - - add edi,2 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - mov bh,bl ;Duplicate color through the - mov ax,bx ; entire dword register. - - IF PHARLAP_TNT - mov [es:edi],ax ;Write 1st row to dest - mov ebx,[bufwidth] - mov [es:edi+ebx],ax ;Write 2nd row to dest - ELSE - mov [edi],ax ;Write 1st row to dest - mov ebx,[bufwidth] - mov [edi+ebx],ax ;Write 2nd row to dest - ENDIF - - add edi,2 ;Next dest block positionw - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ_6 ENDP - - -;;;; same as UnVQ_1 except fetches from buffer instead of HicolorTable ;;;; -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ1_C1_4x4 - Draw 4x4 block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ1_C1_4x4(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ1_C1_4x4(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ1_C1_4x4 - ASM_UnVQ1_C1_4x4 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL unknown:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - shl [bufwidth],1 - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,2 ; row of blocks - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - IF PHARLAP_TNT - push es - les edi,[FWORD buffer] ;KLUDGE - bcc32 pads FARPTR - ELSE - mov edi,[buffer] - ENDIF - - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - test bh,080h ;Is it a one color block? - js short ??One_color - -; Draw multi-color block - - shl ebx,5 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] ;Read 1st row of codeword - mov edx,[ebx+4] ;Read 2nd row of codeword - - mov [edi],eax - mov [edi+4],edx - - mov eax,[ebx+8] - mov edx,[ebx+12] - mov [unknown],ebx - mov ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - mov ebx,[unknown] - mov eax,[ebx+16] - mov edx,[ebx+20] - mov ebx,[bufwidth] - shl ebx,1 - mov [edi+ebx],eax - mov [edi+ebx+4],edx - mov ebx,[unknown] - - mov eax,[ebx+24] - mov edx,[ebx+28] - mov ebx,[bufwidth] - shl ebx,1 - add ebx,[bufwidth] - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - and bx,07FFFh - mov ax,bx - shl eax,16 - mov ax,bx - - mov [edi],eax - mov [edi+4],eax - - mov ebx,[bufwidth] - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add ebx,[bufwidth] - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add ebx,[bufwidth] - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz ??Not_finished_a_line; jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ1_C1_4x4 ENDP - - -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ_8 - Draw XxX block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ_8(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ_8(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_8 - ASM_UnVQ_8 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL unknown:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - shl [bufwidth],1 - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,1 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - mov edi,[buffer] - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bh,[esi + eax] ;Get the codebook pointer value - mov bl,[esi] - inc esi ; then advance to the next one. - - test bh,080h ;Is it a one color block? - js short ??One_color - -; Draw multi-color block - - shl ebx,4 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] ;Read 1st row of codeword - mov edx,[ebx+4] ;Read 2nd row of codeword - - mov [edi],eax - mov [edi+4],edx - - mov eax,[ebx+8] - mov edx,[ebx+12] - - mov ebx,[bufwidth] - - mov [edi+ebx],eax - mov [edi+ebx+4],edx - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - and bx,07FFFh - mov ax,bx - shl eax,16 - mov ax,bx - - mov [edi],eax - mov [edi+4],eax - - mov ebx,[bufwidth] - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ_8 ENDP - - -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ_9 - Draw XxX block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ_9(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ_9(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_9 - ASM_UnVQ_9 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,3 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - mov edi,[buffer] - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bl,[esi] - mov bh,[esi + eax] ;Get the codebook pointer value - inc esi ; then advance to the next one. - - cmp bh,0FFh ;Is it a one color block? - je short ??One_color - -; Draw multi-color block - - shl ebx,5 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] - mov edx,[bufwidth] - - mov [edi],eax - - mov eax,[ebx+4] - mov [edi+edx],eax - - shl edx,1 - - mov eax,[ebx+8] - mov [edi+edx],eax - - add edx,[bufwidth] - - mov eax,[ebx+12] - mov [edi+edx],eax - - add edx,[bufwidth] - - mov eax,[ebx+16] - mov [edi+edx],eax - - add edx,[bufwidth] - - mov eax,[ebx+20] - mov [edi+edx],eax - - add edx,[bufwidth] - - mov eax,[ebx+24] - mov [edi+edx],eax - - add edx,[bufwidth] - - mov eax,[ebx+28] - mov [edi+edx],eax - - add edi,4 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - mov bh,bl ;Duplicate color through the - mov ax,bx ; entire dword register. - rol eax,16 - mov ax,bx - mov ebx,[bufwidth] - - mov [edi],eax - - mov [edi+ebx],eax - - shl ebx,1 - mov [edi+ebx],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - - add ebx,[bufwidth] - mov [edi+ebx],eax - - add edi,4 ;Next dest block position - dec ecx ;More blocks for this row? - jnz ??Not_finished_a_line ;jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ_9 ENDP - - -;**************************************************************************** -;* -;* NAME -;* ASM_UnVQ_10 - Draw XxX block VQ frame to a buffer. -;* -;* SYNOPSIS -;* ASM_UnVQ_10(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) -;* -;* void ASM_UnVQ_10(unsigned char *, unsigned char *, unsigned char *, -;* long, long, long); -;* -;* FUNCTION -;* This function draws an image into the specified buffer from the -;* pointers and codebook provided. This routine has been optimized for -;* a 320x200 image. -;* -;* INPUTS -;* Codebook - Pointer to codebook used to draw image. -;* Pointers - Pointer to vector pointer data. -;* Buffer - Pointer to buffer to draw image into. -;* BPR - Number of blocks per row. -;* Rows - Number of rows. -;* BufWidth - Width of destination buffer in pixels. -;* -;* RESULT -;* NONE -;* -;**************************************************************************** - - PUBLIC ASM_UnVQ_10 - ASM_UnVQ_10 PROC C USES ebx ecx edx esi edi \ - \ - codebook:DWORD, \ - pointers:DWORD, \ - buffer:DWORD, \ - blocksperrow:DWORD, \ - numrows:DWORD, \ - bufwidth:DWORD - - LOCAL data_end:DWORD - ;LOCAL cb_offset:DWORD - LOCAL edi_startval:DWORD - LOCAL rowoffset:DWORD - LOCAL entries:DWORD - -;---------------------------------------------------------------------------- -; Initialize -;---------------------------------------------------------------------------- - -; mov eax,[codebook] ;Adjust the codebook address so -; sub eax,4 ; that the pointer offsets will -; mov [cb_offset],eax ; point directly at the codeword. - - mov eax,[bufwidth] ;Compute the offset to the next - shl eax,2 ; row of blocks. - mov [rowoffset],eax - - mov esi,[pointers] - mov eax,[numrows] ;Compute the end address of the - mul [blocksperrow] ; pointer data. - mov [entries],eax - add eax,esi - mov [data_end],eax - - mov edi,[buffer] - mov [edi_startval],edi - -;---------------------------------------------------------------------------- -; Drawing loop -;---------------------------------------------------------------------------- - -??Start_row: - mov ecx,[blocksperrow] ;Number of blocks in a line - -??Not_finished_a_line: - mov eax,[entries] - xor ebx,ebx - mov bl,[esi] - mov bh,[esi + eax] ;Get the codebook pointer value - inc esi ; then advance to the next one. - - cmp bh,0FFh ;Is it a one color block? - je short ??One_color - -; Draw multi-color block - - shl ebx,5 - add ebx,[codebook] ;Codeword address - mov eax,[ebx] - mov edx,[bufwidth] - - mov [edi],eax - - mov eax,[ebx+4] - mov [edi+4],eax - - mov eax,[ebx+8] - mov [edi+edx],eax - - mov eax,[ebx+12] - mov [edi+edx+4],eax - - shl edx,1 - - mov eax,[ebx+16] - mov [edi+edx],eax - - mov eax,[ebx+20] - mov [edi+edx+4],eax - - add edx,[bufwidth] - - mov eax,[ebx+24] - mov [edi+edx],eax - - mov eax,[ebx+28] - mov [edi+edx+4],eax - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -; Draw 1-color block - -??One_color: -; cmp bx,SKIP_PTR ;Is this a skip block? -; jne ??Draw_One_Color -; -; add edi,4 ;Move to next dest block position -; dec ecx ;More blocks for this row? -; jnz short ??Not_finished_a_line -; jmp ??Next_row - -??Draw_One_Color: -; not bx ;NOT pointer value to get color - mov bh,bl ;Duplicate color through the - mov ax,bx ; entire dword register. - rol eax,16 - mov ax,bx - mov ebx,[bufwidth] - - mov [edi],eax - mov [edi+4],eax - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - shl ebx,1 - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add ebx,[bufwidth] - - mov [edi+ebx],eax - mov [edi+ebx+4],eax - - add edi,8 ;Next dest block position - dec ecx ;More blocks for this row? - jnz ??Not_finished_a_line ;jnz short ??Not_finished_a_line - -; Advance to the next destination row of blocks. - -??Next_row: - mov edi,[edi_startval] - add edi,[rowoffset] - mov [edi_startval],edi - - cmp esi,[data_end] ;Have we reached the end of the - jnb short ??End_of_data ; pointers buffer? - jmp ??Start_row - -??End_of_data: - ret - - ASM_UnVQ_10 ENDP - -END diff --git a/code/unvqdec.cpp b/code/unvqdec.cpp new file mode 100644 index 000000000..9e2ceba7a --- /dev/null +++ b/code/unvqdec.cpp @@ -0,0 +1,428 @@ +/******************************************************************************* + * O P E N T S + ******************************************************************************* + * SPDX-License-Identifier: GPL-3.0-or-later + * Copyright 2025 Electronic Arts Inc. + * Copyright 2026 OpenTS contributors + * + * Contains material derived from Electronic Arts source code. + * Modified by OpenTS contributors, 2026. + * EA's GPLv3 Section 7 additional terms and supplemental warranty + * disclaimers apply; see LICENSE.md. + ******************************************************************************/ + +/**************************************************************************** +* +* File : unvq_asm.asm +* Description : VQA UnVQ1 full-frame decoders, drawing a VQ compressed +* video frame into a pixel buffer. +* +****************************************************************************/ + +#include "always.h" + +#include "vqalib/unvq.h" + +#include "_vqa.h" + +/* + * Six full-frame decoders, each replacing an assembly routine of the same name. They share a + * shape: a frame is a grid of blocks, and every block carries a pointer into the codebook. + * + * The pointers arrive as two planes rather than as pairs -- every block's low byte first, then + * every block's high byte -- so a block's codebook index is assembled from the two. + * + * A block is either a codebook entry copied out, or a single colour filling the whole block. + * The two families differ in how they say which: an 8 bit frame marks a solid block with a + * high byte of 0xFF and takes the colour from the low byte, while a 16 bit frame marks it with + * the top bit and takes the remaining 15 as the colour. Of the 16 bit decoders, the two named + * TABLE run that colour through HicolorTable; ASM_UnVQ1_C1_4x4 uses it as the pixel directly. + * + * Names carry the block size the codebook holds, not always the size written: 4x4_HALF reads a + * 4x4 entry and writes every other pixel of every other row, and TABLE_ALT reads a 4x4 entry + * and writes its first and third rows two screen rows apart. + */ + +namespace { + +/// +/// Assembles one block's codebook index from the two pointer planes. +/// +/// Base of the pointer data. +/// Total block count, which is where the high plane starts. +/// Which block to read. +/// unsigned int; The codebook index. +inline unsigned int Block_Index(unsigned char const * pointers, unsigned long entries, unsigned long block) +{ + return(((unsigned int)pointers[entries + block] << 8) | (unsigned int)pointers[block]); +} + + +inline void Put32(unsigned char * dest, unsigned char const * source) +{ + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; +} + + +inline void Fill32(unsigned char * dest, unsigned int value) +{ + dest[0] = (unsigned char)(value & 0xFF); + dest[1] = (unsigned char)((value >> 8) & 0xFF); + dest[2] = (unsigned char)((value >> 16) & 0xFF); + dest[3] = (unsigned char)((value >> 24) & 0xFF); +} + + +inline void Put16(unsigned char * dest, unsigned char const * source) +{ + dest[0] = source[0]; + dest[1] = source[1]; +} + + +inline void Fill16(unsigned char * dest, unsigned int value) +{ + dest[0] = (unsigned char)(value & 0xFF); + dest[1] = (unsigned char)((value >> 8) & 0xFF); +} + + +/* + * Spreads a 16 bit pixel across a doubleword so a solid block is filled four bytes at a time, + * the way the assembly did it. + */ +inline unsigned int Pair16(unsigned int pixel) +{ + return((pixel << 16) | pixel); +} + + +inline unsigned int Quad8(unsigned int colour) +{ + unsigned int const pair = (colour << 8) | colour; + return((pair << 16) | pair); +} + +} // namespace + + +/// +/// Draws a 16 bit frame from 4x4 codebook entries, taking a solid block's colour from +/// HicolorTable. +/// +/// Codebook the blocks are drawn from. +/// Block pointer data, low plane then high plane. +/// Destination pixel buffer. +/// Blocks across one row of the frame. +/// Rows of blocks in the frame. +/// Destination width in pixels. +void __cdecl ASM_UnVQ1_C1_TABLE(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, + unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +{ + if (blocksperrow == 0) { + return; + } + + unsigned long const pitch = bufwidth * 2; + unsigned long const rowoffset = pitch * 4; + unsigned long const entries = numrows * blocksperrow; + + unsigned char * rowstart = buffer; + unsigned long block = 0; + + do { + unsigned char * dest = rowstart; + + for (unsigned long i = 0; i < blocksperrow; i++) { + unsigned int const index = Block_Index(pointers, entries, block); + block++; + + if ((index & 0x8000) != 0) { + unsigned int const pixels = Pair16(HicolorTable[index & 0x7FFF]); + + for (int row = 0; row < 4; row++) { + Fill32(dest + row * pitch, pixels); + Fill32(dest + row * pitch + 4, pixels); + } + } else { + unsigned char const * word = codebook + index * 32; + + for (int row = 0; row < 4; row++) { + Put32(dest + row * pitch, word + row * 8); + Put32(dest + row * pitch + 4, word + row * 8 + 4); + } + } + + dest += 8; + } + + rowstart += rowoffset; + } while (block < entries); +} + + +/// +/// Draws a 16 bit frame from the first and third rows of 4x4 codebook entries, written two +/// screen rows apart. A solid block's colour comes from HicolorTable. +/// +/// Codebook the blocks are drawn from. +/// Block pointer data, low plane then high plane. +/// Destination pixel buffer. +/// Blocks across one row of the frame. +/// Rows of blocks in the frame. +/// Destination width in pixels. +void __cdecl ASM_UnVQ1_C1_TABLE_ALT(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, + unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +{ + if (blocksperrow == 0) { + return; + } + + unsigned long const pitch = bufwidth * 2; + unsigned long const rowoffset = pitch * 4; + unsigned long const entries = numrows * blocksperrow; + + unsigned char * rowstart = buffer; + unsigned long block = 0; + + do { + unsigned char * dest = rowstart; + + for (unsigned long i = 0; i < blocksperrow; i++) { + unsigned int const index = Block_Index(pointers, entries, block); + block++; + + if ((index & 0x8000) != 0) { + unsigned int const pixels = Pair16(HicolorTable[index & 0x7FFF]); + + Fill32(dest, pixels); + Fill32(dest + 4, pixels); + Fill32(dest + pitch * 2, pixels); + Fill32(dest + pitch * 2 + 4, pixels); + } else { + unsigned char const * word = codebook + index * 32; + + Put32(dest, word); + Put32(dest + 4, word + 4); + Put32(dest + pitch * 2, word + 16); + Put32(dest + pitch * 2 + 4, word + 20); + } + + dest += 8; + } + + rowstart += rowoffset; + } while (block < entries); +} + + +/// +/// Draws an 8 bit frame from 4x2 codebook entries. +/// +/// Codebook the blocks are drawn from. +/// Block pointer data, low plane then high plane. +/// Destination pixel buffer. +/// Blocks across one row of the frame. +/// Rows of blocks in the frame. +/// Destination width in pixels. +void __cdecl ASM_UnVQ_4x2(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, + unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +{ + if (blocksperrow == 0) { + return; + } + + unsigned long const rowoffset = bufwidth * 2; + unsigned long const entries = numrows * blocksperrow; + + unsigned char * rowstart = buffer; + unsigned long block = 0; + + do { + unsigned char * dest = rowstart; + + for (unsigned long i = 0; i < blocksperrow; i++) { + unsigned int const index = Block_Index(pointers, entries, block); + block++; + + if ((index >> 8) == 0xFF) { + unsigned int const pixels = Quad8(index & 0xFF); + + Fill32(dest, pixels); + Fill32(dest + bufwidth, pixels); + } else { + unsigned char const * word = codebook + index * 8; + + Put32(dest, word); + Put32(dest + bufwidth, word + 4); + } + + dest += 4; + } + + rowstart += rowoffset; + } while (block < entries); +} + + +/// +/// Draws an 8 bit frame from 4x4 codebook entries. +/// +/// Codebook the blocks are drawn from. +/// Block pointer data, low plane then high plane. +/// Destination pixel buffer. +/// Blocks across one row of the frame. +/// Rows of blocks in the frame. +/// Destination width in pixels. +void __cdecl ASM_UnVQ_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, + unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +{ + if (blocksperrow == 0) { + return; + } + + unsigned long const rowoffset = bufwidth * 4; + unsigned long const entries = numrows * blocksperrow; + + unsigned char * rowstart = buffer; + unsigned long block = 0; + + do { + unsigned char * dest = rowstart; + + for (unsigned long i = 0; i < blocksperrow; i++) { + unsigned int const index = Block_Index(pointers, entries, block); + block++; + + if ((index >> 8) == 0xFF) { + unsigned int const pixels = Quad8(index & 0xFF); + + for (int row = 0; row < 4; row++) { + Fill32(dest + row * bufwidth, pixels); + } + } else { + unsigned char const * word = codebook + index * 16; + + for (int row = 0; row < 4; row++) { + Put32(dest + row * bufwidth, word + row * 4); + } + } + + dest += 4; + } + + rowstart += rowoffset; + } while (block < entries); +} + + +/// +/// Draws an 8 bit frame at half size, reading 4x4 codebook entries but keeping every other +/// pixel of every other row. +/// +/// Codebook the blocks are drawn from. +/// Block pointer data, low plane then high plane. +/// Destination pixel buffer. +/// Blocks across one row of the frame. +/// Rows of blocks in the frame. +/// Destination width in pixels. +void __cdecl ASM_UnVQ_4x4_HALF(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, + unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +{ + if (blocksperrow == 0) { + return; + } + + unsigned long const rowoffset = bufwidth * 2; + unsigned long const entries = numrows * blocksperrow; + + unsigned char * rowstart = buffer; + unsigned long block = 0; + + do { + unsigned char * dest = rowstart; + + for (unsigned long i = 0; i < blocksperrow; i++) { + unsigned int const index = Block_Index(pointers, entries, block); + block++; + + if ((index >> 8) == 0xFF) { + unsigned char const colour = (unsigned char)(index & 0xFF); + + dest[0] = colour; + dest[1] = colour; + dest[bufwidth] = colour; + dest[bufwidth + 1] = colour; + } else { + unsigned char const * word = codebook + index * 16; + + dest[0] = word[0]; + dest[1] = word[2]; + dest[bufwidth] = word[8]; + dest[bufwidth + 1] = word[10]; + } + + dest += 2; + } + + rowstart += rowoffset; + } while (block < entries); +} + + +/// +/// Draws a 16 bit frame from 4x4 codebook entries, taking a solid block's colour from the +/// pointer value itself rather than through HicolorTable. +/// +/// Codebook the blocks are drawn from. +/// Block pointer data, low plane then high plane. +/// Destination pixel buffer. +/// Blocks across one row of the frame. +/// Rows of blocks in the frame. +/// Destination width in pixels. +void __cdecl ASM_UnVQ1_C1_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, + unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +{ + if (blocksperrow == 0) { + return; + } + + unsigned long const pitch = bufwidth * 2; + unsigned long const rowoffset = pitch * 4; + unsigned long const entries = numrows * blocksperrow; + + unsigned char * rowstart = buffer; + unsigned long block = 0; + + do { + unsigned char * dest = rowstart; + + for (unsigned long i = 0; i < blocksperrow; i++) { + unsigned int const index = Block_Index(pointers, entries, block); + block++; + + if ((index & 0x8000) != 0) { + unsigned int const pixels = Pair16(index & 0x7FFF); + + for (int row = 0; row < 4; row++) { + Fill32(dest + row * pitch, pixels); + Fill32(dest + row * pitch + 4, pixels); + } + } else { + unsigned char const * word = codebook + index * 32; + + for (int row = 0; row < 4; row++) { + Put32(dest + row * pitch, word + row * 8); + Put32(dest + row * pitch + 4, word + row * 8 + 4); + } + } + + dest += 8; + } + + rowstart += rowoffset; + } while (block < entries); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 003214f46..e56c05c37 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(spawner) add_subdirectory(syncrec) add_subdirectory(colorops) add_subdirectory(voxeldraw) +add_subdirectory(unvqdec) diff --git a/tests/unvqdec/CMakeLists.txt b/tests/unvqdec/CMakeLists.txt new file mode 100644 index 000000000..5b94bcd16 --- /dev/null +++ b/tests/unvqdec/CMakeLists.txt @@ -0,0 +1,30 @@ +# The decoders are compiled straight into the harness. It lives outside code/ so that the +# recursive glob building OpenTS cannot pick this target's entry point up. +add_executable(UnvqDec + "${CMAKE_CURRENT_SOURCE_DIR}/unvqparity.cpp" + "${CMAKE_SOURCE_DIR}/code/unvqdec.cpp" +) + +target_compile_features(UnvqDec PRIVATE cxx_std_20) + +target_include_directories(UnvqDec PRIVATE + "${CMAKE_SOURCE_DIR}/code" + "${CMAKE_CURRENT_SOURCE_DIR}" +) + +target_compile_definitions(UnvqDec PRIVATE WIN32 _WINDOWS _MBCS) + +# The engine builds this source with SSE2 and precise floating point. The harness matches that +# so a result here carries over to the engine. +target_compile_options(UnvqDec PRIVATE + $<$:/MTd /EHsc /Zc:__cplusplus /arch:SSE2 /fp:precise> + $<$:/MT /EHsc /Zc:__cplusplus /arch:SSE2 /fp:precise> +) + +target_link_libraries(UnvqDec PRIVATE kernel32 user32 shell32) + +set_target_properties(UnvqDec PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +) + +add_test(NAME unvqdec COMMAND UnvqDec) diff --git a/tests/unvqdec/unvqgolden.h b/tests/unvqdec/unvqgolden.h new file mode 100644 index 000000000..bc67a1968 --- /dev/null +++ b/tests/unvqdec/unvqgolden.h @@ -0,0 +1,174 @@ +/******************************************************************************* + * O P E N T S + ******************************************************************************* + * SPDX-License-Identifier: GPL-3.0-or-later + * Copyright 2026 OpenTS contributors + * + * See LICENSE.md for applicable additional terms and warranty disclaimers. + ******************************************************************************/ + +// Generated from the UnVQ1 block decoders while they were still hand-written assembly, +// and kept so the C++ that replaced them can be held to the same output. +// +// Generated file. Do not hand-edit. + +#pragma once + +struct UnVQGoldenCase { + int Which; + unsigned long BlocksPerRow; + unsigned long NumRows; + unsigned long BufWidth; + unsigned int Seed; + int Solid; + unsigned long long Hash; +}; + +static UnVQGoldenCase const UnVQGoldenCases[] = { + {0, 1ul, 1ul, 8ul, 39256u, 0, 2895180338204187794ULL}, + {0, 1ul, 1ul, 8ul, 47175u, 3, 17757882376145931266ULL}, + {0, 1ul, 1ul, 8ul, 55094u, 6, 1310722270548503139ULL}, + {0, 2ul, 1ul, 16ul, 63013u, 0, 13290677462593678327ULL}, + {0, 2ul, 1ul, 16ul, 70932u, 3, 18036005907330044508ULL}, + {0, 2ul, 1ul, 16ul, 78851u, 6, 13899957888247383084ULL}, + {0, 1ul, 2ul, 8ul, 86770u, 0, 16205816349972030866ULL}, + {0, 1ul, 2ul, 8ul, 94689u, 3, 2089316313385929475ULL}, + {0, 1ul, 2ul, 8ul, 102608u, 6, 176863261255263274ULL}, + {0, 4ul, 3ul, 32ul, 110527u, 0, 11407330926932259914ULL}, + {0, 4ul, 3ul, 32ul, 118446u, 3, 9095622258641437780ULL}, + {0, 4ul, 3ul, 32ul, 126365u, 6, 12123533738725787750ULL}, + {0, 8ul, 5ul, 64ul, 134284u, 0, 6234379622060752775ULL}, + {0, 8ul, 5ul, 64ul, 142203u, 3, 5384650114977810682ULL}, + {0, 8ul, 5ul, 64ul, 150122u, 6, 18341148558070273986ULL}, + {0, 16ul, 4ul, 128ul, 158041u, 0, 9489199241227354259ULL}, + {0, 16ul, 4ul, 128ul, 165960u, 3, 410521912332868001ULL}, + {0, 16ul, 4ul, 128ul, 173879u, 6, 16714704385500838210ULL}, + {0, 40ul, 8ul, 320ul, 181798u, 0, 1680827606164676883ULL}, + {0, 40ul, 8ul, 320ul, 189717u, 3, 9918701732719108227ULL}, + {0, 40ul, 8ul, 320ul, 197636u, 6, 4093886688550579255ULL}, + {0, 80ul, 6ul, 640ul, 205555u, 0, 1728636679431568073ULL}, + {0, 80ul, 6ul, 640ul, 213474u, 3, 9815469616241825781ULL}, + {0, 80ul, 6ul, 640ul, 221393u, 6, 15879347310269872882ULL}, + {1, 1ul, 1ul, 8ul, 229312u, 0, 6904545672353592445ULL}, + {1, 1ul, 1ul, 8ul, 237231u, 3, 7572489033761486867ULL}, + {1, 1ul, 1ul, 8ul, 245150u, 6, 10460081396690070835ULL}, + {1, 2ul, 1ul, 16ul, 253069u, 0, 4346579680639647831ULL}, + {1, 2ul, 1ul, 16ul, 260988u, 3, 13358952695467658649ULL}, + {1, 2ul, 1ul, 16ul, 268907u, 6, 15231705630455511699ULL}, + {1, 1ul, 2ul, 8ul, 276826u, 0, 11399492110333932431ULL}, + {1, 1ul, 2ul, 8ul, 284745u, 3, 14527847966156556939ULL}, + {1, 1ul, 2ul, 8ul, 292664u, 6, 4593385139775936671ULL}, + {1, 4ul, 3ul, 32ul, 300583u, 0, 7916149013438277554ULL}, + {1, 4ul, 3ul, 32ul, 308502u, 3, 5723184743254390524ULL}, + {1, 4ul, 3ul, 32ul, 316421u, 6, 14361154402489545643ULL}, + {1, 8ul, 5ul, 64ul, 324340u, 0, 2598479551401106955ULL}, + {1, 8ul, 5ul, 64ul, 332259u, 3, 6011383005848795415ULL}, + {1, 8ul, 5ul, 64ul, 340178u, 6, 10350345297621128583ULL}, + {1, 16ul, 4ul, 128ul, 348097u, 0, 659948498303876753ULL}, + {1, 16ul, 4ul, 128ul, 356016u, 3, 16557186128372377563ULL}, + {1, 16ul, 4ul, 128ul, 363935u, 6, 12903925725161468289ULL}, + {1, 40ul, 8ul, 320ul, 371854u, 0, 16836206211057703994ULL}, + {1, 40ul, 8ul, 320ul, 379773u, 3, 6555152581767122262ULL}, + {1, 40ul, 8ul, 320ul, 387692u, 6, 5914197655047528973ULL}, + {1, 80ul, 6ul, 640ul, 395611u, 0, 1860580819577028376ULL}, + {1, 80ul, 6ul, 640ul, 403530u, 3, 273668743315395098ULL}, + {1, 80ul, 6ul, 640ul, 411449u, 6, 3274477421171696524ULL}, + {2, 1ul, 1ul, 8ul, 419368u, 0, 7319516721727266879ULL}, + {2, 1ul, 1ul, 8ul, 427287u, 3, 2692286575745468862ULL}, + {2, 1ul, 1ul, 8ul, 435206u, 6, 9835579519873410565ULL}, + {2, 2ul, 1ul, 16ul, 443125u, 0, 9560146741277564686ULL}, + {2, 2ul, 1ul, 16ul, 451044u, 3, 2702462808681971654ULL}, + {2, 2ul, 1ul, 16ul, 458963u, 6, 17530099301393760915ULL}, + {2, 1ul, 2ul, 8ul, 466882u, 0, 15290904700629570014ULL}, + {2, 1ul, 2ul, 8ul, 474801u, 3, 14945406362136875703ULL}, + {2, 1ul, 2ul, 8ul, 482720u, 6, 13687515445097241811ULL}, + {2, 4ul, 3ul, 32ul, 490639u, 0, 7767801254153680791ULL}, + {2, 4ul, 3ul, 32ul, 498558u, 3, 6790497685525502818ULL}, + {2, 4ul, 3ul, 32ul, 506477u, 6, 12622260113368074327ULL}, + {2, 8ul, 5ul, 64ul, 514396u, 0, 16331290944465145099ULL}, + {2, 8ul, 5ul, 64ul, 522315u, 3, 227455183991645826ULL}, + {2, 8ul, 5ul, 64ul, 530234u, 6, 9709753186217421527ULL}, + {2, 16ul, 4ul, 128ul, 538153u, 0, 7460992342372724961ULL}, + {2, 16ul, 4ul, 128ul, 546072u, 3, 6622418918924008381ULL}, + {2, 16ul, 4ul, 128ul, 553991u, 6, 15190498848712983205ULL}, + {2, 40ul, 8ul, 320ul, 561910u, 0, 444001270176792181ULL}, + {2, 40ul, 8ul, 320ul, 569829u, 3, 18418762446303843907ULL}, + {2, 40ul, 8ul, 320ul, 577748u, 6, 322233945295055196ULL}, + {2, 80ul, 6ul, 640ul, 585667u, 0, 18041946778258598643ULL}, + {2, 80ul, 6ul, 640ul, 593586u, 3, 14299794166472370116ULL}, + {2, 80ul, 6ul, 640ul, 601505u, 6, 7650313287078190776ULL}, + {3, 1ul, 1ul, 8ul, 609424u, 0, 8336221726965572926ULL}, + {3, 1ul, 1ul, 8ul, 617343u, 3, 14357669097801118602ULL}, + {3, 1ul, 1ul, 8ul, 625262u, 6, 11888461547242737411ULL}, + {3, 2ul, 1ul, 16ul, 633181u, 0, 12451402414277933228ULL}, + {3, 2ul, 1ul, 16ul, 641100u, 3, 14031562617456302358ULL}, + {3, 2ul, 1ul, 16ul, 649019u, 6, 12682485296615916062ULL}, + {3, 1ul, 2ul, 8ul, 656938u, 0, 17025345068406506660ULL}, + {3, 1ul, 2ul, 8ul, 664857u, 3, 14855605504341511520ULL}, + {3, 1ul, 2ul, 8ul, 672776u, 6, 8439885122264472260ULL}, + {3, 4ul, 3ul, 32ul, 680695u, 0, 8823368132228201645ULL}, + {3, 4ul, 3ul, 32ul, 688614u, 3, 14331363456787526435ULL}, + {3, 4ul, 3ul, 32ul, 696533u, 6, 3263843499962730247ULL}, + {3, 8ul, 5ul, 64ul, 704452u, 0, 334276754665621425ULL}, + {3, 8ul, 5ul, 64ul, 712371u, 3, 17406228746353370517ULL}, + {3, 8ul, 5ul, 64ul, 720290u, 6, 2412999515486084193ULL}, + {3, 16ul, 4ul, 128ul, 728209u, 0, 6515991890092044561ULL}, + {3, 16ul, 4ul, 128ul, 736128u, 3, 14862942283240370395ULL}, + {3, 16ul, 4ul, 128ul, 744047u, 6, 11418913403603726657ULL}, + {3, 40ul, 8ul, 320ul, 751966u, 0, 1520305175013350579ULL}, + {3, 40ul, 8ul, 320ul, 759885u, 3, 5503740123338513368ULL}, + {3, 40ul, 8ul, 320ul, 767804u, 6, 15730164623780678191ULL}, + {3, 80ul, 6ul, 640ul, 775723u, 0, 1082841911554596682ULL}, + {3, 80ul, 6ul, 640ul, 783642u, 3, 5163514330395019813ULL}, + {3, 80ul, 6ul, 640ul, 791561u, 6, 37323671311232753ULL}, + {4, 1ul, 1ul, 8ul, 799480u, 0, 1810900035607166633ULL}, + {4, 1ul, 1ul, 8ul, 807399u, 3, 5422460428662588071ULL}, + {4, 1ul, 1ul, 8ul, 815318u, 6, 9890215725304960084ULL}, + {4, 2ul, 1ul, 16ul, 823237u, 0, 12872001784068871327ULL}, + {4, 2ul, 1ul, 16ul, 831156u, 3, 6794633583440300094ULL}, + {4, 2ul, 1ul, 16ul, 839075u, 6, 7053783228759131829ULL}, + {4, 1ul, 2ul, 8ul, 846994u, 0, 16029464194912996640ULL}, + {4, 1ul, 2ul, 8ul, 854913u, 3, 4061107708200613361ULL}, + {4, 1ul, 2ul, 8ul, 862832u, 6, 4287611396669678951ULL}, + {4, 4ul, 3ul, 32ul, 870751u, 0, 17589643954509062724ULL}, + {4, 4ul, 3ul, 32ul, 878670u, 3, 13894740507817048105ULL}, + {4, 4ul, 3ul, 32ul, 886589u, 6, 4051733282120936329ULL}, + {4, 8ul, 5ul, 64ul, 894508u, 0, 10873377070287797979ULL}, + {4, 8ul, 5ul, 64ul, 902427u, 3, 10458937627385746432ULL}, + {4, 8ul, 5ul, 64ul, 910346u, 6, 1070299413120541637ULL}, + {4, 16ul, 4ul, 128ul, 918265u, 0, 7965563385219278396ULL}, + {4, 16ul, 4ul, 128ul, 926184u, 3, 13262030059095557298ULL}, + {4, 16ul, 4ul, 128ul, 934103u, 6, 3969192512777103613ULL}, + {4, 40ul, 8ul, 320ul, 942022u, 0, 6680452675702737586ULL}, + {4, 40ul, 8ul, 320ul, 949941u, 3, 14168562727132037992ULL}, + {4, 40ul, 8ul, 320ul, 957860u, 6, 5969306658812640273ULL}, + {4, 80ul, 6ul, 640ul, 965779u, 0, 9614296579228538735ULL}, + {4, 80ul, 6ul, 640ul, 973698u, 3, 16362478091999660680ULL}, + {4, 80ul, 6ul, 640ul, 981617u, 6, 3759891232464906609ULL}, + {5, 1ul, 1ul, 8ul, 989536u, 0, 9562682815685531595ULL}, + {5, 1ul, 1ul, 8ul, 997455u, 3, 3713967301877667905ULL}, + {5, 1ul, 1ul, 8ul, 1005374u, 6, 15825502959710816937ULL}, + {5, 2ul, 1ul, 16ul, 1013293u, 0, 18092955949082007219ULL}, + {5, 2ul, 1ul, 16ul, 1021212u, 3, 5049477157122299998ULL}, + {5, 2ul, 1ul, 16ul, 1029131u, 6, 12138214995037531598ULL}, + {5, 1ul, 2ul, 8ul, 1037050u, 0, 5011464688791974774ULL}, + {5, 1ul, 2ul, 8ul, 1044969u, 3, 16671972731677576087ULL}, + {5, 1ul, 2ul, 8ul, 1052888u, 6, 13814250979399252388ULL}, + {5, 4ul, 3ul, 32ul, 1060807u, 0, 1316452514753016705ULL}, + {5, 4ul, 3ul, 32ul, 1068726u, 3, 7728036922611984938ULL}, + {5, 4ul, 3ul, 32ul, 1076645u, 6, 15758488203009734528ULL}, + {5, 8ul, 5ul, 64ul, 1084564u, 0, 4686816581985809121ULL}, + {5, 8ul, 5ul, 64ul, 1092483u, 3, 8615585687532332172ULL}, + {5, 8ul, 5ul, 64ul, 1100402u, 6, 8465735642007006319ULL}, + {5, 16ul, 4ul, 128ul, 1108321u, 0, 16606183072978705678ULL}, + {5, 16ul, 4ul, 128ul, 1116240u, 3, 6751492619167284339ULL}, + {5, 16ul, 4ul, 128ul, 1124159u, 6, 13600317944702643181ULL}, + {5, 40ul, 8ul, 320ul, 1132078u, 0, 17852441066602527924ULL}, + {5, 40ul, 8ul, 320ul, 1139997u, 3, 12864533129715870536ULL}, + {5, 40ul, 8ul, 320ul, 1147916u, 6, 17944196833427838413ULL}, + {5, 80ul, 6ul, 640ul, 1155835u, 0, 11902721631645551582ULL}, + {5, 80ul, 6ul, 640ul, 1163754u, 3, 15019696812734146483ULL}, + {5, 80ul, 6ul, 640ul, 1171673u, 6, 8790841772678952242ULL}, +}; + +static int const UnVQGoldenCaseCount = 144; diff --git a/tests/unvqdec/unvqparity.cpp b/tests/unvqdec/unvqparity.cpp new file mode 100644 index 000000000..673733895 --- /dev/null +++ b/tests/unvqdec/unvqparity.cpp @@ -0,0 +1,172 @@ +/******************************************************************************* + * O P E N T S + ******************************************************************************* + * SPDX-License-Identifier: GPL-3.0-or-later + * Copyright 2026 OpenTS contributors + * + * See LICENSE.md for applicable additional terms and warranty disclaimers. + ******************************************************************************/ + +// Holds the UnVQ1 block decoders in unvqdec.cpp to the output the assembly they replaced +// produced. The vectors in unvqgolden.h were recorded from that assembly before it was +// removed. Needs no game data. + +#include +#include + +#include "vqalib/unvq.h" + +#include "unvqgolden.h" + +extern "C" unsigned short * HicolorTable = 0; + +namespace { + +int const CBMAX = 65536; +int const DSTMAX = 1048576; +int const PTRMAX = 8192; +unsigned char const GUARD = 0xA5; + +unsigned char Codebook[CBMAX]; +unsigned char Pointers[PTRMAX * 2]; +unsigned char DestStore[DSTMAX]; +unsigned short HicolorStore[32768]; + +unsigned int Seed = 0; + +int Failures = 0; +int Checked = 0; + + +unsigned int Next_Random(void) +{ + Seed = Seed * 1103515245u + 12345u; + return(Seed >> 8); +} + + +unsigned long long Hash(unsigned char const * data, int size) +{ + unsigned long long hash = 1469598103934665603ULL; + for (int i = 0; i < size; i++) { + hash ^= (unsigned long long)data[i]; + hash *= 1099511628211ULL; + } + return(hash); +} + + +/* + * Must build byte for byte what the generator built, or the recorded output describes a + * different frame than the one replayed here. + */ +void Build_Pointers(unsigned int seed, unsigned long entries, int maxindex, bool hicolour, int solid) +{ + Seed = seed; + + for (unsigned long i = 0; i < entries; i++) { + unsigned int index = 0; + + if ((int)(Next_Random() % 10) < solid) { + index = hicolour ? (0x8000 | (Next_Random() & 0x7FFF)) : (0xFF00 | (Next_Random() & 0xFF)); + } else { + index = Next_Random() % (unsigned int)maxindex; + + if (hicolour) { + index &= 0x7FFF; + } else if ((index >> 8) == 0xFF) { + index = 0; + } + } + + Pointers[i] = (unsigned char)(index & 0xFF); + Pointers[entries + i] = (unsigned char)((index >> 8) & 0xFF); + } +} + + +int Span(UnVQGoldenCase const & test, int bytesperpixel, int rowsperblock) +{ + return((int)(test.BufWidth * bytesperpixel * test.NumRows * rowsperblock) + 256); +} + +} // namespace + + +int main(void) +{ + HicolorTable = HicolorStore; + + Seed = 777; + for (int i = 0; i < 32768; i++) { + HicolorStore[i] = (unsigned short)(Next_Random() & 0xFFFF); + } + + Seed = 555; + for (int i = 0; i < CBMAX; i++) { + Codebook[i] = (unsigned char)(Next_Random() & 0xFF); + } + + for (int i = 0; i < UnVQGoldenCaseCount; i++) { + UnVQGoldenCase const & test = UnVQGoldenCases[i]; + unsigned long const entries = test.BlocksPerRow * test.NumRows; + + std::memset(DestStore, GUARD, sizeof(DestStore)); + + int span = 0; + int const solid = test.Solid; + + switch (test.Which) { + case 0: + Build_Pointers(test.Seed, entries, 2048, true, solid); + ASM_UnVQ1_C1_TABLE(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + span = Span(test, 2, 4); + break; + + case 1: + Build_Pointers(test.Seed, entries, 2048, true, solid); + ASM_UnVQ1_C1_TABLE_ALT(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + span = Span(test, 2, 4); + break; + + case 2: + Build_Pointers(test.Seed, entries, 8192, false, solid); + ASM_UnVQ_4x2(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + span = Span(test, 1, 2); + break; + + case 3: + Build_Pointers(test.Seed, entries, 4096, false, solid); + ASM_UnVQ_4x4(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + span = Span(test, 1, 4); + break; + + case 4: + Build_Pointers(test.Seed, entries, 4096, false, solid); + ASM_UnVQ_4x4_HALF(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + span = Span(test, 1, 2); + break; + + default: + Build_Pointers(test.Seed, entries, 2048, true, solid); + ASM_UnVQ1_C1_4x4(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + span = Span(test, 2, 4); + break; + } + + unsigned long long const hash = Hash(DestStore, span); + + if (hash != test.Hash) { + std::printf("FAILED decoder %d blocks %lu rows %lu width %lu: expected %llu, got %llu\n", + test.Which, test.BlocksPerRow, test.NumRows, test.BufWidth, test.Hash, hash); + Failures++; + } + + Checked++; + } + + std::printf("%-52s %s\n", "UnVQ block decode matches the recorded assembly", Failures == 0 ? "ok" : "FAILED"); + std::printf("checked %d cases, %d mismatches\n", Checked, Failures); + + return(Failures == 0 ? 0 : 1); +} From bc682d2ba08a4e5591ab48853d75ff161b981445 Mon Sep 17 00:00:00 2001 From: Jakub Vesely <1251980+tinix0@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:03:56 +0200 Subject: [PATCH 2/4] Cleanup VQ method naming --- code/unvqdec.cpp | 58 ++++-------------------------------- code/vqa.cpp | 6 ++-- code/vqalib/drawer.cpp | 8 ++--- code/vqalib/unvq.h | 12 ++++---- tests/unvqdec/unvqparity.cpp | 12 ++++---- 5 files changed, 25 insertions(+), 71 deletions(-) diff --git a/code/unvqdec.cpp b/code/unvqdec.cpp index 9e2ceba7a..11e359e50 100644 --- a/code/unvqdec.cpp +++ b/code/unvqdec.cpp @@ -10,41 +10,12 @@ * EA's GPLv3 Section 7 additional terms and supplemental warranty * disclaimers apply; see LICENSE.md. ******************************************************************************/ - -/**************************************************************************** -* -* File : unvq_asm.asm -* Description : VQA UnVQ1 full-frame decoders, drawing a VQ compressed -* video frame into a pixel buffer. -* -****************************************************************************/ - #include "always.h" #include "vqalib/unvq.h" #include "_vqa.h" -/* - * Six full-frame decoders, each replacing an assembly routine of the same name. They share a - * shape: a frame is a grid of blocks, and every block carries a pointer into the codebook. - * - * The pointers arrive as two planes rather than as pairs -- every block's low byte first, then - * every block's high byte -- so a block's codebook index is assembled from the two. - * - * A block is either a codebook entry copied out, or a single colour filling the whole block. - * The two families differ in how they say which: an 8 bit frame marks a solid block with a - * high byte of 0xFF and takes the colour from the low byte, while a 16 bit frame marks it with - * the top bit and takes the remaining 15 as the colour. Of the 16 bit decoders, the two named - * TABLE run that colour through HicolorTable; ASM_UnVQ1_C1_4x4 uses it as the pixel directly. - * - * Names carry the block size the codebook holds, not always the size written: 4x4_HALF reads a - * 4x4 entry and writes every other pixel of every other row, and TABLE_ALT reads a 4x4 entry - * and writes its first and third rows two screen rows apart. - */ - -namespace { - /// /// Assembles one block's codebook index from the two pointer planes. /// @@ -76,20 +47,6 @@ inline void Fill32(unsigned char * dest, unsigned int value) } -inline void Put16(unsigned char * dest, unsigned char const * source) -{ - dest[0] = source[0]; - dest[1] = source[1]; -} - - -inline void Fill16(unsigned char * dest, unsigned int value) -{ - dest[0] = (unsigned char)(value & 0xFF); - dest[1] = (unsigned char)((value >> 8) & 0xFF); -} - - /* * Spreads a 16 bit pixel across a doubleword so a solid block is filled four bytes at a time, * the way the assembly did it. @@ -106,9 +63,6 @@ inline unsigned int Quad8(unsigned int colour) return((pair << 16) | pair); } -} // namespace - - /// /// Draws a 16 bit frame from 4x4 codebook entries, taking a solid block's colour from /// HicolorTable. @@ -119,7 +73,7 @@ inline unsigned int Quad8(unsigned int colour) /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl ASM_UnVQ1_C1_TABLE(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, +void __cdecl UnVQ1_C1_TABLE(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) { if (blocksperrow == 0) { @@ -174,7 +128,7 @@ void __cdecl ASM_UnVQ1_C1_TABLE(unsigned char * codebook, unsigned char * pointe /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl ASM_UnVQ1_C1_TABLE_ALT(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, +void __cdecl UnVQ1_C1_TABLE_ALT(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) { if (blocksperrow == 0) { @@ -228,7 +182,7 @@ void __cdecl ASM_UnVQ1_C1_TABLE_ALT(unsigned char * codebook, unsigned char * po /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl ASM_UnVQ_4x2(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, +void __cdecl UnVQ_4x2(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) { if (blocksperrow == 0) { @@ -277,7 +231,7 @@ void __cdecl ASM_UnVQ_4x2(unsigned char * codebook, unsigned char * pointers, un /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl ASM_UnVQ_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, +void __cdecl UnVQ_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) { if (blocksperrow == 0) { @@ -329,7 +283,7 @@ void __cdecl ASM_UnVQ_4x4(unsigned char * codebook, unsigned char * pointers, un /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl ASM_UnVQ_4x4_HALF(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, +void __cdecl UnVQ_4x4_HALF(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) { if (blocksperrow == 0) { @@ -383,7 +337,7 @@ void __cdecl ASM_UnVQ_4x4_HALF(unsigned char * codebook, unsigned char * pointer /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl ASM_UnVQ1_C1_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, +void __cdecl UnVQ1_C1_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) { if (blocksperrow == 0) { diff --git a/code/vqa.cpp b/code/vqa.cpp index dd2672372..b1ec53c51 100644 --- a/code/vqa.cpp +++ b/code/vqa.cpp @@ -495,9 +495,9 @@ int VQAClass::Play_VQA(int last_frame_to_play, bool nobreakout) if (cmode == 1) { Hicolor_Init_Table(PrimaryColorMode); if (Get_Option(OPTION_ALTERNATE_UNVQ)) { - VQA_SetUnVQ(Handle, ASM_UnVQ1_C1_TABLE_ALT, UnVQ2_4x2_Table); + VQA_SetUnVQ(Handle, UnVQ1_C1_TABLE_ALT, UnVQ2_4x2_Table); } else { - VQA_SetUnVQ(Handle, ASM_UnVQ1_C1_TABLE, UnVQ2_4x4_Table); + VQA_SetUnVQ(Handle, UnVQ1_C1_TABLE, UnVQ2_4x4_Table); } } else if (cmode == 4) { Hicolor_Init_Table(PrimaryColorMode); @@ -629,7 +629,7 @@ bool VQAClass::Advance_Frame(bool & finished) if (cmode == 1 || cmode == 4) { Hicolor_Init_Table(PrimaryColorMode); if (cmode == 1) { - VQA_SetUnVQ(Handle, ASM_UnVQ1_C1_TABLE, UnVQ2_4x4_Table); + VQA_SetUnVQ(Handle, UnVQ1_C1_TABLE, UnVQ2_4x4_Table); } } } diff --git a/code/vqalib/drawer.cpp b/code/vqalib/drawer.cpp index 6ad5564d0..b65e0f35b 100644 --- a/code/vqalib/drawer.cpp +++ b/code/vqalib/drawer.cpp @@ -185,7 +185,7 @@ long VQA_Configure_Drawer(VQAHandleP *vqap) case BLOCK_4X2: switch (header->ColorMode) { case 0: - vqap->UnVQ1 = ASM_UnVQ_4x2; + vqap->UnVQ1 = UnVQ_4x2; if (header->Flags & VQAHDF_TRANS) { if (vqap->Config.DrawFlags & VQACFGF_NOTRANS) { @@ -214,12 +214,12 @@ long VQA_Configure_Drawer(VQAHandleP *vqap) break; case 1: - vqap->UnVQ1 = ASM_UnVQ1_C1_4x4; + vqap->UnVQ1 = UnVQ1_C1_4x4; vqap->UnVQ2 = UnVQ2_C1_4x4; break; case 0: - vqap->UnVQ1 = ASM_UnVQ_4x4; + vqap->UnVQ1 = UnVQ_4x4; if (header->Flags & VQAHDF_TRANS) { if (vqap->Config.DrawFlags & VQACFGF_NOTRANS) { @@ -231,7 +231,7 @@ long VQA_Configure_Drawer(VQAHandleP *vqap) } } else { if (vqap->Config.DrawFlags & VQACFGF_HALFSIZE) { - vqap->UnVQ1 = ASM_UnVQ_4x4_HALF; + vqap->UnVQ1 = UnVQ_4x4_HALF; } } break; diff --git a/code/vqalib/unvq.h b/code/vqalib/unvq.h index d4acfe73c..69e6012b1 100644 --- a/code/vqalib/unvq.h +++ b/code/vqalib/unvq.h @@ -84,27 +84,27 @@ void __cdecl UnVQ2_C0_4x2_KEY(unsigned char *codebook, unsigned char *pointers, #ifdef __cplusplus extern "C" { #endif -void __cdecl ASM_UnVQ1_C1_TABLE(unsigned char *codebook, unsigned char *pointers, +void __cdecl UnVQ1_C1_TABLE(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl ASM_UnVQ1_C1_TABLE_ALT(unsigned char *codebook, unsigned char *pointers, +void __cdecl UnVQ1_C1_TABLE_ALT(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl ASM_UnVQ_4x2(unsigned char *codebook, unsigned char *pointers, +void __cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl ASM_UnVQ_4x4(unsigned char *codebook, unsigned char *pointers, +void __cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl ASM_UnVQ_4x4_HALF(unsigned char *codebook, unsigned char *pointers, +void __cdecl UnVQ_4x4_HALF(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl ASM_UnVQ1_C1_4x4(unsigned char *codebook, unsigned char *pointers, +void __cdecl UnVQ1_C1_4x4(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); diff --git a/tests/unvqdec/unvqparity.cpp b/tests/unvqdec/unvqparity.cpp index 673733895..fd8d08331 100644 --- a/tests/unvqdec/unvqparity.cpp +++ b/tests/unvqdec/unvqparity.cpp @@ -119,37 +119,37 @@ int main(void) switch (test.Which) { case 0: Build_Pointers(test.Seed, entries, 2048, true, solid); - ASM_UnVQ1_C1_TABLE(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + UnVQ1_C1_TABLE(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); span = Span(test, 2, 4); break; case 1: Build_Pointers(test.Seed, entries, 2048, true, solid); - ASM_UnVQ1_C1_TABLE_ALT(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + UnVQ1_C1_TABLE_ALT(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); span = Span(test, 2, 4); break; case 2: Build_Pointers(test.Seed, entries, 8192, false, solid); - ASM_UnVQ_4x2(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + UnVQ_4x2(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); span = Span(test, 1, 2); break; case 3: Build_Pointers(test.Seed, entries, 4096, false, solid); - ASM_UnVQ_4x4(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + UnVQ_4x4(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); span = Span(test, 1, 4); break; case 4: Build_Pointers(test.Seed, entries, 4096, false, solid); - ASM_UnVQ_4x4_HALF(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + UnVQ_4x4_HALF(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); span = Span(test, 1, 2); break; default: Build_Pointers(test.Seed, entries, 2048, true, solid); - ASM_UnVQ1_C1_4x4(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); + UnVQ1_C1_4x4(Codebook, Pointers, DestStore, test.BlocksPerRow, test.NumRows, test.BufWidth); span = Span(test, 2, 4); break; } From 8a8ba73c635d7f33f5e0ab94900a00c56c572151 Mon Sep 17 00:00:00 2001 From: Jakub Vesely <1251980+tinix0@users.noreply.github.com> Date: Wed, 2 Sep 2026 08:17:27 +0200 Subject: [PATCH 3/4] Widen the VQ decoder interface to uint8_t and size_t --- code/unvqdec.cpp | 189 +++++++++++++++++++---------------------- code/unvqtblc.cpp | 9 +- code/unvqtblc.h | 11 ++- code/vqalib/drawer.cpp | 12 +-- code/vqalib/task.cpp | 6 +- code/vqalib/unvq.cpp | 20 ++--- code/vqalib/unvq.h | 99 ++++++++++----------- code/vqalib/vqaplay.h | 5 +- 8 files changed, 173 insertions(+), 178 deletions(-) diff --git a/code/unvqdec.cpp b/code/unvqdec.cpp index 11e359e50..e72768eca 100644 --- a/code/unvqdec.cpp +++ b/code/unvqdec.cpp @@ -13,6 +13,8 @@ #include "always.h" #include "vqalib/unvq.h" +#include +#include #include "_vqa.h" @@ -22,28 +24,17 @@ /// Base of the pointer data. /// Total block count, which is where the high plane starts. /// Which block to read. -/// unsigned int; The codebook index. -inline unsigned int Block_Index(unsigned char const * pointers, unsigned long entries, unsigned long block) +/// uint32_t; The codebook index. +inline uint32_t Block_Index(uint8_t const * pointers, size_t entries, size_t block) { - return(((unsigned int)pointers[entries + block] << 8) | (unsigned int)pointers[block]); + return((static_cast(pointers[entries + block]) << 8) | static_cast(pointers[block])); } -inline void Put32(unsigned char * dest, unsigned char const * source) +inline void Fill32(uint8_t * dest, uint32_t value) { - dest[0] = source[0]; - dest[1] = source[1]; - dest[2] = source[2]; - dest[3] = source[3]; -} - - -inline void Fill32(unsigned char * dest, unsigned int value) -{ - dest[0] = (unsigned char)(value & 0xFF); - dest[1] = (unsigned char)((value >> 8) & 0xFF); - dest[2] = (unsigned char)((value >> 16) & 0xFF); - dest[3] = (unsigned char)((value >> 24) & 0xFF); + // memcpy folds to one store where MSVC won't optimize a byte-wise copy; assumes a little-endian host. + std::memcpy(dest, reinterpret_cast(&value), 4); } @@ -51,15 +42,15 @@ inline void Fill32(unsigned char * dest, unsigned int value) * Spreads a 16 bit pixel across a doubleword so a solid block is filled four bytes at a time, * the way the assembly did it. */ -inline unsigned int Pair16(unsigned int pixel) +inline uint32_t Pair16(uint16_t pixel) { - return((pixel << 16) | pixel); + return((static_cast(pixel) << 16) | pixel); } -inline unsigned int Quad8(unsigned int colour) +inline uint32_t Quad8(uint8_t colour) { - unsigned int const pair = (colour << 8) | colour; + uint32_t const pair = (static_cast(colour) << 8) | colour; return((pair << 16) | pair); } @@ -73,40 +64,39 @@ inline unsigned int Quad8(unsigned int colour) /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl UnVQ1_C1_TABLE(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, - unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_C1_TABLE(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, + size_t blocksperrow, size_t numrows, size_t bufwidth) { if (blocksperrow == 0) { return; } - unsigned long const pitch = bufwidth * 2; - unsigned long const rowoffset = pitch * 4; - unsigned long const entries = numrows * blocksperrow; + size_t const pitch = bufwidth * 2; + size_t const rowoffset = pitch * 4; + size_t const entries = numrows * blocksperrow; - unsigned char * rowstart = buffer; - unsigned long block = 0; + uint8_t * rowstart = buffer; + size_t block = 0; do { - unsigned char * dest = rowstart; + uint8_t * dest = rowstart; - for (unsigned long i = 0; i < blocksperrow; i++) { - unsigned int const index = Block_Index(pointers, entries, block); + for (size_t i = 0; i < blocksperrow; i++) { + uint32_t const index = Block_Index(pointers, entries, block); block++; if ((index & 0x8000) != 0) { - unsigned int const pixels = Pair16(HicolorTable[index & 0x7FFF]); + uint32_t const pixels = Pair16(HicolorTable[index & 0x7FFF]); for (int row = 0; row < 4; row++) { Fill32(dest + row * pitch, pixels); Fill32(dest + row * pitch + 4, pixels); } } else { - unsigned char const * word = codebook + index * 32; + uint8_t const * word = codebook + index * 32; for (int row = 0; row < 4; row++) { - Put32(dest + row * pitch, word + row * 8); - Put32(dest + row * pitch + 4, word + row * 8 + 4); + std::memcpy(dest + row * pitch, word + row * 8, 8); } } @@ -128,41 +118,39 @@ void __cdecl UnVQ1_C1_TABLE(unsigned char * codebook, unsigned char * pointers, /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl UnVQ1_C1_TABLE_ALT(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, - unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_C1_TABLE_ALT(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, + size_t blocksperrow, size_t numrows, size_t bufwidth) { if (blocksperrow == 0) { return; } - unsigned long const pitch = bufwidth * 2; - unsigned long const rowoffset = pitch * 4; - unsigned long const entries = numrows * blocksperrow; + size_t const pitch = bufwidth * 2; + size_t const rowoffset = pitch * 4; + size_t const entries = numrows * blocksperrow; - unsigned char * rowstart = buffer; - unsigned long block = 0; + uint8_t * rowstart = buffer; + size_t block = 0; do { - unsigned char * dest = rowstart; + uint8_t * dest = rowstart; - for (unsigned long i = 0; i < blocksperrow; i++) { - unsigned int const index = Block_Index(pointers, entries, block); + for (size_t i = 0; i < blocksperrow; i++) { + uint32_t const index = Block_Index(pointers, entries, block); block++; if ((index & 0x8000) != 0) { - unsigned int const pixels = Pair16(HicolorTable[index & 0x7FFF]); + uint32_t const pixels = Pair16(HicolorTable[index & 0x7FFF]); Fill32(dest, pixels); Fill32(dest + 4, pixels); Fill32(dest + pitch * 2, pixels); Fill32(dest + pitch * 2 + 4, pixels); } else { - unsigned char const * word = codebook + index * 32; + uint8_t const * word = codebook + index * 32; - Put32(dest, word); - Put32(dest + 4, word + 4); - Put32(dest + pitch * 2, word + 16); - Put32(dest + pitch * 2 + 4, word + 20); + std::memcpy(dest, word, 8); + std::memcpy(dest + pitch * 2, word + 16, 8); } dest += 8; @@ -182,36 +170,36 @@ void __cdecl UnVQ1_C1_TABLE_ALT(unsigned char * codebook, unsigned char * pointe /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl UnVQ_4x2(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, - unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ_4x2(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, + size_t blocksperrow, size_t numrows, size_t bufwidth) { if (blocksperrow == 0) { return; } - unsigned long const rowoffset = bufwidth * 2; - unsigned long const entries = numrows * blocksperrow; + size_t const rowoffset = bufwidth * 2; + size_t const entries = numrows * blocksperrow; - unsigned char * rowstart = buffer; - unsigned long block = 0; + uint8_t * rowstart = buffer; + size_t block = 0; do { - unsigned char * dest = rowstart; + uint8_t * dest = rowstart; - for (unsigned long i = 0; i < blocksperrow; i++) { - unsigned int const index = Block_Index(pointers, entries, block); + for (size_t i = 0; i < blocksperrow; i++) { + uint32_t const index = Block_Index(pointers, entries, block); block++; if ((index >> 8) == 0xFF) { - unsigned int const pixels = Quad8(index & 0xFF); + uint32_t const pixels = Quad8(index & 0xFF); Fill32(dest, pixels); Fill32(dest + bufwidth, pixels); } else { - unsigned char const * word = codebook + index * 8; + uint8_t const * word = codebook + index * 8; - Put32(dest, word); - Put32(dest + bufwidth, word + 4); + std::memcpy(dest, word, 4); + std::memcpy(dest + bufwidth, word + 4, 4); } dest += 4; @@ -231,37 +219,37 @@ void __cdecl UnVQ_4x2(unsigned char * codebook, unsigned char * pointers, unsign /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl UnVQ_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, - unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ_4x4(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, + size_t blocksperrow, size_t numrows, size_t bufwidth) { if (blocksperrow == 0) { return; } - unsigned long const rowoffset = bufwidth * 4; - unsigned long const entries = numrows * blocksperrow; + size_t const rowoffset = bufwidth * 4; + size_t const entries = numrows * blocksperrow; - unsigned char * rowstart = buffer; - unsigned long block = 0; + uint8_t * rowstart = buffer; + size_t block = 0; do { - unsigned char * dest = rowstart; + uint8_t * dest = rowstart; - for (unsigned long i = 0; i < blocksperrow; i++) { - unsigned int const index = Block_Index(pointers, entries, block); + for (size_t i = 0; i < blocksperrow; i++) { + uint32_t const index = Block_Index(pointers, entries, block); block++; if ((index >> 8) == 0xFF) { - unsigned int const pixels = Quad8(index & 0xFF); + uint32_t const pixels = Quad8(index & 0xFF); for (int row = 0; row < 4; row++) { Fill32(dest + row * bufwidth, pixels); } } else { - unsigned char const * word = codebook + index * 16; + uint8_t const * word = codebook + index * 16; for (int row = 0; row < 4; row++) { - Put32(dest + row * bufwidth, word + row * 4); + std::memcpy(dest + row * bufwidth, word + row * 4, 4); } } @@ -283,35 +271,35 @@ void __cdecl UnVQ_4x4(unsigned char * codebook, unsigned char * pointers, unsign /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl UnVQ_4x4_HALF(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, - unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ_4x4_HALF(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, + size_t blocksperrow, size_t numrows, size_t bufwidth) { if (blocksperrow == 0) { return; } - unsigned long const rowoffset = bufwidth * 2; - unsigned long const entries = numrows * blocksperrow; + size_t const rowoffset = bufwidth * 2; + size_t const entries = numrows * blocksperrow; - unsigned char * rowstart = buffer; - unsigned long block = 0; + uint8_t * rowstart = buffer; + size_t block = 0; do { - unsigned char * dest = rowstart; + uint8_t * dest = rowstart; - for (unsigned long i = 0; i < blocksperrow; i++) { - unsigned int const index = Block_Index(pointers, entries, block); + for (size_t i = 0; i < blocksperrow; i++) { + uint32_t const index = Block_Index(pointers, entries, block); block++; if ((index >> 8) == 0xFF) { - unsigned char const colour = (unsigned char)(index & 0xFF); + uint8_t const colour = static_cast(index & 0xFF); dest[0] = colour; dest[1] = colour; dest[bufwidth] = colour; dest[bufwidth + 1] = colour; } else { - unsigned char const * word = codebook + index * 16; + uint8_t const * word = codebook + index * 16; dest[0] = word[0]; dest[1] = word[2]; @@ -337,40 +325,39 @@ void __cdecl UnVQ_4x4_HALF(unsigned char * codebook, unsigned char * pointers, u /// Blocks across one row of the frame. /// Rows of blocks in the frame. /// Destination width in pixels. -void __cdecl UnVQ1_C1_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, - unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_C1_4x4(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, + size_t blocksperrow, size_t numrows, size_t bufwidth) { if (blocksperrow == 0) { return; } - unsigned long const pitch = bufwidth * 2; - unsigned long const rowoffset = pitch * 4; - unsigned long const entries = numrows * blocksperrow; + size_t const pitch = bufwidth * 2; + size_t const rowoffset = pitch * 4; + size_t const entries = numrows * blocksperrow; - unsigned char * rowstart = buffer; - unsigned long block = 0; + uint8_t * rowstart = buffer; + size_t block = 0; do { - unsigned char * dest = rowstart; + uint8_t * dest = rowstart; - for (unsigned long i = 0; i < blocksperrow; i++) { - unsigned int const index = Block_Index(pointers, entries, block); + for (size_t i = 0; i < blocksperrow; i++) { + uint32_t const index = Block_Index(pointers, entries, block); block++; if ((index & 0x8000) != 0) { - unsigned int const pixels = Pair16(index & 0x7FFF); + uint32_t const pixels = Pair16(index & 0x7FFF); for (int row = 0; row < 4; row++) { Fill32(dest + row * pitch, pixels); Fill32(dest + row * pitch + 4, pixels); } } else { - unsigned char const * word = codebook + index * 32; + uint8_t const * word = codebook + index * 32; for (int row = 0; row < 4; row++) { - Put32(dest + row * pitch, word + row * 8); - Put32(dest + row * pitch + 4, word + row * 8 + 4); + std::memcpy(dest + row * pitch, word + row * 8, 8); } } diff --git a/code/unvqtblc.cpp b/code/unvqtblc.cpp index 29e45f33e..fbaa28135 100644 --- a/code/unvqtblc.cpp +++ b/code/unvqtblc.cpp @@ -110,8 +110,7 @@ static inline void memset32(void * D, unsigned int val, unsigned int n) for (i = 0; i < n; i++) dst[i] = val; } - -void __cdecl UnVQ2_4x4_Table(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_4x4_Table(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { assert(HicolorTable != 0); assert(codebook != 0); @@ -298,7 +297,7 @@ void __cdecl UnVQ2_4x4_Table(unsigned char * codebook, unsigned char * pointers, } -void __cdecl UnVQ2_4x2_Table(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_4x2_Table(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { assert(HicolorTable != 0); assert(codebook != 0); @@ -481,7 +480,7 @@ void __cdecl UnVQ2_4x2_Table(unsigned char * codebook, unsigned char * pointers, #define __int16 short #define __int32 long -void __cdecl UnVQ1_4x4_Table(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_4x4_Table(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { assert(codebook != 0); assert(pointers != 0); @@ -568,7 +567,7 @@ void __cdecl UnVQ1_4x4_Table(unsigned char * codebook, unsigned char * pointers, } -void __cdecl UnVQ1_4x2_Table(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_4x2_Table(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { assert(codebook != 0); assert(pointers != 0); diff --git a/code/unvqtblc.h b/code/unvqtblc.h index 2d889b01d..6e9fc5646 100644 --- a/code/unvqtblc.h +++ b/code/unvqtblc.h @@ -9,12 +9,15 @@ #pragma once +#include +#include + bool Hicolor_Init_Table(int cmode); void Hicolor_Clear_Table(void); void Hicolor_Translate(void *buffer, int size); -void __cdecl UnVQ2_4x4_Table(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl UnVQ2_4x2_Table(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_4x4_Table(uint8_t *codebook, uint8_t *pointers, uint8_t *buffer, size_t blocksperrow, size_t numrows, size_t bufwidth); +void __cdecl UnVQ2_4x2_Table(uint8_t *codebook, uint8_t *pointers, uint8_t *buffer, size_t blocksperrow, size_t numrows, size_t bufwidth); -void __cdecl UnVQ1_4x4_Table(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); -void __cdecl UnVQ1_4x2_Table(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ1_4x4_Table(uint8_t *codebook, uint8_t *pointers, uint8_t *buffer, size_t blocksperrow, size_t numrows, size_t bufwidth); +void __cdecl UnVQ1_4x2_Table(uint8_t *codebook, uint8_t *pointers, uint8_t *buffer, size_t blocksperrow, size_t numrows, size_t bufwidth); diff --git a/code/vqalib/drawer.cpp b/code/vqalib/drawer.cpp index b65e0f35b..6264750f7 100644 --- a/code/vqalib/drawer.cpp +++ b/code/vqalib/drawer.cpp @@ -82,7 +82,7 @@ long PageFlip_MCGABuf(VQAHandle *vqa); long DrawFrame_MCGA(VQAHandle *vqa); long PageFlip_MCGA(VQAHandle *vqa); -void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ_Nop(uint8_t *codebook, uint8_t *pointers, uint8_t *buffer, size_t blocksperrow, size_t numrows, size_t bufwidth); long PageFlip_Nop(VQAHandle *vqa); void VQA_SetTimer(VQAHandleP *vqap, long time); @@ -1187,8 +1187,8 @@ STATIC long PageFlip_MCGABuf(VQAHandle *vqa) * SYNOPSIS * UnVQ_Nop(Codebook, Pointers, Buffer, BPR, Rows, BufWidth) * -* void UnVQ_Nop(unsigned char *, unsigned char *, unsigned char *, -* unsigned long, unsigned long, unsigned long); +* void UnVQ_Nop(uint8_t *, uint8_t *, uint8_t *, +* size_t, size_t, size_t); * FUNCTION * * INPUTS @@ -1204,9 +1204,9 @@ STATIC long PageFlip_MCGABuf(VQAHandle *vqa) * ****************************************************************************/ -STATIC void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth) +STATIC void __cdecl UnVQ_Nop(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth) { /* Suppress compiler warnings */ codebook = codebook; diff --git a/code/vqalib/task.cpp b/code/vqalib/task.cpp index 6cdc73919..73bf4cbb0 100644 --- a/code/vqalib/task.cpp +++ b/code/vqalib/task.cpp @@ -103,9 +103,9 @@ long __cdecl Disk_VQA_Stream_Handler(VQAHandle *vqa, long action, void *buffer, long VQA_LargestLoop(VQAHandleP *vqap, long); -extern void __cdecl UnVQ_Nop(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +extern void __cdecl UnVQ_Nop(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); /**************************************************************************** * diff --git a/code/vqalib/unvq.cpp b/code/vqalib/unvq.cpp index f218874ef..2ecc99fb4 100644 --- a/code/vqalib/unvq.cpp +++ b/code/vqalib/unvq.cpp @@ -21,7 +21,7 @@ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; -void __cdecl UnVQ2_C1_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C1_4x4(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { bufwidth *= 2u; uint32_t block_row_stride = bufwidth * 4u; @@ -287,7 +287,7 @@ void __cdecl UnVQ2_C1_4x4(unsigned char * codebook, unsigned char * pointers, un } -void __cdecl UnVQ1_C4_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_C4_4x4(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { bufwidth *= 2u; uint32_t block_row_stride = bufwidth * 4u; @@ -383,7 +383,7 @@ void __cdecl UnVQ1_C4_4x4(unsigned char * codebook, unsigned char * pointers, un } -void __cdecl UnVQ2_C4_4x4(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C4_4x4(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { bufwidth *= 2u; uint32_t block_row_stride = bufwidth * 4u; @@ -619,7 +619,7 @@ void __cdecl UnVQ2_C4_4x4(unsigned char * codebook, unsigned char * pointers, un } -void __cdecl UnVQ1_C4_4x2(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ1_C4_4x2(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { bufwidth *= 2u; uint32_t block_row_stride = bufwidth * 2u; @@ -715,7 +715,7 @@ void __cdecl UnVQ1_C4_4x2(unsigned char * codebook, unsigned char * pointers, un } -void __cdecl UnVQ2_C4_4x2(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C4_4x2(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { bufwidth *= 2u; uint32_t block_row_stride = bufwidth * 2u; @@ -952,7 +952,7 @@ void __cdecl UnVQ2_C4_4x2(unsigned char * codebook, unsigned char * pointers, un } -void __cdecl UnVQ2_C0_4x4_TRANS(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C0_4x4_TRANS(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { uint8_t * dst = (uint8_t *)buffer; uint8_t * row_base = (uint8_t *)buffer; @@ -1218,7 +1218,7 @@ void __cdecl UnVQ2_C0_4x4_TRANS(unsigned char * codebook, unsigned char * pointe } -void __cdecl UnVQ2_C0_4x4_KEY(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C0_4x4_KEY(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { uint8_t * dst = (uint8_t *)buffer; uint8_t * row_base = (uint8_t *)buffer; @@ -1470,7 +1470,7 @@ void __cdecl UnVQ2_C0_4x4_KEY(unsigned char * codebook, unsigned char * pointers } -void __cdecl UnVQ2_C0_4x4_TRANS_HALF(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C0_4x4_TRANS_HALF(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { uint8_t * dst = (uint8_t *)buffer; uint8_t * row_base = (uint8_t *)buffer; @@ -1738,7 +1738,7 @@ void __cdecl UnVQ2_C0_4x4_TRANS_HALF(unsigned char * codebook, unsigned char * p } -void __cdecl UnVQ2_C0_4x2_TRANS(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C0_4x2_TRANS(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { uint8_t * dst = (uint8_t *)buffer; uint16_t * src = (uint16_t *)pointers; @@ -2006,7 +2006,7 @@ void __cdecl UnVQ2_C0_4x2_TRANS(unsigned char * codebook, unsigned char * pointe } -void __cdecl UnVQ2_C0_4x2_KEY(unsigned char * codebook, unsigned char * pointers, unsigned char * buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth) +void __cdecl UnVQ2_C0_4x2_KEY(uint8_t * codebook, uint8_t * pointers, uint8_t * buffer, size_t blocksperrow, size_t numrows, size_t bufwidth) { uint8_t * dst = (uint8_t *)buffer; uint8_t * row_base = (uint8_t *)buffer; diff --git a/code/vqalib/unvq.h b/code/vqalib/unvq.h index 69e6012b1..981720dea 100644 --- a/code/vqalib/unvq.h +++ b/code/vqalib/unvq.h @@ -13,6 +13,9 @@ #ifndef VQAUNVQ_H #define VQAUNVQ_H + +#include +#include /**************************************************************************** * * C O N F I D E N T I A L -- W E S T W O O D S T U D I O S @@ -40,73 +43,73 @@ * FUNCTION PROTOTYPES *-------------------------------------------------------------------------*/ -void __cdecl UnVQ2_C1_4x4(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C1_4x4(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ1_C4_4x4(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ1_C4_4x4(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C4_4x4(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C4_4x4(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ1_C4_4x2(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ1_C4_4x2(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C4_4x2(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C4_4x2(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C0_4x4_TRANS(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C0_4x4_TRANS(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C0_4x4_KEY(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C0_4x4_KEY(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C0_4x4_TRANS_HALF(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C0_4x4_TRANS_HALF(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C0_4x2_TRANS(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C0_4x2_TRANS(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ2_C0_4x2_KEY(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ2_C0_4x2_KEY(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); #ifdef __cplusplus extern "C" { #endif -void __cdecl UnVQ1_C1_TABLE(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ1_C1_TABLE(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ1_C1_TABLE_ALT(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ1_C1_TABLE_ALT(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ_4x2(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ_4x2(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ_4x4(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ_4x4(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ_4x4_HALF(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ_4x4_HALF(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); -void __cdecl UnVQ1_C1_4x4(unsigned char *codebook, unsigned char *pointers, - unsigned char *buffer, unsigned long blocksperrow, - unsigned long numrows, unsigned long bufwidth); +void __cdecl UnVQ1_C1_4x4(uint8_t *codebook, uint8_t *pointers, + uint8_t *buffer, size_t blocksperrow, + size_t numrows, size_t bufwidth); #ifdef __cplusplus } diff --git a/code/vqalib/vqaplay.h b/code/vqalib/vqaplay.h index 7fe06ad73..2204872cf 100644 --- a/code/vqalib/vqaplay.h +++ b/code/vqalib/vqaplay.h @@ -13,6 +13,9 @@ #ifndef VQAPLAY_H #define VQAPLAY_H + +#include +#include /**************************************************************************** * * C O N F I D E N T I A L -- W E S T W O O D S T U D I O S @@ -158,7 +161,7 @@ class VQAClass; typedef struct _VQAHandle VQAHandle; // UnVQ functions must be this type -typedef void (__cdecl *UNVQ_FUNC)(unsigned char *codebook, unsigned char *pointers, unsigned char *buffer, unsigned long blocksperrow, unsigned long numrows, unsigned long bufwidth); +typedef void (__cdecl *UNVQ_FUNC)(uint8_t *codebook, uint8_t *pointers, uint8_t *buffer, size_t blocksperrow, size_t numrows, size_t bufwidth); // Handlers must be this type typedef long (__cdecl *VQA_H_FUNC)(VQAHandle *vqa, long action, void *buffer, long nbytes); From a5ca474dea7bd98e58072d8e7c5fab50bc3e5d06 Mon Sep 17 00:00:00 2001 From: Jakub Vesely <1251980+tinix0@users.noreply.github.com> Date: Thu, 3 Sep 2026 18:48:33 +0200 Subject: [PATCH 4/4] Formatting cleanup --- code/unvqdec.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/unvqdec.cpp b/code/unvqdec.cpp index e72768eca..38f36b9f3 100644 --- a/code/unvqdec.cpp +++ b/code/unvqdec.cpp @@ -10,13 +10,14 @@ * EA's GPLv3 Section 7 additional terms and supplemental warranty * disclaimers apply; see LICENSE.md. ******************************************************************************/ + #include "always.h" +#include "_vqa.h" #include "vqalib/unvq.h" -#include -#include -#include "_vqa.h" +#include +#include /// /// Assembles one block's codebook index from the two pointer planes.