Access vesa modes in freebasic ?
Access vesa modes in freebasic ?
I am looking to speed up a program.
How does one access 8 bit graphic vesa modes with linear frame buffer in freebasic ?
How does one access 8 bit graphic vesa modes with linear frame buffer in freebasic ?
-
- Posts: 42
- Joined: Mar 05, 2013 5:37
Re: Access vesa modes in freebasic ?
FreeBASIC graphic library automatically uses VESA for high resolution or high color modes.
For example, If you set screen mode 18 (640x480x8), gfxlib will use VESA interface.
If you want use VESA directly, it is possible with functions "int86" or "int86x" (declared in file "dos\dos.bi") to call VESA interrupt, functions DOSMEMGET/DOSMEMPUT for access to the banked video buffer (declared in "dos\go32.bi") and functions
__dpmi_physical_address_mapping
__dpmi_allocate_ldt_descriptors
__dpmi_set_segment_base_address
__dpmi_set_segment_limit
(declared in "dos\dpmi.bi")
for access to the linear video buffer.
For example, If you set screen mode 18 (640x480x8), gfxlib will use VESA interface.
If you want use VESA directly, it is possible with functions "int86" or "int86x" (declared in file "dos\dos.bi") to call VESA interrupt, functions DOSMEMGET/DOSMEMPUT for access to the banked video buffer (declared in "dos\go32.bi") and functions
__dpmi_physical_address_mapping
__dpmi_allocate_ldt_descriptors
__dpmi_set_segment_base_address
__dpmi_set_segment_limit
(declared in "dos\dpmi.bi")
for access to the linear video buffer.
Re: Access vesa modes in freebasic ?
How do you acess VESA directly using the linear frame buffer?
-
- Posts: 42
- Joined: Mar 05, 2013 5:37
Re: Access vesa modes in freebasic ?
Then you will not need DOSMEMGET/DOSMEMPUT.
1. Set required video mode through int86.
2. Get physical address and size of frame buffer (int86).
3. Map it to linear address space (__dpmi_physical_address_mapping)
4. Allocate descriptor (__dpmi_allocate_ldt_descriptors)
5. Set it's parameters (base address and limit) to frame buffer (__dpmi_set_segment_base_address
and __dpmi_set_segment_limit)
6 . Seems, that's all.
1. Set required video mode through int86.
2. Get physical address and size of frame buffer (int86).
3. Map it to linear address space (__dpmi_physical_address_mapping)
4. Allocate descriptor (__dpmi_allocate_ldt_descriptors)
5. Set it's parameters (base address and limit) to frame buffer (__dpmi_set_segment_base_address
and __dpmi_set_segment_limit)
6 . Seems, that's all.
Re: Access vesa modes in freebasic ?
Could you post a example that does this?
-
- Posts: 42
- Joined: Mar 05, 2013 5:37
Re: Access vesa modes in freebasic ?
This is small example of working with VESA in FreeBASIC for DOS.
It contains analogs of ScreenList, ScreenRes, Pset, Cls and Line FreeBASIC subroutines.
During work program enumerates all accessible graphic modes with 8-bit color depth,
sets mode with resolution 640x480x8 and draws some graphical primitives.
Program is very simple and contains some comments, but in case of difficulty, ask questions here.
It contains analogs of ScreenList, ScreenRes, Pset, Cls and Line FreeBASIC subroutines.
During work program enumerates all accessible graphic modes with 8-bit color depth,
sets mode with resolution 640x480x8 and draws some graphical primitives.
Program is very simple and contains some comments, but in case of difficulty, ask questions here.
Code: Select all
'$LANG: "fblite"
'$INCLUDE: 'dos\go32.bi'
'$INCLUDE: 'dos\dpmi.bi'
TYPE RealModePtr FIELD = 1
ROffs AS USHORT
RSegm AS USHORT
END TYPE
TYPE VbeInfoBlock FIELD = 1
VbeSignature AS UINTEGER 'VBE Signature
VbeVersion AS USHORT 'VBE Version
OemStringPtr AS RealModePtr 'Pointer to OEM String
Capabilities AS UINTEGER 'Capabilities of graphics cont.
VideoModePtr AS RealModePtr 'Pointer to Video Mode List
TotalMemory AS USHORT 'Number of 64kb memory blocks
OemSoftwareRev AS USHORT 'VBE implementation Software revision
OemVendorNamePtr AS RealModePtr 'Pointer to Vendor Name String
OemProductNamePtr AS RealModePtr 'Pointer to Product Name String
OemProductRevPtr AS RealModePtr 'Pointer to Product Revision String
VSReserved (0 TO 221) AS UBYTE 'Reserved for VBE implementation scratch area
OemData (0 TO 255) AS UBYTE 'Data Area for OEM Strings
END TYPE
TYPE ModeInfoBlock FIELD = 1
'Mandatory information for all VBE revisions
ModeAttributes AS USHORT 'mode attributes
WinAAttributes AS UBYTE 'window A attributes
WinBAttributes AS UBYTE 'window B attributes
WinGranularity AS USHORT 'window granularity
WinSize AS USHORT 'window size
WinASegment AS USHORT 'window A start segment
WinBSegment AS USHORT 'window B start segment
WinFuncPtr AS RealModePtr 'pointer to window function
BytesPerScanLine AS USHORT 'bytes per scan line
'Mandatory information for VBE 1.2 and above
XResolution AS USHORT 'horizontal resolution in pixels or chars
YResolution AS USHORT 'vertical resolution in pixels or chars
XCharSize AS UBYTE 'character cell width in pixels
YCharSize AS UBYTE 'character cell height in pixels
NumberOfPlanes AS UBYTE 'number of memory planes
BitsPerPixel AS UBYTE 'bits per pixel
NumberOfBanks AS UBYTE 'number of banks
MemoryModel AS UBYTE 'memory model type
BankSize AS UBYTE 'bank size in KB
NumberOfImagePages AS UBYTE 'number of images
MBReserved AS UBYTE 'reserved for page function
'Direct Color fields (required for direct/6 and YUV/7 memory models)
RedMaskSize AS UBYTE 'size of direct color red mask in bits
RedFieldPosition AS UBYTE 'bit position of lsb of red mask
GreenMaskSize AS UBYTE 'size of direct color green mask in bits
GreenFieldPosition AS UBYTE 'bit position of lsb of green mask
BlueMaskSize AS UBYTE 'size of direct color blue mask in bits
BlueFieldPosition AS UBYTE 'bit position of lsb of blue mask
RsvdMaskSize AS UBYTE 'size of direct color reserved mask in bits
RsvdFieldPosition AS UBYTE 'bit position of lsb of reserved mask
DirectColorModeInfo AS UBYTE 'direct color mode attributes
'Mandatory information for VBE 2.0 and above
PhysBasePtr AS UINTEGER 'physical address for flat frame buffer
OffScreenMemOffset AS UINTEGER 'pointer to start of off screen memory
OffScreenMemSize AS USHORT 'amount of off screen memory in 1k units
MB2Reserved (0 TO 205) AS UBYTE 'remainder of ModeInfoBlock
END TYPE
DIM SHARED DOSBlock AS USHORT, DOSBlockAddr AS UINTEGER, regs AS __dpmi_regs, UseSelector%
DIM SHARED VBEI AS VbeInfoBlock, VMDI AS ModeInfoBlock, CurNum%, ModeList(1 TO 256) AS USHORT
DIM SHARED TmpUI AS UINTEGER
FUNCTION AllocDOSMem (BYVAL NeedSize%) AS USHORT
ParSize% = NeedSize% \ 16
IF (NeedSize% MOD 16) <> 0 THEN ParSize% = ParSize% + 1
IF (ParSize% > 65535) OR (ParSize% <= 0) THEN AllocDOSMem = 0: EXIT FUNCTION
regs.x.ax = &H4800: regs.x.bx = ParSize%: __dpmi_int(&H21, @regs)
IF BIT(regs.x.flags, 0) THEN AllocDOSMem = 0: ERR = 255: EXIT FUNCTION
ERR = 0: AllocDOSMem = regs.x.ax 'сегмент выделенного блока
END FUNCTION
FUNCTION FreeDOSMem (BYVAL BlockSegm AS USHORT) AS USHORT
regs.x.ax = &H4900: regs.x.es = BlockSegm: __dpmi_int(&H21, @regs)
FreeDOSMem = BIT(regs.x.flags, 0)
END FUNCTION
FUNCTION VSScreenList (NDepth% = 0) AS UINTEGER
STATIC CurDepth%
VSScreenList = 0
IF NDepth% > 0 THEN 'это первое обращение - получаем список доступных режимов
CurDepth% = 0: CurNum% = 0: tmp$ = "VBE2"
DOSMEMPUT STRPTR(tmp$), 4, DOSBlockAddr
regs.x.ax = &H4F00: regs.x.es = DOSBlock: regs.x.di = 0: __dpmi_int(&H10, @regs)
IF regs.x.ax <> &H4F THEN ERR = 254: EXIT FUNCTION
DOSMEMGET DOSBlockAddr, LEN(VBEI), @VBEI
IF VBEI.VbeSignature <> CVL("VESA") THEN ERR = 253: EXIT FUNCTION 'нет верной сигнатуры
IF VBEI.VbeVersion < &H200 THEN ERR = 252: EXIT FUNCTION 'версия VESA меньше 2.0 - линейный кадровый буфер не поддерживается
'Считываем список доступных видеорежимов
DOSMEMGET (CUINT(VBEI.VideoModePtr.RSegm) SHL 4) + VBEI.VideoModePtr.ROffs, 512, @ModeList(1)
CurDepth% = NDepth%
END IF
'Процедура не вызывалась ранее с явным указанием NDepth% или при построении списка режимов произошла ошибка
IF CurDepth% <= 0 THEN ERR = 251: EXIT FUNCTION
DO
CurNum% = CurNum% + 1
IF (CurNum% < LBOUND(ModeList)) OR (CurNum% > UBOUND(ModeList)) THEN EXIT DO
IF ModeList(CurNum%) = -1 THEN CurDepth% = 0: EXIT DO 'список доступных видеорежимов закончен
'получим информацию о текущем видеорежиме
regs.x.ax = &H4F01: regs.x.cx = ModeList(CurNum%)
regs.x.es = DOSBlock: regs.x.di = 0: __dpmi_int(&H10, @regs)
IF regs.x.ax <> &H4F THEN CONTINUE DO
DOSMEMGET DOSBlockAddr, LEN(VMDI), @VMDI 'получаем блок информации о режиме
'режим не поддерживается или он неграфический - не подходит
IF NOT (BIT(VMDI.ModeAttributes, 0) AND BIT(VMDI.ModeAttributes, 0)) THEN CONTINUE DO
'недоступен режим с линейным кадровым буфером
IF (NOT BIT(VMDI.ModeAttributes, 7)) OR (VMDI.PhysBasePtr = 0) THEN CONTINUE DO
'неподходящая модель цветности (поддерживаются только упаук ованные пиксели или "прямой цвет")
IF (VMDI.MemoryModel <> 4) AND (VMDI.MemoryModel <> 6) THEN CONTINUE DO
IF (VMDI.NumberOfBanks <> 1) OR (VMDI.NumberOfPlanes <> 1) THEN CONTINUE DO
'количество разрядов цветности не совпадает с искомым
IF VMDI.BitsPerPixel <> CurDepth% THEN CONTINUE DO
VSScreenList = (CUINT(VMDI.XResolution) SHL 16) + VMDI.YResolution: EXIT DO
LOOP
IF (CurNum% < LBOUND(ModeList)) OR (CurNum% > UBOUND(ModeList)) THEN CurDepth% = 0 'список доступных видеорежимов закончен
ERR = 0
END FUNCTION
SUB VSScreenRes (NWidth%, NHeight%, NDepth%)
DIM VModeParam AS UINTEGER, minfo as __dpmi_meminfo, UseSize AS UINTEGER
VModeParam = VSScreenList(NDepth%)
DO UNTIL VModeParam = 0
IF (HiWord(VModeParam) = NWidth%) AND (LoWord(VModeParam) = NHeight%) THEN EXIT DO
VModeParam = VSScreenList
LOOP
IF (HiWord(VModeParam) <> NWidth%) OR (LoWord(VModeParam) <> NHeight%) THEN
ERR = 255: EXIT SUB 'подходящего под требования режима не найдено
END IF
'Требуемый режим найден - его номер ModeList(CurNum%). Блок VMDI также уже заполнен.
UseSelector% = __dpmi_allocate_ldt_descriptors(1)
IF UseSelector% = 0 THEN ERR = 254: EXIT SUB
'Создаем дескриптор для обращения к кадровому буферу
UseSize = VMDI.BytesPerScanLine * VMDI.YResolution
IF (UseSize MOD &H1000) <> 0 THEN UseSize = ((UseSize \ &H1000) + 1) * &H1000 'выравниваем размер по целым страницам
minfo.address = VMDI.PhysBasePtr: minfo.size = UseSize
IF __dpmi_physical_address_mapping (@minfo) <> 0 THEN
ERR = 253: EXIT SUB 'не удалось картировать видеобуфер в линейное адресное пространство
END IF
IF __dpmi_set_segment_base_address(UseSelector%, minfo.address) <> 0 THEN
ERR = 252: EXIT SUB 'ошибка установки базового адреса
END IF
IF __dpmi_set_segment_limit(UseSelector%, UseSize - 1) <> 0 THEN
ERR = 251: EXIT SUB 'ошибка установки предела сегмента
END IF
'Видеобуфер к работе подготовлен, соответствующий ему селектор настроен
'Теперь устанавливаем собственно сам графический режим
regs.x.ax = &H4F02: regs.x.bx = BITSET(ModeList(CurNum%), 14): __dpmi_int(&H10, @regs) 'режим с плоским буфером
IF regs.x.ax <> &H4F THEN ERR = 250: EXIT SUB
ERR = 0
END SUB
SUB VSScreenReset ()
'Освобождаем селектор и устанавливаем стандартный текстовый режим
IF UseSelector% <> 0 THEN
__dpmi_free_ldt_descriptor(UseSelector%): UseSelector% = 0
END IF
regs.x.ax = 0: __dpmi_int(&H10, @regs) 'режим 0 - стандартный текстовый режим
END SUB
SUB VSDrawPset (XP%, YP%, LColor%)
'Выводит точку с координатами (XP%, YP%) цветом LColor%
DIM OfsCount AS UINTEGER
IF (XP% < 0) OR (XP% >= VMDI.XResolution) THEN EXIT SUB
IF (YP% < 0) OR (YP% >= VMDI.YResolution) THEN EXIT SUB
OfsCount = YP% * VMDI.BytesPerScanLine + XP% * (VMDI.BitsPerPixel SHR 3)
ASM
push es
push ebx
mov ebx, [LColor%]
mov al, [ebx]
mov ebx, [OfsCount]
mov es, word ptr [UseSelector%]
mov es:[ebx], al
pop ebx
pop es
END ASM
END SUB
SUB VSCls
'Процедура очистки экрана. Заполняет весь кадровый буфер нулевым цветом
DIM OfsCount AS UINTEGER
OfsCount = VMDI.YResolution * VMDI.BytesPerScanLine
ASM
push es
push ecx
push edi
xor al, al
mov ecx, [OfsCount]
xor edi, edi
mov es, word ptr [UseSelector%]
rep stosb
pop edi
pop ecx
pop es
END ASM
END SUB
SUB VSDrawLine (X1%, Y1%, X2%, Y2%, LColor%)
'Рисует отрезок между точками (X1%, Y1%) и (X2%, Y2%) цветом LColor% с помощью алгоритма Брезенхейма
IF ABS(X2% - X1%) >= ABS(Y2% - Y1%) THEN 'наклон прямой меньше 45 градусов
Deff% = 2 * ABS(Y2% - Y1%): CritDeff% = ABS(X2% - X1%)
CurY% = Y1%: AddDeff% = 0
IF X2% > X1% THEN StppX% = 1 ELSE StppX% = -1
IF Y2% > Y1% THEN StppY% = 1 ELSE StppY% = -1
FOR CurX% = X1% TO X2% STEP StppX%
CALL VSDrawPset(CurX%, CurY%, LColor%) 'рисуем текущую точку
AddDeff% = AddDeff% + Deff%
IF AddDeff% >= CritDeff% THEN CurY% = CurY% + StppY%: AddDeff% = AddDeff% - 2 * CritDeff%
NEXT CurX%
ELSE 'наклон прямой больше 45 градусов
Deff% = 2 * ABS(X2% - X1%): CritDeff% = ABS(Y2% - Y1%)
CurX% = X1%: AddDeff% = 0
IF X2% > X1% THEN StppX% = 1 ELSE StppX% = -1
IF Y2% > Y1% THEN StppY% = 1 ELSE StppY% = -1
FOR CurY% = Y1% TO Y2% STEP StppY%
CALL VSDrawPset(CurX%, CurY%, LColor%) 'рисуем текущую точку
AddDeff% = AddDeff% + Deff%
IF AddDeff% >= CritDeff% THEN CurX% = CurX% + StppX%: AddDeff% = AddDeff% - 2 * CritDeff%
NEXT CurY%
END IF
END SUB
UseSelector% = 0: DOSBlock = AllocDOSMem(4096) 'выделяем блок нижней памяти в 4к
DOSBlockAddr = CUINT(DOSBlock) SHL 4 'линейный адрес выделенного блока
PRINT "Список доступных 8-битовых графических режимов"
TmpUI = VSScreenList(8)
IF ERR <> 0 THEN
PRINT "Ошибка при вызове ScreenList - "; ERR: END 255
END IF
WHILE TmpUI <> 0
PRINT "Режим"; CurNum%; " разрешение - "; HiWord(TmpUI);"x"; LoWord(TmpUI); " цветность - "; VMDI.BitsPerPixel
TmpUI = VSScreenList
WEND
SLEEP
WHILE LEN(INKEY$) > 0: WEND
CALL VSScreenRes(640, 480, 8)
IF ERR <> 0 THEN
PRINT "Ошибка при вызове ScreenRes - "; ERR: END 255
END IF
FOR r% = 0 TO 639: CALL VSDrawPset(r%, 240, r% MOD 256): NEXT r%
CALL VSDrawLine(0, 100, 639, 100, 100)
CALL VSDrawLine(320, 0, 320, 479, 100)
SLEEP: WHILE LEN(INKEY$) > 0: WEND
CALL VSCls
FOR r% = 0 TO 479 STEP 20
CALL VSDrawLine(0, r%, 639, r% + 50, r% MOD 256)
NEXT r%
SLEEP: WHILE LEN(INKEY$) > 0: WEND
FOR r% = 479 TO 0 STEP -20
CALL VSDrawLine(0, r%, 639, r% - 50, r% MOD 256)
NEXT r%
SLEEP: WHILE LEN(INKEY$) > 0: WEND
FOR r% = 0 TO 639 STEP 20
CALL VSDrawLine(r%, 0, r% + 50, 479, r% MOD 256)
NEXT r%
SLEEP: WHILE LEN(INKEY$) > 0: WEND
FOR r% = 639 TO 0 STEP -20
CALL VSDrawLine(r%, 0, r% - 50, 479, r% MOD 256)
NEXT r%
SLEEP: WHILE LEN(INKEY$) > 0: WEND
CALL VSScreenReset: DOSBlock = FreeDOSMem(DOSBlock)
END
Re: Access vesa modes in freebasic ?
Tried to get your code to work in dosbox. It crashed. Page seg and that sort of thing.
What about the DS Fat trick?
I think Freebasic uses the DS Fat trick.
http://www.chelograph.8m.com/html/djgpp ... m#Fat%20DS
I have been trying to get the following code to work.
No luck so far.
What about the DS Fat trick?
I think Freebasic uses the DS Fat trick.
http://www.chelograph.8m.com/html/djgpp ... m#Fat%20DS
I have been trying to get the following code to work.
No luck so far.
Code: Select all
#LANG "fblite"
#define _BORLAND_DOS_REGS 1 // djgpp specific switch
#include "dos/pc.bi"
#include "dos/dos.bi"
#include "dos/go32.bi"
#include "dos/dpmi.bi"
Declare Function __djgpp_nearptr_enable cdecl Alias "__djgpp_nearptr_enable" () As Integer ' Returns 0 if feature not avail
Declare Sub __djgpp_nearptr_disable cdecl Alias "__djgpp_nearptr_disable" () ' Enables protection
extern __djgpp_selector_limit Alias "__djgpp_selector_" As Integer ' Limit on CS and on DS if prot
extern __djgpp_base_address Alias "__djgpp_base_address" As Integer ' Used in calculation below
Type SVGA_dos_vbe_vgainfo Field = 1
VESASignature As UINTEGER ' /* VESA 4-byte signature */
VESAVersion As uShort ' /* VBE version number */
OEMStringPtr As uInteger ' /* Pointer to OEM string */
Capabilities(0 To 3) As uByte ' /* Capabilities of video card */
VideoModePtr As uInteger ' /* Pointer to supported modes */
TotalMemory As uShort ' /* Number of 64kb memory blocks */
OEMSoftwareRev As uShort ' /* VBE software revision */
OEMVendorNamePtr As uInteger ' /* Pointer to vendor name string */
OEMProductNamePtr As uInteger ' /* Pointer to product name string */
OEMProductRevPtr As uInteger ' /* Pointer to product revision string */
Reserved(0 To 221) As Byte ' /* Reserved as working space */
OEMData(0 To 255) As Byte ' /* Data area for OEM strings */
End Type
Type SVGA_dos_vbe_modeinfo
ModeAttributes As Short '/* Mode attributes */
WinAAttributes As Byte '/* Window A attributes */
WinBAttributes As Byte '/* Window B attributes */
WinGranularity As Short '/* Window granularity in k */
WinSize As Short '/* Window size in k */
WinASegment As Short '/* Window A segment */
WinBSegment As Short '/* Window B segment */
WinFuncPtr As Any ptr '/* Pointer to window function */
BytesPerScanLine As Short '/* Bytes per scanline */
XResolution As Short '/* Horizontal resolution */
YResolution As Short '/* Vertical resolution */
XCharSize As Byte '/* Character cell width */
YCharSize As Byte '/* Character cell height */
NumberOfPlanes As Byte '/* Number of memory planes */
BitsPerPixel As Byte '/* Bits per pixel */
NumberOfBanks As Byte '/* Number of CGA style banks */
MemoryModel As Byte '/* Memory model type */
BankSize As Byte '/* Size of CGA style banks */
NumberOfImagePages As Byte '/* Number of images pages */
res1 As Byte '/* Reserved */
RedMaskSize As Byte '/* Size of direct color red mask */
RedFieldPosition As Byte '/* Bit posn of lsb of red mask */
GreenMaskSize As Byte '/* Size of direct color green mask */
GreenFieldPosition As Byte '/* Bit posn of lsb of green mask */
BlueMaskSize As Byte '/* Size of direct color blue mask */
BlueFieldPosition As Byte '/* Bit posn of lsb of blue mask */
RsvdMaskSize As Byte '/* Size of direct color res mask */
RsvdFieldPosition As Byte '/* Bit posn of lsb of res mask */
DirectColorModeInfo As Byte '/* Direct color mode attributes */
' VESA 2.0 variables
PhysBasePtr As UINTEGER '/* physical address for flat frame buffer */
OffScreenMemOffset As UINTEGER '/* pointer to start of off screen memory */
OffScreenMemSize As UShort '/* amount of off screen memory in 1k units */
res2(0 To 205) As Byte '/* Pad to 256 byte block size */
End Type
DECLARE Function DetectVBE%(vbeinfo AS SVGA_dos_vbe_vgainfo)
DECLARE Function GetVBEModeInfo%(modeinfo As SVGA_dos_vbe_modeinfo)
DECLARE SUB MapMemory(Vbe AS SVGA_dos_vbe_modeinfo)
DECLARE Sub Screen18()
DECLARE Sub VESA_End()
DECLARE Sub SetColor(cindex As uByte, redval As uByte, greenval As uByte, blueval As uByte)
DECLARE SUB Box(BYVAL X1 AS LONG,BYVAL X2 AS LONG,BYVAL Y1 AS LONG,BYVAL Y2 AS LONG, BYVAL Col3 AS UBYTE)
DIM DosVbe AS SVGA_dos_vbe_vgainfo
DIM VesaInfo AS SVGA_dos_vbe_modeinfo
DIM SHARED BufferPtr AS UBYTE PTR
DIM Shared VideoPtr AS UBYTE PTR
IF DetectVBE%(DosVbe) THEN
IF GetVBEModeInfo%(VesaInfo) THEN
MapMemory VesaInfo
Screen18
END IF
END IF
BufferPtr = VideoPtr
Box 200,400,100,300,4
SLEEP
VESA_End
END
Function DetectVBE%(vbeinfo AS SVGA_dos_vbe_vgainfo)
Dim regs As __dpmi_regs
regs.x.ax = &H4F00
regs.x.di = __tb AND &H0F
regs.x.es = (__tb shr 4) AND &HFFFF
dosmemput(@vbeinfo, sizeof(SVGA_dos_vbe_vgainfo), __tb)
__dpmi_int(&H10, @regs)
dosmemget(__tb, sizeof(SVGA_dos_vbe_vgainfo), @vbeinfo)
Result% = regs.h.ah
IF Result% = 0 THEN Return 1
End Function
Function GetVBEModeInfo%(modeinfo As SVGA_dos_vbe_modeinfo)
Dim Mode AS USHORT
Mode = BitSet(&H101, 14)
Dim regs As __dpmi_regs
regs.x.ax = &H4F01
regs.x.cx = mode
regs.x.di= __tb AND &H0F
regs.x.es = (__tb shr 4) AND &HFFFF
__dpmi_int(&H10, @regs)
dosmemget(__tb, sizeof(SVGA_dos_vbe_modeinfo), @modeinfo)
Result% = regs.h.ah
IF Result% = 0 THEN Return 1
End Function
SUB MapMemory(Vbe AS SVGA_dos_vbe_modeinfo)
DIM mapping as __dpmi_meminfo
'selector% = __dpmi_allocate_ldt_descriptors(1)
__djgpp_nearptr_enable
' map into linear memory
mapping.address = Vbe.PhysBasePtr
mapping.size = 307200
IF __dpmi_physical_address_mapping(@mapping) <> 0 THEN
EXIT SUB
END IF
VideoPtr = mapping.address + __djgpp_conventional_base
'__dpmi_free_physical_address_mapping @mapping
END SUB
Sub Screen18()
DIM Mode AS USHORT
Mode = BitSet(&H101, 14)
'Mode = &H101 'OR &B0100000000000000
Dim regs As REGS
regs.x.eax = &H4f02
regs.x.ebx = Mode
int86(&H10,@regs,@regs)
End Sub
Sub VESA_End()
DIM mapping as __dpmi_meminfo
Dim regs As __dpmi_regs
regs.x.ax = 3
__dpmi_int(&H10, @regs)
__dpmi_free_physical_address_mapping(@mapping)
__djgpp_nearptr_disable()
End Sub
Sub SetColor(cindex As uByte, redval As uByte, greenval As uByte, blueval As uByte)
outp(&H03c6, &HFF)
outp(&H03c8, cindex)
outp(&H03c9, redval)
outp(&H03c9, greenval)
outp(&H03c9, blueval)
End Sub
SUB Box(BYVAL X1 AS LONG,BYVAL X2 AS LONG,BYVAL Y1 AS LONG,BYVAL Y2 AS LONG, BYVAL Col3 AS UBYTE)
DIM DwordCounter AS UINTEGER
DIM ByteCounter AS UINTEGER
ASM
MOV EDI,[BufferPtr]
MOV EDX,[X1]
MOV ECX,[X2]
CMP EDX,ECX
JL NoSwap1
MOV [X1],ECX
MOV [X2],EDX
NoSwap1:
MOV ECX,[X2]
SUB ECX,[X1]
INC ECX
MOV EAX,ECX
SHR EAX,2
MOV [DwordCounter],EAX
ADD EDI,[X1]
MOV EBX,[Y1] 'figure out Video[EDI] starting position
SHL EBX,6
MOV EDX, EBX
SHL EBX,2
ADD EDX, EBX
SHL EDX,1
ADD EDI,EDX
MOV EBX,[Y2]
SUB EBX,[Y1]
INC EBX
MOV EAX,ECX
AND EAX,3
MOV [ByteCounter],EAX
MOV EDX, 640
'ADD EDX,EAX
SUB EDX, ECX 'EDX will have Y add value
MOV AL, [Col3]
MOV AH,AL
BSWAP EAX
MOV AL, [Col3]
MOV AH,AL
DoAgain:
CLD
MOV ECX, [DwordCounter]
REP STOSD
MOV ECX, [ByteCounter]
REP STOSB
DEC EBX
CMP EBX,0
JE EndBox
ADD EDI, EDX
JMP DoAgain
EndBox:
END ASM
END SUB
-
- Posts: 42
- Joined: Mar 05, 2013 5:37
Re: Access vesa modes in freebasic ?
Computer is very obscure thing and filled by paradoxes.
The cause of exception, which is observed in program in DOSBOX, is statement SLEEP.
FreeBASIC "SLEEP" in current condition is incompatible with DOSBOX.
Yes, it's hard to believe, but this is a fact.
Try this small example and you receive GPF.
This is version of the program without SLEEP, and it works much better.
"Fat DS".
This is version of the program, which uses "Fat DS".
Results of testing:
Both programs work excellently in pure DOS (FreeDOS 1.1, MS-DOS 7.1) and in Win98 DOS session.
Also both programs work reasonably good in DOSBOX 0.74 ("Fat DS" version periodically
crashes DOSBOX, the cause is still unclear).
NTVDM DPMI server in Windows XP don't support mapping of physical memory regions
(0800h function). Seems, applying of flat frame buffer is impossible there at all.
At least, I do not know how to do it.
The cause of exception, which is observed in program in DOSBOX, is statement SLEEP.
FreeBASIC "SLEEP" in current condition is incompatible with DOSBOX.
Yes, it's hard to believe, but this is a fact.
Try this small example and you receive GPF.
Code: Select all
SLEEP
WHILE LEN(INKEY$) > 0: WEND
Code: Select all
'$LANG: "fblite"
'$INCLUDE: 'dos\go32.bi'
'$INCLUDE: 'dos\dpmi.bi'
TYPE RealModePtr FIELD = 1
ROffs AS USHORT
RSegm AS USHORT
END TYPE
TYPE VbeInfoBlock FIELD = 1
VbeSignature AS UINTEGER 'VBE Signature
VbeVersion AS USHORT 'VBE Version
OemStringPtr AS RealModePtr 'Pointer to OEM String
Capabilities AS UINTEGER 'Capabilities of graphics cont.
VideoModePtr AS RealModePtr 'Pointer to Video Mode List
TotalMemory AS USHORT 'Number of 64kb memory blocks
OemSoftwareRev AS USHORT 'VBE implementation Software revision
OemVendorNamePtr AS RealModePtr 'Pointer to Vendor Name String
OemProductNamePtr AS RealModePtr 'Pointer to Product Name String
OemProductRevPtr AS RealModePtr 'Pointer to Product Revision String
VSReserved (0 TO 221) AS UBYTE 'Reserved for VBE implementation scratch area
OemData (0 TO 255) AS UBYTE 'Data Area for OEM Strings
END TYPE
TYPE ModeInfoBlock FIELD = 1
'Mandatory information for all VBE revisions
ModeAttributes AS USHORT 'mode attributes
WinAAttributes AS UBYTE 'window A attributes
WinBAttributes AS UBYTE 'window B attributes
WinGranularity AS USHORT 'window granularity
WinSize AS USHORT 'window size
WinASegment AS USHORT 'window A start segment
WinBSegment AS USHORT 'window B start segment
WinFuncPtr AS RealModePtr 'pointer to window function
BytesPerScanLine AS USHORT 'bytes per scan line
'Mandatory information for VBE 1.2 and above
XResolution AS USHORT 'horizontal resolution in pixels or chars
YResolution AS USHORT 'vertical resolution in pixels or chars
XCharSize AS UBYTE 'character cell width in pixels
YCharSize AS UBYTE 'character cell height in pixels
NumberOfPlanes AS UBYTE 'number of memory planes
BitsPerPixel AS UBYTE 'bits per pixel
NumberOfBanks AS UBYTE 'number of banks
MemoryModel AS UBYTE 'memory model type
BankSize AS UBYTE 'bank size in KB
NumberOfImagePages AS UBYTE 'number of images
MBReserved AS UBYTE 'reserved for page function
'Direct Color fields (required for direct/6 and YUV/7 memory models)
RedMaskSize AS UBYTE 'size of direct color red mask in bits
RedFieldPosition AS UBYTE 'bit position of lsb of red mask
GreenMaskSize AS UBYTE 'size of direct color green mask in bits
GreenFieldPosition AS UBYTE 'bit position of lsb of green mask
BlueMaskSize AS UBYTE 'size of direct color blue mask in bits
BlueFieldPosition AS UBYTE 'bit position of lsb of blue mask
RsvdMaskSize AS UBYTE 'size of direct color reserved mask in bits
RsvdFieldPosition AS UBYTE 'bit position of lsb of reserved mask
DirectColorModeInfo AS UBYTE 'direct color mode attributes
'Mandatory information for VBE 2.0 and above
PhysBasePtr AS UINTEGER 'physical address for flat frame buffer
OffScreenMemOffset AS UINTEGER 'pointer to start of off screen memory
OffScreenMemSize AS USHORT 'amount of off screen memory in 1k units
MB2Reserved (0 TO 205) AS UBYTE 'remainder of ModeInfoBlock
END TYPE
DIM SHARED DOSBlock AS USHORT, DOSBlockAddr AS UINTEGER, regs AS __dpmi_regs, UseSelector%
DIM SHARED VBEI AS VbeInfoBlock, VMDI AS ModeInfoBlock, CurNum%, ModeList(1 TO 256) AS USHORT
DIM SHARED TmpUI AS UINTEGER
FUNCTION AllocDOSMem (BYVAL NeedSize%) AS USHORT
ParSize% = NeedSize% \ 16
IF (NeedSize% MOD 16) <> 0 THEN ParSize% = ParSize% + 1
IF (ParSize% > 65535) OR (ParSize% <= 0) THEN AllocDOSMem = 0: EXIT FUNCTION
regs.x.ax = &H4800: regs.x.bx = ParSize%: __dpmi_int(&H21, @regs)
IF BIT(regs.x.flags, 0) THEN AllocDOSMem = 0: ERR = 255: EXIT FUNCTION
ERR = 0: AllocDOSMem = regs.x.ax 'сегмент выделенного блока
END FUNCTION
FUNCTION FreeDOSMem (BYVAL BlockSegm AS USHORT) AS USHORT
regs.x.ax = &H4900: regs.x.es = BlockSegm: __dpmi_int(&H21, @regs)
FreeDOSMem = BIT(regs.x.flags, 0)
END FUNCTION
FUNCTION VSScreenList (NDepth% = 0) AS UINTEGER
STATIC CurDepth%
VSScreenList = 0
IF NDepth% > 0 THEN 'это первое обращение - получаем список доступных режимов
CurDepth% = 0: CurNum% = 0: tmp$ = "VBE2"
DOSMEMPUT STRPTR(tmp$), 4, DOSBlockAddr
regs.x.ax = &H4F00: regs.x.es = DOSBlock: regs.x.di = 0: __dpmi_int(&H10, @regs)
IF regs.x.ax <> &H4F THEN ERR = 254: EXIT FUNCTION
DOSMEMGET DOSBlockAddr, LEN(VBEI), @VBEI
IF VBEI.VbeSignature <> CVL("VESA") THEN ERR = 253: EXIT FUNCTION 'нет верной сигнатуры
IF VBEI.VbeVersion < &H200 THEN ERR = 252: EXIT FUNCTION 'версия VESA меньше 2.0 - линейный кадровый буфер не поддерживается
'Считываем список доступных видеорежимов
DOSMEMGET (CUINT(VBEI.VideoModePtr.RSegm) SHL 4) + VBEI.VideoModePtr.ROffs, 512, @ModeList(1)
CurDepth% = NDepth%
END IF
'Процедура не вызывалась ранее с явным указанием NDepth% или при построении списка режимов произошла ошибка
IF CurDepth% <= 0 THEN ERR = 251: EXIT FUNCTION
DO
CurNum% = CurNum% + 1
IF (CurNum% < LBOUND(ModeList)) OR (CurNum% > UBOUND(ModeList)) THEN EXIT DO
IF ModeList(CurNum%) = -1 THEN CurDepth% = 0: EXIT DO 'список доступных видеорежимов закончен
'получим информацию о текущем видеорежиме
regs.x.ax = &H4F01: regs.x.cx = ModeList(CurNum%)
regs.x.es = DOSBlock: regs.x.di = 0: __dpmi_int(&H10, @regs)
IF regs.x.ax <> &H4F THEN CONTINUE DO
DOSMEMGET DOSBlockAddr, LEN(VMDI), @VMDI 'получаем блок информации о режиме
'режим не поддерживается или он неграфический - не подходит
IF NOT (BIT(VMDI.ModeAttributes, 0) AND BIT(VMDI.ModeAttributes, 0)) THEN CONTINUE DO
'недоступен режим с линейным кадровым буфером
IF (NOT BIT(VMDI.ModeAttributes, 7)) OR (VMDI.PhysBasePtr = 0) THEN CONTINUE DO
'неподходящая модель цветности (поддерживаются только упаук ованные пиксели или "прямой цвет")
IF (VMDI.MemoryModel <> 4) AND (VMDI.MemoryModel <> 6) THEN CONTINUE DO
IF (VMDI.NumberOfBanks <> 1) OR (VMDI.NumberOfPlanes <> 1) THEN CONTINUE DO
'количество разрядов цветности не совпадает с искомым
IF VMDI.BitsPerPixel <> CurDepth% THEN CONTINUE DO
VSScreenList = (CUINT(VMDI.XResolution) SHL 16) + VMDI.YResolution: EXIT DO
LOOP
IF (CurNum% < LBOUND(ModeList)) OR (CurNum% > UBOUND(ModeList)) THEN CurDepth% = 0 'список доступных видеорежимов закончен
ERR = 0
END FUNCTION
SUB VSScreenRes (NWidth%, NHeight%, NDepth%)
DIM VModeParam AS UINTEGER, minfo as __dpmi_meminfo, UseSize AS UINTEGER
VModeParam = VSScreenList(NDepth%)
DO UNTIL VModeParam = 0
IF (HiWord(VModeParam) = NWidth%) AND (LoWord(VModeParam) = NHeight%) THEN EXIT DO
VModeParam = VSScreenList
LOOP
IF (HiWord(VModeParam) <> NWidth%) OR (LoWord(VModeParam) <> NHeight%) THEN
ERR = 255: EXIT SUB 'подходящего под требования режима не найдено
END IF
'Требуемый режим найден - его номер ModeList(CurNum%). Блок VMDI также уже заполнен.
UseSelector% = __dpmi_allocate_ldt_descriptors(1)
IF UseSelector% = 0 THEN ERR = 254: EXIT SUB
'Создаем дескриптор для обращения к кадровому буферу
UseSize = VMDI.BytesPerScanLine * VMDI.YResolution
IF (UseSize MOD &H1000) <> 0 THEN UseSize = ((UseSize \ &H1000) + 1) * &H1000 'выравниваем размер по целым страницам
minfo.address = VMDI.PhysBasePtr: minfo.size = UseSize
IF __dpmi_physical_address_mapping (@minfo) <> 0 THEN
ERR = 253: EXIT SUB 'не удалось картировать видеобуфер в линейное адресное пространство
END IF
IF __dpmi_set_segment_base_address(UseSelector%, minfo.address) <> 0 THEN
ERR = 252: EXIT SUB 'ошибка установки базового адреса
END IF
IF __dpmi_set_segment_limit(UseSelector%, UseSize - 1) <> 0 THEN
ERR = 251: EXIT SUB 'ошибка установки предела сегмента
END IF
'Видеобуфер к работе подготовлен, соответствующий ему селектор настроен
'Теперь устанавливаем собственно сам графический режим
regs.x.ax = &H4F02: regs.x.bx = BITSET(ModeList(CurNum%), 14): __dpmi_int(&H10, @regs) 'режим с плоским буфером
IF regs.x.ax <> &H4F THEN ERR = 250: EXIT SUB
ERR = 0
END SUB
SUB VSScreenReset ()
'Освобождаем селектор и устанавливаем стандартный текстовый режим
IF UseSelector% <> 0 THEN
__dpmi_free_ldt_descriptor(UseSelector%): UseSelector% = 0
END IF
regs.x.ax = 0: __dpmi_int(&H10, @regs) 'режим 0 - стандартный текстовый режим
END SUB
SUB VSDrawPset (XP%, YP%, LColor%)
'Выводит точку с координатами (XP%, YP%) цветом LColor%
DIM OfsCount AS UINTEGER
IF (XP% < 0) OR (XP% >= VMDI.XResolution) THEN EXIT SUB
IF (YP% < 0) OR (YP% >= VMDI.YResolution) THEN EXIT SUB
OfsCount = YP% * VMDI.BytesPerScanLine + XP% * (VMDI.BitsPerPixel SHR 3)
ASM
push es
push ebx
mov ebx, [LColor%]
mov al, [ebx]
mov ebx, [OfsCount]
mov es, word ptr [UseSelector%]
mov es:[ebx], al
pop ebx
pop es
END ASM
END SUB
SUB VSCls
'Процедура очистки экрана. Заполняет весь кадровый буфер нулевым цветом
DIM OfsCount AS UINTEGER
OfsCount = VMDI.YResolution * VMDI.BytesPerScanLine
ASM
push es
push ecx
push edi
xor al, al
mov ecx, [OfsCount]
xor edi, edi
mov es, word ptr [UseSelector%]
rep stosb
pop edi
pop ecx
pop es
END ASM
END SUB
SUB VSDrawLine (X1%, Y1%, X2%, Y2%, LColor%)
'Рисует отрезок между точками (X1%, Y1%) и (X2%, Y2%) цветом LColor% с помощью алгоритма Брезенхейма
IF ABS(X2% - X1%) >= ABS(Y2% - Y1%) THEN 'наклон прямой меньше 45 градусов
Deff% = 2 * ABS(Y2% - Y1%): CritDeff% = ABS(X2% - X1%)
CurY% = Y1%: AddDeff% = 0
IF X2% > X1% THEN StppX% = 1 ELSE StppX% = -1
IF Y2% > Y1% THEN StppY% = 1 ELSE StppY% = -1
FOR CurX% = X1% TO X2% STEP StppX%
CALL VSDrawPset(CurX%, CurY%, LColor%) 'рисуем текущую точку
AddDeff% = AddDeff% + Deff%
IF AddDeff% >= CritDeff% THEN CurY% = CurY% + StppY%: AddDeff% = AddDeff% - 2 * CritDeff%
NEXT CurX%
ELSE 'наклон прямой больше 45 градусов
Deff% = 2 * ABS(X2% - X1%): CritDeff% = ABS(Y2% - Y1%)
CurX% = X1%: AddDeff% = 0
IF X2% > X1% THEN StppX% = 1 ELSE StppX% = -1
IF Y2% > Y1% THEN StppY% = 1 ELSE StppY% = -1
FOR CurY% = Y1% TO Y2% STEP StppY%
CALL VSDrawPset(CurX%, CurY%, LColor%) 'рисуем текущую точку
AddDeff% = AddDeff% + Deff%
IF AddDeff% >= CritDeff% THEN CurX% = CurX% + StppX%: AddDeff% = AddDeff% - 2 * CritDeff%
NEXT CurY%
END IF
END SUB
UseSelector% = 0: DOSBlock = AllocDOSMem(4096) 'выделяем блок нижней памяти в 4к
DOSBlockAddr = CUINT(DOSBlock) SHL 4 'линейный адрес выделенного блока
PRINT "Список доступных 8-битовых графических режимов"
TmpUI = VSScreenList(8)
IF ERR <> 0 THEN
r% = ERR: PRINT "Ошибка при вызове ScreenList - "; r%: END 255
END IF
WHILE TmpUI <> 0
PRINT "Режим"; CurNum%; " разрешение - "; HiWord(TmpUI);"x"; LoWord(TmpUI); " цветность - "; VMDI.BitsPerPixel
TmpUI = VSScreenList
WEND
WHILE LEN(INKEY$) = 0: WEND
CALL VSScreenRes(640, 480, 8)
IF ERR <> 0 THEN
r% = ERR: PRINT "Ошибка при вызове ScreenRes - "; r%: END 255
END IF
FOR r% = 0 TO 639: CALL VSDrawPset(r%, 240, r% MOD 256): NEXT r%
CALL VSDrawLine(0, 100, 639, 100, 100)
CALL VSDrawLine(320, 0, 320, 479, 100)
WHILE LEN(INKEY$) = 0: WEND
CALL VSCls
FOR r% = 0 TO 479 STEP 20
CALL VSDrawLine(0, r%, 639, r% + 50, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
FOR r% = 479 TO 0 STEP -20
CALL VSDrawLine(0, r%, 639, r% - 50, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
FOR r% = 0 TO 639 STEP 20
CALL VSDrawLine(r%, 0, r% + 50, 479, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
FOR r% = 639 TO 0 STEP -20
CALL VSDrawLine(r%, 0, r% - 50, 479, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
CALL VSScreenReset: DOSBlock = FreeDOSMem(DOSBlock)
END
This is version of the program, which uses "Fat DS".
Code: Select all
'Вариант использования VESA с использованием техники ЖИРНОГО DS
'(раздувания селектора DS на все адресное пространство)
'$LANG: "fblite"
'$INCLUDE: 'dos\go32.bi'
'$INCLUDE: 'dos\dpmi.bi'
TYPE RealModePtr FIELD = 1
ROffs AS USHORT
RSegm AS USHORT
END TYPE
TYPE VbeInfoBlock FIELD = 1
VbeSignature AS UINTEGER 'VBE Signature
VbeVersion AS USHORT 'VBE Version
OemStringPtr AS RealModePtr 'Pointer to OEM String
Capabilities AS UINTEGER 'Capabilities of graphics cont.
VideoModePtr AS RealModePtr 'Pointer to Video Mode List
TotalMemory AS USHORT 'Number of 64kb memory blocks
OemSoftwareRev AS USHORT 'VBE implementation Software revision
OemVendorNamePtr AS RealModePtr 'Pointer to Vendor Name String
OemProductNamePtr AS RealModePtr 'Pointer to Product Name String
OemProductRevPtr AS RealModePtr 'Pointer to Product Revision String
VSReserved (0 TO 221) AS UBYTE 'Reserved for VBE implementation scratch area
OemData (0 TO 255) AS UBYTE 'Data Area for OEM Strings
END TYPE
TYPE ModeInfoBlock FIELD = 1
'Mandatory information for all VBE revisions
ModeAttributes AS USHORT 'mode attributes
WinAAttributes AS UBYTE 'window A attributes
WinBAttributes AS UBYTE 'window B attributes
WinGranularity AS USHORT 'window granularity
WinSize AS USHORT 'window size
WinASegment AS USHORT 'window A start segment
WinBSegment AS USHORT 'window B start segment
WinFuncPtr AS RealModePtr 'pointer to window function
BytesPerScanLine AS USHORT 'bytes per scan line
'Mandatory information for VBE 1.2 and above
XResolution AS USHORT 'horizontal resolution in pixels or chars
YResolution AS USHORT 'vertical resolution in pixels or chars
XCharSize AS UBYTE 'character cell width in pixels
YCharSize AS UBYTE 'character cell height in pixels
NumberOfPlanes AS UBYTE 'number of memory planes
BitsPerPixel AS UBYTE 'bits per pixel
NumberOfBanks AS UBYTE 'number of banks
MemoryModel AS UBYTE 'memory model type
BankSize AS UBYTE 'bank size in KB
NumberOfImagePages AS UBYTE 'number of images
MBReserved AS UBYTE 'reserved for page function
'Direct Color fields (required for direct/6 and YUV/7 memory models)
RedMaskSize AS UBYTE 'size of direct color red mask in bits
RedFieldPosition AS UBYTE 'bit position of lsb of red mask
GreenMaskSize AS UBYTE 'size of direct color green mask in bits
GreenFieldPosition AS UBYTE 'bit position of lsb of green mask
BlueMaskSize AS UBYTE 'size of direct color blue mask in bits
BlueFieldPosition AS UBYTE 'bit position of lsb of blue mask
RsvdMaskSize AS UBYTE 'size of direct color reserved mask in bits
RsvdFieldPosition AS UBYTE 'bit position of lsb of reserved mask
DirectColorModeInfo AS UBYTE 'direct color mode attributes
'Mandatory information for VBE 2.0 and above
PhysBasePtr AS UINTEGER 'physical address for flat frame buffer
OffScreenMemOffset AS UINTEGER 'pointer to start of off screen memory
OffScreenMemSize AS USHORT 'amount of off screen memory in 1k units
MB2Reserved (0 TO 205) AS UBYTE 'remainder of ModeInfoBlock
END TYPE
DIM SHARED DOSBlock AS USHORT, DOSBlockAddr AS UINTEGER, regs AS __dpmi_regs, FrameBuffer AS UBYTE PTR
DIM SHARED VBEI AS VbeInfoBlock, VMDI AS ModeInfoBlock, CurNum%, ModeList(1 TO 256) AS USHORT
DIM SHARED TmpUI AS UINTEGER
FUNCTION AllocDOSMem (BYVAL NeedSize%) AS USHORT
ParSize% = NeedSize% \ 16
IF (NeedSize% MOD 16) <> 0 THEN ParSize% = ParSize% + 1
IF (ParSize% > 65535) OR (ParSize% <= 0) THEN AllocDOSMem = 0: EXIT FUNCTION
regs.x.ax = &H4800: regs.x.bx = ParSize%: __dpmi_int(&H21, @regs)
IF BIT(regs.x.flags, 0) THEN AllocDOSMem = 0: ERR = 255: EXIT FUNCTION
ERR = 0: AllocDOSMem = regs.x.ax 'сегмент выделенного блока
END FUNCTION
FUNCTION FreeDOSMem (BYVAL BlockSegm AS USHORT) AS USHORT
regs.x.ax = &H4900: regs.x.es = BlockSegm: __dpmi_int(&H21, @regs)
FreeDOSMem = BIT(regs.x.flags, 0)
END FUNCTION
FUNCTION VSScreenList (NDepth% = 0) AS UINTEGER
STATIC CurDepth%
VSScreenList = 0
IF NDepth% > 0 THEN 'это первое обращение - получаем список доступных режимов
CurDepth% = 0: CurNum% = 0: tmp$ = "VBE2"
DOSMEMPUT STRPTR(tmp$), 4, DOSBlockAddr
regs.x.ax = &H4F00: regs.x.es = DOSBlock: regs.x.di = 0: __dpmi_int(&H10, @regs)
IF regs.x.ax <> &H4F THEN ERR = 254: EXIT FUNCTION
DOSMEMGET DOSBlockAddr, LEN(VBEI), @VBEI
IF VBEI.VbeSignature <> CVL("VESA") THEN ERR = 253: EXIT FUNCTION 'нет верной сигнатуры
IF VBEI.VbeVersion < &H200 THEN ERR = 252: EXIT FUNCTION 'версия VESA меньше 2.0 - линейный кадровый буфер не поддерживается
'Считываем список доступных видеорежимов
DOSMEMGET (CUINT(VBEI.VideoModePtr.RSegm) SHL 4) + VBEI.VideoModePtr.ROffs, 512, @ModeList(1)
CurDepth% = NDepth%
END IF
'Процедура не вызывалась ранее с явным указанием NDepth% или при построении списка режимов произошла ошибка
IF CurDepth% <= 0 THEN ERR = 251: EXIT FUNCTION
DO
CurNum% = CurNum% + 1
IF (CurNum% < LBOUND(ModeList)) OR (CurNum% > UBOUND(ModeList)) THEN EXIT DO
IF ModeList(CurNum%) = -1 THEN CurDepth% = 0: EXIT DO 'список доступных видеорежимов закончен
'получим информацию о текущем видеорежиме
regs.x.ax = &H4F01: regs.x.cx = ModeList(CurNum%)
regs.x.es = DOSBlock: regs.x.di = 0: __dpmi_int(&H10, @regs)
IF regs.x.ax <> &H4F THEN CONTINUE DO
DOSMEMGET DOSBlockAddr, LEN(VMDI), @VMDI 'получаем блок информации о режиме
'режим не поддерживается или он неграфический - не подходит
IF NOT (BIT(VMDI.ModeAttributes, 0) AND BIT(VMDI.ModeAttributes, 0)) THEN CONTINUE DO
'недоступен режим с линейным кадровым буфером
IF (NOT BIT(VMDI.ModeAttributes, 7)) OR (VMDI.PhysBasePtr = 0) THEN CONTINUE DO
'неподходящая модель цветности (поддерживаются только упаук ованные пиксели или "прямой цвет")
IF (VMDI.MemoryModel <> 4) AND (VMDI.MemoryModel <> 6) THEN CONTINUE DO
IF (VMDI.NumberOfBanks <> 1) OR (VMDI.NumberOfPlanes <> 1) THEN CONTINUE DO
'количество разрядов цветности не совпадает с искомым
IF VMDI.BitsPerPixel <> CurDepth% THEN CONTINUE DO
VSScreenList = (CUINT(VMDI.XResolution) SHL 16) + VMDI.YResolution: EXIT DO
LOOP
IF (CurNum% < LBOUND(ModeList)) OR (CurNum% > UBOUND(ModeList)) THEN CurDepth% = 0 'список доступных видеорежимов закончен
ERR = 0
END FUNCTION
SUB VSScreenRes (NWidth%, NHeight%, NDepth%)
DIM VModeParam AS UINTEGER, minfo as __dpmi_meminfo, UseSize AS UINTEGER, DSAddr AS UINTEGER
VModeParam = VSScreenList(NDepth%)
DO UNTIL VModeParam = 0
IF (HiWord(VModeParam) = NWidth%) AND (LoWord(VModeParam) = NHeight%) THEN EXIT DO
VModeParam = VSScreenList
LOOP
IF (HiWord(VModeParam) <> NWidth%) OR (LoWord(VModeParam) <> NHeight%) THEN
ERR = 255: EXIT SUB 'подходящего под требования режима не найдено
END IF
'Требуемый режим найден - его номер ModeList(CurNum%). Блок VMDI также уже заполнен.
'Картируем видеобуфер в пространство линейных адресов
UseSize = VMDI.BytesPerScanLine * VMDI.YResolution
IF (UseSize MOD &H1000) <> 0 THEN UseSize = ((UseSize \ &H1000) + 1) * &H1000 'выравниваем размер по целым страницам
minfo.address = VMDI.PhysBasePtr: minfo.size = UseSize
IF __dpmi_physical_address_mapping (@minfo) <> 0 THEN
ERR = 254: EXIT SUB 'не удалось картировать видеобуфер в линейное адресное пространство
END IF
DSSelector% = 0
ASM mov word ptr [DSSelector], ds
IF __dpmi_set_segment_limit(DSSelector%, &HFFFFFFFF) <> 0 THEN
ERR = 253: EXIT SUB 'ошибка установки предела сегмента
END IF
IF __dpmi_get_segment_base_address(DSSelector%, @DSAddr) <> 0 THEN
ERR = 252: EXIT SUB 'ошибка получения базового адреса сегмента
END IF
IF minfo.address < DSAddr THEN 'сегмент начинается за видеобуфером - исправляем
IF __dpmi_set_segment_base_address(DSSelector%, minfo.address - 2) <> 0 THEN
ERR = 251: EXIT SUB 'ошибка установки базового адреса
END IF
DSAddr = minfo.address - 2
END IF
FrameBuffer = CAST(UBYTE PTR, minfo.address - DSAddr)
'Видеобуфер к работе подготовлен, соответствующий ему указатель настроен
'Теперь устанавливаем собственно сам графический режим
regs.x.ax = &H4F02: regs.x.bx = BITSET(ModeList(CurNum%), 14): __dpmi_int(&H10, @regs) 'режим с плоским буфером
IF regs.x.ax <> &H4F THEN ERR = 250: EXIT SUB
ERR = 0
END SUB
SUB VSScreenReset ()
'Освобождаем селектор и устанавливаем стандартный текстовый режим
regs.x.ax = 0: __dpmi_int(&H10, @regs) 'режим 0 - стандартный текстовый режим
END SUB
SUB VSDrawPset (XP%, YP%, LColor%)
'Выводит точку с координатами (XP%, YP%) цветом LColor%
DIM OfsCount AS UINTEGER
IF (XP% < 0) OR (XP% >= VMDI.XResolution) THEN EXIT SUB
IF (YP% < 0) OR (YP% >= VMDI.YResolution) THEN EXIT SUB
OfsCount = YP% * VMDI.BytesPerScanLine + XP% * (VMDI.BitsPerPixel SHR 3)
*(FrameBuffer + OfsCount) = LColor%
END SUB
SUB VSCls
'Процедура очистки экрана. Заполняет весь кадровый буфер нулевым цветом
CALL CLEAR (*FrameBuffer, 0, VMDI.YResolution * VMDI.BytesPerScanLine)
END SUB
SUB VSDrawLine (X1%, Y1%, X2%, Y2%, LColor%)
'Рисует отрезок между точками (X1%, Y1%) и (X2%, Y2%) цветом LColor% с помощью алгоритма Брезенхейма
IF ABS(X2% - X1%) >= ABS(Y2% - Y1%) THEN 'наклон прямой меньше 45 градусов
Deff% = 2 * ABS(Y2% - Y1%): CritDeff% = ABS(X2% - X1%)
CurY% = Y1%: AddDeff% = 0
IF X2% > X1% THEN StppX% = 1 ELSE StppX% = -1
IF Y2% > Y1% THEN StppY% = 1 ELSE StppY% = -1
FOR CurX% = X1% TO X2% STEP StppX%
CALL VSDrawPset(CurX%, CurY%, LColor%) 'рисуем текущую точку
AddDeff% = AddDeff% + Deff%
IF AddDeff% >= CritDeff% THEN CurY% = CurY% + StppY%: AddDeff% = AddDeff% - 2 * CritDeff%
NEXT CurX%
ELSE 'наклон прямой больше 45 градусов
Deff% = 2 * ABS(X2% - X1%): CritDeff% = ABS(Y2% - Y1%)
CurX% = X1%: AddDeff% = 0
IF X2% > X1% THEN StppX% = 1 ELSE StppX% = -1
IF Y2% > Y1% THEN StppY% = 1 ELSE StppY% = -1
FOR CurY% = Y1% TO Y2% STEP StppY%
CALL VSDrawPset(CurX%, CurY%, LColor%) 'рисуем текущую точку
AddDeff% = AddDeff% + Deff%
IF AddDeff% >= CritDeff% THEN CurX% = CurX% + StppX%: AddDeff% = AddDeff% - 2 * CritDeff%
NEXT CurY%
END IF
END SUB
DOSBlock = AllocDOSMem(4096) 'выделяем блок нижней памяти в 4к
DOSBlockAddr = CUINT(DOSBlock) SHL 4 'линейный адрес выделенного блока
PRINT "Список доступных 8-битовых графических режимов"
TmpUI = VSScreenList(8)
IF ERR <> 0 THEN
r% = ERR: PRINT "Ошибка при вызове ScreenList - "; r%: END 255
END IF
WHILE TmpUI <> 0
PRINT "Режим"; CurNum%; " разрешение - "; HiWord(TmpUI);"x"; LoWord(TmpUI); " цветность - "; VMDI.BitsPerPixel
TmpUI = VSScreenList
WEND
WHILE LEN(INKEY$) = 0: WEND
CALL VSScreenRes(640, 480, 8)
IF ERR <> 0 THEN
r% = ERR: PRINT "Ошибка при вызове ScreenRes - "; r%: END 255
END IF
FOR r% = 0 TO 639: CALL VSDrawPset(r%, 240, r% MOD 256): NEXT r%
CALL VSDrawLine(0, 100, 639, 100, 100)
CALL VSDrawLine(320, 0, 320, 479, 100)
WHILE LEN(INKEY$) = 0: WEND
CALL VSCls
FOR r% = 0 TO 479 STEP 20
CALL VSDrawLine(0, r%, 639, r% + 50, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
FOR r% = 479 TO 0 STEP -20
CALL VSDrawLine(0, r%, 639, r% - 50, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
FOR r% = 0 TO 639 STEP 20
CALL VSDrawLine(r%, 0, r% + 50, 479, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
FOR r% = 639 TO 0 STEP -20
CALL VSDrawLine(r%, 0, r% - 50, 479, r% MOD 256)
NEXT r%
WHILE LEN(INKEY$) = 0: WEND
CALL VSScreenReset: DOSBlock = FreeDOSMem(DOSBlock)
END
Both programs work excellently in pure DOS (FreeDOS 1.1, MS-DOS 7.1) and in Win98 DOS session.
Also both programs work reasonably good in DOSBOX 0.74 ("Fat DS" version periodically
crashes DOSBOX, the cause is still unclear).
NTVDM DPMI server in Windows XP don't support mapping of physical memory regions
(0800h function). Seems, applying of flat frame buffer is impossible there at all.
At least, I do not know how to do it.
Re: Access vesa modes in freebasic ?
It is still page faulting in dosbox and virtual pc.
I am using CWSDPMI for the DPMI server.
What dpmi server are you using?
I am using CWSDPMI for the DPMI server.
What dpmi server are you using?
-
- Posts: 42
- Joined: Mar 05, 2013 5:37
Re: Access vesa modes in freebasic ?
For DOS I use CWSDPMI r7.
May you use earlier version of CWSDPMI?
As far as I remember, version 3 is really less stable.
PS. Additionally i tested both programs in FreeDOS 1.1 under VirtualBox. All work excellently.
May you use earlier version of CWSDPMI?
As far as I remember, version 3 is really less stable.
PS. Additionally i tested both programs in FreeDOS 1.1 under VirtualBox. All work excellently.
Re: Access vesa modes in freebasic ?
Okay I am still having trouble with page faults. What version of freebasic are you using.
-
- Posts: 42
- Joined: Mar 05, 2013 5:37
Re: Access vesa modes in freebasic ?
I use FreeBASIC 0.25, which was downloaded from github in form of source code
approximately three months before.
At this link (http://tempfile.ru/file/2888375) there are executable files of the both programs. Try
execute it directly without compilation.
approximately three months before.
At this link (http://tempfile.ru/file/2888375) there are executable files of the both programs. Try
execute it directly without compilation.
Re: Access vesa modes in freebasic ?
I got my version of it to work!
I managed to cut and paste you fat ds part.
What I like about the fat ds is, that I don't have to change my assembly code.
I can now get RadioTelephone Tutor to run speedy in dosbox at 500 cycles!
Freebasic updating the framebuffer was really making the keyboard interface sluggish at 500 cycles.
The interface is definitely not sluggish now.
I managed to cut and paste you fat ds part.
What I like about the fat ds is, that I don't have to change my assembly code.
I can now get RadioTelephone Tutor to run speedy in dosbox at 500 cycles!
Freebasic updating the framebuffer was really making the keyboard interface sluggish at 500 cycles.
The interface is definitely not sluggish now.
Last edited by lassar on Jul 05, 2013 21:22, edited 1 time in total.
Re: Access vesa modes in freebasic ?
VESA graphics under XP's NTVDM are probably a lost cause (though way better than Vista/7/8). I think there are some third-party hacks to get it working there, but I don't remember the details (and never tried and don't have XP anymore to test, sadly). The person to ask would probably be RayeR from BTTR Forum as he seemed fairly knowledgeable about such things.monochromator wrote:NTVDM DPMI server in Windows XP don't support mapping of physical memory regions
(0800h function). Seems, applying of flat frame buffer is impossible there at all.
At least, I do not know how to do it.
Otherwise, it's probably best to use DOSEMU or VirtualBox or even native FreeDOS (e.g. atop bootable USB from RUFUS).
Re: Access vesa modes in freebasic ?
Thank you monochromator for reply to my post and helping me out with my code.
I managed to get GFX_NULL vesa mouse routines working.
Here is the link to it in tricks and tips.
Again I say thank you.
I managed to get GFX_NULL vesa mouse routines working.
Here is the link to it in tricks and tips.
Again I say thank you.