• Please review our updated Terms and Rules here

new VNC client in quickbasic.. video demo, and also question!

Mike Chambers

Veteran Member
Joined
Sep 2, 2006
Messages
2,621
http://www.youtube.com/watch?v=1rAurls9-G0

i started working on this yesterday. excuse the unprofessional demo.

i have a question for you ASM guys. i want to dynamically "assemble" some binary code into a string in QB that will let me CALL ABSOLUTE to it. i need it to copy a memory block of arbitrary size from a specified seg : ptr to another specified seg : ptr

you probably see where i'm going with this.. string variables to segment A000h for fast video writes. :p

what would be the simplest way of implementing this binary code??

if you need this info, here's the CALL ABSOLUTE info from the QBX help file:

Code:
│CALL Absolute ([argumentlist,] integervariable%)
│
│    ■ argumentlist       Arguments passed to a machine-language
│                         procedure as offsets (near pointers) from the
│                         current data segment.
│    ■ integervariable%   The offset from the current code segment, set
│                         by DEF SEG, to the starting location of the
│                         procedure.

so, ideally i could do it like this:

lets say i have 320 bytes of pixel data to write starting at 0, 0 in 320x200x8.. for simplicity's sake, we'll just make them all of value 255 here:

bincode$ = asmcodeformemoryblahblahineedhelpwiththat
pixels$ = string$(320, chr$(255))
vidoffset% = 0
pixelcount% = len(pixels$)
CALL ABSOLUTE VARSEG(pixels$), VARPTR(pixels$), &HA000, vidoffset%, pixelcount%, VARPTR(bincode$)

obviously, i could do stuff like change vidoffset% to 320 and it'd copy the pixel data to the SECOND line rather than the first. you get what i'm doing here, you guys are smart that's why i'm here :p


how would the binary code handle the 5 variables i'm feeding it? if i know that, i can probably just write the code myself with MOVs and stuff.
 
Last edited:
I think this will get you going in the right direction:

Code:
push bp
push ds
push es
mov bp, sp
mov ax, [bp+6]   ; argument #1 segment of source
mov bx, [bp+8]   ; argument #2 segment of destination
mov si, [bp+0ah]   ; argment #3 offset of source
mov di, [bp+0ch]   ; argument #4 offset of destination
mov cx, [bp+0eh]  ;  # of bytes to copy
mov ds, ax           ; load segments
mov es, bx
rep movsb            ; do the copy
pop es
pop ds
pop bp
retf 2

I took a portion of this from one of my early qbasic programs where I passed a variable into the asm code. Not sure how or where I found out it was passed in at bp+6, but whatever. From there, I assumed that each argument passed in was a 16bit value, and should be stacked up one after another.

You very well may want to code an INT 3 at the top of that routine, load up soft-ice in the background, and have it pop up whenever int 3 is called so you can debug this and follow the register loading to make sure it's putting things in the order you think they are.

edit: Ah, I see you're calling absolute in a slightly different order than I'm expecting them to come in. I think you can adjust either your code or mine to make it work...

-jeff!
 
You are killing me. What you're able to do in a short amount of time just kills me because you are totally being held back by your language.

The fact that you were able to do it has now inspired me to do a CGA version in assembler.
 
I think this will get you going in the right direction:

Code:
push bp
push ds
push es
mov bp, sp
mov ax, [bp+6]   ; argument #1 segment of source
mov bx, [bp+8]   ; argument #2 segment of destination
mov si, [bp+0ah]   ; argment #3 offset of source
mov di, [bp+0ch]   ; argument #4 offset of destination
mov cx, [bp+0eh]  ;  # of bytes to copy
mov ds, ax           ; load segments
mov es, bx
rep movsb            ; do the copy
pop es
pop ds
pop bp
retf 2

I took a portion of this from one of my early qbasic programs where I passed a variable into the asm code. Not sure how or where I found out it was passed in at bp+6, but whatever. From there, I assumed that each argument passed in was a 16bit value, and should be stacked up one after another.

You very well may want to code an INT 3 at the top of that routine, load up soft-ice in the background, and have it pop up whenever int 3 is called so you can debug this and follow the register loading to make sure it's putting things in the order you think they are.

edit: Ah, I see you're calling absolute in a slightly different order than I'm expecting them to come in. I think you can adjust either your code or mine to make it work...

-jeff!

thank you! i compiled it in emu8086 and moved it over to the 286, but it locks up. it doesn't look like it even writes the screen. you're probably right on about the soft-ice thing. the vars could be in different places than you wrote this for.

also, would it be safe to just use PUSHA and POPA instead of the separate PUSH and POP operations?

also, maybe i should use RET instead of RETF since it's a near call? not sure. i don't know ASM well enough to know if that even matters.
 
You are killing me. What you're able to do in a short amount of time just kills me because you are totally being held back by your language.

The fact that you were able to do it has now inspired me to do a CGA version in assembler.

lol. i agree. i am killing myself.

this code will be worth continuing though, if i get the ASM bit working. screen writes should be extremely fast. (obviously)
 
yeah, if you used the old QBasic 1.1 that came with DOS 5, there will probably be some differences between that and QB 7.1 PDS. i'm looking up info on it. i think basically your code will work if i can figure out how to modify it correctly.
 
Not if you want it to run on 8086. Those are 286 instructions.

