{ Hi Kai. I read your message about 360x256x256 and saw you were using Tweak. This is message 1/2 which includes Pascal versions of Twkuser.c and Tweak2c. Thought they might be helpful to you. Maurice L. Marvin maurice@cs.pdx.edu } {$I-} UNIT TWKUSER; {========================================================================= TWKUSER.PAS is a Borland Pascal 7.0 compatible unit for using Robert Schmidt's TWEAK generated files. Ported to Pascal from Robert Schmidt's original C code. Donated to public domain. Maurice L. Marvin maurice@cs.pdx.edu ==========================================================================} INTERFACE CONST { xxxxADDR defines the base port number used to access VGA component xxxx, and is defined for xxxx = ATTRCON - Attribute Controller MISC - Miscellaneous Register VGAENABLE - VGA Enable Register SEQ - Sequencer GRACON - Graphics Controller CRTC - Cathode Ray Tube Controller STATUS - Status Register } ATTRCON_ADDR = $3C0; MISC_ADDR = $3C2; VGAENABLE_ADDR = $3C3; SEQ_ADDR = $3C4; GRACON_ADDR = $3CE; CRTC_ADDR = $3D4; STATUS_ADDR = $3DA; TYPE Register = RECORD port : WORD; index : BYTE; value : BYTE; END; RegisterPtr = ^Register; PROCEDURE ReadyVgaRegs; PROCEDURE OutReg(r : Register); PROCEDURE OutRegArray(r : RegisterPtr; n : INTEGER); FUNCTION LoadRegArray(fpath : STRING; VAR RegArray : RegisterPtr) : INTEGER; IMPLEMENTATION {-------------------------------------------------------------------------- ReadyVGARegs does the initialization to make the VGA ready to accept any combination of configuration register settings. This involves enabling writes to index 0 to 7 of the CRT controller (port $3d4), by clearing the most significant bit (bit 7) of index $11. --------------------------------------------------------------------------} PROCEDURE ReadyVGARegs; VAR v : BYTE; BEGIN {*** Begin procedure ReadyVGARegs ***} Port[$3d4] := $11; v := Port[$3d5] AND $7f; Port[$3d4] := $11; Port[$3d5] := v; END; {*** End procedure ReadyVGARegs ***} {-------------------------------------------------------------------------- OutReg sets a single register according to the contents of the passed Register structure. --------------------------------------------------------------------------} PROCEDURE OutReg(r : Register); VAR v : BYTE; BEGIN {*** Begin procedure OutReg ***} CASE (r.port) OF ATTRCON_ADDR : BEGIN v := Port[STATUS_ADDR]; { Reset read/write flip flop } Port[ATTRCON_ADDR] := r.index OR $20; { Ensure VGA output is enabled } Port[ATTRCON_ADDR] := r.value; END; MISC_ADDR, VGAENABLE_ADDR : BEGIN Port[r.port] := r.value; { Directly to the port } END; ELSE { Default method } BEGIN Port[r.port] := r.index; { Index to port } Port[r.port + 1] := r.value; { Value to port + 1} END; END; END; {*** End procedure OutReg ***} {-------------------------------------------------------------------------- OutRegArray sets n registers according to the array pointed to by r. First, indexes 0-7 of the CRT controller are enabled for writing. --------------------------------------------------------------------------} PROCEDURE OutRegArray(r : RegisterPtr; n : INTEGER); VAR s : WORD; BEGIN {*** Begin procedure OutRegArray ***} s := SizeOf(Register); ReadyVGARegs; WHILE (n > 0) DO BEGIN OutReg(r^); ASM { Increment pointer to next record } MOV DX,s ADD WORD PTR [r],DX END; DEC(n); END; END; {*** End procedure OutRegArray ***} {-------------------------------------------------------------------------- LoadRegArray opens the given file, does some validity checking, then reads the entire file into an array of Registers, which is returned via the RegArray parameter. You will probably want to provide your own error handling code in this function, as it never aborts the program, rather than just printing an error message and returning NULL. The returned value is the number of registers read. The RegArray parameter is set to the allocated register array. If you use this function, remember to dispose the returned array pointer, as it was allocated dynamically using GetMem (unless NULL is returned, which designates an error). --------------------------------------------------------------------------} FUNCTION LoadRegArray(fpath : STRING; VAR RegArray : RegisterPtr) : INTEGER; VAR handle : FILE; fsize : LONGINT; BEGIN {*** Begin function LoadRegArray ***} LoadRegArray := 0; RegArray := NIL; ASSIGN(handle,fpath); RESET(handle,1); IF (IOResult <> 0) THEN { error opening file ? } BEGIN { include error handling code here } Exit; END; fsize := FileSize(handle); IF (IOResult <> 0) THEN { error acquiring file size ? } BEGIN CLOSE(handle); Exit; END; IF (fsize MOD SizeOf(Register) <> 0) THEN { Is filesize multiple of record ? } BEGIN WriteLn('Illegal TWEAK file size: ',fpath); CLOSE(handle); Exit; END; IF (MaxAvail < fsize) THEN { Is there enough memory ? } BEGIN WriteLn('Out of memory allocating buffer for ',fpath); CLOSE(handle); Exit; END; GetMem(RegArray,fsize); BlockRead(handle,RegArray^,fsize); IF (IOResult <> 0) THEN { Error reading file ? } BEGIN CLOSE(handle); Dispose(RegArray); RegArray := NIL; Exit; END; CLOSE(handle); IF (IOResult <> 0) THEN { Error closing file ? } BEGIN Dispose(RegArray); RegArray := NIL; Exit; END; LoadRegArray := fsize DIV SizeOf(Register); END; {*** End function LoadRegArray ***} END. {$I-} PROGRAM TWEAK2P; USES TWKUSER; {========================================================================= TWEAK2P version 1.0 Ported to Pascal from Robert Schmidt's original C code. Converts a TWEAK version 1.0 file to an include-able Pascal file, defining the equivalent register array, which is passable to the OutRegArray function defined in the TWKUSER unit. Maurice L. Marvin maurice@cs.pdx.edu =========================================================================} VAR table : RegisterPtr; btable : RegisterPtr; regsize : INTEGER; handle : TEXT; b1 : BYTE; b2 : BYTE; s : WORD; BEGIN {*** Begin program TWEAK2P ***} { Check command line arguments. } IF (ParamCount < 3) THEN BEGIN WriteLn; WriteLn('TWEAK2P version 1.0'); WriteLn('Converts a TWEAK version 1.x file to an include-able Pascal file.'); WriteLn; WriteLn('SYNTAX: TWEAK2P '); WriteLn('All Parameters are required.'); Halt(1); END; { Load the register file. } regsize := LoadRegArray(ParamStr(1),table); { Save a pointer to the start of the table. The pointer 'table' will be corrupted due to pointer arithmetic. } btable := table; { Check if we loaded the table successfully. } IF (Table = NIL) THEN BEGIN WriteLn; WriteLn('ERROR : Unable to load register file.'); Halt(1); END; { Open the destination file. } ASSIGN(handle,ParamStr(2)); REWRITE(handle); IF (IOResult <> 0) THEN { Check if error creating file. } BEGIN WriteLn; WriteLn('ERROR : Unable to create destination file.'); Halt(1); END; { Write data structure } WriteLn(handle,'{ Tweaked include file generated by TWEAK2P } '); WriteLn(handle,''); WriteLn(handle,'CONST'); WriteLn(handle); Write(handle,' ',ParamStr(3),' : ARRAY[1..',RegSize); WriteLn(handle,'] OF Register = ('); Write(handle,' '); s := SizeOf(Register); { Write register values } WHILE (RegSize > 0) DO BEGIN Write(handle,'(Port : ',table^.port); Write(handle,'; Index : ',table^.index); Write(handle,'; Value : ',table^.value,')'); DEC(RegSize); IF (RegSize = 0) THEN WriteLn(handle,');') ELSE WriteLn(handle,','); ASM { move to next record } MOV DX,s ADD WORD PTR [table],DX END; Write(handle,' '); END; CLOSE(handle); Dispose(btable); END. {*** End program Tweak2P ***}