GW-BASIC clone with extensions
Steve++

This is a project proposition/announcement. Yes, I know it's still Monday in some backward parts of the world ::).

I want to make a line-numbered interactive BASIC interpreter that is as similar as possible to GW-BASIC. This is not because I think it will have any commercial value (although I may try to sell it, just to see how it goes). This idea is a result of nothing more than nostalgia. Although I started BASIC on the C64 (then Amstrad CPC-6128), GW-BASIC has a lot of nostalgic value for me. Perhaps that's because it was my first foray into PC programming, which was followed shortly by QBasic (which has little nostalgic charm), Turbo Pascal 7.0, then C/x86/C++/Java/etc (no nostalgic value there).

I just got my hands on a GW-BASIC reference manual for $2.

So far, the only compatibility issue I can think of is PEEK/POKE. Any old GW-BASIC programs that use PEEK/POKE won't work, unless I add some sort of emulation layer (but still no guarantee, especially if a program dynamically changes itself).

I'll be adding extra screen modes so the full range of resolutions are available. Of course, all the graphics functionality will use Allegro :).

Beyond that, I'll add some sort of loadable language extension system (i.e. library loading).

axilmar

There was a version of BASIC developed for Allegro, if I recall. What happened to that?

A J

So if it acts just like GW-BASIC what value has it ?
Why not just use GW-BASIC ?

Steve++

Extra screen modes beyond EGA (for a start). It will allow (old) programmers familiar with GW-BASIC to make programs that take advantage of current hardware using a nostalgic interpreter. It is not intended for developing any serious commercial software; just for having fun. But I'm sure some really nice games could be made.

Edit:
I'll start coding it in Java, then I'll migrate to C++ once I get the core interpreter and module loader working. Then I'll add the graphics/sound module using Allegro.

Arthur Kalliokoski

IIRC, there was a DEF SEG thing that'll trip you up as well. Perhaps the best thing to do is to rewrite the programs to use something a little less hardware dependant. If you have code that peeks or pokes something without comments, try Ralf Browns Interrupt List.

Evert

Segmented memory is annoying, but it's not that hard to work around.
That said, I actually see a point (sortof) in writing a QuickBASIC interpreter (as in I can see some people feel like using it); I can't really say the same for a GW-BASIC one.

A J

Open a new project on source forge, call if OpenGW.

Get all your friends to access it like mad for a week, it'll rise to the top of the list.

Watch as the bandwagon is infiltrated by everyone that wants to get in at the ground floor.. offer everyone 'positions' like Chief _____. then when the army of developers are assembled, declare a $10,000 prize for the 1st person to finish the project.. watch as hundreds of off-shore developers hack away at it for the prize money. of course, this will cost you $10,000, but at least it would be done in a week.

Steve++