yep, i don't plan to run this on an 8088 lol. at least not for now. i thought it was 186 btw?

is the 186 a fairy tale? i've NEVER seen one. 80186 (c)1979 The Tooth Fairy

i understand there was a tandy that used em.
 
The Tandy 2000.

Not compatible with practically everything.

They got suckered in by Intel, as did a few other companies, as the 80286 came out very shortly thereafter.
 
The Tandy 2000.

Not compatible with practically everything.

They got suckered in by Intel, as did a few other companies, as the 80286 came out very shortly thereafter.

And more than just a little "suckering" by Microsoft.

"Just make it BIOS comapatible. No one will write directly to hardware."

There's even an ad out there somewhere with Bill G himselft touting the benefits of the 2000.
 
maybe i should use RET instead of RETF since it's a near call? not sure. i don't know ASM well enough to know if that even matters.

The code snippet I have has opcodes of "ca 02 00" and that's retf 02, and mine works, but mine is compiled under qbasic 7.1, so maybe it is a near call as you say.

Drop an INT 3 as the first line of that subroutine, compile it and PM me a link to the .exe and I'll debug here.

The nice thing is that we're slowly teaching you assembly language as we work through these programs, and one day you'll just make the jump altogether!

-jeff!
 
The code snippet I have has opcodes of "ca 02 00" and that's retf 02, and mine works, but mine is compiled under qbasic 7.1, so maybe it is a near call as you say.

Drop an INT 3 as the first line of that subroutine, compile it and PM me a link to the .exe and I'll debug here.

The nice thing is that we're slowly teaching you assembly language as we work through these programs, and one day you'll just make the jump altogether!

-jeff!

yes! i appreciate the help. :)

do you have qb 7.1? this should work fine in 4.5 also. i can give you the dosvnc.bas code as well if you'd like.

if i can get good with both ASM and C i think i could start having a lot of fun. QB is actually a very flexible language though, when you get down these absolute calls. you can basically make it do anything. you can do far calls as well if you use DEF SEG to specify a segment before the call absolute line.

btw does it have to be EXE, or should i just make BIN files like i've been doing? i figured that was the way to go.
 
i just slightly (okay, alot) modified the code and created a VNC stream recorder. i wrote a win32 player for the files. :)

here, download this and check it out. it's the vncplay.exe player for windows and a TEST.VNC file that is a demo of me doing stuff in XP for the playback lol.

http://www.rubbermallet.org/vncplay.zip

note: you will need MSVBVM60.DLL but XP comes with it, starting with i believe SP1.

i'm working on making it full 24bpp color right now, and it'll have timing so it doesn't play so fast. i also plan to have it support compressed VNC encoding methods instead of just the HUGE "raw" method. :p

tell me what you think!

something like this would be awesome for tutorials of whatever, or demonstations, um spying on people and recording evidence (if you're a jerkface), or what have you.

EDIT: here's a new, much longer test .VNC file that you can play with vnc play. zipped.. http://www.rubbermallet.org/TEST2.zip
 
Last edited:
what i would REALLY like to program next, is a "passthrough" app to act as a middleman between the VNC server and client. it would be able to record the stream, while allowing you to actually use the VNC client.

this would of course, be a windows program.
 
yes! i appreciate the help. :)
do you have qb 7.1? this should work fine in 4.5 also. i can give you the dosvnc.bas code as well if you'd like.

Yeah, I have qb7.1 here at my disposal.
that would be great if I can get the source, then I can hack on it til it works and get back to you with the fixed source.
 
Yeah, I have qb7.1 here at my disposal.
that would be great if I can get the source, then I can hack on it til it works and get back to you with the fixed source.

awesome! i appreciate the help. i'm going to add mouse support real quick-like than post the code. :)

btw, once we get this ASM bit working i am adding full VESA support! you can select either 320x200 256-color or 640x480 16-color when you connect to a server, but while you're playing with the mem copy code you will obviously probably want to use 320x200. 8 bit per pixel = friendlier for testing.
 
i'm using it as is on a celeron 300 mhz (i think 300, something like that anyway) and believe it or not, it's actually pretty fast! i am amazed, but it still needs ASM writes for sure. it'd be useble on a 286 or 386 methinks. if you have a VESA card anyway.
 
I tested it on a Pentium 1@233MHz with 64MB RAM. It's quite fast compared to your 286, but the inverted colors in VGA mode and wrong colors in EGA mode combined with no right mouse or modifier key support make it somewhat hard to use. :p

Nice work, though! :D

here's a picture of the computer (the picture shows it running windows 98 and using a wireless card, but I tested the VNC client in DOS with a Xircom ethernet card, then rebooted into windows before taking the picture. :p):
83792207gt8.png
 
What version of MASM are you guys using? In 6.x, calling conventions and parameter passing (as well as local variables) are all nicely handled automatically for you.

And 6.x is free for the download from Micros~1.

There were more 186 boxes than you think, and a fair number of 188 ones also. (The USR Courier Dual Standard modem has one under the hood). You can find them in all sorts of embedded applications.

In many ways, the 186 is superior to the 8086/88. 20 bit DMA, built-in chip selects, timers, etc.

There were chips beyond the NEC V20/V30 that were used in PCs. Didn't some of the Epson boxes use a V40?
 
Back
Top