Displaying a character on two consecutive lines

Started by zak100, August 28, 2009, 05:34:37 AM

Previous topic - Next topic

FORTRANS

Hi,

   As the speed of BIOS functions versus writing to memory
is always brought up when a put pixel is mentioned, I put
together two throw-away programs.  One each for video
mode 12H and 13H.  And assembled for both BIOS calls
and direct memory writes.  Note: the memory write routines
are general purpose, and while good, are not optimized for
speed.

Enjoy,

Steve N.

zak100

Thanks for these replies. It would take sometime for me to start graphics.

Zulfi.

zak100

Hi,
Steve, I ran your application and found them very interesting. I dont thing I would be doing such a beautiful stuff but its something I must appreciate. Its a new idea. I havent seen them before. I might consider such exercises for my graphics course.

Zulfi.

FORTRANS

Hi Zulfi,

   Glad you liked them.  Most benchmarks are a bit dull so I used
some existing code to make them a bit more colorful.

   Since I did print out the times for the 16 color program, I'll
post some results for our friends in the Laboratory sub-forum
that like to see numbers.  "Undocumented DOS" showed
that DOS interrupts could slow down by factor of ten when
run under a protected mode environment.  So I ran that
experiment, but didn't see that dramatic an effect.  Though
I may have to try that on the Win 98 machine.

Cheers,

Steve N.


Shows Pythagorean triangles.

  BIOS time:   Subroutine time:
                             Pentium III, Matrox Video
  0:01:14.47   0:00:36.47        OS/2 4.0 VDM
  0:01:11.07   0:00:25.65        Windows 2000 Command Prompt
  0:00:33.89   0:00:24.01        DOS 5.0 HIMEM.SYS
  0:00:32.63   0:00:23.18        DOS 5.0

                             Pentium, Western Digital Video
  0:01:45.57   0:00:56.91        DOS 6.2x
  0:02:32.86   0:01:02.78        DOS 6.2x HIMEM.SYS EMM386.SYS
  0:02:28.51   0:01:03.06        As above + Windows 3.11 MS-DOS Prompt
  0:02:38.71   0:01:03.59        OS/2 4.0 VDM

                             Pentium MMX, Nvidia Video
  0:03:59.97   0:00:45.98        Windows 98

                             AMD 64, RADEON Video
  0:00:58.55   0:00:25.98        Windows XP
  0:00:40.75   0:00:26.26        DOS 5.0

zak100

Hi,
I dont know much about what you have said and what you have done but as a programmer I want to tell something about win98. It gave me problem of spaces but later on when I was working on TurboC (DOS application) and trying hard to take the printout of graphics stuff, it came out that this can only be done on win 98.

Zulfi.

dedndave

hi Zulfi
yah - some programmers wanted fast graphics
on older systems, that meant programming the video card directly
while some of that can be done under NT+ OS's, not all functionality may be available
in general, XP and other newer OS's do not allow direct i/o
i have played with it a little bit, and i see you are able to program the palette registers, etc (XP Pro, here)
from a boot floppy, though, you do not have any limitations, because you are providing the OS

zak100

Hi Steve,
I am also interested in your timing work.Have  you done it programmatically? Once I tried to compare the timings of a pool of threads with a standalone program.In that case, I used the prime number program. But I was not printing the timings. If its not a secret and if you have some spare time, kindly guide me how you accomplished this task??

Zulfi.   

dedndave

Zulfi
most of us use timing macros by MichaelW
the macros are available in the first post of the first thread in the Laboratory Forum
there are two sets - slightly different
timers.asm and counter2.asm
d/l them, unzip them, and place them in the \masm32\macros folder
here is an example program....

Magnum

Quote from: FORTRANS on September 05, 2009, 01:30:32 PM
Hi,

   As the speed of BIOS functions versus writing to memory
is always brought up when a put pixel is mentioned, I put
together two throw-away programs.  One each for video
mode 12H and 13H.  And assembled for both BIOS calls
and direct memory writes.  Note: the memory write routines
are general purpose, and while good, are not optimized for
speed.

Enjoy,

Steve N.