It's one of those projects I want to do myself. I've always wanted to make some sort of language translator. The ultimate ambition is to make a compiler for the best programming language ever (a language I haven't designed yet), but I've realised that I should start somewhere at the bottom. As far as I know, line-numbered interactive BASIC interpreters are a good place to start. They're usually rather small and uncomplicated.

I'll enhance the language immediately, such as adding support for variable names longer than two characters. I'll make an intermediate code format that's a little bit more compressed and faster to run than GW-BASIC. I think GW-BASIC stored variable names as is, and they got away with it because they were only two bytes. I would probably have to have some sort of table with indices stored in place of variable names.

As for PEEK/POKE, I'll either disable them or somehow check them (throwing Illegal function call if applicable) - they could be useful for playing with already allocated memory, or perhaps even accessing the video framebuffer. I'll probably add some memcpy functionality too.

I'll allow the SCREEN function with all the original (ugly) modes, probably emulated in (S)VGA. I'll extend it with something like
SCREEN MODE <width>, <height>, <depth> [,pages]

LennyLen
Quote:

they could be useful for playing with already allocated memory, or perhaps even accessing the video framebuffer. I'll probably add some memcpy functionality too.

The only version of BASIC I ever used was Atari BASIC, so I'm not sure if what I'm about to describe was possible with GW-BASIC, but it was something I used quite a bit in the games I wrote.

The font for the text modes were stored in memory. Each character was a 8x8 bitmap and was stored in 8 bytes of memory. Each byte represented a line of the bitmap, and the value determined which pixels were 'on'.

So for the letter A:

 ........ = 0
 ..**.... = 48
 .****... = 120
 **..**.. = 204
 **..**.. = 204
 ******.. = 252
 **..**.. = 204
 **..**.. = 204

It was therefor quite easy to do graphics by overwriting the character set with your own set using POKE. You could then POKE the ASCII value of the character you had overwritten to the screen memory and bingo, you had graphics. The Atari 800XL also had an undocumented multicolour graphics mode, but I can't remember how it was stored in memory (though it was similar).

If you could add something similar to your GW-BASIC clone, I'd give it a go for nostalgia sake. I had a lot of fun making games using that method.

axilmar

There was an Allegro based BASIC language. What happened to that? maybe it can be resurrected.

Steve++

I looked for it after you mentioned it the first time. I found a link but it was broken. Apparently it wasn't very good as a BASIC interpreter. It calculated all expressions in left-to-right order regardless of operators, brackets, etc.

Richard Phipps

My C book "C: The complete reference - Herbert Schildt" has a whole section on a 'Little C' interpreted language. Perhaps this kind of information would prove useful to you? If so, check out the book in your local bookstore.

Steve++

Cool - thanks. I'll have a look if it's there.

I've never written any kind of language translator, but I've got a fair idea how to go about most of it. I think the most challenging part will be parsing equations; challenging in the sense that I know the least about that than anything else. But I've got a fair idea about using a stack in that situation.

In case people actually want to distribute stand-alone applications, I may even include a utility that converts a BASIC text file into p-code, attaches the interpreter to it and wraps it up in an executable. Perhaps the step after that is to make a "compiler" that converts the BASIC code to C + Allegro.

I just realised one of the challenges is that many different commands have their own unique syntax, which will make it hard to include them simply as modules (i.e. standard library functions). Perhaps each library would be a DLL (or shared object), with each keyword represented by a parsing function. It seems a bit vague now, but the details will come to me, I'm sure.

nonnus29
Quote:

It seems a bit vague now, but the details will come to me, I'm sure.

Sounds like your at about the level I was at when I wrote my vm/basic interpreter about 3 years ago. It was pretty easy at first just doing the simple: IF, THEN, FOR, NEXT, LET, stuff. Even equation parsing is pretty straight forward if you use a stack to put it in postfix notation. BUT when you start thinking about how to nest if statements, loops, etc... that's when you smack head on into the REAL issues of compiler writing.

After that I started researching actual compiler writing. It's a vast subject and C isn't necessarily the best language to do it in. But regardless I highly recommend researching and using the tools built for the job lex/flex and yacc/bison. Also, the Dragon book really is an exceptional peice of work. That thing is amazing, it's very accesible and readable.

Also, there are murmurs and whispers around today about a new programming paradigm known by several names: software factories, model driven architecture, Language oriented programming, all centered around 'DSL's' ie Domain Specific Languages. Basically the idea is that instead of using a general purpose language like C/C#/Java to create a solution to a problem, first create a language that approaches the constructs of the problem to develope the solution. This is what Lisp programmers have been doing for years. This little gwbasic clone of yours could be a great learning experience in that direction...

Steve++

Nested selection/looping... meh. The good thing about line-numbered BASIC is that I don't have to worry about that for the most part, except for FOR-NEXT loops. For that all I need is a simple stack with TOS being the variable expected in the next NEXT statement. If something else is found, either an error can be thrown, or the program can carry on and act appropriately weird. I just realised there's also WHILE-WEND nesting to any level in GW-BASIC. This should be very easy, once again with a stack. Good old stacks. There's certainly no IF-THEN-ELSE nesting allowed in this sort of interpreter.

Sometimes murmurs and whispers are just murmurs and whispers.

Quote:

This little gwbasic clone of yours could be a great learning experience in that direction...

I'm sure it will be a great learning experience in many directions.

Quote:

After that I started researching actual compiler writing. It's a vast subject and C isn't necessarily the best language to do it in. But regardless I highly recommend researching and using the tools built for the job lex/flex and yacc/bison.

I've given a lot of thought to this recently, which is probably why I'm writing a BASIC interpreter. You see, yacc/bison would protect me too much from really learning what drives interpreters and compilers. Yet if I started writing a compiler or interpreter for a full-blown procedural (or even OO) language without such tools, I would quickly reach an unmanageable level of complexity that would kill the project. More than anything right now, I am interested in making an interpreter using an imperative (including OO) language that I already know. There's a certain appeal to that. And since it's strictly a hobby project, I'm allowed to follow my heart more than my head.

And who knows, I may use that knowledge to make new BASIC interpreters and compilers that would become competitors of Dark, Blitz, Cool, etc. But that's not my goal.

EDIT: Just realised the FOR-NEXT and WHILE-WEND loops will need to use the same stack. Quite obvious really... wouldn't want to have a WHILE-FOR-WEND-NEXT sequence. Only a single stack for all loop constructs could help manage that.

nonnus29
Quote:

You see, yacc/bison would protect me too much from really learning what drives interpreters and compilers.

Actually you couldn't be more wrong. But you'll find that out. ;)

