-
Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
For anyone longing to use Q(uick)BASIC (or VBDOS) again:
Code:
DEFINT A-Z
DECLARE FUNCTION Escape$ (Text AS STRING)
DECLARE FUNCTION GetLoopList$ (Code AS STRING)
DECLARE FUNCTION LoadCode$ (Path AS STRING)
DECLARE FUNCTION Loops (LoopList AS STRING, InstructionP AS INTEGER, Backwards AS INTEGER)
DECLARE FUNCTION NextArgument (Arguments AS STRING)
DECLARE FUNCTION PopArgument$ (Arguments AS STRING, Argument AS STRING)
DECLARE FUNCTION Unescape$ (Text AS STRING)
DECLARE SUB Execute (Code AS STRING, InputLineBreak AS STRING, OutputLineBreak AS STRING)
DECLARE SUB Main ()
CALL Main
FUNCTION Escape$ (Text AS STRING)
DIM Character AS STRING * 1
DIM Escaped AS STRING
DIM Hexed AS STRING
DIM Position AS INTEGER
Escaped = ""
FOR Position = 1 TO LEN(Text)
Character = MID$(Text, Position, 1)
SELECT CASE Character
CASE "/"
Escaped = Escaped + "//"
CASE " " TO "~"
Escaped = Escaped + Character
CASE ELSE
Hexed = HEX$(ASC(Character))
IF LEN(Hexed) = 1 THEN Hexed = "0" + Hexed
Escaped = Escaped + "/" + Hexed
END SELECT
NEXT Position
Escape$ = Escaped
END FUNCTION
SUB Execute (Code AS STRING, InputLineBreak AS STRING, OutputLineBreak AS STRING)
DIM Character AS STRING * 1
DIM InputBuffer AS STRING
DIM InstructionP AS INTEGER
DIM LoopList AS STRING
DIM Memory AS STRING
DIM MemoryP AS INTEGER
DIM OutputBuffer AS STRING
DIM UserInput AS STRING
InstructionP = &H0
LoopList = GetLoopList$(Code)
Memory = STRING$(&H7FFF, &H0)
MemoryP = &H0
DO
SELECT CASE MID$(Code, InstructionP + &H1, &H1)
CASE ">"
IF MemoryP >= LEN(Memory) THEN MemoryP = &H0 ELSE MemoryP = MemoryP + &H1
CASE "<"
IF MemoryP = &H0 THEN MemoryP = LEN(Memory) - &H1 ELSE MemoryP = MemoryP - &H1
CASE "+"
IF ASC(MID$(Memory, MemoryP + &H1, &H1)) = &HFF THEN
MID$(Memory, MemoryP + &H1, &H1) = CHR$(&H0)
ELSE
MID$(Memory, MemoryP + &H1, &H1) = CHR$(ASC(MID$(Memory, MemoryP + &H1, &H1)) + &H1)
END IF
CASE "-"
IF ASC(MID$(Memory, MemoryP + &H1, &H1)) = &H0 THEN
MID$(Memory, MemoryP + &H1, &H1) = CHR$(&HFF)
ELSE
MID$(Memory, MemoryP + &H1, &H1) = CHR$(ASC(MID$(Memory, MemoryP + &H1, &H1)) - &H1)
END IF
CASE "."
Character = MID$(Memory, MemoryP + &H1, &H1)
IF OutputLineBreak = "" THEN
PRINT Escape$(Character);
ELSE
OutputBuffer = OutputBuffer + Character
IF NOT LEFT$(OutputLineBreak, LEN(OutputBuffer)) = OutputBuffer THEN
PRINT Escape$(OutputBuffer);
OutputBuffer = ""
ELSEIF OutputBuffer = OutputLineBreak THEN
PRINT
OutputBuffer = ""
END IF
END IF
CASE ","
IF InputBuffer = "" THEN
LINE INPUT UserInput
InputBuffer = Unescape$(UserInput) + InputBuffer + InputLineBreak
END IF
IF NOT InputBuffer = "" THEN
MID$(Memory, MemoryP + &H1, &H1) = LEFT$(InputBuffer, 1)
InputBuffer = MID$(InputBuffer, 2)
END IF
CASE "["
IF ASC(MID$(Memory, MemoryP + &H1, &H1)) = &H0 THEN
InstructionP = Loops(LoopList, InstructionP, 0)
END IF
CASE "]"
IF NOT ASC(MID$(Memory, MemoryP + &H1, &H1)) = &H0 THEN
InstructionP = Loops(LoopList, InstructionP, -1)
END IF
END SELECT
InstructionP = InstructionP + &H1
LOOP WHILE InstructionP > &H0 AND InstructionP < LEN(Code)
END SUB
FUNCTION GetLoopList$ (Code AS STRING)
DIM Character AS STRING * 1
DIM LoopList AS STRING
DIM LoopStack AS STRING
DIM Position AS INTEGER
DIM StartOfLoop AS INTEGER
LoopList = ""
LoopStack = ""
FOR Position = 1 TO LEN(Code)
Character = MID$(Code, Position, 1)
SELECT CASE Character
CASE "["
LoopStack = LoopStack + MKI$(Position - 1)
CASE "]"
IF LoopStack = "" THEN
PRINT "End of loop without start."
EXIT FOR
ELSE
StartOfLoop = CVI(MID$(LoopStack, LEN(LoopStack) - 1, 2))
LoopStack = LEFT$(LoopStack, LEN(LoopStack) - 2)
LoopList = LoopList + MKI$(StartOfLoop) + MKI$(Position - 1)
END IF
END SELECT
NEXT Position
IF NOT LoopStack = "" THEN
PRINT "Loop without end."
END IF
GetLoopList$ = LoopList
END FUNCTION
FUNCTION LoadCode$ (Path AS STRING)
DIM Code AS STRING
DIM FileH AS INTEGER
FileH = FREEFILE
OPEN Path FOR INPUT LOCK READ WRITE AS FileH
CLOSE FileH
FileH = FREEFILE
OPEN Path FOR BINARY LOCK READ WRITE AS FileH
Code = INPUT$(LOF(FileH), FileH)
CLOSE FileH
LoadCode$ = Code
END FUNCTION
FUNCTION Loops (LoopList AS STRING, InstructionP AS INTEGER, Backwards AS INTEGER)
DIM NewInstructionP AS INTEGER
DIM Position AS INTEGER
FOR Position = 1 TO LEN(LoopList) STEP 4
SELECT CASE Backwards
CASE 0
IF InstructionP = CVI(MID$(LoopList, Position, 2)) THEN
NewInstructionP = CVI(MID$(LoopList, Position + 2, 2))
EXIT FOR
END IF
CASE -1
IF InstructionP = CVI(MID$(LoopList, Position + 2, 2)) THEN
NewInstructionP = CVI(MID$(LoopList, Position, 2))
EXIT FOR
END IF
END SELECT
NEXT Position
Loops = NewInstructionP
END FUNCTION
SUB Main
DIM Arguments AS STRING
DIM InputLineBreak AS STRING
DIM OutputLineBreak AS STRING
DIM Path AS STRING
Arguments = LTRIM$(RTRIM$(COMMAND$))
InputLineBreak = CHR$(13)
OutputLineBreak = CHR$(13)
IF NOT Arguments = "" THEN
Arguments = PopArgument$(Arguments, Path)
IF NOT Arguments = "" THEN
Arguments = PopArgument$(Arguments, InputLineBreak)
IF NOT Arguments = "" THEN
Arguments = PopArgument$(Arguments, OutputLineBreak)
END IF
END IF
END IF
IF Path = "" THEN
PRINT "Brain***** Interpreter v1.00, by: Peter Swinkels, ***2023***"
PRINT
PRINT "Usage:"
PRINT "BFInterp.exe PATH LINE_BREAK_IN LINE_BREAK_OUT"
ELSE
Execute LoadCode$(Path), Unescape$(InputLineBreak), Unescape$(OutputLineBreak)
END IF
END SUB
FUNCTION NextArgument (Arguments AS STRING)
DIM Position AS INTEGER
Position = INSTR(1, Arguments, " ")
IF Position = 0 THEN Position = LEN(Arguments) + 1
IF Position = 1 THEN Position = 0
NextArgument = Position
END FUNCTION
FUNCTION PopArgument$ (Arguments AS STRING, Argument AS STRING)
DIM NextPosition AS INTEGER
Arguments = LTRIM$(RTRIM$(Arguments))
NextPosition = NextArgument(Arguments)
IF NextPosition > 0 THEN
Argument = LEFT$(Arguments, NextPosition - 1)
Arguments = MID$(Arguments, NextPosition + 1)
END IF
PopArgument$ = Arguments
END FUNCTION
FUNCTION Unescape$ (Text AS STRING)
DIM Character AS STRING * 1
DIM Position AS INTEGER
DIM Unescaped AS STRING
Position = 1
Unescaped = ""
DO UNTIL Position > LEN(Text)
Character = MID$(Text, Position, 1)
IF Character = "/" THEN
IF MID$(Text, Position + 1, 1) = "/" THEN
Unescaped = Unescaped + Character
Position = Position + 2
ELSE
Unescaped = Unescaped + CHR$(VAL("&H" + MID$(Text, Position + 1, 2) + "%"))
Position = Position + 3
END IF
ELSE
Unescaped = Unescaped + Character
Position = Position + 1
END IF
LOOP
Unescape$ = Unescaped
END FUNCTION
This is just a toy project for fun, so don't expect it to be particularly efficient! ;-)
The complete project:
https://github.com/PeterSwinkels/QB-...ck-Interpreter
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
I think it's really interesting QB had predeclared functions... I had been contemplating posting a request for these in tB so we could provide prototypes of callback functions like the SDK headers, but it seemed like pushing it too far into C/C++ territory. But looks like it would just be getting back to it's roots.
Must say though QB+Brain****? Sir, please stop trying to destroy planet Earth. :wave:
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
@Fafalone, it would make it more appealing to developers used to such functionality. Although I guess since TwinBASIC is primarily intended as a modern substitute for classic Visual Basic, it would be unnecessary for most people who might adapt to TwinBASIC.
LOL - *Attempting to combine the evils of BF and QB* "Tomorrow my evil plan to destroy the Earth will succeed! MUHAHAHA"
Seriously, anyone want to have some fun with this? It does work already, it could be made to run faster and memory usage could be improved.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Just one word - STTR1 (for those old enough to know about this)! :p
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
@2kaud, are you having fun with me? XP
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
Originally Posted by
fafalone
Must say though QB+Brain****? Sir, please stop trying to destroy planet Earth. :wave:
That's right. You SHOULD be writing a Rockstar interpreter.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Code:
Midnight takes your heart and your soul
While your heart is as high as your soul
Put your heart without your soul into your heart
Give back your heart
Desires for yours have opened up the door
Waiting for them, you're gonna be mine
LOL - And then I should write it in low-level x86 assembly?! LOL - (Btw ChatGPT wrote that code.)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
STTR1 - The original Basic Star Trek game for HP TSB from 1972. Much loved by those that had access or access to ports to other systems.
https://github.com/darkoverlordofdat...hp2k/STTR1.bas
Now that's 'Other Basic' :)
I spent hours playing this when I should have been doing other things :D
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
I think I will try to resolve my program's efficiency issues by porting it to VBDOS - which should be slightly more efficient than QBasic and still similar enough to meet my purpose of pulling this off in a hopelessly ancient BASIC dialect.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
@2kaud: naughty naughy! :-)
I did once pull off a maze generator in MBasic running under CP/M 2 in an Altair emulator... LOL - Wasn't that from 1977 or something like that?
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Ah, CP/M that amber goddess!
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
@2kaud: naughty naughy! :-)
Keep this to yourself - but I still play it (i know, I know...) as I have the Windows simh HPTSB installed together with the software libraries. Also I have simh RSTS and TOP20 installed.... Ah the good old days! :thumb:
http://simh.trailing-edge.com/
http://simh.trailing-edge.com/hp/
http://simh.trailing-edge.com/software.html
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Oooh, interesting! But, how can I keep this to myself when you openly posted it on this very forum? :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Look, I am not one to talk. I am a guy who fired up an Altair emulator just to write a maze generator in msbasic under cp/m... on an ipad! LOL - For the heck of it! :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Okay, the interpreter has been ported it to vbdos. Memory management has improved. However it is still slow! :-)
Link:
https://github.com/PeterSwinkels/vbd...ck_Interpreter
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Well a port to PowerBASIC is up next on my list. And oh boy, pb has its own quirks! Yay! :-) But it should be much faster if it succeeds though! :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
I only have one surviving QBASIC program and that was migrated to QB64 to take advantage of event handling
https://www.vbforums.com/images/ieimages/2024/01/11.png
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Hey is that a screenshot of your QB64 progrram? Also, I tried downloading stuff from your GitHub but Windows Defender interferes when I download your *.exes directly. It probably is falsely detecting threats.
EDIT:
Windows Defender also interferes with *.zip files of your repositories...
EDIT 2:
It claims to have detected Trojan:Win32/Wacatac.B!ml in your Mars widget project.
-
2 Attachment(s)
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Attached to this post is a very early conversion to PowerBASIC. It's not much faster than before, but PowerBASIC offers a lot of features I haven't tried implementing yet, so that may change. :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
Originally Posted by
Peter Swinkels
Hey is that a screenshot of your QB64 progrram? Also, I tried downloading stuff from your GitHub but Windows Defender interferes when I download your *.exes directly. It probably is falsely detecting threats.
EDIT:
Windows Defender also interferes with *.zip files of your repositories...
EDIT 2:
It claims to have detected Trojan:Win32/Wacatac.B!ml in your Mars widget project.
Yup! Good ol' Windows Defender, the setup.exe may be old, it is built using setup2go and produces an exe rather than a .msi. A/V tools won't like it. Just download the source and compile yourself. I have Avast and Malwarebytes and Defender (of course) on Windows 7/10/11 and receive no such errors/false positives. I pull/push the code using github desktop.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
Originally Posted by
Peter Swinkels
Hey is that a screenshot of your QB64 program?
Yes, that IS a screenshot of the QB64 project, complete with button objects and associated events attached. It is a replacement to the Windows RUN dialog and I operate it on all my systems. Aiming to rewrite it in VB6 in time.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
Originally Posted by
yereverluvinuncleber
Just download the source and compile yourself code using github desktop.
Vb6 is giving massive amounts of activex related object errors attempting to compile your project. To be honest I thought your Mars widget project looked interesting and wanted to give it a quick look. At the moment I don't really feel like trying to put much effort in to get it to work because of other priorities.
Anyway, thank you for giving me a glimpse of your project on GitHub, they look really amazing!
PS:
Good luck with your "Run Dialog" project. It looks amazing too! :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Just ensure your project references are selected as per the instructions, that you have RC5 installed and registered. I have checked and updated the instructions to ensure they are correct.
Typically, on a new machine, I clone using github, install VB6 and it just compiles straight away. Don't expect it to run without following the instructions. There are dependencies and they are essential. Without them errors will inevitably appear.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Yereverluvinuncleber, thank you for your advice, I will keep that in mind for future reference. : -)
Now, unless anyone has any other suggestions I am going to try implement a byte array instead of a string for to emulate memory, that might resolve the speed issue.
-
1 Attachment(s)
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Okay, INCR/DECR statements have been implemented where applicable and a byte array makes the code a heck of a lot more efficient! :-) The program appears to be running slightly faster now.
And:
If anyone knows anything about dynamic arrays (REDIM PRESERVE) in PowerBASIC 3.5 for MS-DOS, please reply. PowerBASIC gave me a hard time trying to implement these as an alternative for the string I am using to keep track loop addresses. Yes, I used a string because I saw no other reasonable method of simulating a list in QuickBASIC. Anyway I tried fiddling the array's scope such as making it global instead of local to procedures and passing it around as a parameter. How exactly did PowerBASIC give me hard time? Mostly by simply freezing or throwing some error about string handles concerning a string variable that happens to be in the same procedure as the dynamic error. My guess is the stack is somehow getting trashed. I deleted the code concerning the dynamic array, but I could easily rewrite it if anyone would like to see it. Still, if anyone knows about dynamic arrays in PowerBASIC, your help would be much appreciated! :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Okay, seeing as FRE(-3) (the amount free of stackspace) shoots into the negatives before the program freezes while trying to resize an array it is most definitively the stack being trashed. Now I could use the $STACK directive to adjust the amount of available stack space, but this will cost me memory elsewhere. Also, I am not about to implement a complicated mechanism that attempts to dynamically adjust the stack size. In short, REDIM PRESERVE is probably useless in my case. Unless someone has any suggestions, I am going to forget about using it for my interpreter.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Unless I think of any other changes I am done here for now:
https://github.com/PeterSwinkels/Pow...rpreter/upload
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Okay, I implemented user defined types and dynamic arrays in the vbdos version. It should be faster now. Link to GitHub is somewhere in this thread.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
@2kaud, that's the PowerBASIC version! - LOL - I was referring to the link in post #16.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
Originally Posted by
Shaggy Hiker
That's right. You SHOULD be writing a Rockstar interpreter.
Now this I would love to see!
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
LOL - I would like to see myself pulling that one off without suffering a mental breakdown! I might post another tirade!
Seriously, I think a Rockstar interpreter could be done in vb.net or even vb6 but probably not in older BASICs, especially not me.
If someone thinks of a more realistic challenge, I might consider it just to prove a point and for the heck of it. :-) My only constraint is, that it should be feasible in a BASIC for Dos.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
@jdelano: Amber godess eh? Hmmm, I remember my dad's first computer having an amber screen and it ran MS-DOS 3.3 or whatever, ah the memories. Can you believe getting a pc with color graphics was something amazing back then? LOL
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Yeah it was. It has been a fun ride, thats for sure.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
We had an original IBM PC with monochrome display and just one floppy drive (no hard drive - that came with the XT) and it used PC-dos 2.0 and not ms-dos.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Indeed, so many memories! :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
I came across a free copy of the book "Basic - A Self-Teaching Guide 2nd Edition" tonight. Published in 1978. Good stuff.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Ah, that reminds of the times before I got to know the internet during 1995. How I had to make do with the built-in help in programs (if any), the few books in the library and bookstores about BASIC, sample programs, and what little I could gather from other people. I learned a lot through trial and error back then. Even the early internet wasn't all that great, first of all my parents had to pay for each minute I was online occupying the phoneline and there where only a few dozen personal sites with limited information. One of the better websites for BASIC used to be QBasic.com, but even there resources were limited. That site also had a pretty good forum, however there were many flamewars and users not being particularly helpful or friendly. One of the many reasons we now got forums where you have to register. And who remembers Neozones btw? And before I forget unlike today those old forums were vulnerable to HTML code injections. You could format your post or mess up the entire forum that way! :-)
Here is one of the very few 90's style BASIC programming personal websites that is still up and running: https://www.phatcode.net/ - Even the forum had some activity this month! LOL
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Before moving into PC programming, I developed applications for mini-computers (Wang, Dec, DG, Systime and Pick) in various Basic dialects (and Fortran/Assembler for Dec). But when we moved to PC we developed in c, pascal and assembly (using Microsoft and Borland compilers/assemblers - I preferred Borland at the time) but not Basic. I can't really remember why but conversations around pc Basic being just for 'hobbyists' come to mind.... I then moved to C++. I think in total I've written about 3 - 4 programs in GW Basic/Qbasic which if I remember correctly were 'quick ports' of existing Basic programs from a mini-system.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
I guess the BASIC for hobbyists notion stems from the fact those languages were kind of looked down upon. Not entirely unjustified either, GW-BASIC for example, while decent back then for writing some simple programs on your home computer was a sluggish overly verbose piece of crap compared to C for example. The later BASICs have come quite far after that though.
PS:
Imho Visual BASIC for MS-DOS was one of the best basics back for DOS.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
GW-BASIC for example, while decent back then for writing some simple programs on your home computer was a sluggish overly verbose piece of crap compared to C for example
:check:
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Here is the content of a text file that came with PowerBASIC 3.5 about PB vs QB:
Code:
100 ways PowerBASIC 3.2 beats QuickBasic
========================================
1- PB 3.2 supports true pointer variables. Traditionally, a Basic
programmer had to use a combination of DEF SEG and PEEK and POKE to
access memory. Pointers are not only more flexible, they also make
data access much faster.
2- Code pointers allow a programmer to call a routine or jump to a label
without having to know their name. The CALL DWORD extension allows
programmers to call subs by address and pass up to 16 arguments.
3- Calling procedures that accept a variable number of arguments.
4- Underscores "_" in variable names, allowing for more flexibility in
naming variables and procedures.
5- Enhanced communications support. Support for COM1 through COM4 at up
to 115200 bps. Even support for non-standard addresses and IRQs as
well as 16550 FIFO support.
6- PB3 directly creates TSR (terminate/stay-resident) programs which can
"pop-down" to a memory image of 4K! Memory resident programs can be
activated by practically any stimulus: a hot key, timer, inactivity,
a hardware or software interrupt, even a message from a foreground
program. In fact, it's possible for multiple TSRs to activate each
other repeatedly, with two-way communication throughout. No other
language offers this capability as an integral part of the compiler.
7- PB3 uses all real mode memory for dynamic strings. It's the first
and only Basic with a no-limit, handle-based string memory manager;
QB is limited to substantially less than 64k, and PDS has "inside"
segmentation limits (<64k per module, per sub-program, etc.)
8- The PB3 String Memory Manager is a resource available to any user
code. Both Basic and Assembler code can allocate, release, and alter
memory blocks as required by the programmer. While other compilers
may allow you to calcluate string location or assignment, none allow
the full memory management functionality of PowerBASIC.
9- PB3 compiles to true machine code in the integrated environment; the
identical code as an .EXE file. You never need to deal with a slow,
p-code interpreter as in QB and PDS. That means faster development,
and the elimination of subtle differences between interpreted and
compiled results.
10- PB3 offers unsigned integer variable types: BYTE, WORD, DOUBLE WORD.
(byte: 0-255 word: 0-65,535 dword: 0-4,294,967,295). Unsigned
integers are not available in other Basic compilers.
11- Optionally, PB3 can require that all variables be declared before use;
this option greatly enhances the probability of catching "typos"
automatically during compilation.
12- Dual Monitor Support is offered in both the PowerBASIC Integrated
Environment and the PBD Standalone debugger. This allows the
programmer to simultaneously view a full screen of source code and
debug information alongside a second full screen generated by the
target program. Annoying screen flashes and pauses are eliminated.
13- PowerBASIC is DesqView aware.
14- As an enhancement to user-defined TYPES, PowerBASIC is the first Basic
compiler to offer user-defined UNIONS as well.
15- PB3 offers 64-bit signed integer variables types. Quad-word integers
are not available in other Basic compilers.
16- With PowerBASIC, there is no need to maintain numerous sets of
libraries. Other compilers require one set of run time libraries for
near strings, another for far strings, and still another for each of
the floating point options. Then you need Quick Libraries for work
in the IDE, but Link Libraries to create an .EXE. With PowerBASIC,
there's no more confusion: All run time libraries are built into
the compiler, and PB3 selects them automatically! Furthermore, the
built-in PowerBASIC linker recognizes the same object modules, units,
and libraries, whether you're running in the IDE or creating an .EXE.
17- PB3 offers a USING$ function, which may be referenced in any string
expression. It duplicates the numeric and text formatting capability
of PRINT USING, but allows the result to be saved or modified, rather
than require immediate printing.
18- PB3 offers extended precision (80-bit) floating point variable types.
19- The PRINT USING and USING$ functions in PB3 may be dynamically altered
to format numeric values with leading zeros, or other special
characters. Further, currency characters ("$,.") may be easily
adapted to non-USA standards when needed.
20- PB3 offers conditional compilation directives ($IF/$ELSE/$ENDIF) to
allow easy version control, as well as large comment blocks in your
source code.
21- PB3 supports HUGE arrays (total data size > 64k) on a selective basis.
Unlike other Basic compilers, the extra overhead of huge array
calculation is only applied to those arrays which require it.
22- PB3 supports fixed-point BCD variable type with variable precision
from 0-18 digits, not a forced 4 digits which introduces additional
round-off errors.
23- PB3 supports floating point BCD variable type.
24- PB3 offers built-in array manipulation functions: ARRAY SORT,
ARRAY SCAN, ARRAY INSERT, and ARRAY DELETE.
25- PB3 offers a full-functioned, built-in assembler. Critical sections
of a program can easily be hand-optimized to provide the utmost
performance, as Assembler and Basic can be intermixed line-by-line.
26- PB3 won't run out of memory compiling the largest programs. It
automatically uses EMS, XMS, and VMS virtual disk memory.
27- User-defined TYPE arrays need not be a power of two in element
size in order to exceed 128k of data space.
28- The PB3 program editor offers the capability to read and write
blocks of text to external disk files.
29- PB3 supports source-level metastatements for all compilation
switches.
30- VIEW TEXT supports scrollable rectangular text view ports.
31- PEEK and POKE extensions support byte, integer, and long integer.
32- PEEK$ and POKE$ extensions support memory block moves or assignment.
33- FLUSH will force all buffered data to be written to a disk file,
while minimizing the overhead of a file close and re-open.
34- PowerBASIC offers MIN and MAX functions which allow a variable
number of arguments: PRINT MIN(a%,b%,c%,d%)
35- BIT operations include shift, rotate, set, reset, toggle, test.
36- BIT arrays up to 512k bits are implicitly supported.
37- CHR$ allows a variable number of arguments. CRLF$ = chr$(13,10)
38- Optional procedural math package offers faster calculation
(improvement of 40% to 500%) when no numeric co-processor is
installed. Procedural math package uses the 8087 if it is
available, and can toggle between the emulator/procedural option
on a statement-by-statement basis for the highest optimization.
Procedural package adheres to IEEE floating-point standard.
39- Flex string variable type offers fixed-length strings which may
be sized dynamically at run-time.
40- MAP statement allows flex scalar and array variables to be
linked together into dynamic data structures, with nesting
capabilities limited only by available memory. These data
structures are created and sized dynamically at the time of
program execution to offer dynamic data base capabilities.
41- Many string and numeric functions offer the ANY option, such
as INSTR("abcde", ANY "cq") returns 3.
42- EXTRACT$ captures that portion of a string up to a sub-string.
43- REPEAT$ creates a string from a repetition of another string.
44- REPLACE substitutes one sub-string for all occurrences of another.
REMOVE$ removes all occurrences of a sub-string.
45- VERIFY ascertains that all characters in one string also occur
in a second string.
46- TALLY counts the occurrences of a sub-string.
47- LTRIM$/RTRIM$ strip leading/trailing spaces or other characters.
48- STR$(x,y) function specifies y significant decimal digits.
49- ROUND(x,y) rounds off x to y digits past the decimal point.
50- STRPTR/STRSEG return the address of any string variable data.
Dynamic, Flex, and Fixed-length strings are supported as both
scalars and arrays.
51- END statement may return an optional error level.
52- ASCII functions avoids error conditions of ASC function, by
returning -1 if the argument is a zero-length string.
53- Integer divide, MOD, AND, OR, XOR, EQV, and IMP are valid
on all numeric values in the range of a quad-word (64-bit)
integer (+/- 2^63-1).
54- PB3 optionally generates 80286/80386 specific code.
55- Library stripping for ambiguous library functions is controlled
directly by meta-statements or menu choices, rather than the
necessity of complex linker commands.
56- Separate compilation via unit modules is simpler, faster, and offers
standard PUBLIC/EXTERNAL statements. Assembler object modules may be
linked via $LINK meta-statements.
57- Executable files are generated directly rather than complex
shells to a compiler and linker, resulting in faster compilation.
58- A full complement of error checks can easily enabled or
disabled, including STACK, NUMERIC, OVERFLOW, and BOUNDS.
59- The PowerBasic editor doesn't alter capitalization or spacing,
and doesn't insert or remove code from the source program.
60- Line continuation characters are supported inside and outside of
the IDE.
61- Identical code, just as efficient, is generated when error
trapping is enabled. Other compilers generate larger, slower
code whenever a program includes an ON ERROR GOTO clause. This
is a serious factor often overlooked in published benchmarks.
62- PowerBasic supports a single-line if/then/else statement which
is 100% compatible with BASICA/GW-BASIC. Other Basics force this
code to be re-written.
63- PowerBasic performs short-circuit expression evaluation in
boolean expressions.
64- Interpreted print: the user chooses graphic character or
interpreted actions for special ascii characters.
65- MTIMER function provides microtimer accuracy.
66- INSTAT function tests for a keypress without removing it from
the keyboard buffer.
67- INCR and DECR statements are offered for all numeric data types.
68- Forward references to DEF FN, SUB, and FUNCTION are allowed.
69- $SEGMENT allows multiple segments of module level code within
the same source file. There is no requirement to split your
program into multiple modules as your program size increases.
70- EXP2, EXP10, LOG2 and LOG10 are supported.
71- CEIL function returns the smallest integer greater or equal to n.
72- CALL INTERRUPT is built right into the PowerBASIC language. There's
no need to load a special library in order to access this capability.
73- FRAC function returns the fractional part of n.
74- FIX function returns the whole number part of n.
75- ISTRUE and ISFALSE Boolean operators force true and false values
to -1 and 0 respectively.
76- ITERATE forces a new iteration of a loop.
77- PB3 offers absolute arrays at any specific memory location.
78- EXIT FAR provides a controlled, multi-level SUB/FUNCTION
exit - a safe, yet powerful enhancement to the SETJMP and
LONGJMP functions found in C compilers. This allows you to
exit a SUB/FUNCTION, and immediately branch to the label most
recently specified as an EXIT FAR destination in any "parent"
procedure with any number of intervening procedure calls. All
temporaries and local variables are released as necessary, so
this is readily usable for special exception-processing. EXIT
FAR constructs may be nested to any level.
79- CODEPTR and CODESEG functions allow you to obtain the offset
and Segment of any SUB, FUNCTION, or LABEL in the program.
This capability, unavailable in other Basics, is essential
for interrupt handlers and certain other assembler code.
80- A standalone debugger (PBD.EXE) is included with PowerBASIC 3.0.
81- The PB3 Librarian (PBLIB.EXE) constructs libraries which may
include both industry-standard object modules (.obj), as well as
highly efficient binary unit modules (.pbu) constructed by the
PowerBASIC compiler.
82- Internal assembler code can access all PowerBASIC variables (even
local and static variables), as well as subs, functions, and labels.
83- $ALIAS metastatement allows the name of the main data segment to be
redefined for external object modules.
84- BITS function allows fast, one-step conversion between signed and
unsigned representations of a numeric value.
85- Internal procedures ARRAYCALC and ARRAYINFO are provided so that
assembler code can manipulate all aspects of PowerBASIC arrays.
86- PowerBASIC offers the option to preserve or discard the GOSUB stack
at the current SUB/FUNCTION level in case of a trapped error. If
the choice is to discard it, substantially more efficient code can
be generated.
87- PowerBASIC functions can be called just as if they were a SUB, and
the returned result is discarded.
88- CLS statement offers options to clear the text viewport, the graphics
viewport, the key line, or the entire screen.
89- ERRTEST function returns the current error number, while resetting it
to zero for future calls. This provides an efficient means of error
polling when using ON ERROR RESUME NEXT to mask system errors.
90- FILEATTR function can optionally return the open/closed status of a
particular file number, as well as the record length of a random file.
91- KEY statement now offers an optional third parameter which allows the
programmer to define any shift keys which should be ignored in
determining if ON KEY GOSUB should be called. With other Basics,
it's necessary to declare numerous key statements to cover every
possible combination of shift keys., or else an errant "caps lock"
or "num lock" key can cause a defined hot-key to be ignored.
92- NAME statement allows renaming of directories as well as files.
93- DIR$ function allows you to read directory items with any attribute,
not just normal files: sub-directories, volumes, hidden/system files.
94- OPEN COM supports the DT option which causes DTR to be asserted after
the communications file is closed. PowerBASIC supports direct access
to COM3 and COM4.
95- OPTION BINARY BASE allows the programmer to choose binary file access
based at zero or one, depending upon the program logic.
96- PowerBASIC provides documented Basic and Assembler access to numerous
internal system variables. This provides easy access to the cpu type,
co-processor type, cursor shape and visibility, PB revision, screen
page and attributes, video card, print using format characters,
screen/viewport size, and much more.
97- BIN$ function returns the binary representation of a number.
98- GET$ statement reads a binary file, assigning a specified number of
bytes to a string variable. PUT$ statement writes a string expression
to a binary file.
99- DELAY statement pauses program execution for n seconds without the
possibility of interrupt by a keystroke.
100- While PowerBASIC offers a large superset of the functionality found
in other compilers, moving up to PowerBASIC 3.0 couldn't be easier!
PB3 is 99+% compatible with QuickBasic syntax, and our Programmer's
Guide devotes a chapter to the minor differences which remain.
PowerBASIC . . . it's not your basic BASIC!
Check List
==========
Feature PB 3.0 QB 4.5 PDS 7.1 VBDOS
======= ====== ====== ======= =====
TSR programming support built-in X
Internal Assembler in the language X
Option to require variable declaration X X
Unsigned byte, word, dword integer variables X
User-Defined TYPES X X X X
User-Defined UNIONS X
User-Defined Dynamic Data Structures (MAPS) X
Array sort, scan, insert, delete statement X
Pointers to a sub, function, or label X
EXIT FAR multi-level sub/function exit X
Unlimited dynamic string space <1> X
ON LOCAL ERROR X X X
Standalone debugger included X X X
Editor never changes your source programs X
Conditional compilation ($IF/$ELSE/$ENDIF) X
Viewport for screen text display X X
Alternate procedural math package X X X
Procedural math package utilizes 8087 X
Extended 80-bit floats & 64-bit integers X
Floating point BCD variables X
Fixed point BCD variables <2> X X X
Block memory moves with PEEK$/POKE$ X
<1> PowerBASIC can allocate all real mode memory for any and all dynamic
strings. There are no "inside limits" (such as 64k limit per module
or sub-program) as are found in far string implementations.
<2> PowerBASIC Fixed-Point BCD variables are implemented as 64-bit scaled
integers for computational efficiency. The decimal digits (to the right
of the decimal point) may be user-defined from 0 to 18. Some Microsoft
products offer a currency data type, which is fixed at 4 decimal places.
Even though the internal format is identical to that of PowerBASIC,
additional round-off code is typically required in financial calculations
to correct the precision to standard dollars/cents levels. Since this
binary-coded-decimal format differs from traditional "natural bcd",
Microsoft contends that their products do not support BCD variables.
That's all very impressive, however here's what QB can do and PB can't:
1. Low-resolution 320x200 256 color VGA.
2. 60 rows of text in default VGA (640x480 16 color)
3. Constants of a datatype other than integer.
4. QB's IDE and help are more user friendly imho.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Quote:
Originally Posted by
fafalone
I think it's really interesting QB had predeclared functions... I had been contemplating posting a request for these in tB so we could provide prototypes of callback functions like the SDK headers, but it seemed like pushing it too far into C/C++ territory. But looks like it would just be getting back to it's roots.
I'd strongly advise against such a suggestion. This existed in C/C++ out of necessity. Ancient compilers were single pass compilers which means if you call a function, that function must be compiled before any call to the function is compiled. Modern compilers are multi-pass compilers which means you can call a function in the first compilation unit and implement that function in the 1000th compilation unit and your program will still work because the compiler will resolve the all the functions on in all compilation units on the first pass.
Single pass compilers do not make sense anymore considering the excess of computing power we have today so I doubt TwinBASIC uses a single pass compiler.
Note: When I say single pass, it's not single pass in the strictest sense. I'm sure there is some backtracking but due to the constraints on computing power back in the day, it was avoided as much as possible.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Lately I have been thinking about writing a vbdos vs qb list, anyway I remembered explaining to someone why qb is vastly superior to GWBasic:
Q(uick) Basic:
1. Is faster.
2. Supports long integers.
3. Supports 64k strings.
4. Supports binary file access.
5. Supports VGA.
6. Supports structures.
7. Supports procedures and functions with their own separate scope.
8. No mandatory line numbers.
9. Supports labels.
10. Offers a way to exit loops without resorting to using to the GOTO statement.
11. Supports unconditional loops.
12. Conditional expressions can be placed at the end of the loop.
13. Supports SELECT CASE.
14. Supports multiline blocks in IF statements.
15. Supports multiple branches for IF statements.
16. Supports constants.
17. Offers functions for converting the letter case in strings.
18. Comes with a much better editor.
19. Supports arrays with a variable base.
20. Has a way to check array boundaries.
Also, if I remember correctly GWBasis has a buggy INSTR function which is likely to return a value of one instead of zero when it could not find the specified substring.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
If I were to sum up what makes QuickBasic superior to GWBasic in a single statement, I'd say QB is vastly superior because it introduced structured programming constructs to the language. GWBasic was like assembly. Every line of assembly operates in isolation, performing a discrete, self-contained action without any relation to the surrounding lines. There was no concept of aggregating related statements into cohesive blocks, such as Do...While loops, If...Else...Then conditional blocks, or subroutines/functions etc.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Not quite, GWBasic did support blocks inside loops, however QB vastly did expand on that concept.
btw:
I keep seeing something about ISAM databases in qb 7.1 and vbdos’s online help. They seemingly throw a lot of keywords at you without really explaining the fundamentals and the sample code I did find confused me. I thought I had a pretty good grasp on programming in BASIC and figuring out code but this concept has me stumped.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Is it ISAM you don't understand or using ISAM within QB? If it's ISAM there's plenty of info on the Internet.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
I don’t really know about either, however given that there is enough info about ISAM in general, I’d probably benefit the most from an example in either vbdos or qb.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Duh, I overlooked the Booklook example that came with VBDOS. Its entire bookgen.bas module appears to contain ISAM related code. The only question now is whether I can figure it out. :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
vbdos vs qb:
1. Object oriented and event driven interface controls.
2. Better interface.
3. More efficient with memory thanks to EMS support.
4. Database support (ISAM).
5. Mandatory variable declaration with OPTION EXPLICIT.
6. COMMON SHARED variables can be grouped into memory blocks.
7. Error traps can be local to procedures.
8. More flexible syntax: underscores in names, empty braces for function calls, AS clauses for functions.
9. REDIM PRESERVE.
10. DIR$
11. CURDIR$
12. CHDRIVE
13. Currency datatype.
14. Has a clipboard for text.
15. Has the ability to extract specific sub values from the date and time.
16. Finance related functions.
16. Has a printer object which could replace the LPRINT statement.
17. A string formatting function. (FORMAT$)
18. The NOW, TIMESERIAL and DATESERIAL functions.
19. ERROR$ returns descriptions that go with error codes.
20. More flexible way to manage the stack size with STACK statement and function of the same name. Also less drastic than CLEAR in resetting data.
This is all I think of atm. :-)
PS:
It seems that even if you don't use the ability to create forms there would still be many subtle advantages over qb! :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Does anyone here know whether there is any real advantage to using PRINTER.PRINT instead of LPRINT? Both appear to behave the same way. The only reason I think of for the PRINTER object is compatibility with Visual BASIC for Windows.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Don't take this as gospel but when I see LPRINT it evokes memories of writing directly to a parallel port like LPT1. It's been far too long since I touched a classic BASIC variant like QuickBasic. I barely remember how anything works there anymore so I could be wrong here.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Now that you mention it, VBDOS's PRINTER object does have a PrintTarget property which allows you to specify an LPT port (1-3), but wouldn't that still mean that internally it basically still writes directly to the port except for the fact you get to select which port? Now, I know Windows has drivers mediating between devices and software, from the very first version if I am not mistaken, but I don't think VBDOS applications use drivers, correct? In fact, does an MS-DOS application writing to LPT1 write directly to the parallel port? Wouldn't you need to use the OUT statement for that? I am not sure, but I believe IO.SYS was meant to serve has a rudimentary hardware abstraction layer which would mean it probably had a "driver" embedded for writing to parallel ports among other things. But, like you said, this is all very long ago, I never to knew every detail about MS-DOS and probably forgot a few things too. :-)
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
DOS had drivers but it was also a real mode operating system. Drivers in DOS were in the form of something called a TSR which is most closely equivalent to a modern Windows service or a Linux/Unix daemon. When it came to hardware access like Printers and such, real mode allows your applications to directly access to the hardware so I'd expect the Printer object to also use LPT ports. Perhaps they changed it when Visual Basic was ported to Windows because Windows is a protected mode operating system so you can only access the hardware through a user mode intermediary.
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Yes, but until this was mostly blocked when NT versions of Windows were released MS-DOS programs could still mostly directly access the hardware while running in Windows. Something about v86 mode from what I understood. I never really quite understood how exactly early versions of Windows managed to run DOS programs. Once I really started thinking about it I was really confused about how exactly Windows captured a DOS program's graphical output (which except for text mode stuff) was mostly directly written to video memory and (usually) neatly displayed in a Window. And while I have stated before that I felt that many early versions of Windows were unstable bug ridled pieces of *** it was kind of impressive how Windows juggled executing all those different processes. As long as no process interfered too much with the rest that is. I was especially impressed when I first used Windows 2000 that it wasn't so easy to crash as earlier Windows versions I'd worked with.
And yes, I've told this story several times before, but I can't resist bringing it up again: the fact Windows 2000 ran on my old piece of *** a 80586 at all was perhaps the most impressive thing about it. :-) According to the sysytem requirements it needed a 80686 with twice (128 mb) the amount of memory mine had. (64 mb.) It slow as heck, *but* it was surprisingly stable! :-)
-
1 Attachment(s)
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Well, I decided to have some fun and make a rudimentary Notepad clone in VBDOS. On one hand it is wonderful to be able to implement fully functioning forms, messageboxes, and dialogs with relative ease in a BASIC dialect for MS-DOS, on the other VBDOS's form designer is definitely a bit more laborious than the one found the Windows versions, but that's kind of to be expected. ;-)
EDIT:
And before I forget, this project isn't finished yet. ;-)
-
1 Attachment(s)
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
-
1 Attachment(s)
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Attached is a much more complete version of DOSPad, and also for who might have tried to download my previous file, I forgot that VBDos saves certain files in a binary format by default. Personally I don't like that because I prefer to be able to open a source file in an external editor if need be. (It is rare, but sometimes necessary.) Also, binary format files can set-off false virus warnings, so that is one more reason I dislike them, especially when sharing my projects online such as on this forum.
Since my project is meant to be fun little exploration of building a form-based app in VBDos I am probably not going to add much more features to my program other than some rudimentary error-handling capabilities. Don't expect much more than the most basic of basic Notepad clones. It should work as intended, but isn't meant to be truly practical.
I am considering attaching a compiled program, but I need to check whether such file-types are allowed, also virus scanners don't like binaries, so there's that. :-)
Asssuming a moderator at Vogons won't remove it, the compiled program as included as an attachment in this post at their forum:
https://www.vogons.org/viewtopic.php...37881#p1237881
-
Re: Feeling nostalgic I fired up QuickBASIC and wrote a Brain***** interpreter!
Final version can be found here:
https://www.vogons.org/viewtopic.php...38001#p1238001
Unless serious bugs are found, I probably won't change it much anymore. :-)