flat assembler
Message board for the users of flat assembler.
Index
> DOS > VESA from DPMI |
Author |
|
DOS386 05 Jan 2007, 23:28
I'd like to use VESA graph modes from DPMI. Well, i DID use the
forum search and Google search, and there were some "hits", but none of them usable: - In most forum "hits" about VESA the thing was asked, but not really clarified since I need a classic DOS / DPMI version - Google hits are mostly "C" or PASCAL, quite useless for me For simplicity, I limit to LFB'ed 24 and 32 bpp modes 800x600 and 1024x768, and VESA 2.0 version, and no "MTTRR". I need to do from DPMI, and not from "raw" PC, not from real mode, and not from Unreal mode ... What it the simplest and correct way to do ? Can I rely on the mode numbers or not ? Probably need: Code: Int 10/AX=4F01h - VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION Int 10/AX=4F02h - VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE but: Code: 10 ax=1002h set all palette registers ES:E/DX 10 ax=1009h get all palette registers ES:E/DX 10 ax=1012h set DAC registers ES:E/DX 10 ax=1017h get DAC registers ES:E/DX 13 ah=02h disk read into buffer ES:E/BX 13 ah=03h disk write from buffer ES:E/BX 13 ah=08h for FD return drive parameter table in ES:E/DI 15 ah=C0h read configuration into ES:E/BX 15 ax=C207h set pointing device event proc ES:E/BX 25 absolute disk read buffer in DS:E/BX 26 absolute disk write buffer in DS:E/BX 2F ax=168Ah supports vendor "MS-DOS" and "VIRTUAL SUPPORT" callback for "MS-DOS" supports function 100h (LDT sel) 33 ax=0009h define graphics cursor ES:E/DX 33 ax=000Ch define interrupt subroutine ES:E/DX 33 ax=0012h define large graphics cursor ES:E/DX 33 ax=0014h exchange interrupt subroutine ES:E/DX 33 ax=0016h save driver state ES:E/DX 33 ax=0017h restore driver state ES:E/DX 33 ax=0018h set alternate mouse user handler ES:E/DX VESA seems to be barred out ^^^ from the "DOS API" translation Do I need Code: Int 31/AX=0300h - DPMI 0.9+ - SIMULATE REAL MODE INTERRUPT http://www.ctyme.com/intr/rb-5831.htm this ^^^ thing ?? How to execute the INT ? Need DOS memory ? I should already have some allocated. EDIT: answered my question myself later (with help of Tomasz, Japheth, ...) http://board.flatassembler.net/download.php?id=3472 _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug Last edited by DOS386 on 16 Jan 2008, 01:44; edited 1 time in total |
|||
05 Jan 2007, 23:28 |
|
DOS386 06 Jan 2007, 00:22
Thanks.
Quote: you need to provide buffer in DOS memory, thus you'll need to use int 31h/300h for it (and some DOS memory allocated) OK, I think I have the DOS memory, (from loading my MZ-loader/stub, alternatively, HDPMI has a 8 KB buffer) Could you please provide an example how to call Int 10/AX=4F02h with int 31h/300h ? Quote: like the "pitch" of the screen (the amount of bytes at which the rows are aligned, this is not necessarily equal to the amount of bytes per all pixels in row - such assumption is a frequent mistake) Didn't know this Quote: And to access the LFB you need a physical address mapping - you've got function 800h of int 31h for this. http://www.ctyme.com/intr/rb-5861.htm Quote: Implementations may refuse this call because it can circumvent protects. The caller must build an appropriate selector for the memory. Do not use for memory mapped in the first megabyte Seems I neen both: Create a segment/selector AND INT $31,$800 ??? In what order to execute all the stuff ? Or are there some GOOD (FASM, DPMI) examples around ? _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
06 Jan 2007, 00:22 |
|
Japheth 07 Jan 2007, 09:22
Here is an example for Vesa 4F00h, but written for MASM and for a non-flat model:
rmcs is a DPMI Real Mode Call Structure @flat is a FLAT, zero-based selector Code: GetVesaInfo proc public pVesaInfo:ptr VESAINFO local dosmemsel:dword local linDosMem:dword local rcptr:dword local rmcs:RMCS xor eax,eax mov dosmemsel,eax mov ax,0100h ;alloc DOS memory mov bx,20h ;256+256 bytes = sizeof VESAINFO int 31h jc svmx_er mov dosmemsel,edx mov rmcs.rES,ax mov rmcs.rAX,4F00h mov rmcs.rDI,0 mov rmcs.rSSSP,0 ;clear the VESA info buffer movzx eax,ax shl eax,4 mov linDosMem, eax mov edi,eax mov ecx,200h/4 xor eax,eax push es push @flat pop es rep stosd pop es mov ebx, linDosMem ; mov eax,"ASEV" mov eax,"2EBV" mov @flat:[ebx],eax push ebx lea edi,rmcs push es push ss pop es mov bx,0010h mov cx,0000h mov ax,0300h int 31h pop es pop ebx jc svmx_er cmp rmcs.rAX,004Fh jnz svmx_er mov esi,linDosMem mov edi, pVesaInfo mov ecx,sizeof VESAINFO push ds push @flat pop ds rep movsb pop ds mov eax,1 jmp svmx_ex svmx_er: xor eax,eax svmx_ex: mov edx,dosmemsel and edx,edx jz @F push eax mov ax,0101h int 31h pop eax @@: ret GetVesaInfo endp |
|||
07 Jan 2007, 09:22 |
|
DOS386 14 Jan 2007, 05:00
Quote: Here is an example for Vesa 4F00h Thanks. Quote: but written for MASM The instructions seem OK, but the MASM stuff ... Quote: and for a non-flat model flat / non-flat , zero / non-zero ... Is this a problem ? My model is from 2 previous threads: code running in DPMI memory, additional 0-based segment for "dosmemget" and "dosmemput", well, and the starting/loader segment from USEDPMI - should I kick this one maybe ??? Quote: rmcs is a DPMI Real Mode Call Structure This is the problem. Declared somewhere ... in MASM style ... and lacking in the example ... what is it ? A buffer in DPMI memory ? Zeroized ? Quote: @flat is a FLAT, zero-based selector For my "dosmemget&dosmemput-segment" from previous thread ? Code: ; ; *** Get VESA info *** ;pVesaInfo ;local dosmemsel:dword ;local linDosMem:dword ;local rcptr:dword ;local rmcs:RMCS ; *** mem alloc, rmcs ??? *** xor eax,eax mov dosmemsel,eax ; No alloc yet mov ax,0100h ; Alloc DOS memory mov bx,20h ; $200 bytes = sizeof VESAINFO int $31 jc svmx_er ; Failure mov dosmemsel,edx ; Selector: only for deallocation // may NOT (?) = 0 mov rmcs.rES,ax ; Segment mov rmcs.rAX,$4F00 ; INT $10/$4F00 mov rmcs.rDI,0 ; ??? mov rmcs.rSSSP,0 ; ??? ; *** clear the VESA info buffer *** movzx eax,ax ; Clear 16 top bits in EAX shl eax,4 ; Segment to linear mov linDosMem, eax mov edi,eax mov ecx,$80 ; $200/4 xor eax,eax ; eax:=0 push es push xxxflat pop es rep stosd ; write EAX (=0) to ES:EDI and this ECX times !!! pop es ; restore es ; *** Finally execute the INT *** mov ebx, linDosMem ; mov eax,"ASEV" mov eax,"2EBV" mov xxxflat:[ebx],eax ; Just write to DOS mem without segment reg hack ??? push ebx lea edi,rmcs ; ?????????????????????????? push es push ss ; vvv pop es ; ^^^ ES:=SS but why ??? mov bx,$0010 ; Should be INT $10 finally mov cx,0 ; Don't copy stack junk ??? mov ax,$0300 ; The "simulate real mode INT" thing int 31h pop es ; Restore ES pop ebx ; Restore EBX, was "linDosMem" jc svmx_er ; INT $300 failure cmp rmcs.rAX,$004F ; Anything else means FAILURE jnz svmx_er mov esi,linDosMem mov edi, pVesaInfo ; ???????????????????????????????? mov ecx,sizeof VESAINFO ; ???????????????? simply $200 maybe ??? push ds push xxxflat pop ds ; ds:=xxxflat // "es" was NEVER set !!! rep movsb ; MOVE DS:ESI -> ES:EDI, ECX (bytes) pop ds ; Restore ds mov eax,1 ; 1 : OK jmp svmx_ex svmx_er: xor eax,eax ; 0 : Failure Grrrrrhhhhhhhhh svmx_ex: mov edx,dosmemsel and edx,edx ; cmp edx,0 jz @F ; No memory push eax mov ax,$0101 ; Deallocate the memory int $31 ; Ignore potential errors pop eax @@: ret ; Hard work done Nice code (added comments), some issues: - RMSC ??? - RCPTR ??? - dosmemsel&lindosmem: 2 UINT32 variables in code segment ? - PVESAinfo: ??? Addr of buffer in code segment, $200 bytes ? - "sizeof VESAINFO": complicated way to say $200 ? - ES=??? supposed to be ES=CS at code start ? - "lea edi,rmcs" what does this do ? Would "mov" not work ? - "mov xxxflat:[ebx],eax" is "dosmemput" that easy (when I have the segment/selector) ??? - Why is ES set to SS before INT $300 ? _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
14 Jan 2007, 05:00 |
|
Japheth 14 Jan 2007, 08:39
for
- RMSC ??? - "lea edi,rmcs" what does this do ? Would "mov" not work ? - Why is ES set to SS before INT $300 ? issues see RBIL (search "310300") - ES=??? supposed to be ES=CS at code start ? Yes. Code is for a flat (but not necessarily zero-base) memory model, that is, CS=ES=DS. No assumption is made about SS, however. - RCPTR ??? is a leftover - dosmemsel&lindosmem: 2 UINT32 variables in code segment ? they are local (temporary) variables |
|||
14 Jan 2007, 08:39 |
|
DOS386 15 Jan 2007, 02:50
Thanks.
Quote:
This one: http://www.ctyme.com/intr/rb-5831.htm Code: Int 31/AX=0300h DPMI 0.9+ - SIMULATE REAL MODE INTERRUPT AX = 0300h BL = interrupt number BH = flags bit 0: Reset the interrupt controller and A20 line (DPMI 0.9) reserved, must be 0 ( DPMI 1.0+ ) others: Reserved, must be 0. CX = number of words to copy from protected mode to real mode stack. ES: (E)DI = selector:offset of real mode call structure (see #03148) Return: CF clear if successful real mode call structure modified (all fields except SS:SP, CS:IP filled with return values from real mode interrupt) CF set on error AX = error code (DPMI 1.0+ ) (8012h,8013h,8014h,8021h) (see #03143) protected mode stack unchanged Notes: 16-bit programs use ES:DI as pointer, 32-bit programs use ES:EDI. CS:IP in the real mode call structure is ignored for this call, instead, the indicated interrupt vector is used for the address. The flags in the call structure are pushed on the real mode stack to form an interrupt stack frame, and the trace and interrupt flags are clear on entry to the handler. DPMI will provide a small (30 words) real mode stack if SS:SP is zero. The real mode handler must return with the stack in the same state as it was on being called See Also: AX=0302h - AX=FF01h INT 21/AX=2511h - INT 21/AH=E3h"OS/286" INT 2C/AX=0026h INT 2F/AX=FB42h/BX=000Dh Format of DPMI real mode call structure: Offset Size Description (Table 03148) 00h DWORD EDI 04h DWORD ESI 08h DWORD EBP 0Ch DWORD reserved (00h) 10h DWORD EBX 14h DWORD EDX 18h DWORD ECX 1Ch DWORD EAX 20h WORD flags 22h WORD ES 24h WORD DS 26h WORD FS 28h WORD GS 2Ah WORD IP 2Ch WORD CS 2Eh WORD SP 30h WORD SS The lea edi,rmcs is NOT described here ^^^ and it is a serious problem since FASM refuses to compile it Quote:
Good, but ES is set to SS before the INT $31/$0300 and I still can't figure out why ... and what I also noticed just now that "my" USEDPMI based code does NOT deal with SS at all ... HDPMI32 probably creates one for me but I have no idea where "my" stack is and how big it is Is this "rmcs" a $32 bytes buffer ? In the stack ? _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
15 Jan 2007, 02:50 |
|
LocoDelAssembly 15 Jan 2007, 03:03
Quote:
Did you use the square brackets around rcms? (LEA EDI, [rmcs]) |
|||
15 Jan 2007, 03:03 |
|
DOS386 15 Jan 2007, 03:17
Quote: Did you use the square brackets around rcms? (LEA EDI, [rmcs]) NO. See code above. Nevertheless: could you please explain me, what this lea does in this code and why I can't use mov instead ? _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
15 Jan 2007, 03:17 |
|
LocoDelAssembly 15 Jan 2007, 04:15
Depends on where the structure resides. If it's located at an EBP-based stack frame then you have to use "lea edi, [ebp-offset of rmcs]"(automatically done by using "lea edi, [rmcs]" if you are using PROC32.inc), but if you have a label that holds the structure then using "mov edi, label" is enough and takes one byte less than "lea edi, [label]". In your last code I don't see the structure RMCS defined nowhere so define it too.
Note that FASM requires all memory references square bracketed so things like "mov rmcs.rES,ax" must be converted to "mov [rmcs.rES],ax". LEA does not access any memory but since it needs a memory address it needs the source operand square bracketed too. I have no experience with PMODE VESA (and the very few experience with real mode VESA I forgot it all ) so I can't help you beyond those sintax things, sorry |
|||
15 Jan 2007, 04:15 |
|
DOS386 15 Jan 2007, 04:49
Quote: Depends on where the structure resides. I have no idea Quote: If it's located at an EBP-based stack frame then you have to use "lea edi, [ebp-offset of rmcs]"(automatically done by using "lea edi, [rmcs]" if you are using PROC32.inc), but if you have a label that holds the structure then using "mov edi, label" is enough and takes one byte less than "lea edi, [label]". COOL. Seems MASM where the example comes from does such tricks. Quote: In your last code I don't see the structure RMCS defined nowhere so define it too. Know issue Quote: I have no experience with PMODE VESA (and the very few experience with real mode VESA I forgot it all Razz) so I can't help you beyond those sintax things, sorry Thanks. Hope that someone else answers also ... _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
15 Jan 2007, 04:49 |
|
Japheth 15 Jan 2007, 08:37
> Good, but ES is set to SS before the INT $31/$0300 and I still can't figure
out why ... you will have to fully understand what a local variable is. Without this knowledge you will get some troubles when coding in ASM. This line ;local rmcs:RMCS which you commented out defines - in MASM - a local variable of type RMCS. One important difference between local and global variables is that for the first the address is known at run time only, while for the latter the address is known at link time. That's why LEA (load effective address) has to be used. > and what I also noticed just now that "my" USEDPMI based code does NOT deal with SS at all the DPMI host will translate the SS segment into a selector on initial switch to protected-mode. > but I have no idea where "my" stack is and how big it is Confused as already mentioned, the stack's location and size won't change by the switch to protected-mode. |
|||
15 Jan 2007, 08:37 |
|
DOS386 16 Jan 2007, 03:02
Thanks.
Quote: you will have to fully understand what a local variable is. Theoretically I know this ... but thought this issue would be limited to prog langs like PASCAL or "C" ... but have no idea how MASM handles them Does FASM support local variables at all ? Quote: Without this knowledge you will get some troubles when coding in ASM Probably one can always stay global only ... it's a question approach I had discovered various things that make simple things complicated in the past and local variables in ASM might join this list Quote: This line OK, marginally smarter again, MASM seems to translate those mov and lea in some obscure way Quote: the DPMI host will translate the SS segment into a selector on initial switch to protected-mode. Does this mean that the "main" stack my DPMI app is running on is the same stack as defined in the MZ-header (well, there are 3 more stacks according to HDPMI docs) ? Code: 6.4 Stacks When a client is running the host will switch among 4 stacks: _ the protected mode stack (PMS), which is the stack the DPMI client uses. It can switch these stacks as it likes and there are no special requirements about it. _ the locked protected mode stack (LPMS). The DPMI host switches the client application to this stack when - a hardware interrupt (IRQ) has occured - an interrupt is reflected from real mode (mostly IRQs, but also software interrupts 1Ch, 23h and 24h. - the DPMI client executes a real mode callback - the server notifies the client about an exception There exists 1 LPMS only and its size must be at least 4 KB. Once it is "in use" the host will no longer switch stacks until the LPMS is free again. _ the real mode stack (RMS). Usually this stack is located in the memory block the DPMI client has to deliver to the server on its initial switch to protected mode. This stack's size will be at least 200h bytes. It is used when there is a reflection from protected mode interrupts to real mode. If protected-mode is reentered (by a real-mode callback, a raw jump or a hardware IRQ), the RMS is in use and HDPMI will then use the real mode SS:SP of the last entry to protected mode as current real-mode stack. _ the ring 0 stack. This stack is invisible to the client, it is used by the dpmi host. For HDPMI this stack is 2 kB in size, and it is located in conventional memory. The host uses this stack for it's normal processing and to save the client's segment register values. Maybe I don't have to bother too much since HDPMI ^^^ does well for me Code: ; *** INT $31 / $0300 test *** use32 org 0 ; *** Print text using DOS API Translation *** mov ax,$0900 mov edx,t8 int 21h jmp @f t8 db 'Hello (API Trans) !!!',0Dh,0Ah,24h ; *** Create ZERO-based segment *** @@: mov cx,1 xor ax,ax int 31h ; allocate descriptor for data mov di,ax mov dx,ds lar cx,dx shr cx,8 or cx,0C000h mov bx,di int 31h ; set data descriptor access rights mov ecx,0 ;ZERO mov edx,0 mov ax,7 ; set descriptor base address CX:DX // CX high int 31h mov bx,di ;HACK ??? int 31h mov cx,0FFFFh mov dx,0FFFFh mov ax,8 ; set segment limit to 4 GB int 31h ; result : di : data descriptor mov fs,di ; store low segment ; *** Report success *** mov ax,0900h mov edx,t9 int 21h jmp @f t9 db 'Zero-based seg created (API Trans) !!!',0Dh,0Ah,24h ; *** Throw text into "buffer" *** @@: mov eax,"Bum$" mov ebx,$B8000 ; Text screen, no need to allocate mov [fs:ebx],eax ; Just write to DOS mem without segment reg hack ??? ; *** Prepare INT $300 *** BUF32=$100000 ; 1 MB , more than high enough (code < 1KB, segment 4 MB) mov ecx,$32 mov al,0 mov ebx,BUF32 @@: mov byte [ebx],al ; Clear $32 bytes buffer inc ebx dec ecx jnz @b mov word [BUF32+$1C],$0900 ; AX: INT $21,9 mov word [BUF32+$24],$B800 ; DS // DX=0 push ds pop es mov edi,BUF32 mov bx,$0021 ; Should be INT $21 finally mov cx,0 ; No stack junk mov ax,$0300 ; The "simulate real mode INT" thing int 31h @@: mov ax,$4C00 int $21 Well, testing INT $300 ^^^ and it seems to work. Is the code correct and safe ? (Except abusing text screen as transfer buffer ) ? I completely barred out lea, and reduced the PUSHing and POPeing of segment registers Will this code work with $10/$4F00 and any other INT or are there some potential pitfalls ? Code: mov @flat:[ebx],eax This ^^^ does NOT compile in FASM ... but Code: mov [fs:ebx],eax ;fs is the ZERO-based segment this ^^^ is the simplest DOSMEMPUT without hacking with the segment registers _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
16 Jan 2007, 03:02 |
|
Japheth 16 Jan 2007, 08:13
> Theoretically I know this ... but thought this issue would be limited to
> prog langs like PASCAL or "C" ... but have no idea how MASM handles > them masm creates an "EBP-based" stack frame. > Does FASM support local variables at all ? I'm sure it does. It's a rather trivial thing. >Probably one can always stay global only ... it's a question approach Yes, but "global only" is worse > I had discovered various things that make simple things complicated > in the past and local variables in ASM might join this list This definitely is wrong. Using local variables whereever possible is the best thing to do. > Is the code correct and safe ? If it runs... Using the text screen to store the string for int 21h, ah=09 might not always work as expected, though, if DOS happens to overwrite your input. |
|||
16 Jan 2007, 08:13 |
|
DOS386 27 Jan 2007, 04:15
Code: ; ; VESA ; SOMEMEMORY = $100000 ; 1 MB , more than high enough (code < 1KB, segment 4 MB) BUF32 = SOMEMEMORY ; $32 = #50 bytes DOSMEMSEL = SOMEMEMORY + $32 ; 2 bytes DOSMEMSEG = SOMEMEMORY + $34 ; 2 bytes DOSMEMLIN = SOMEMEMORY + $36 ; 4 bytes VESABUF = SOMEMEMORY + $3A ; $200 bytes VESAOK = SOMEMEMORY + $023A ; 1 byte PBUF = SOMEMEMORY + $023B ; $50 = #80 bytes VESABUFPO = SOMEMEMORY + $028B ; 2 bytes use32 org 0 ; *** Print text using DOS API Translation *** mov ax,$0900 mov edx,t8 int 21h jmp @f t8 db 'Hello (API Trans) !!!',0Dh,0Ah,24h @@: ; *** Create ZERO-based segment *** mov cx,1 xor ax,ax int 31h ; allocate descriptor for data mov di,ax mov dx,ds lar cx,dx shr cx,8 or cx,0C000h mov bx,di int 31h ; set data descriptor access rights mov ecx,0 ;ZERO mov edx,0 mov ax,7 ; set descriptor base address CX:DX // CX high int 31h mov bx,di ;HACK ??? int 31h mov cx,0FFFFh mov dx,0FFFFh mov ax,8 ; set segment limit to 4 GB int 31h ; result : di : data descriptor mov fs,di ; store low segment ; *** Report success *** mov ax,0900h mov edx,t9 int 21h jmp @f t9 db 'Zero-based seg created (API Trans) !!!',0Dh,0Ah,24h @@: ; *** Prepare INT $300 - zeroize $32 buffer *** mov cl,$32 mov al,0 mov ebx,BUF32 @@: mov byte [ebx],al ; Clear $32 bytes buffer inc ebx dec cl jnz @b ; *** Alloc DOS memory *** xor ax,ax mov [VESAOK],al ; Failure mov [DOSMEMSEL],ax ; Not yet alloced mov ax,$0100 ; Alloc DOS memory mov bx,$40 ; $0400 bytes (some buggy cards write > $0200 ???) int $31 ; Alloc returns: DX: selector AX: segment jc xxfail ; Failure in alloc mov [DOSMEMSEL],dx mov [DOSMEMSEG],ax movzx eax,ax ; Fill upper 16 bits with 0 shl eax,4 mov [DOSMEMLIN], eax ; Linear absolute addr ; *** Zeroize the $0400 buffer *** cld ; !!! Important !!! mov edi,eax mov ecx,$0100 ; $100 of 32-bit writes xor eax,eax push es push fs ; Here our ZERO-based selector is stored pop es ; ES:EDI is dest for STOSD rep stosd pop es ; Restore ES ; *** Write "VBE2" into "buffer" *** mov ebx, [DOSMEMLIN] ; mov eax,"ASEV" mov eax,"VBE2" mov [fs:ebx],eax ; *** INT $0300 register block & boom *** mov word [BUF32+$1C],$4F00 ; AX: INT $21,$4F00 // [ES:DI]: buffer mov word ax, [DOSMEMSEG] mov word [BUF32+$22],ax ; Set ES // DI=0 push ds ; & pop es ; & mov edi,BUF32 ; & [ES:EDI] for INT $0300 mov bx,$0010 ; Should be INT $10 finally mov cx,0 ; No stack junk mov ax,$0300 ; The "simulate real mode INT" thing int $31 jc xxfail ; INT $0300 failed ; *** Check the result *** mov ax,[BUF32+$1C] ; Capture AX from "simulate" buffer cmp ax,$004F ; !!! Was $4F00 now must be $004F otherwise failure !!! jne xxfail ; INT $10 failed inc byte [VESAOK] ; Report success ; *** Move from DOS memory to DPMI memory *** cld ; !!! mov esi,[DOSMEMLIN] mov edi,VESABUF mov ecx,$0200 ; Number of bytes push ds push ds pop es push fs ; Our ZERO-based selector pop ds rep movsb ; MOVE [DS:ESI] -> [ES:EDI], ECX (bytes) pop ds ; *** Dealloc DOS mem ? *** xxfail: mov dx, [DOSMEMSEL] and dx,dx ; cmp dx,0 jz @F mov ax,$0101 ; Deallocate int $31 @@: ; *** Report *** mov al,[VESAOK] cmp al, 0 jne xxok2 ; OK mov ax,0900h mov edx,t10 int 21h ; Grrrrhhh (((( jmp xxend t10 db 'No VESA or FATAL VESA error !!!',0Dh,0Ah,$24 xxok2: mov ax,0900h mov edx,t11 int 21h ; Great jmp @f t11 db 'VESA info captured !!! Let',$27,'s have a look:',0Dh,0Ah,24h @@: ; *** Dump the stuff *** xor ax,ax mov [VESABUFPO],ax ; Pointer inside VESABUF call xxcpbuf ; Clear and prepare print buffer xxdump: mov dx, [VESABUFPO] movzx ebx, dx add ebx, VESABUF mov al, [ebx] ; Pick one byte and dl, $0F ; VESABUFPO MOD 16 // offset in line mov dh,al mov ah,al and ah,$0F ; & Low 4 bits // reversed : LITTLE ENDIAN shr al,4 ; & High 4 bits add ax,$3030 ; Convert 0 -> ASCII "0" cmp al,$3A jb @f ; "b":below // OK, a number add al, 7 @@: cmp ah, $3A jb @f ; "b":below // OK, a number add ah, 7 @@: mov cx, ax ; Move the HEX to cx mov al, dl ; *1 add al, dl ; *2 add al, dl ; *3 movzx ebx, al add ebx, PBUF mov [ebx], cx ; Write the HEX number cmp dh,$24 je xxfaultychar ; $24 ("$") is THE MOST faulty char !!! cmp dh,$20 jb xxfaultychar ; <$20, faulty char cmp dh,$7E jb @f ; <$7E, good char xxfaultychar: mov dh, $2E ; Replace faulty char with "." @@: movzx ebx, dl ; dl still is offset in line add ebx, PBUF+50 mov [ebx], dh ; Write the ASCII char cmp dl,$0F jne xxnyp ; Not yet print mov ax,$0900 mov edx,PBUF int $21 ; Print content call xxcpbuf ; And kick it out from buffer mov eax,10000000 ; 10 Mega @@: nop or eax,eax ; Silly delay dec eax jnz @b xxnyp: mov ax, [VESABUFPO] inc ax cmp ax,$0200 je xxend ; End mov [VESABUFPO], ax jmp xxdump xxend: mov ax,$4C00 int $21 ; *** PROC: Clear PBUF buffer *** ;Trashes EAX,EBX,ECX // EDX remains intact xxcpbuf: mov ebx,PBUF mov ecx,$4C ; Count of passes mov al,$20 @@: mov [ebx],al ; Clear $4C bytes in $50 buffer inc ebx dec ecx jnz @b mov dword [PBUF+$4C],$240A0D20 ; SPC CR LF EOT ret ;END. ;00 DWORD EDI ;04 DWORD ESI ;08 DWORD EBP ;0C DWORD reserved (00h) ;10 DWORD EBX ;14 DWORD EDX ;18 DWORD ECX ;1C DWORD EAX ;20 WORD flags ;22 WORD ES ;24 WORD DS ;26 WORD FS ;28 WORD GS ;2A WORD IP ;2C WORD CS ;2E WORD SP ;30 WORD SS Seems I got the INT $4F00 working my buffer gets filled with sort of usable info Code: Format of SuperVGA information: Offset Size Description ) 00h 4 BYTEs (ret) signature ("VESA") (call) VESA 2.0 request signature ("VBE2"), required to receive version 2.0 info 04h WORD VESA version number (one-digit minor version -- 0102h = v1.2) 06h DWORD pointer to OEM name "761295520" for ATI 0Ah DWORD capabilities flags (see #00078) 0Eh DWORD pointer to list of supported VESA and OEM video modes (list of words terminated with FFFFh) 12h WORD total amount of video memory in 64K blocks ---VBE v1.x --- 14h 236 BYTEs reserved ---VBE v2.0 --- 14h WORD OEM software version (BCD, high byte = major, low byte = minor) 16h DWORD pointer to vendor name 1Ah DWORD pointer to product name 1Eh DWORD pointer to product revision string How to analyze the content correctly and decode all the 32-bit "pointers" ? "761295520" for ATI ($2D6072A0) - any use of this number ? Why do I need 32-bit pointers inside a $200 bytes buffer What's next ? Brute-force through all the modes using INT $4F01: Code: 00h WORD mode attributes (see #00080) 10h WORD bytes per scan line 12h WORD width in pixels (graphics) or characters (text) 14h WORD height in pixels (graphics) or characters (text) 19h BYTE number of bits per pixel 28h DWORD physical address of linear video buffer 2Ch DWORD pointer to start of offscreen memory Bitfields for VESA SuperVGA mode attributes: Bit(s) Description ) 0 mode supported by present hardware configuration 1 optional information available (must be =1 for VBE v1.2+) 2 BIOS output supported 3 set if color, clear if monochrome 4 set if graphics mode, clear if text mode ---VBE v2.0+ --- 5 mode is not VGA-compatible 6 bank-switched mode not supported 7 linear framebuffer mode supported Is it enough to analyze ^^^ this info ??? "10h WORD bytes per scan line" is the "pitch" ??? Quote: And to access the LFB you need a physical address mapping - you've got function 800h of int 31h for this. Code: INT 31 - DPMI 0.9+ - PHYSICAL ADDRESS MAPPING AX = 0800h BX:CX = physical address (should be above 1 MB) SI:DI = size in bytes Return: CF clear if successful BX:CX = linear address which maps the requested physical memory CF set on error AX = error code (DPMI 1.0+) (8003h,8021h) (see #03143) Notes: implementations may refuse this call because it can circumvent protects the caller must build an appropriate selector for the memory do not use for memory mapped in the first megabyte How to put it together ? Push "28h DWORD physical address of linear video buffer" and size of the LFB into INT $31/$0800 ? "build an appropriate selector" - Same way as I "build" for the low DOS memory, just replace 0 with output from INT $31/$0800 ? Is there a problem if my LFB falls into RAM area (already in use ) or will someone (DPMI kernel / hardware) workaround the problem for me ? Other things to care about ? _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
27 Jan 2007, 04:15 |
|
Japheth 27 Jan 2007, 16:34
> Seems I got the INT $4F00 working Laughing my buffer gets filled with sort of
Good! > Why do I need 32-bit pointers inside a $200 bytes buffer those are 32-bit real-mode pointers and it is not for sure that they will point inside the 200h buffer. > What's next ? Brute-force through all the modes using INT $4F01: Why not? At least it is a nice exercise. > Is it enough to analyze ^^^ this info ??? enough for what? > "10h WORD bytes per scan line" is the "pitch" ??? yes > Push "28h DWORD physical address of linear video buffer" and size of > the LFB into INT $31/$0800 ? yes > "build an appropriate selector" - Same way as I "build" for the low > DOS memory, just replace 0 with output from INT $31/$0800 ? it might be sufficient to build 1 true flat (base==0) selector with limit -1 and access anything with it. > Is there a problem if my LFB falls into RAM area (already in use or will > someone (DPMI kernel / hardware) workaround the problem for me ? this should never be an issue (it's similiar to the A000-BFFF video segment) |
|||
27 Jan 2007, 16:34 |
|
DOS386 27 Jan 2007, 19:28
Thanks.
I'll look at $4F01 and then $4F02 now Quote: enough for what? To set up a LFB'ed 32 or 24 bpp, 1024*768 or 800*600 mode and be able to write into the LFB as stated at thread start. Quote: It might be sufficient to build 1 true flat (base==0) selector with limit -1 and access anything with it Can I just reuse the selector from code above or are there problems with it ? The stuff is still sort of mysterious, found out that: Code: push cs pop ds known from RM generates a crash in DPMI Although both have same (non-ZERO) base address _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
27 Jan 2007, 19:28 |
|
Japheth 28 Jan 2007, 10:55
Code: push cs pop ds it is possible to load DS with a code selector in protected-mode, but you cannot write to the memory then. Trying to load SS with a code selector (or CS with a data selector) will cause a GPF immediately. |
|||
28 Jan 2007, 10:55 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.