Michael Jensen

I also vote for QBasic... GW-BASIC is silly...; I've been waiting for a qbasic "emulator" for a long time now... remember qbasic supported strcuts...

As for peek and poke, you have to emulate a console anyway, you might as well map the array of your consoles memory to peek and poke, and if you have to keep track of anything else in an array (and you will) you might as well map those values to peek and poke also, even the char fonts (as someone said the atari let you maniuplate)... etc.

Also your code should execute in a sandbox from the interpreter, IE: even if peek/poke corrupt memory of the program while running, BREAK still works, and you can exit back to the interpreter with a normal font, nothing broken, etc...

Paul Pridham
Quote:

Actually you couldn't be more wrong. But you'll find that out.

Actually you couldn't be more wrong. ;) ;) smug ::)

You certainly don't need yacc/bison for a line-numbered BASIC. Even the problem of operator precedence isn't that big of a deal if you think about it a little. I wrote a rather BASIC-like scripting language in a day, and it had operators with proper precedence, while loops, conditionals, variables, etc. Here's an example test script in it:

1a = 0
2if a then
3 writeln IF!
4endif
5 
6a = b + 3 = 100 - 1
7writeln a
8 
9a = b = c = 200
10writeln a
11 
12while a = b and a = c do
13 writeln a=b
14 c = 100
15repeat
16 
17a = 1 + 2 + test - 4 + 2
18writeln a
19 
20 
21a = b = c = -1
22 
23a = 9
24a = a + 1 + 2 + 3 + 7
25writeln a
26 
27a = 1 + 1 - 5 + 2 - 5
28writeln a
29 
30a = 0
31 
32while a <> b do
33 writeln a<>b
34 a = b
35repeat
36 
37a = 0
38 
39while a < b do
40 a = b
41 writeln a<b
42repeat
43 
44a = 300
45 
46while a > b do
47 writeln a>b
48 a = b
49repeat
50 
51while a and b and c do
52 writeln aANDbANDc
53 a = 0
54repeat
55 
56while a or b and c do
57 writeln aORbANDc
58 c = 0
59repeat
60 
61writeln DONE!
62pause

I'm sure you can do what you want. Just take the simplest approach and don't get mired in all of the wonder-libs and crap that are supposed to solve all of your problems and world peace to boot. ;)

Also, since you're going to play with stacks, you should take a look at Forth for some ideas. It's the stack MASTER. :D

nonnus29
Quote:

Actually you couldn't be more wrong. ;) ;) smug ::)

No, Actually *you* couldn't be more wrong. ;) ;) smug ::)

:P

I was talking about doing anything more complex than a line-numbered basic. I knew you'd say something forthlike if you noticed the thread though... ;D

Matthew Leverton

I used GW-BASIC when I was 11. And I knew even then that it was horrible. Imagine my surprise when I realized that our computer actually had QBASIC! It gave me incentive to finish my first game (monopoly). That source is full of gems like:

1097 If play$ = b$ Then
       Print b$; " must pay "; a$; " a bill of "; owe
       dola = dola + owe: dolb = dolb - owe
     End If
1098 If play$ = a$ Then
       Print a$; " must pay "; b$; " a bill of "; owe
       dola = dola - owe: dolb = dolb + owe
     End If
1099 GoTo 1110

The line numbers are there because I began it in GW-BASIC. That was the project where it finally hit me what arrays were for. ;) Now I look at my 11 year old nephew and wonder what in the world I was doing programming a monopoly game at that age. :-/

So anyway. GW-BASIC stinks. QBASIC rules!

Steve++

Yes, QBasic is better. But it has already been cloned (FreeBASIC). GW-BASIC just has more nostalgic value. A friend of mine wrote a reasonable good (for the time) adventure game and a whole bunch of other fun programs. I also wrote a few things, like rotating cubes, starfields, etc.

Maybe the next step will be a QBasic clone with extra capabilities. Not yet though.

Paul whoknows

Don't forget the save "myprog.bas",p feature.
How are you going to implement the sound instruction? and play?

Steve++

I'll probably have two different syntaxes for the sound and play commands. Using the old syntax will make PC-speaker-like audio eminate from the default sound device, unless I can figure out a way to use the PC speaker. The new syntax will generate audio in a more contemporary manner. Perhaps play will use a MIDI resource. Sound could just play wav/mp3/ogg/whatever.

Don't worry, I won't forget the ,p feature. I'm reading the manual thoroughly!

Progress note: I've done some research on infix->RPN->solve, with a few hand-iterated expressions to test my understanding. It's quite straight forward. It shouldn't be too hard to add function calls to that (the predefined ones plus any user defined functions via DEF FN). All I need to do is find the time to put it all together! Oh, and I need to figure out the loadable module system for commands (so all commands are implemented as loadable modules). The expression parser itself will be a loadable module.

I'm using modern techniques to write a dinosaur interpreter.

Camm Camm

It sounds like a great idea Steve.

For many of us, programming in BASIC on the Commodore 64, Amstrad 128, Spectrum, Amiga and any number of other Micro computers out at the time, was the most common language the indie games programmer knew. Then when the IBM compatible came out, many of these games programmers embraced Basica and GW-Basic. Even with the release of Q-Basic, many features that should have been part of the language were missing, making the process of creating games very difficult. Here is a list of features that I would have liked to see in the original GW-Basic:

- A full range of Hi res screen modes(Super VGA at least)

- Access to the sound card, not just the PC speaker

- Easy importing and manipulation of image formats such as bitmaps

- Something in the GUI to keep track of subroutines, Q-Basic did it nicely

- Some features for animated sprites and collision detection

If GW-Basic or even Q-Basic had these features my games would have been so much better. Yes I am aware of Blitz Basic and Dark Basic, but I like the nostalgia of Steves proposed project and can see how it could be a great step in Steve eventually developing the best Indie games programming language on the planet

Johan Halmén

I used mbasic on my Bondwell 16. I'm ashamed to admit but that was a pirate copy. At school we had a strange CP/M machine with two floppies (real floppies, that's 5.25") and I simply copied the mbasic to a floppy of my own, a kind of backup thing. Some years later I bought my Bondwell 16, which could read most floppies of that time. So I managed to copy the mbasic interpreter to the 10 MB HD.

Evert
Quote:

Here is a list of features that I would have liked to see in the original GW-Basic:

- A full range of Hi res screen modes(Super VGA at least)

- Access to the sound card, not just the PC speaker

You do realise that when GW-BASIC came out most people would have liked to own a computer with the hardware to do that, right? It would have been years ahead of its time (or it might have been an Amiga, I think those things had high-resolution high-colour and decent sound long before PCs did).

Camm Camm

Yeah, I see your point. What I didn't like is that qbasic came out and never had screen modes past 320x200 with 256 colors (the dreaded screen 13). At the time we would have really liked a screen mode with 640x480 with 256 colors, with bitmap and sound card support. So for Steves project I guess some extra screen modes and sound card support go without saying. I just really liked those early days, before hardware specifications went throught the roof, where the indie programmer, even in basic had a chance to make something playable not laughable {^_^}

Evert
Quote:

What I didn't like is that qbasic came out and never had screen modes past 320x200 with 256 colors (the dreaded screen 13). At the time we would have really liked a screen mode with 640x480 with 256 colors, with bitmap and sound card support.

QBasic came out in 1991. While SVGA was around at the time, it was definately not a standard feature in consumer PCs. Same for sound cards.

Steve++

Everything up to VGA, which is 320x200x256 and 640x480x16, is industry standard. Beyond that, manufacturers made their own standards which the industry collectively labelled Super VGA (or just SVGA). Although the screen modes were pretty much the same (eg. each SVGA adapter could do 640x480x256), the hardware interface to program these adapters wasn't standard at all. This is because video memory is mapped into the first 1MB of memory (the only region of memory directly accessible from 16-bit DOS applications), but there wasn't enough space to map the whole video buffer to real-mode RAM.

Manufacturers decided to devise their own workarounds without first standardising, presumably to get an advantage over competitors. Eventually enough companies came together to support the VESA standards (1, 2 & 3, and some sub-versions I think). The VESA standards allowed DOS programs to gain access to these video cards through a common software interface. I think this all came after QBasic anyway. QBasic in its days supported all the modes guaranteed to be available on a VGA system.

Audric

I'd advise against the line numbers, they are an artifact from another time...
Their usefulness is in:
1) providing identifed targets for GOTO/GOSUB
2) allow command-line editing, for a system which doesn't have decent text editing capabilities. Ie: In a command-line BASIC, type 150 CLS it will insert/replace line 150 of the current program.

Unless you want to write a complete text editor, you can safely assume every programmer will use one of those good free text editor, and customize syntax highlighting to your Basic variant, so the second usage is moot.

For the first usage of line numbers (target for GOTO), custom labels are way more human-readable... And from the parsing point of view, there is no difference between storing the goto targets as numbers or string - you'll check they are unique the same. (line "100" or label "start_of_loop")

Check and see, but I'm pretty sure you'll soon accept line numbers as compatibility only, since:
10 CLS
20 PRINT "HELLO WORLD"
30 GOTO 20

can be parsed and stored in-memory exactly like:

10:
CLS
20:
PRINT "HELLO WORLD"
30:
GOTO 20

Either way. It's YOUR Basic, so don't feel forced to make it support exactly the same syntax as another's :)

Michael Jensen
Quote:

I'd advise against the line numbers, they are an artifact from another time...

You can't have GW-BASIC without line numbers -- commands typed in without line numbers execute immediatley -- which is the correct behavior because otherwise GW-BASIC would have no idea where to store your code.

Hence, QBASIC > GW-BASIC.

-- However, if you wanted to support scripts without line numbers, you could simply add them in on load (You could have a command to set the default transposition) -- with that approach you could also do a lot of other powerful things like load two programs into memory at once, transposing the line numbers of one program to proceed at the end of the first program...

Of course for goto to work on a file with line numbers to be added in after the fact, you might want to allow multiple labels per line

10 labelish: goto labelish
or
labelish: goto labelish

anyway, my head is in the process of exploding -- later.

Thread #585559. Printed from Allegro.cc