Good coding. Thanks a lot.
I may copy them to my floppy boot disk and compare the speed with running under XP.

Andy
Have a great day,
                         Andy

FORTRANS

Quote from: zak100 on September 11, 2009, 03:49:45 AM
Hi Steve,
I am also interested in your timing work.Have  you done it programmatically? Once I tried to compare the timings of a pool of threads with a standalone program.In that case, I used the prime number program. But I was not printing the timings. If its not a secret and if you have some spare time, kindly guide me how you accomplished this task??

Zulfi.   

Hi,

   Not a secret at all, I use the DOS function 2CH (44) "Get
Time".  I call it before running the benchmark, and then
again when the benchmark is complete.  Subtract the values,
format for printing, and print them.


; Let the program time stuff.
        SCALL GTIME      ; MS-DOS fn 2CH
        MOV     [FHun],DL
        MOV     [FSec],DH
        MOV     [FMin],CL
        MOV     [FHour],CH


   Calling again and subtracting is pretty dull, so I'll
skip that.  Here is the format and print.  SCALL is
a simple macro to call MS-DOS functions with a mnemonic.
CONOUT is "Console Output" function 2, which prints
a character.


; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OutSaveT:       ; Output saved time.
                ; 26 September 2007, SRN
; Enter: BX, Offset into saved time array.
; Uses  AX, CX, DX.

        MOV     DL,' '
        SCALL CONOUT

; MS-DOS System Time
; CH = Hour, CL = Minute, DH = Seconds, DL = 1/100 s

        XOR     AH,AH
        MOV     AL,[Fhour+BX]   ; Play with hour
        AAM     ; ASCII Adjust AX after Multiply (unpack BCD digits).
        OR      AX,3030H
        CMP     AH,30H ; suppress leading zero?
        JNZ     OST_1
        MOV     AH,' '
OST_1:  PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        MOV     DL,':'
        SCALL CONOUT

        MOV     AL,[FMin+BX]    ; Play with minutes
        XOR     AH,AH
        AAM                     ; unpack
        OR      AX,3030H        ; convert binary to ASCII
        PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        MOV     DL,':'
        SCALL CONOUT

        XOR     AH,AH
        MOV     AL,[FSec+BX]    ; Play with seconds
        AAM
        OR      AX,3030H
        PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        MOV     DL,'.'
        SCALL CONOUT

        XOR     AH,AH
        MOV     AL,[FHun+BX]    ; Play with 1/100 seconds
        AAM
        OR      AX,3030H
        PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


   Hm, probably should skip the hundredths of a second.

HTH,

Steve N.

Magnum

Quote from: zak100 on August 29, 2009, 10:13:15 AM
I have not checked but I want to know can we display images also using BIOS?

Zulfi.

I dug this out of 16 bit code dungeon and attached to source code and com file.

Andy


;  AMB2.ASM  [ For DOS ] Much help from Annie from alt.lang.asm newsgroup
;  An ambulance races across the bottom of the screen
;  with its siren wailing and its light flashing.
;
;  Code added to turn off cursor allows this to work in a DOS box under
;  Win XP.
;
;   Animation code extracted from the "Ambulance"
;   by AK   10/02
;
.model  tiny
.386
.code
org     100h                    ; DOS .COM file

begin:
        jmp     start                   ; go start the program
;
BDA_addr                equ     40h     ; BDA (Bios Data Area) segment address
BDA_video_mode          equ     49h     ; BDA location of current video mode
BDA_timer_counter       equ     6Ch     ; BDA location of nmbr of timer ticks
                                        ; (18.2 per second) since midnight
counter dw      9
;
start:
        mov     ch,10h                  ; set bits to turn cursor off
        call    cursor                  ; do it
host:
        nop
;
real_start:
        call    find_displacement
        db      01h                     ; Used to make this add up to 3 bytes
find_displacement:
        pop     si
        sub     si, offset host
        call    payload
next_step:
        ret

payload:
        push    es
        mov     ax, word ptr [si+counter-4]
        and     ax, 00000111b
        cmp     ax, 00000110b          ; Show payload every eighth
                                        ; (starting with the sixth) time
