Opening a DOS CLI in FreeBasic is easy (SHELL command with no arguments), but works only under text mode. If you are in graphic mode, the DOS command line is not visible (although it's still possible to type commands and have them executed). Under QB and GWBasic the DOS prompt was visible, although it usually broke all the screen layout.
A more elegant solution would be to have the DOS console inside a window displayed on the graphic screen (as it was done under Windows 3.1, for example, or in DesqView). Besides Windows and Desqview, there aren't many other software for DOS that offer a similar features, one is WinDos by Oscar Gonzalez. I looked at the code to do that, and it was pretty simple, so I ported it to FreeBasic.
Code: Select all
#include "dos/dpmi.bi"
#include "dos/go32.bi"
#include "dos/sys/farptr.bi"
dim shared as _go32_dpmi_registers regs_0x10
dim shared as _go32_dpmi_seginfo info_0x10
dim shared as _go32_dpmi_seginfo old_vector_0x10
dim shared as _go32_dpmi_seginfo old_handler_0x08, new_handler_0x08
dim shared as integer VideoRows = 24
dim shared as integer VideoCols = 80
dim shared as integer CursorX = 0
dim shared as integer CursorY = 0
dim shared as integer CursorIniRow = 6
dim shared as integer CursorEndRow = 7
dim shared as integer Attr = &h07
dim shared as integer ox, oy 'Position of the 'Window'
Dim shared DosColors(16) As integer = {&H000000, &H0000AA, &H00AA00, &H00AAAA, &HAA0000, &HAA00AA, &HAA5500, &HAAAAAA, &H555555, &H5555FF, &H55FF55, &H55FFFF, &HFF5555, &HFF55FF, &HFFFF55, &HFFFFFF}
declare function Int_0x10 cdecl(r as _go32_dpmi_registers ptr) as integer
function GetChar(x as integer, y as integer) as integer
_farsetsel(_go32_info_block.selector_for_linear_memory)
return _farnspeekw( _go32_info_block.linear_address_of_primary_screen + 2 * ( ( ( y ) * VideoCols ) + ( x ) ) )
end function
sub PutCh(x as integer, y as integer, c as integer)
_farsetsel(_go32_info_block.selector_for_linear_memory)
_farnspokew( _go32_info_block.linear_address_of_primary_screen + 2 * ( ( ( y ) * VideoCols ) + ( x ) ) , c )
end sub
sub DrawScreen
screenlock
static t as ubyte
for y as integer=0 to VideoRows
for x as integer=0 to VideoCols-1
dim vmem as integer=GetChar(x,y)
dim as ubyte c,a
c=vmem and 255: a= vmem shr 8
line (ox+x*8,oy+y*8)-step(7,7),DosColors(a shr 4),bf
draw string (ox+x*8,oy+y*8),chr(c),DosColors(a and 15)
next
next
t+=1: if t>18 then t=0
if t>9 then 'draw blinking cursor
'dim as integer p = 2 * (RAM[&h450 + RAM[&h462]*2] + RAM[&h451 + RAM[&h462]*2] * RAM[&h44A])
line (ox+CursorX*8,oy+CursorY*8+CursorIniRow) - step(7,CursorEndRow-CursorIniRow),DosColors(Attr),bf
end if
screenunlock
end sub
sub Bios_Scroll (x as integer, y as integer, w as integer, h as integer, d as byte, a as ubyte)
dim as integer i, px, py
if d=0 then
for py=y to h
for px=x to w
PutCh (px,py,a*256+32)
next
next
exit sub
end if
for py as integer= y to h
dim as integer yy = py - 1
for px = x to w
PutCh( px, yy, GetChar( px, py ) )
next
next
for px=x to w
PutCh (px,h-1,a*256+32)
next
end sub
sub Bios_Putchar( c as integer )
select case c
case &h0a ' Line feed
CursorY+=1
case &h0d ' Return
CursorX = 0
case &h08 ' Backspace
CursorX-=1
case &h07 'Bell
exit sub
case else
PutCh( CursorX, CursorY, c+ Attr shl 8 )
CursorX+=1
end select
if CursorX >= VideoCols then
CursorX = 0
CursorY+=1
end if
if CursorX < 0 then
CursorX = VideoCols - 1
CursorY-=1
end if
if CursorY >= VideoRows then
Bios_Scroll( 0, 1, VideoCols - 1, VideoRows, 1, Attr )
CursorY = VideoRows - 1
end if
if CursorY < 0 then
CursorY = 0
end if
end sub
function Int_0x10(r as _go32_dpmi_registers ptr) as integer
dim as integer i,j
select case r->h.ah
case &h00
Attr = &h07
select case r->h.al
case 0,1
VideoCols=40:VideoRows=24
case 3
VideoCols=80:VideoRows=24
end select
case &h01
CursorIniRow=r->h.ch
CursorEndRow=r->h.cl
case &h02
CursorX=r->h.dl
CursorY=r->h.dh
case &h03
r->h.dl=CursorX
r->h.dh=CursorX
case &h06
Attr = r->h.bh
Bios_Scroll( r->h.cl, r->h.ch, r->h.dl, r->h.dh, r->h.al, Attr )
case &h07
Attr = r->h.bh
Bios_Scroll( r->h.cl, r->h.ch, r->h.dl, r->h.dh, -r->h.al, Attr )
case &h8
i=GetChar( CursorX, CursorY )
r->h.al=i and &hFF
r->h.ah=i shr 8
case &h9
Attr=r->h.bl
for i = 1 to r->x.cx
Bios_Putchar( r->h.al )
next
case &h0A
for i = 1 to r->x.cx
Bios_Putchar( r->h.al )
next
case &h0E
Bios_Putchar( r->h.al )
case &hF
r->h.al=&h03
r->h.ah=VideoCols
case &h11
select case r->h.al
case &h2, &h12
if VideoRows = 24 then VideoRows = 50 else VideoRows = 24
case &h30
r->h.cl = &h10
r->h.ch = &h10
r->h.dl = &h18
r->x.es = &hC000
r->x.bp = &h422C
r->x.cx = &h10
end select
case &h12
select case r->h.bl
case &h10
r->h.bl = &h0
r->h.bh = &h0
r->x.cx = &h0
end select
case &h12
r->h.bl = 8
end select
return 1
end function
private sub Int_0x10_end cdecl()
end sub
sub Int_0x08 cdecl()
static D as ubyte
if d=0 then
d=255
DrawScreen
d=4
elseif d<255 then
d-=1
end if
end sub
private sub Int_0x08_end cdecl()
end sub
sub InstallInt0x10
' LOCK_FUNCTION( My_Int_0x10 );
dim as byte ptr ptr_end = cast( byte ptr, @Int_0x10_end )
dim as byte ptr ptr_start = cast( byte ptr, @Int_0x10 )
_go32_dpmi_lock_code(@Int_0x10, ptr_end-ptr_start)
' memset( VideoChar, 0x20, 80 * 25 );
' memset( VideoAttr, Attr, 80 * 25 );
' Cls( &Me );
for y as integer=0 to VideoRows
for x as integer=1 to VideoCols
PutCh (x,y,attr*256+32)
next
next
_go32_dpmi_get_real_mode_interrupt_vector( &h10, @old_vector_0x10 )
info_0x10.pm_offset = cast (integer,@Int_0x10)
_go32_dpmi_allocate_real_mode_callback_iret( @info_0x10, @regs_0x10 )
_go32_dpmi_set_real_mode_interrupt_vector( &h10, @info_0x10 )
end sub
sub RemoveInt0x10()
_go32_dpmi_set_real_mode_interrupt_vector( &h10, @old_vector_0x10 )
_go32_dpmi_free_real_mode_callback( @info_0x10 )
end sub
sub InstallInt0x08()
dim as byte ptr ptr_end = cast( byte ptr, @Int_0x08_end )
dim as byte ptr ptr_start = cast( byte ptr, @Int_0x08 )
_go32_dpmi_lock_code(@Int_0x08, ptr_end-ptr_start)
_go32_dpmi_get_protected_mode_interrupt_vector( &h08, @old_handler_0x08 )
new_handler_0x08.pm_offset = cast(integer,@Int_0x08)
new_handler_0x08.pm_selector = _go32_my_cs()
_go32_dpmi_chain_protected_mode_interrupt_vector( &h08, @new_handler_0x08 )
end sub
sub RemoveInt0x08()
_go32_dpmi_set_protected_mode_interrupt_vector( &h08, @old_handler_0x08 )
end sub
screenres 800,600,32
line (0,0)-(800,600),rgb(0,0,255),bf
ox=80:oy=200
InstallInt0x10
InstallInt0x08
shell
RemoveInt0x10
RemoveInt0x08