Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ Programming ➜ General ➜ GPascal - a blast from the past

GPascal - a blast from the past

Posting of new messages is disabled at present.

Refresh page


Pages: 1 2  

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Sat 25 Jun 2011 05:22 AM (UTC)

Amended on Sat 25 Jun 2011 11:33 PM (UTC) by Nick Gammon

Message

Commodore 64 manual cover


Quite a few years ago (1978) I started working with microprocessors, in particular the Motorola 6800 evaluation board.

Subsequently I made a "tiny" Pascal compiler for it, which was entirely stored in EEPROM (eraseable ROM).

Later it was converted to run on the Apple II, and later again the Commodore 64.

Andrew Stuart from Supercoders in Melbourne has put together a lengthy blog post which describes (with images and PDF files) the history of this project:

http://www.supercoders.com.au/blog/nickgammongpascal.shtml


I managed to dig up the old ads, "GPascal News" issues, and magazine reviews about GPascal. Also, with a large stroke of luck, the source listing of the original (Commodore 64 version) compiler - in assembler.

Snapshot of GPascal source

Full source: http://www.gammon.com.au/GPascal/source/


Andrew has assembled those into a nice read, with links to the various articles and images that I sent him.

So if you want to know what I was doing with computers 30 years ago take a read of that!

You can even grab a copy of the compiler, and a Commodore 64 emulator, and try it out!

Thanks, Andrew, for motivating me to dig out all this archival material. Another 10 years and the DVD with the source backed up on it might have been lost.


Apple II manual cover


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Fiendish   USA  (2,533 posts)  Bio   Global Moderator
Date Reply #1 on Sat 25 Jun 2011 06:48 PM (UTC)
Message
That's a wicked piece of work, Nick. Stellar writeup. :)

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #2 on Sun 26 Jun 2011 12:30 AM (UTC)

Amended on Sun 26 Jun 2011 06:07 AM (UTC) by Nick Gammon

Message
Thanks, Fiendish!

To explain the source (http://www.gammon.com.au/GPascal/source/) a bit, a lot of work was put into fitting it into the available memory. One approach I used was to tokenise things like error messages.

Message tokens


This was done by putting bytes with the high-order bit set inside messages, and then expanding them out at display time. This is a table I extracted of the various tokens, in hex, (from PAS1.ASM lines 1754+):


B0 = P-codes
B1 = full
B2 = Constant
B3 = Identifier
B4 = expected
B5 = missing
B6 = Illegal
B7 = Incorrect
B8 = string
BA = compiler
BB = literal
BC = mismatch
BD = Error
BE = zero
BF = source file
C0 = of
C1 = or
C2 = to
C3 = ended at 
C4 = Symbol
C6 = Stack
C7 = Instruction
C8 = table
C9 = Type
CA = list
CC = Number
CD = Line
CE = Gambit
CF = Games
D2 = Version 3.1 Ser# 5001
D3 = Copyright 1983
D4 = <C>ompile
D5 = <S>yntax
D6 = Written by Nick Gammon 
D7 = <Q>uit
D8 = Range
D9 = Parameter
DA = <E>dit,
DB = <


Error messages


The error messages, in decimal, once the tokens are expanded, are (from PAS1.ASM lines 1222+):


 1:  Memory full 
 2:  Constant expected     
 3:  = expected 
 4:  Identifier expected     
 5:  , or : expected  
 6:  bug
 7:  *) expected 
 8:  Incorrect string     
 9:  . expected 
