TRSE

Started by Xerra, January 03, 2021, 11:59:52

Previous topic - Next topic

Xerra

Any of you nerd-heads ever come across TRSE before? Correct name being "Turbo Rascal Syntax Error, expected but BEGIN"

https://lemonspawn.com/turbo-rascal-syntax-error-expected-but-begin/

What started off as a C64 dev system ended up being a cross-machine tool to create programs for Vic, C64, Pet, C128, C16, Plus4, Amiga 500, BBC, NES and god knows what over systems as well. It's pretty amazing what can be done with this thing as the author has left it open for developers to create their own functions for the machine they are creating code for as well as a lot of already added stuff. The Vic - which is the one I've been tinkering with - has loads of stuff added by an enthusiast for making it stupid-easy to create bitmapped games, for example.

C64 Prg Ed is a great tool but it's based on Visual studio, so no direct Mac access without Parallels, and limited to only a few Commodore machines whereas this is catering for loads of others and is very-much geared towards demo's and games development, as can be seen with all the hardware hitting example code. And you can run it on both OSX and Linux as well as Windows machines. Graphics editing tools and   compiler are built in, but you can use another compiler if you don't like the default one. It also does template stuff like generating the code for your graphics into your projects automatically and other clever stuff like that.

The only thing a bit odd with it is that it uses a language very much based on Pascal so a bit of coding-style adjustment would be needed to get stuff going with it. I'm not sure if there's any way of using a different language. Some of the example source code shows some very clever stuff using very few lines of code so it's obviously been done for that reason. The general layout of code seems to be an init procedure for global variables, another procedure which has all your functions within, and use local variables, and the main loop is after this. The layout is something like what's shown below:



Program MyProgram;
var
    a,b,c : byte = 0;

Procedure Myprocedure(mp_i:byte);
var
  somProcedureVariable : byte;
begin
  // Do someting
end;

// This is the main block.
begin
   // Call user-defined procedures etc
   MyProcedure(2);
end.





M2 Pro Mac mini - 16GB 512 SSD
ACER Nitro 5 15.6" Gaming Laptop - Intel® Core™ i7, RTX 3050, 1 TB SSD
Vic 20 - 3.5k 1mhz 6502

Latest game - https://xerra.itch.io/Gridrunner
Blog: http://xerra.co.uk
Itch.IO: https://xerra.itch.io/

iWasAdam

I remember that image from my turbo pascal days. Great looking editor they have though ;)

Steve Elliott

That looks very cool, thanks for sharing.   8)
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

Xerra

I've been tinkering with this a fair bit this week, trying to get my head around Pascal, because this is definitely the way forward to creating proper 100% machine code games on the Vic 20 for me. Having spoken with the author, it seems he picked Pascal as it's a lot easier to write code that's compilable into 6502 with a good deal of optimisation, as well as easy to add custom functions to the dev system itself. I've been keeping up with the Slack channel they have where other people are adding to the program as well now.

Here's an example of something simple I tried as a start of recreating an old game I made on the Vic 20 around 35 years ago. This shows the pascal syntax and how I've been incorporating a simple game state system to build my game into.


program SpaceSplat;

// Vic 20 unexpanded game

var 

Title : cstring = ("Space Splat");
Author : cstring = ("by Tony Brice, 2021");
Start : cstring = ("Space to Start");
Play : cstring = ("Game in progress");

gameState: byte = 1;
// 1 = title
// 2 = game
// 3 = game over