;
; Did we already show the car?
;
        mov     ax, BDA_addr
        mov     es, ax
        call    show_payload
exit_payload:
        pop     es
        mov     ch,5                    ; set bits to turn cursor on
        mov     cl,6                    ; ditto
        call    cursor                  ; go do it
        int     20h                     ; exit to DOS
;
; Setup and show the 'ambulance car'
;
show_payload:
;
; Check video mode
;
; Text mode 3 (80x25) - video buffer address (color) = 0B800h
; Text mode 7 (80x25) - video buffer address (monochrome) = 0B000h
;
        push    ds
        mov     di, 0B800h
        mov     ax, BDA_addr
        mov     ds, ax
        mov     al, ds:BDA_video_mode
        cmp     al, 7                   ; Check which video mode we're
        jne     setup_video_n_tune      ; on, if not Monochrome text
        mov     di, 0B000h              ; mode 7, assume mode 3

setup_video_n_tune:
        mov     es, di
        pop     ds
        mov     bp, 0FFF0h              ; Setup number of tones to play
                                        ; (will increment up to 50h)
setup_animation:
        mov     dx, 0                   ; Setup ambulance_data column
        mov     cx, 16                  ; Number of characters that make
                                        ; up one ambulance_data line
do_ambulance:
        call    show_ambulance          ; Print the ambulance to screen
        inc     dx
        loop    do_ambulance
        call    play_siren              ; Play a tone of the 'siren'
        call    wait_tick               ; and wait for a tick
        inc     bp
        cmp     bp, 50h                 ; Already played the 'ambulance
        jne     setup_animation         ; siren' tune 12 times?
        call    speaker_off             ; If yes, then turn speaker off
        push    ds
        pop     es
        ret
;
; Turn the PC speaker off
;
; 8255 PPI - Programmable Peripheral Interface
; Port 61h, 8255 Port B output
;
; (see description below)
;
speaker_off:
        in      al, 61h
        and     al, 11111100b          ; Disable timer channel 2 and 'ungate'
        out     61h, al                 ; its output to the speaker
        ret
;
; Turn on the speaker and play the "ambulance siren" sound
;
; Select tone frequency to generate
;
; Tone frequency is selected by means of the 3rd least significant bit of BP
;
;
; Bit(s)                        Description
; ------                        -----------
; ... 3 2 1 0
; ... x 0 x x                    Play 1st tone frequency
; ... x 1 x x                    Play 2nd tone frequency
;
; If we consider A to be the 1st tone and B to be the 2nd tone,
; then the whole 'ambulance siren' tune will be: (AAAABBBB) x 12
;
play_siren:
        mov     dx, 07D0h               ; "ambulance siren" 1st tone freq.
        test    bp, 00000100b          ; Check if we are to play
        jz      speaker_on              ; the first or the second
                                        ; tone frequency
        mov     dx, 0BB8h           ; "ambulance siren" 2nd tone frequency
;
; Turn on the speaker
;
; 8255 PPI - Programmable Peripheral Interface
; Port 61h, 8255 Port B output
;
; Bit(s)                        Description
; ------                        -----------
; 7 6 5 4 3 2 1 0
; . . . . . . . 1                Timer 2 gate to speaker enable
; . . . . . . 1 .                Speaker data enable
; x x x x x x . .                Other non-concerning fields
;
speaker_on:
        in      al, 61h
        test    al, 00000011b          ; If speaker is already on, then
        jnz     play_tone               ; play the sound tone
        or      al, 00000011b          ; Else, enable timer channel 2 and
        out     61h, al                 ; 'gate' its output to the speaker
;
; Program the PIT
;
; 8253 PIT - Programmable Interval Timer
; Port 43h, 8253 Mode Control Register
;
; Bit(s)                        Description
; ------                        -----------
; 7 6 5 4 3 2 1 0
; . . . . . . . 0                16 binary counter
; . . . . 0 1 1 .                Mode 3, square wave generator
; . . 1 1 . . . .                Read/Write LSB, followed by write of MSB
; 1 0 . . . . . .                Select counter (channel) 2
;
        mov     al, 10110110b          ; Set 8253 command register
        out     43h, al                 ; for mode 3, channel 2, etc
