GVBE03: Code Addendum
  Home FAQ Contact Sign in
comp.lang.forth only
 
Advanced search
POPULAR GROUPS

more...

 Up
GVBE03: Code Addendum         

Group: comp.lang.forth · Group Profile
Author: Tim Trussell
Date: May 26, 2008 15:49

\ ---[ Code Addendum 02 ]-----------------------------[05/26/2008]---
\
\ For Graphics: VESA BIOS Extensions Part III
\
\ by Timothy Trussell
\
\ -------------------------------------------------------------------
\ This code is meant for use with the 32Forth system.
\ This is the DOS DPMI version of the compiler in Rick van Norman's
\ OS2FORTH.ZIP package, available on the Taygeta Scientific site at
\
\ ftp://ftp.taygeta.com/pub/Forth/Compilers/native/OS-2/
\ -------------------------------------------------------------------
\ Save as GVBE03.4th in your \os2forth\forth directory
\ -------------------------------------------------------------------

exists [GVBE03] [if]
forget [GVBE03]
[then]

: [GVBE03] ;

decimal

\ ---[Note]----------------------------------------------------------
\ This module requires the previous Code Addendum - GVBE02.4th
\ ------------------------------------------------------[End Note]---

include gvbe02.4th

\ ---[ Prototypes in GVBE02.4th ]------------------------------------

\ code AllocDOSMem ( -- 0/1 )
\ code FreeDOSMem ( -- )
\ code PokeDOSMem ( n offset -- )
\ code GetLowBuffer ( size &dst -- )
\ code IsVBE? ( -- 0/1 )
\ : VBEDetect ( -- 0/1 )

\ Demonstration code for GVBE02

\ : zprint ( &str -- )
\ : ShowInfo ( -- )

\ ---[ Prototypes in GVBE03.4th ]------------------------------------