// -------------------------------------------------------------------------------
// **** Procedures ****
// -------------------------------------------------------------------------------
procedure RenderTitleScreen();
begin
moveto(5,2,hi(screen_char_loc));
PrintString( #Title, 0, 11 );
moveto(0,5,hi(screen_char_loc));
PrintString( #Author, 0, 19 );
moveto(3,10,hi(screen_char_loc));
PrintString( #Start, 0, 14 );
end;

procedure RenderPlayScreen();
begin
moveto(3,16,hi(screen_char_loc));
PrintString( #Play, 0, 16 );
end;

procedure ScreenClear();
begin
ClearScreen( 32, #SCREEN_CHAR_LOC); // ^$1e00 - unexpanded screen location
ClearScreen( BLUE, #SCREEN_COL_LOC); // ^$9600 - unexpanded colour location
//AUX_COLOR_AND_VOLUME := %00000010;
SCREEN_BG_COLOR := BLACK + SCREEN_BG_WHITE;
screenmemory := #SCREEN_CHAR_LOC;
end;


// -------------------------------------------------------------------------------
// **** Main  Loop ****
// -------------------------------------------------------------------------------
begin
ScreenClear();
while (true) do
begin
readjoy1();
if ( joy1 & JOY_FIRE  ) then
begin
gameState := gameState+1;
ScreenClear();
end;
if (gameState > 2) then gameState := 1;
if (gameState=1) then RenderTitleScreen();
if (gameState=2) then RenderPlayScreen();
end;
end.



And how it actually translates into assembler itself (TRSE lets you see the assembler created source code from your pascal project after you compile it) is pretty efficient, and also pretty daunting, if you were to write it that way direct, like I did previously with the scrolling demo I did for the C64 using CBM Prg Studio.


processor 6502
org $1000
; Starting new memory block at $1000
StartBlock1000
.byte    $0, $0E, $08, $0A, $00, $9E, $20, $28
.byte   $34,$31,$31,$32
.byte    $29, $00, $00, $00
; Ending memory block
EndBlock1000
org $1010
; Starting new memory block at $1010
StartBlock1010
SpaceSplat
jmp block1
Title
dc.b $13, $10, $01, $03, $05, $20, $13, $10, $0c
dc.b $01, $14, 0
Author
dc.b $02, $19, $20, $14, $0f, $0e, $19, $20, $02
dc.b $12, $09, $03, $05, $2c, $20, $32, $30, $32
dc.b $31, 0
Start
dc.b $13, $10, $01, $03, $05, $20, $14, $0f, $20
dc.b $13, $14, $01, $12, $14, 0
Play
dc.b $07, $01, $0d, $05, $20, $09, $0e, $20, $10
dc.b $12, $0f, $07, $12, $05, $13, $13, 0
gameState dc.b $01
; NodeProcedureDecl -1
; ***********  Defining procedure : initjoy1
;    Procedure type : Built-in function
;    Requires initialization : no
; ----------
; ReadJoy1 and ReadJoy2 (on supported platforms)
; populates joy1 and joy1pressed which can be tested by AND-ing with the following constants:
;JOY_DOWN  = %00000100
;JOY_UP    = %00000010
;JOY_LEFT  = %00001000
;JOY_RIGHT = %00000001
;JOY_FIRE  = %00010000
VIC20_PORTACASS = $911F
VIC20_PORTBVIA2 = $9120  ; Port B 6522 2 value (joystick)
VIC20_PORTBVIA2d = $9122 ; Port B 6522 2 direction (joystick)
joy1 = $5e
joy1last = $5f
joy1pressed = $60
callReadJoy1
LDA VIC20_PORTACASS
EOR #$FF
AND #$3C
LDX #$7F
SEI
STX VIC20_PORTBVIA2d
LDY VIC20_PORTBVIA2
BMI initjoy1_JoySkip2
ORA #$02
initjoy1_JoySkip2
LDX #$FF
STX VIC20_PORTBVIA2d
CLI
LSR
STA joy1
eor joy1last
and joy1
sta joy1pressed
lda joy1
sta joy1last
rts
; NodeProcedureDecl -1
; ***********  Defining procedure : initmoveto
;    Procedure type : Built-in function
;    Requires initialization : no
jmp initmoveto_moveto3
screenmemory =  $fe
colormemory =  $fc
screen_x = $80
screen_y = $82
SetScreenPosition
sta screenmemory+1
lda #0
sta screenmemory
ldy screen_y
beq sydone
syloop
clc
adc #22
bcc sskip
inc screenmemory+1
sskip
dey
bne syloop
sydone
ldx screen_x
beq sxdone
clc
adc screen_x
bcc sxdone
inc screenmemory+1
sxdone
sta screenmemory
rts
initmoveto_moveto3
rts
; NodeProcedureDecl -1
; ***********  Defining procedure : initprintstring
;    Procedure type : User-defined procedure
print_text = $80
print_number_text .dc "    ",0
printstring
ldy #0
printstringloop
lda (print_text),y
cmp #0 ;keep
beq printstring_done
cmp #64
bcc printstring_skip
sec
sbc #64
printstring_skip
sta (screenmemory),y
iny
dex
cpx #0
beq printstring_done
jmp printstringloop
printstring_done
rts

; // Vic 20 unexpanded game
; // 1 = title
; // 2 = game
; // 3 = game over
; // -------------------------------------------------------------------------------
; // **** Procedures ****
; // -------------------------------------------------------------------------------
; NodeProcedureDecl -1
; ***********  Defining procedure : RenderTitleScreen
;    Procedure type : User-defined procedure
RenderTitleScreen
; MoveTo optimization
lda #$31
sta screenmemory
lda #>$1e00
clc
adc #$00
sta screenmemory+1
clc
lda #<Title
adc #$0
ldy #>Title
sta print_text+0
sty print_text+1
ldx #$b ; optimized, look out for bugs
jsr printstring
; MoveTo optimization
lda #$6e
sta screenmemory
lda #>$1e00
clc
adc #$00
sta screenmemory+1
clc
lda #<Author
adc #$0
ldy #>Author
sta print_text+0
sty print_text+1
ldx #$13 ; optimized, look out for bugs
jsr printstring
; MoveTo optimization
lda #$df
sta screenmemory
lda #>$1e00
clc
adc #$00
sta screenmemory+1
clc
lda #<Start
adc #$0
ldy #>Start
sta print_text+0
sty print_text+1
ldx #$e ; optimized, look out for bugs
jsr printstring
rts
; NodeProcedureDecl -1
; ***********  Defining procedure : RenderPlayScreen
;    Procedure type : User-defined procedure
RenderPlayScreen
; MoveTo optimization
lda #$63
sta screenmemory
lda #>$1e00
clc
adc #$01
sta screenmemory+1
clc
lda #<Play
adc #$0
ldy #>Play
sta print_text+0
sty print_text+1
ldx #$10 ; optimized, look out for bugs
jsr printstring
rts
; NodeProcedureDecl -1
; ***********  Defining procedure : ScreenClear
;    Procedure type : User-defined procedure
ScreenClear
; Clear screen with offset
lda #$20
ldx #$fe
ScreenClear_clearloop15
dex
sta $0000+$1e00,x
sta $00fd+$1e00,x
bne ScreenClear_clearloop15

; // ^$1e00 - unexpanded screen location
; Clear screen with offset
lda #$6
ldx #$fe
ScreenClear_clearloop16
dex
sta $0000+$9600,x
sta $00fd+$9600,x
bne ScreenClear_clearloop16

; // ^$9600 - unexpanded colour location
; //AUX_COLOR_AND_VOLUME := %00000010;
; Assigning memory location
; Assigning single variable : $900f
lda #$18
; Calling storevariable
sta $900f
; Assigning single variable : screenmemory
lda #$00
ldx #$1e
sta screenmemory
stx screenmemory+1
rts
block1

; // -------------------------------------------------------------------------------
; // **** Main  Loop ****
; // -------------------------------------------------------------------------------
jsr ScreenClear
MainProgram_while17
; Binary clause Simplified: NOTEQUALS
lda #$1
; Compare with pure num / var optimization
cmp #$0;keep
beq MainProgram_elsedoneblock20
MainProgram_ConditionalTrueBlock18: ;Main true block ;keep
jsr callReadJoy1
; Binary clause Simplified: NOTEQUALS
; 8 bit binop
; Add/sub where right value is constant number
lda joy1
and #$10
; end add / sub var with constant
; Compare with pure num / var optimization
cmp #$0;keep
beq MainProgram_elsedoneblock50
MainProgram_ConditionalTrueBlock48: ;Main true block ;keep
; Assigning single variable : gameState
inc gameState
jsr ScreenClear
MainProgram_elsedoneblock50
; Binary clause Simplified: GREATEREQUAL
lda gameState
; Compare with pure num / var optimization
cmp #$3;keep
bcc MainProgram_elsedoneblock56
MainProgram_ConditionalTrueBlock54: ;Main true block ;keep
; Assigning single variable : gameState
lda #$1
; Calling storevariable
sta gameState
MainProgram_elsedoneblock56
; Binary clause Simplified: EQUALS
lda gameState
; Compare with pure num / var optimization
cmp #$1;keep
bne MainProgram_elsedoneblock62
MainProgram_ConditionalTrueBlock60: ;Main true block ;keep
jsr RenderTitleScreen
MainProgram_elsedoneblock62
; Binary clause Simplified: EQUALS
lda gameState
; Compare with pure num / var optimization
cmp #$2;keep
bne MainProgram_elsedoneblock68
MainProgram_ConditionalTrueBlock66: ;Main true block ;keep
jsr RenderPlayScreen
MainProgram_elsedoneblock68
jmp MainProgram_while17
MainProgram_elsedoneblock20
; End of program
; Ending memory block
EndBlock1010



So, after weeding through that, you can probably see why I'm rather impressed with TRSE. Hopefully actually knock one off the bucket list and actually finally have a 100% machine code game for the Vic 20 written by me. Here's hoping :)
M2 Pro Mac mini - 16GB 512 SSD
ACER Nitro 5 15.6" Gaming Laptop - Intel® Core™ i7, RTX 3050, 1 TB SSD
Vic 20 - 3.5k 1mhz 6502

Latest game - https://xerra.itch.io/Gridrunner
Blog: http://xerra.co.uk
Itch.IO: https://xerra.itch.io/

Dabz

Intel Core i5 6400 2.7GHz, NVIDIA GeForce GTX 1070 (8GB), 16Gig DDR4 RAM, 256GB SSD, 1TB HDD, Windows 10 64bit

dawlane

Quote from: Xerra on January 07, 2021, 01:25:33
I've been tinkering with this a fair bit this week, trying to get my head around Pascal, because this is definitely the way forward to creating proper 100% machine code games on the Vic 20 for me.
Pascal is a hell of a lot easier to learn than C/C++. There are a number reasons that it's not the de facto industry programming language and some of these were, multiple dialects, the code being closed source, so it never got round universities and the real killer available for DOS/Window only.

MikeHart

Imho Pascal is the superior language to C++. Delphi was very popular in the 90s here in Gemany. A lot of mid size companies created business with it. It was my tool of choice for my editor called IndeED.
But yes, the lack of cross platforming, the higher price tag, owner ship changes were responsible for its future.
FreePasal now keeps up the flag. For personal stuff I keep using it.


Xerra

Been working some more on the simple gamestate to start putting a simple Vic 20 game together, based on a listing I remember typing in my youth. I have a moving ship now and done some other simple stuff which has been a great learning curve. It's probably already a more advanced program when assembled than any of the simple 6502 routines I did back then. TRSE is getting better and better all the time.

I threw the author £30 in Norwegian Krone so he could buy some beer for his efforts and it turns out that will just about buy 6 cans in his local supermarket. Cost of living in Norway must be insane. I could get three cases of Heineken bottles for that.

Here's how the code is coming along, while it's still small enough to throw in a code block.


program SpaceSplat;

// *** Vic 20 unexpanded game ***

var 

// Strings
Title : cstring = ("Space  Splat");
Author : cstring = ("by Tony Brice,2021");
Player : cstring = ("(-O-)");

// Integers
Score : integer = 0; // Player score

// Bytes
Lives : byte = 3; // Player lives
Level : byte = 1; // Difficulty level
Timer : byte = 100; // Used with level to adjust game speed
playerX : byte = 10; // Players X position on fixed Y line
gameState: byte = 1; // 1 = title, 2 = game, 3 = game over
playerFired : byte = 0; // Has player fired

// -------------------------------------------------------------------------------
// **** Procedures ****
// -------------------------------------------------------------------------------
procedure RenderTitleScreen();
begin
// Display Title Screen
moveto(5,4,hi(screen_char_loc));
PrintString( #Title, 0, 12 );
moveto(2,7,hi(screen_char_loc));
PrintString( #Author, 0, 18 );
moveto(0,12,hi(screen_char_loc));
PrintString( "FIRE TO START THE GAME", 0, 22 );
end;

procedure HUD();
begin
// Display Hud Information
moveto(0,0,hi(screen_char_loc));
printString( "SCORE-", 0, 6 );
moveto(6,0,hi(screen_char_loc));
printdecimal(Score,4);
moveto(15,0,hi(screen_char_loc));
printString( "LIVES-", 0, 6 );
moveto(21,0,hi(screen_char_loc));
printdecimal(Lives,0);
moveto(0,1,hi(screen_char_loc));
printString( "PRESS UP TO QUIT GAME!", 0, 22);
end;

procedure BeginGame();
begin
// Set up a new game
Score:= 0;
Lives:= 3;
end;

procedure Delay();
var
i:byte = 0;
begin
// Pause to slow game down (if it worked...)
for i:=0 to Timer do wait(50);
end;

procedure PlayScreen();
begin
// Gameplay stuff
HUD();

// Show player ship
moveto(playerX,3,hi(screen_char_loc));
PrintString(#Player, 0, 5);

// Controls
readjoy1();
if (joy1 & JOY_LEFT) then
begin
if (playerX > 0) then
begin
playerX := playerX - 1;
moveto(playerX+5,3,hi(screen_char_loc));
printString(" ",0,1);
end;
end;
if (joy1 & JOY_RIGHT) then
begin
if (playerX < 17) then
begin
playerX := playerX + 1;
moveto(playerX-1,3,hi(screen_char_loc));
printString(" ",0,1);
end;
end;
Delay();
end;

procedure RenderGameOverScreen();
begin
// Display Game Over
moveto(2,11,hi(screen_char_loc));
printString( "G A M E -- O V E R",0,18);
end;

procedure ScreenClear();
begin
// Clear screen
ClearScreen( 32, #SCREEN_CHAR_LOC); // ^$1e00 - unexpanded screen location
ClearScreen( BLUE, #SCREEN_COL_LOC); // ^$9600 - unexpanded colour location
//AUX_COLOR_AND_VOLUME := %00000010;
SCREEN_BG_COLOR := BLACK + SCREEN_BG_WHITE;
screenmemory := #SCREEN_CHAR_LOC;
end;

// -------------------------------------------------------------------------------
// **** Main  Loop ****
// -------------------------------------------------------------------------------
begin
ScreenClear();
while (true) do
begin
readjoy1();
if (joy1pressed & JOY_UP) then
begin
if (gameState = 2) then
begin
ScreenClear();
gameState := 3;
end;
end;

if ( joy1pressed & JOY_FIRE ) then
begin
if (gameState = 1) then
begin
ScreenClear();
gameState := 2;
// Reset the score and lives on a new game
BeginGame();
end;

if ( gameState=2) then
begin
if (joy1pressed & JOY_FIRE) then
begin
// fire weapon
end;
end;

if (gameState=3) then
begin
ScreenClear();
gameState := 1;
end;
end;

if (gameState=1) then RenderTitleScreen();
if (gameState=2) then PlayScreen();
if (gameState=3) then RenderGameOverScreen();
end;
end.

M2 Pro Mac mini - 16GB 512 SSD
ACER Nitro 5 15.6" Gaming Laptop - Intel® Core™ i7, RTX 3050, 1 TB SSD
Vic 20 - 3.5k 1mhz 6502

Latest game - https://xerra.itch.io/Gridrunner
Blog: http://xerra.co.uk
Itch.IO: https://xerra.itch.io/

Steve Elliott

Quote
Imho Pascal is the superior language to C++

I always liked Pascal and C at College...C++ gets ever larger and larger, with change after change.

Quote
I threw the author £30 in Norwegian Krone so he could buy some beer for his efforts and it turns out that will just about buy 6 cans in his local supermarket.

:o  crazy prices!

Looks like you're making progress Xerra, good stuff.
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

Xerra

Indeed I am. Got the system working with includes and a proper gamestate now so the project is more manageable as I can break up the source files. Amazing how much you pick up if you jump straight into a game, rather than little test programs. Having your work shown on a proper Vic 20 screen is really doing it for me as it was so hard to do in proper machine code for me back when I was a kid.

@qube, I think you should have a play with it and get something working on your new Vic 20.

I intend to stick my game onto the carousel of games you can choose from as soon as it's actually a game. Not to mention testing it out on the real machine, once I get the thing fixed.

M2 Pro Mac mini - 16GB 512 SSD
ACER Nitro 5 15.6" Gaming Laptop - Intel® Core™ i7, RTX 3050, 1 TB SSD
Vic 20 - 3.5k 1mhz 6502

Latest game - https://xerra.itch.io/Gridrunner
Blog: http://xerra.co.uk
Itch.IO: https://xerra.itch.io/

Baggey

Just Downloaded this very interesting!

Baggey
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Xerra

Quote from: Baggey on August 08, 2021, 18:25:19
Just Downloaded this very interesting!

Baggey

Look at the examples for whatever machine you're planning to code on. Some amazing stuff in there.
M2 Pro Mac mini - 16GB 512 SSD
ACER Nitro 5 15.6" Gaming Laptop - Intel® Core™ i7, RTX 3050, 1 TB SSD
Vic 20 - 3.5k 1mhz 6502

Latest game - https://xerra.itch.io/Gridrunner
Blog: http://xerra.co.uk
Itch.IO: https://xerra.itch.io/