;
; Generate a tone from the speaker
;
; 8253 PIT - Programmable Interval Timer
; Port 42h, 8253 Counter 2 Cassette and Speaker Functions
;
play_tone:
        mov     ax, dx
        out     42h, al                 ; Send LSB (Least Significant Byte)
        mov     al, ah
        out     42h, al                 ; Send MSB (Most Significant Byte)
        ret
;
; Show the 'ambulance car'
;
show_ambulance:
        push    cx
        push    dx
        lea     bx, [si+ambulance_data-4]
        add     bx, dx                  ; Setup which ambulance_data column
                                        ; we're going to print
        add     dx, bp                  ; Don't show ambulance_data columns
        or      dx, dx                  ; which aren't still visible
        js      ambulance_done
        cmp     dx, 50h                 ; Check if the column we're printing
        jae     ambulance_done          ; is past the screen limit
                                        ; If yes,  then don't print it
        mov     di, 3200                ; Point to start of screen's 64th line
        add     di, dx                  ; Point to the column we're supposed
        add     di, dx                  ; to be printing at
        sub     dx, bp                  ; Restore to initial column value
        mov     cx, 5                   ; Set it up so we're in the first line

decode_character:
        mov     ah,4d                    ; Set color attribute to red
;                                        ; 7 = white
; Decode the character
;
; It's really pretty ingenius. Each character is encoded in such a way
; that for each line beyond the first one, that character is incremented
; by one -- and for each column beyond the first, the same thing happens.
; So taking that into account, it's not difficult to understand how it
; all works, and how to decode the ambulance_data.
;
        mov     al, [bx]                ; Get the character
        sub     al, 7
        add     al, cl                  ; Account for which line we're in
        sub     al, dl                  ; Account for which column we're in
        cmp     cx, 5                   ; Are we in the first line?
        jne     print_character         ; If we are, then...
        mov     ah,1                    ; Set color attribute to hi-inten blue
        test    bp, 00000011b           ; Is this the ending tone of a AAAA or
                                        ; BBBB tune sequence?
        jz      print_character         ; If not, then go ahead and print the
                                        ; 'siren' characters
        mov     al, ' '                 ; Else, replace them with a ' ' (to
                                        ; accomplish the visual 'siren' effect
print_character:
        stosw                           ; Print the character to screen
        add     bx, 16                  ; Point to next ambulance_data line
        add     di, 158                 ; Point to next screen line
        loop    decode_character
ambulance_done:
        pop     dx
        pop     cx
        ret
;
; Wait for one tick (18.2 per second) to pass
;
wait_tick:
        push    ds
        mov     ax, BDA_addr
        mov     ds, ax
        mov     ax, ds:BDA_timer_counter ; Get ticks since midnight
check_timer:
        cmp     ax, ds:BDA_timer_counter ; Check if one tick has
        je      check_timer              ; already passed
        pop     ds
        ret
;
; Our cursor manipulation routine.
;
cursor:
        mov     ah,1                    ; function 1 - cursor control
        int     10h                     ; call ROM BIOS video services
        ret                             ; return to caller
;
; Data from here below
;
ambulance_data:
   first_line   db     22h, 23h, 24h, 25h, 26h, 27h, 28h, 29h, 66h, 87h, 3Bh
                db     2Dh, 2Eh, 2Fh, 30h, 31h
   second_line  db     23h, 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h
                db     0E7h, 0E9h, 0EAh, 0EBh, 30h, 31h, 32h
   third_line   db     24h, 0E0h, 0E1h, 0E2h, 0E3h, 0E8h, 2Ah, 0EAh, 0E7h
                db     0E8h, 0E9h, 2Fh, 30h, 6Dh, 32h, 33h
   fourth_line  db     25h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E7h, 0E7h, 0E8h
                db     0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh
   fifth_line   db     26h, 0E6h, 0E7h, 29h, 59h, 5Ah, 2Ch, 0ECh, 0EDh, 0EEh
                db     0EFh, 0F0h, 32h, 62h, 34h, 0F4h
Have a great day,
                         Andy