10:  ; expected 
11:  Undeclared Identifier 
12:  Illegal Identifier     
13:  := expected 
14:  literal string of zero length 
15:  compiler limits exceeded 
16:  THEN expected 
17:  ; or END expected  
18:  DO expected 
19:  Incorrect Symbol  
20:  bug   
21:  Use of procedure Identifier in expression 
22:  ) expected 
23:  Illegal factor 
24:  Type mismatch     
25:  BEGIN expected 
26:  "of " expected 
27:  Stack full     
28:  TO or DOWNTO expected  
29:  string literal too big 
30:  Number out of Range  
31:  ( expected 
32:  , expected 
33:  [ expected 
34:  ] expected 
35:  Parameters mismatched
36:  Data Type not recognised 
37:  Symbol table full   
38:  Duplicate Identifier 


Source tokens


When the source was being processed it was turned into "tokens" (eg. numbers, symbols, reserved words, identifieds, etc.).

This made it easy to do comparisons in the compiler proper, because rather than having to do string compares, you simply checked a single byte. The source tokens, in hex, are (from PAS1.ASM line 559+):


81 = get
82 = const
83 = var
84 = array
85 = of
86 = procedure
87 = function
88 = begin
89 = end
8A = or
8B = div
8C = mod
8D = and
8E = shl
8F = shr
90 = not
91 = mem
92 = if
93 = then
94 = else
95 = case
96 = while
97 = do
98 = repeat
99 = until
9A = for
9B = to
9C = downto
9D = write
9E = read
9F = call
A1 = char
A2 = memc
A3 = cursor
A4 = xor
A5 = definesprite
A6 = plot
A7 = getkey
A8 = clear
A9 = address
AA = wait
AB = chr
AC = hex
AD = spritefreeze
AE = close
AF = put
DF = sprite
E0 = positionsprite
E1 = voice
E2 = graphics
E3 = sound
E4 = setclock
E5 = scroll
E6 = spritecollide
E7 = groundcollide
E8 = cursorx
E9 = cursory
EA = clock
EB = paddle
EC = spritex
ED = joystick
EE = spritey
EF = random
F0 = envelope
F1 = scrollx
F2 = scrolly
F3 = spritestatus
F4 = movesprite
F5 = stopsprite
F6 = startsprite
F7 = animatesprite
F8 = abs
F9 = invalid
FA = load
FB = save
FC = open
FD = freezestatus
FE = integer
FF = writeln


Notice that the "message tokens" in the range 0xB0 to 0xDB are not in the list. This is so that the output routine can convert back tokens which are either messages or reserved words without clashes.

This makes the snippet of source in the earlier post more understandable:


                1800 * REPEAT
                1801 *
9734: 20 02 90  1802 REPEAT   JSR  PSHPCODE   
9737: 20 49 80  1803 REP1     JSR  GTOKEN     
973A: 20 63 93  1804          JSR  STMNT      
973D: A5 16     1805          LDA  TOKEN      
973F: C9 3B     1806          CMP  #';'       
9741: F0 F4     1807          BEQ  REP1       
9743: A9 99     1808          LDA  #$99       
9745: A2 0A     1809          LDX  #10        
9747: 20 34 80  1810          JSR  CHKTKN     
974A: 20 40 90  1811          JSR  GETEXPR    
974D: 20 55 80  1812          JSR  PULWRK     
9750: 20 51 90  1813          JSR  WRK:OPND   
9753: A9 3D     1814          LDA  #61        
9755: 4C 88 80  1815          JMP  GENRJMP    


The code calls GTOKEN (get token) and processes a statement. Then it checks if we got a ";" token, and if so, gets another statement. When the statements separated by semicolons run out, it checks for token 0x99 (which is "until" from the above table) and if it doesn't get it outputs error 10 which is "; expected" from the earlier table).

P-codes


This is the meanings of the P-codes (pseudo machine codes):


Code Function   Description
---- ---------- ------------------------------------

00 = LIT     	Load constant
01 = DEF:SPRT	DEFINESPRITE
02 = NEG     	Negate (sp)
03 = HPLOT   	PLOT
04 = ADD     	Add (sp) to (sp - 1)
05 = TOHPLOT 	PLOT (not used)
06 = SUB     	Subtract (sp) from (sp - 1)
07 = GETKEY  	GETKEY
08 = MUL     	Multiply (sp) * (sp - 1)
09 = CLEAR   	CLEAR
0A = DIV     	Divide (sp - 1) / (sp)
0B = MOD     	Modulus (sp - 1) MOD (sp)
0C = ADRNN   	Address of integer
0D = ADRNC   	Address of character
0E = ADRAN   	Address of integer array
0F = ADRAC   	Address of character array
10 = EQL     	Test (sp - 1) == (sp)
11 = FINISHD 	Stop run (end program)
12 = NEQ     	Test (sp - 1) != (sp)
13 = CUR     	Cursor position
14 = LSS     	Test (sp - 1) < (sp)
15 = FREEZE:S 	SPRITEFREEZE
16 = GEQ     	Test (sp - 1) >= (sp)
17 = INH     	Input hex number
18 = GTR     	Test (sp - 1) > (sp)
19 = LEQ     	Test (sp - 1) <= (sp)
1A = ORR     	OR  (sp - 1) | (sp)
1B = AND     	AND (sp - 1) & (sp)
1C = INP     	Input number
1D = INPC    	Input character
1E = OUT     	Output numbher
1F = OUTC    	Output character
20 = EOR     	Not (sp) (logical negate)
21 = OUH     	Output hex number
22 = SHL     	Shift left (sp) bits
23 = OUS     	Output string
24 = SHR     	Shift right (sp) bits
25 = INS     	Input string into array
26 = INC     	Increment (sp) by 1
27 = CLL     	Relative procedure/function call
28 = DEC     	Decrement (sp) by 1
29 = RTN     	Procedure/function return
2A = MOV     	Copy (sp) to (sp + 1)
2B = CLA     	Call absolute address
2C = LOD     	Load integer onto stack
2D = LODC    	Load character onto stack
2E = LDA     	Load absolute address integer
2F = LDAC    	Load absolute address character
30 = LDI     	Load integer indexed
31 = LDIC    	Load character indexed
32 = STO     	Store integer
33 = STOC    	Store character
34 = STA     	Store integer absolute address
35 = STAC    	Store character absolute address
36 = STI     	Store integer indexed
37 = STIC    	Store character indexed
38 = ABSCLL  	Absolute procedure/function call
39 = WAIT    	WAIT
3A = XOR     	XOR (sp - 1) ^ (sp)
3B = INT     	Increment stack pointer
3C = JMP     	Jump unconditionally
3D = JMZ     	Jump if (sp) zero
3E = JM1     	Jump if (sp) not zero
3F = SPRITE  	SPRITE
40 = MVE:SPRT 	POSITIONSPRITE
41 = VOICE   	VOICE
42 = GRAPHICS 	GRAPHICS
43 = SOUND   	SOUND
44 = SET:CLK 	SETCLOCK
45 = SCROLL  	SCROLL
46 = SP:COLL 	SPRITECOLLIDE
47 = BK:COLL 	GROUNDCOLLIDE
48 = CURSORX 	CURSORX
49 = CURSORY 	CURSORY
4A = CLOCK   	CLOCK
4B = PADDLE  	PADDLE
4C = SPRT:X  	SPRITEX
4D = JOY     	JOYSTICK
4E = SPRT:Y  	SPRITEY
4F = OSC3    	RANDOM
50 = VOICE3  	ENVELOPE
51 = SCROLLX 	SCROLLX
52 = SCROLLY 	SCROLLY
53 = SPT:STAT 	SPRITESTSTATUS
54 = MOV:SPT 	MOVESPRITE
55 = STOP:SPT 	STOPSPRITE
56 = STRT:SPT 	STARTSPRITE
57 = ANM:SPT 	ANMINATESPRITE
58 = ABS     	ABS (absolute value of (sp))
59 = INVALID 	INVALID
5A = LOADIT  	LOAD
5B = SAVEIT  	SAVE
5C = X:OPEN  	OPEN
5D = FR:STAT 	FREEZESTATUS
5E = OUTCR   	Output a carriage-return
5F = X:CLOSE 	CLOSE
60 = X:GET   	GET
61 = X:PUT   	PUT


Operations that mention (sp) refer to "whatever value is on the top of the stack", and (sp - 1) is the second value from the top.

Thus for example, when you add, it pulls the stop value from the stack, and then the second top value, adds them, and pushes the result onto the stack.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #3 on Sun 17 Jul 2011 03:31 AM (UTC)

Amended on Fri 28 Nov 2014 02:01 AM (UTC) by Nick Gammon

Message

Below is a quick demo of G-Pascal in operation, running on the VICE emulator:


(Video cannot be shown because scripting is disabled)


This demo shows entering the editor (E), listing the source program (L), compiling it (C), and then running the compiled program (R).


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #4 on Sun 17 Jul 2011 03:35 AM (UTC)
Message
VICE emulator available here:

http://vice-emu.sourceforge.net/

G-Pascal disk image available here:

http://www.gammon.com.au/GPascal/G-Pascal_v3.0.d64

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #5 on Sun 17 Jul 2011 04:09 AM (UTC)

Amended on Fri 28 Nov 2014 02:02 AM (UTC) by Nick Gammon

Message

Another demo, showing a slightly longer program, this time playing sounds using the inbuilt sound chip (emulated of course in this case):


(Video cannot be shown because scripting is disabled)



- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #6 on Sun 17 Jul 2011 04:34 AM (UTC)

Amended on Sun 17 Jul 2011 04:36 AM (UTC) by Nick Gammon

Message

Syntax diagrams, to help understand the code:

These are from the Apple II manual - they doesn't include the extra functions in the Commodore 64 version.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Cjb   Australia  (3 posts)  Bio
Date Reply #7 on Wed 22 Feb 2012 02:25 PM (UTC)
Message
I'd just like to note that I've munged the original Merlin assembler source into something a bit more modern (cc65's assembler to be exact-- it's what I use for my 6502 SBC work), and managed to produce a byte-exact copy of the G-Pascal 3.1 release: it's available from http://kildall.apana.org.au/~cjb/G-Pascal/

It only takes 0.16 seconds to assemble and build the entire program... ;)