\ code GetVBEModeInfo ( mode -- 0/1 )
\ : VBEGetModeInfo ( mode &dst -- 0/1 )
\ : DoFirst ( 1stmode# -- )
\ : AddNode ( mode# -- )
\ : BuildModeList ( -- )
\ : FindMode ( x y bpp -- 0/1 )

\ Demonstration code for GVBE03

\ : Format# ( n -- )
\ : ShowNodeData ( n -- n+1 )
\ : ListNodeData ( -- )
\ : ShowEntries ( -- )
\ : ModeList ( -- )

\ -----------------
\ ---[ Library Modules ]---------------------------------------------
\ -----------------

\ ---[ Modules in GVBE02 ]-------------------------------------------

\ EDO GT Hawkins Data Structure package
\ HeapAllot Static Heap memory allocation

\ ---[ Modules in GVBE02 ]-------------------------------------------

\ HeapAlloc Dynamic heap memory allocation

\ ---[ HeapAlloc ]---------------------------------------------------
\ Modified version of HeapAllot, which allows for dynamic allocation
\ of heap memory. Returns the starting address of the allocated
\ heap memory block, but does not create a dictionary entry.

: HeapAlloc ( size -- addr )
%%HeapPtr over - \ calculate new TOS
dup 16 mod - \ align to lower paragraph boundary
dup >R \ save addr for the moment
dup to %%HeapPtr \ update to new TOS
swap 0 fill \ zero the memory block
R> \ retrieve address
;

\ ------------------------------------------------[End Heap Allot]---

\ -------------------
\ ---[ Array Definitions ]-------------------------------------------
\ -------------------

\ ---[ Definitions in GVBE02 ]---------------------------------------

\ vbeinfo-obj

\ ---[ Definitions in GVBE03 ]---------------------------------------

\ ---[ VESA Mode infomation block ]----------------------------------
\ Data returned when requesting the information for a specific mode

S{
\ Mandatory information for all VBE revisions:

{2BYTE}-DEF :: .ModeAttributes \ mode attributes
{1BYTE}-DEF :: .WinAAttributes \ window A attributes
{1BYTE}-DEF :: .WinBAttributes \ window B attributes
{2BYTE}-DEF :: .WinGranularity \ window granularity
{2BYTE}-DEF :: .WinSize \ window size
{2BYTE}-DEF :: .WinASegment \ window A start segment
{2BYTE}-DEF :: .WinBSegment \ window B start segment
{1WORD}-DEF :: .WinFuncPtr \ pointer to window function
{2BYTE}-DEF :: .BytesPerScanLine \ bytes per scan line

\ Mandatory information for VBE 1.2 and above:

{2BYTE}-DEF :: .XResolution \ horizontal resolution in pixels
{2BYTE}-DEF :: .YResolution \ vertical resolution in pixels
{1BYTE}-DEF :: .XCharSize \ character cell width in pixels
{1BYTE}-DEF :: .YCharSize \ character cell height in pixels
{1BYTE}-DEF :: .NumberOfPlanes \ number of memory planes
{1BYTE}-DEF :: .BitsPerPixel \ bits per pixel
{1BYTE}-DEF :: .NumberOfBanks \ number of banks
{1BYTE}-DEF :: .MemoryModel \ memory model type
{1BYTE}-DEF :: .BankSize \ bank size in KB
{1BYTE}-DEF :: .#ImagePages \ number of images
{1BYTE}-DEF :: ._Reserved \ reserved for page function

\ Direct Color fields (req'd for direct/6 and YUV/7 memory models)

{1BYTE}-DEF :: .RedMaskSize \ size of red mask in bits
{1BYTE}-DEF :: .RedFieldPos \ bit pos of lsb of red mask
{1BYTE}-DEF :: .GreenMaskSize \ size of green mask in bits
{1BYTE}-DEF :: .GreenFieldPos \ bit pos of lsb of green mask
{1BYTE}-DEF :: .BlueMaskSize \ size of blue mask in bits
{1BYTE}-DEF :: .BlueFieldPos \ bit pos of lsb of blue mask
{1BYTE}-DEF :: .RsvdMaskSize \ size of reserved mask in bits
{1BYTE}-DEF :: .RsvdFieldPos \ bit pos of lsb of reserved mask
{1BYTE}-DEF :: .DirectColorInfo \ direct color mode attributes

\ Mandatory information for VBE 2.0 and above:

{1WORD}-DEF :: .PhysBasePtr \ flat frame buffer address
{1WORD}-DEF :: .OffScreenMemPtr \ start of offscreen memory ptr
{2BYTE}-DEF :: .OffScreenMemSize \ amount of offscreen memory in
\ 1k units
206 BYTE* :: .reserved2[] \ pad to 256 byte block size
}S vbemodeinfo-obj

\ ---[ VESA Surface structure ]--------------------------------------
\ When a VESA mode has successfully been initialized, an array with
\ the following structure will be set to the parameters that define
\ the characteristics of that mode

S{
{1WORD}-DEF :: .vbeMode \ VBE mode number
{1WORD}-DEF :: .node^ \ linked list node address of data
{1WORD}-DEF :: .width \ width of screen
{1WORD}-DEF :: .height \ height of screen
{1WORD}-DEF :: .bits \ bits per pixel
{1WORD}-DEF :: .depth \ bytes per pixel
{1WORD}-DEF :: .^lfb \ pointer to LFB
\ determine if this is a SEG:OFS pair
}S vbesurface-obj

\ ---[ Linked List structure ]---------------------------------------
\ Each mode entry will be put into a Linked List on the Heap, and
\ has the following format:

S{
{1WORD}-DEF :: .next \ pointer to next list entry
{1WORD}-DEF :: .mode# \ VESA mode number for this list
vbemodeinfo-obj :: .modeinfo \ data that defines this mode
}S vbelist-obj

\ -----------
\ ---[ Variables ]---------------------------------------------------
\ -----------
\ change to VALUEs when coding is finished - if applicable

variable VBEInit
variable vbeMode
variable vbeScreenWidth
variable vbeScreenHeight
variable vbeScreenBits
variable vbeLfbPtr

\ --------------------
\ ---[ Array Declarations ]------------------------------------------
\ --------------------

\ ---[ Declarations in GVBE02 ]--------------------------------------

\ VBEInfo[]
\ LocalBuf[]

\ ---[ Declarations in GVBE03 ]--------------------------------------

vbesurface-obj HeapAllot VBESurface

\ ---------------
\ ---[ (GetModeInfo) ]-----------------------------------------------
\ ---------------
\ Retrieves the information for the specified mode, returning data to
\ the buffer specified by the dosmem_segment selector
\
\ NOTE: Will probably cause some kind of execution error if run by
\ itself, as it requires the DPMI allocated low memory block.

code (GetModeInfo) ( mode -- 0/1 )
es push
di push
ds push
si push
dosmem_segment #) ax mov
op: ax PREGS 34 + #) mov \ reges/regds are not set by INT10
di di xor \ a/b/c/dx and e/si are, though
$4F01 # ax mov
bx cx mov
INT10 #) call
1 L# jc \ error if carry set
$4F # al cmp
1 L# jne \ 4Fh not returned, error out
1 # bx mov \ return bx=1 as success
2 L# ju
1 L:
bx bx xor \ return bx=0 as error
2 L:
si pop
ds pop
di pop
es pop
end-code
no-expand

\ ----------------
\ ---[ VBEGetModeInfo ]----------------------------------------------
\ ----------------
\ Wrapper for (GetModeInfo):
\
\ 1. Detects VBE
\ 2. Allocates DPMI memory block
\ 3. Calls (GetModeInfo)
\ 4. Transfers data from low memory to specified aray
\ 5. Frees DPMI memory block
\ 6. Returns BOOLEAN on Failure/Success (0/1)
\ -------------------------------------------------------------------

: VBEGetModeInfo ( mode &dst -- 0/1 )
VBEDetect if
AllocDOSMem if
swap (GetModeInfo) if
64 swap GetLowBuffer
1
else
drop 0
then
FreeDOSMem
else
2drop 0
then
else
drop
cr ." Error: Problem accessing information for mode #: "
hex . decimal cr
\ should probably abort here...
0
then
;

\ ------------------
\ ---[ Mini Linked List ]--------------------------------------------
\ ------------------
\ Allows for loading ALL of the mode information into a linked list
\ structure array.

value %%first \ first list entry - anchor
value %%current \ the one we're working with
value %%prev \ the last one we worked with

\ Create the initial linked list node

: DoFirst ( 1stmode# -- )
vbelist-obj HeapAlloc dup \ allocate first block on heap
to %%current \ init list pointers
to %%first
dup
%%current .mode# ! \ set .mode# element of structure
%%current .modeinfo \ get .modeinfo address pointer
VBEGetModeInfo not if \ get the mode information data
." DoFirst: Error getting $"
hex
%%current .mode# 3 .R
decimal
." mode information"
cr
then
;

\ Add a new node to the list, and populate it

: AddNode ( mode# -- )
%%current to %%prev \ set %%prev to %%current
vbelist-obj HeapAlloc \ allocate new memory block
to %%current \ set %%current to new block
%%current %%prev .next ! \ link to %%prev
dup
%%current .mode# ! \ set .mode# element of structure
%%current .modeinfo \ get .modeinfo address pointer
VBEGetModeInfo not if \ get the mode information data
." AddNode: Error getting $"
hex
%%current .mode# 3 .R
decimal
." mode information"
cr
then
;

\ Walk through the mode list and add a node for every resolution

value %%modeptr \ work pointer
value %%count \ to count how many nodes are created

\ %%modeptr is initialized to the start of the list data prior to
\ this word being called.
\ Could be passed as a parm on the stack. Depends on the user.

: BuildModeList ( -- )
%%modeptr H@ DoFirst \ create initial list entry
begin
2 +to %%modeptr \ increment to next mode#
1 +to %%count \ count how many nodes we make
%%modeptr H@ \ get a mode entry
dup $0FFFF = if \ end of list when $0FFFF found
drop 1 \ exit loop if found
else
AddNode \ create new node, populate it
0 \ keep going
then
until
;

\ ---[ FindMode ]----------------------------------------------------
\ Search for match to XxYxBPP parameters
\ On success, set elements in VBESurface, returns TRUE
\ On failure, returns FALSE

: FindMode ( x y bpp -- 0/1 )
%%first to %%current
begin
%%current .modeinfo >R
2 pick R@ .XResolution H@ =
2 pick R@ .YResolution H@ = AND
over R> .BitsPerPixel C@ = AND if
1 1 \ exit - found
else
%%current .next @ 0= if
0 1 \ exit - not found
else
%%current .next @ to %%current
0 \ loop again
then
then
until

if
dup 3 RSHIFT \ x y bpp bpp/8
VBESurface .depth ! \ x y bpp
VBESurface .bits ! \ x y
VBESurface .height ! \ x
VBESurface .width ! \ --
%%current .mode# @
VBESurface .vbeMode !
%%current VBESurface .node^ !
1
else
drop 2drop
VBESurface vbesurface-obj 0 fill
0
then \ 0/1
;

\ ---[ Display Mode Information ]------------------------------------
\ View the information about the modes available

\ ---[ Format# ]-----------------------------------------------------
\ Format# sets the field width for the number /n/ to be displayed in.
\ Instead of 640 x 480 x 8, we get 640x480x8

: Format# ( n -- )
dup 10 < if 1 else
dup 100 < if 2 else
dup 1000 < if 3 else
4
then
then
then
.R
;

\ ---[ ShowNodeData ]------------------------------------------------
\ Displays info in the .modeinfo structure of the current list node

: ShowNodeData ( n -- n+1 )
page
." List Entry #: " 1+ dup 2 .R
." for Mode: " %%modeptr .mode# @ hex 4 .R decimal
%%modeptr .modeinfo >R
VBEInfo[] .VBEVersion H@ $011F > if
." h, "
R@ .XResolution H@ Format# ." x"
R@ .YResolution H@ Format# ." x"
R@ .BitsPerPixel C@ Format# cr cr
else
." h" cr cr
then
hex
." Mode Attributes: " R@ .ModeAttributes H@ . cr
." Win A Attributes: " R@ .WinAAttributes C@ . cr
." Win B Attributes: " R@ .WinBAttributes C@ . cr
decimal
." WinGranularity: " R@ .WinGranularity H@ 2 .R ." kb" cr
." Win Size: " R@ .WinSize H@ 2 .R ." kb" cr
hex
." Win A Segment: " R@ .WinASegment H@ 4 .R ." h" cr
." Win B Segment: " R@ .WinBSegment H@ 4 .R ." h" cr
decimal
." Byte/Scan Line: " R@ .BytesPerScanLine H@ . cr
VBEInfo[] .VBEVersion H@ $011F > if
." ==(Has VBE v1.2 or later)==" cr
." X Resolution: " R@ .XResolution H@ . cr
." Y Resolution: " R@ .YResolution H@ . cr
." Number of Planes: " R@ .NumberOfPlanes C@ . cr
." Bits Per Pixel: " R@ .BitsPerPixel C@ . cr
." Number of Banks: " R@ .NumberOfBanks C@ . cr
." Bank Size (KB): " R@ .BankSize C@ . cr
then
\ add check for VBE v2 - these aren't available for 1.2 or lower
VBEInfo[] .VBEVersion H@ $01FF > if
." ==(Has VBE v2.00 or later)==" cr
hex
." Flat Frame Buf&: " R@ .PhysBasePtr @ 8 u.R ." h" cr
." Offscreen Mem ^: " R@ .OffScreenMemPtr @ 8 u.R ." h" cr
decimal
." Offscreen Size: " R@ .OffScreenMemSize H@ . cr
then
R> drop
cr ." exits, any other for next mode"
;

\ ---[ ListModes ]---------------------------------------------------
\ Displays the mode number and resolution for that mode

: ListModes ( -- )
%%first 0= not if
%%first to %%modeptr
cr
0 begin
1+ dup 2 .R ." : "
%%modeptr .mode# @ hex 3 .R decimal
%%modeptr .modeinfo >R
\ this just formats the XxYxBPP display the way I want it
VBEInfo[] .VBEVersion H@ $011F > if
." h, "
R@ .XResolution H@ Format# ." x"
R@ .YResolution H@ Format# ." x"
R> .BitsPerPixel C@ Format# cr
else
R> drop
." h"
cr
then
key 27 = if
1 \ exit if ESC pressed
else
%%modeptr .next @ 0= if
1 \ exit if .next==0
else
0
then
%%modeptr .next @ to %%modeptr \ link to next node
then
until
drop
else
cr
." ListNodeData: Error - list not populated"
cr
then
;

\ ---[ ShowEntries ]-------------------------------------------------
\ Walk the linked list and display the mode# entries

: ShowEntries ( -- )
%%first 0= not if \ skip if %%first==0
%%first to %%modeptr
0 \ counter
begin
ShowNodeData
key 27 = if
1 \ exit if ESC pressed
else
%%modeptr .next @ 0= if \ last node has .next==0
1
else
0
then
%%modeptr .next @ to %%modeptr
then
until
drop \ lose counter
cr ." End of node listing"
decimal
else
cr
." ShowEntries: Error - list not populated"
cr
then

;

\ ---[ ModeList ]----------------------------------------------------
\ GVBE03 main demo code

: ModeList ( -- )
page
ShowInfo \ from gvbe02
0 to %%count
VBEDetect if
LocalBuf[] to %%modeptr \ start of the mode list table
BuildModeList \ create the linked list
cr ." Linked List created with " %%count . ." entries"
cr ." Memory used by list: " %%count vbelist-obj * . ." bytes" cr
cr ." Press the ANYKEY" key drop
ShowEntries
else
cr ." Error: VBE system not detected" cr
then
;

.( GVBE03: modelist showentries listmodes ) cr
no comments
diggit! del.icio.us! reddit!