Thread: old dos hardware and int86() woes

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    3

    old dos hardware and int86() woes

    hi, i'm working with some old hardware, a handheld x86 device from around 1992. It's a 16 bit device running MS DOS 5.0, and doesnt seem to work with C++ STLs, so I'm coding stuff for it in C using a Microsoft C/C++ Compiler version 1.52.

    i need to be able to cleanly redraw the ENTIRE screen (and rather rapidly at times), and system("CLS") doesnt work, probably due to the fact that its proprietary hardware.

    now, i found a function to clear the screen, but i'm not totally sure how the function even works, just something to do with simulating an interrupt:

    Code:
    #include <dos.h>
    void cls(void)
    {
    union REGS regs;
    
    	 regs.h.ah = 0x06;
    	 regs.h.al = 0;
    	 regs.h.bh = 7;
    	 regs.h.ch = 0;
    	 regs.h.cl = 0;
    	 regs.h.dh = 25;
    	 regs.h.dl = 80;
    	 int86(0x10, &regs, &regs);
    }
    this function erases everything onscreen, but leaves the input cursor wherever it happens to be...how could i return the cursor to the first position of the first line (top left corner)? or is there a better C function that will completely clear and reset the screen?

    thanks, i'd appreciate any help i can get

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Just google for "Ralf Brown Interrupt List"
    Then find the int86 to move the cursor.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    3
    thats a big list. heh, i think i found it though. thanks, i appreciate it a LOT!

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well you need to find out if the device will allow you to directly access its video memory. Then you need to find out the format of the video memory.

    If the video display is mono - no colors, then video memory should be byte for byte in that one byte is one character cell on the display. If it contains colors - foreground and background, normally this is in two bytes or one 16-bit unsigned integer. Sometimes the high byte is the color ((foreground *16)+background) and the low byte is the actual ASCII code of the text character.

    So a 80x25 or depending on just how old this thing is, a 40x25 screen with 1 color would be
    1000 bytes. Depending on the CPU in the thing this might work for you. Most low video modes and text modes on IBM compatibles and running x86 CPUs have the video memory starting at B800:0000. For video modes it starts at A000:0000 and for protected mode linear frame buffers the address must be retrieved from the hardware.

    So this is assuming you start at B800:0000 and the screen is 1000 bytes.

    Two simple solutions: Pick your poison. 16-bit code here. FAR denoting the segment pointer is pointing outside of your segment.

    Code:
    #include <mem.h>   //might be memory.h in MS C
    #include <dos.h>
    
    unsigned char far *Screen;
    void InitVideo(void);
    void ClearScreen(void);
    void ClearScreenAsm8(void);
    void ClearScreenAsm16(void);
    
    void CopyScreenToBuf16(void);
    
    
    
    void InitVideo(void)
    {
      //Set screen mode to desired text mode - I don't know the code here
      //Check Ralph Brown's list under interrupt 10h
    
      //Init pointer to video memory
      (unsigned char far *)Screen=(unsigned char far *)MK_FP(0xB800,0);
    }
    
    void ClearScreen(void)
    {
      memset(Screen,0,1000);
    }
       
    void ClearScreenAsm8(void)
    {
      asm {
         les   di,[Screen];
         mov cx,1000d
         mov ax,0
         rep stosb
      }
    }
    
    void ClearScreenAsm16(void)
    {
      asm {
        les   di,[Screen]
        mov  cx,1000d
        shr    cx,1
        mov   ax,0
        rep    stosw
      }
    }
    
    void CopyScreenToBuf16(unsigned char far *Source,unsigned char far *Dest,unsigned int Size16)
    {
       asm {
         push  ds
         lds     si,[Source]
         les     di,[Dest]
         mov   cx,[Size16]
         rep    movsw
         pop   ds
       }
    }
    This is assuming a lot about the environment of the device so don't quote me on all this as it pertains to your little toy.

    Just the start to a small video library that you can use to gain more control over the screen, without having to rely on it's BIOS. Invoking interrupts is slow, and probably very slow, on your device. Don't invoke interrupt 10h for every little function you need.

    The formula to find the offset in memory for the current row and column to print at is this:

    row*width+column

    So:

    Code:
    #define RCTOMEM(row,col,width)  (unsigned int)( ( (row) * (width) )+ col)
    
    void Print(int row,int col,unsigned char ch)
    {
      Screen[RCTOMEM(row,col,40)]=ch;
    }
    Remember video memory layout, starting address, pitch, etc., is key. Not all video memory is alike.

  5. #5
    Registered User
    Join Date
    Oct 2005
    Posts
    3
    wow, that seems to do it! thanks for all the help, guys!

Popular pages Recent additions subscribe to a feed