I've been telling my 6502-dev friends about G-Pascal for years! I've actually made several attempts at decompiling it over the years, so that there could be a nice programming language on the SBC projects I've been involved with... and then just a few days ago, I discovered the Supercoders interview and the SOURCE CODE!
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #8 on Wed 22 Feb 2012 07:56 PM (UTC)
Message
Cool, thanks!

Where do you get the assembler?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Cjb   Australia  (3 posts)  Bio
Date Reply #9 on Thu 23 Feb 2012 02:33 AM (UTC)
Message
>>> Where do you get the assembler?

ca65 is from the CC65 6502 cross-compiler suite (www.cc65.org; ftp://ftp.musoftware.de/pub/uz/cc65/) ... There's a few choices for cross-assemblers out there, but I gravitated to ca65 for it being a no-hassle build on my Unix systems, and its native syntax resembles the 'Commodore' way of doing things a fair bit (What's all that "LABEL = *" business? :P :). It's also a fully-featured macro assembler, supports all the models of 65*02, and your get the source-- which I've used personally to add support for the Mitsubishi 740/50734 CPUs (a very nice 10MHz embedded 6502 clone..)

I've never once thought of using "BLT" and "BGE" in place of BCC and BCS...

Now that I've managed to build a normal working G-Pascal, the project for me now is to make a Generic 6502 version that will build for machines like the SYM-1, VIC20, and 50734; it shouldn't be much effort to make a ROMable GPascal either, so I can have a system that starts up into PASCAL instead of BASIC :D ... And someone I've already talked to is working at separating the IDE into a stand-alone parser and interpreter.
Top

Posted by Cjb   Australia  (3 posts)  Bio
Date Reply #10 on Thu 23 Feb 2012 05:40 PM (UTC)
Message
Cjb said:

Now that I've managed to build a normal working G-Pascal, the project for me now is to make a Generic 6502 version that will build for machines like the SYM-1, VIC20, and 50734 [...]

This might scare people:
http://kildall.apana.org.au/~cjb/vicpascal.png

(Just a rough proof-of-concept attempt...)
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #11 on Thu 23 Feb 2012 10:27 PM (UTC)
Message
Cjb said:

... it shouldn't be much effort to make a ROMable GPascal either, so I can have a system that starts up into PASCAL instead of BASIC :D ... And someone I've already talked to is working at separating the IDE into a stand-alone parser and interpreter.


It was designed to go into ROM - that is, there is no modification inside program space.

Also the stand-alone interpreter should be easy enough. I used to sell/give away a GPascal interpreter, which was basically just the runtime part of the code (easy enough to get at as I think that was just one of the source files).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Deathshadow   USA  (4 posts)  Bio
Date Reply #12 on Wed 19 Sep 2012 07:07 AM (UTC)
Message
I have a question -- it lets me save to a p-code object file; but where's the stand-alone "run time system"?

Be a lot handier if there was a easy standalone -- the C64 manual mentions it, would be nice to have it.

Though I supposed I could start tinkering with "part 4's" source code...

Of course, would be a LOT nicer if it compiled to machine language, since Kyan and "super Pascal" leave a bit to be desired on the C64... but it still beats the tar out of BASIC for speed and C for ease of use.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #13 on Wed 19 Sep 2012 09:55 AM (UTC)
Message
I don't know where you would get the run-time system except for a floppy disk I have here which I don't have any device to stick it into.

As for compiling into machine code, that's a whole new (and more complicated) ball game.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Deathshadow   USA  (4 posts)  Bio
Date Reply #14 on Sat 22 Sep 2012 05:07 PM (UTC)
Message
Nick Gammon said:
I don't know where you would get the run-time system except for a floppy disk I have here which I don't have any device to stick it into.

Hmm... I'm planning on setting my c64 stuff back up (there's a TRS-80 Coco 1 sitting in it's spot right now) sometime over the coming weeks.

I don't suppose you'd be willing to send that disk to someone like myself who could turn it into a .d64 file?

Would be nice to be able to preserve it... assuming said disk even still works.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


95,442 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

Posting of new messages is disabled at present.

Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.