Jump to content
Sign in to follow this  
MrFish

PL65 Problem - WRTSTR/WRTLN

Recommended Posts

I'm doing some coding in PL65 using the 2nd cracked version (where compiling actually produces run-able code). I'm having a problem getting several related library procedures to execute properly when being called from a procedure that has a STRING passed as one of it's parameters.

 

The following code example produces an executable in which the PROC WRTSTR (from 'Terminal.lib') in the PROC PrintText does not print the string A$. At this point during execution the program continuously prints to the screen what looks like the contents of memory.

 

INCLUDE D:Terminal.lib

!--------------------------------------

PROC PrintText (STRING A$[20])

 INT I

BEGIN

 FOR I=1 TO 50000 DO
 NEXT

 WRTSTR (A$)

 REPEAT
 FOREVER

END

!--------------------------------------

MAIN ()

 STRING A$[20]

BEGIN

 A$ = "Main Proc "
 WRTSTR (A$)

 A$ = "PrintText Proc "
 PrintText (A$)

END

 

 

If I code the PROC PrintText without a STRING as a parameter I can then execute a WRTSTR without any problems. This example will work whether I have no parameters or if any parameters that are passed are not STRINGs.

 

 

INCLUDE D:Terminal.lib

!--------------------------------------

PROC PrintText ()

 INT I
 STRING A$[20] DATA "PrintText Proc ";

BEGIN

 FOR I=1 TO 50000 DO
 NEXT

 WRTSTR (A$)

 REPEAT
 FOREVER

END

!--------------------------------------

MAIN ()

 STRING A$[20]

BEGIN

 A$ = "Main Proc "
 WRTSTR (A$)

 PrintText ()

END

 

 

Also, WRTSTR will fail in PROC PrintText if I pass a STRING parameter even if I don't use the passed parameter in the WRTSTR statement. This problem persists with the WRTLN function as well, which is just a variant that sends an EOL at the end of the string being printed to the screen. Using PCHAR (and altering the code accordingly) instead of WRTSTR cures the problem, but I'm still wondering why WRTSTR and WRTLN will not function properly in this particular case?

 

I'm running the compiler off a DOS 2.5 disk rather than the uploaded SpartaDOS disk. I've tried compiling and running it under SpartaDOS X using the original disk and the DOS 2.5 disk as well and it doesn't change the outcome. I've run the executables under emulation and with real hardware and I've compiled it using real hardware. There are no examples of using WRTSTR or WRTLN in the sample game program that Noahsoft included on the PL65 disk. It uses PCHAR for it's title screen.

 

Normally I would post this in the programming forum, but since the cracked disk was posted on the main forum and since this may be a problem with the cracked compiler or an associated library file, I'm posting it here.

 

Here are the files for the above example, including a copy of PL65 on a DOS 2.5 disk:

 

PL65 Example.zip

 

Any help is appreciated.

 

Thanks,

MF

Share this post


Link to post
Share on other sites

Interesting. In either case, surely WRTSTR is passed a pointer value. Only difference I can see is in use the parameter stack between the two calls. I've had a play around with it but am not making any progress.

 

It's an interesting language, this. Pascal-like with assembler thrown in. I have to say it's given me an appetite for coding on the A8 again - which I have sorely missed since going cross-development. I wish we had the sources for PL65 since I think the compiler's I/O could probably be speeded up (assuming it uses single byte put / get).

 

Anyway - getting away from the point here. I'll keep playing with this. :)

Share this post


Link to post
Share on other sites

Hi Mr Fish,

 

I just stumble over your text now and I don't know if my quote may be usefull for you by now in 2014 ...

 

I see you used the same A$ declaration for your procedure and for global variable.

perhaps if compiler is single pass, reservation for A$ as var either as global and local can make a problem. trying to change to B$ in proc declaration, just to see ?

 

perhaps also map A$ to see how strings are implemented (pascal as PL65 seems to get its inspiration use the first byte of data string to define the lenght of the string (quicker process)

while C (azt) check each char/byte to see if zero (slower). perhaps another method here, I don't know.

 

I stumble on your post because PL65 interest me as he can mix ASM & high level language (as we could do in turbo-pascal at his time) (and it remember me a bit the PLM I used 20 years ago on 8031/ 8051 microcontrollers).

 

best regards

 

Rudy

Edited by DearHorse

Share this post


Link to post
Share on other sites

Hello,Friends,

Resently I've tried to write simplest TSR in pl65.

! VBI Procedure for changing colors
! It Stays TSR after loading
BYTE HELPFG=$02DC,COLBAK=$02C8
CONST HELP=$11,BLUE=$80,RED=$32
BYTE OLDHLP
INT DOSINI=$0C,MEMLO=$2E7,FINISH

PROC VBI*()
  CONST SYSVBV=$E45F
BEGIN
    LDA HELPFG
    CMP OLDHLP BEQ Exit
    CMP #HELP BNE Exit
!
    LDA COLBAK
    CMP #RED BNE ToRED
!
    LDA #BLUE STA COLBAK
    GOTO Exit
:ToRED
    LDA #RED STA COLBAK
:Exit
    LDA HELPFG STA OLDHLP
    LDA #$07 STA HELPFG
    JMP SYSVBV
END

PROC SetVBI*()
  CONST SETVBV=$E45C
BEGIN
  STX XSAVE
  LDA #$06
  LDX #VBI/$100
  LDY #VBI AND $FF
  JSR SETVBV
  LDX XSAVE
END

PROC NoRESET*()
BEGIN
  GOTO INIT
! This part is Resident.
:TROJAN
  RTS
:BUMPUP
  LDA #FINISH AND $FF STA MEMLO
  LDA #FINISH/$100    STA MEMLO+1
  RTS
:TSR
  JSR TROJAN
  JSR BUMPUP
  JSR SetVBI
  LDA #BLUE STA COLBAK
  RTS

! This part is executed at power up only.
:INIT
  LDA DOSINI   STA TSR+1
  LDA DOSINI+1 STA TSR+2
!
  LDA #TSR AND $FF STA DOSINI
  LDA #TSR/$100    STA DOSINI+1
!
  JSR BUMPUP
END

CONST [email protected]

MAIN()
BEGIN
  COLBAK=BLUE
  SetVBI*()
  FINISH=LoMem
  NoRESET*()
END

You can see that it's really assembler, but I know that it can be written in clear PL65, as it's no more then moving data between variables, or filling data with the help of pointers.

 

The only thing I can't solve lays in single-pass nature of pl65 and it's assembler.

All things must be declared before compilation.

 

I can't find a way to properly fill address field of JSR TROJAN statement.

 

I'm not a programmer at all, sorry.

 

Share this post


Link to post
Share on other sites

Dear Mr Fish,

 

This is CITE from PL65 manual:

 

Parameter variables are treated within the procedure exactly the same as local variables, ...

 

Thus this strange behavior may be caused by the absense of proper initialisation for

PROC PrintText (STRING A$[20])

 

I mean that as parameter is LOCAL, then A$ in PrintText is different then A$ in MAIN ANYWAY!

 

Parameter declaration in PrintTest only says compiler about the quantity of bytes needed on stack for transmitting to PROC and no more.

 

Really A$ in PrintText never was declared as no address and no length can't be accessed by compiler.

 

This may help IMHO:

INCLUDE TERMINAL.LIB

STRING A$[20] ! Declaration and memory allocation for string
...
PROC PrintText (STRING A$[20]) ! Here compiler knows A$
     INT I
BEGIN
     FOR I=1 TO 50000 DO
     NEXT
     WRTSTR (A$)
     REPEAT
     FOREVER
END
...
MAIN() ! Here compiler knows the same A$ as PrintText thus we can make
       ! proper initialization of string in MAIN()
BEGIN
...
END

In this case A$ is seeing for both PrintText and MAIN.

 

Another way may be using POINTERS to beginning of string.

 

Another note is that real dimension of any string MUST be LEN+4.

2 bytes is string address and two bytes is it's lenght.

 

That's all Folks. ;)

Edited by 130XE

Share this post


Link to post
Share on other sites

I recently found that the meaning of real declaration of string in PL65 is like this:

Adr (2 bytes), Len (2 bytes), String (len-1 bytes), EOL(1 byte)

 

PL65 works with ASM values anyway, thus it can't exclude $9B FROM string, because another program may use $9B as terminator.

 

I recently replaced EOL with SPACE. It works!

 

It was NOT string-dedicated function! (It was some kind of byte oriented function.)

 

String-dedicated functions - all pays attention to EOL after string.

Some of them using it but some not.

Share this post


Link to post
Share on other sites

Hi there, FRIENDS!

Recently I found very convenient russified font editing program...

It takes all my mind and I decided to write some PL65 code for autorun fontloader for programming in russified BASIC F.E...

The PL65 is really the product of ingenious master who placed all it's ideas in lang and never tried to exhaustively testing it.

The code:

INCLUDE TERMINAL.LIB

MAIN()
  STRING S$[2]
BEGIN
  PUT(0,125)
  WRTLN("ENTER STRING, PLEASE ...")
  S$=INPUT$()
  WRTSTR("LEN OF INPUT$ = ") WRITE(LEN(S$))
END

Being tested and working it gives this picture while entered "Return" only:

Thus you know the beast side of beauty!

This problem may be simply recognized.

Manual says that the string in PL65 is defined as addr/len
(it means that TERMINAL.LIB based on pointers)
but ATARI's SIO is defined in other way: addr/EOL

I mean that PL65 never recognizes EOL, because it's internal control symbol for PL65.

I want to say that when some of our procedures or functiones calls SIO,
SIO evidently returns EOL with it's output!

And PL65 adds 1 to LEN(string$)

post-20208-0-49514300-1481973154_thumb.png

Share this post


Link to post
Share on other sites

Here i'll add some workable code:

INCLUDE TERMINAL.LIB

STRING FName$[20]

! Procedures and Functions
!-------------------------
PROC Cls()
BEGIN PUT(0,125) END
!-------------------------
FUNC Prompt$()
  STRING Out$[20]
BEGIN
  Cls()
  WRTLN("INPUT:")
  WRTLN("ENTER FILENAME TO LOAD, PLEASE...")
  Out$=INPUT$()
END Out$
!-------------------------
PROC Adopt()
  STRING D$[20] DATA "D:";
BEGIN
  IF LEN(FName$)=1 THEN ERROR(7) ENDIF

  IF (FName$[1,1]=":" OR FName$[2,2]=":") THEN
! If FName$ contain ':' then we need not concatenation!
    RETURN
  ELSE
! In contrary we need it!
    D$[LEN(D$)]=FName$
    FName$=D$
  ENDIF
END
! Main program
!-------------------------
MAIN()
BEGIN
  TRAP retry
:again
  FName$=Prompt$()
  Adopt()
  WRTLN(FName$)
  GOTO exit
:retry
  TRAP retry
  GOTO again
:exit
END

It's filename normalization.

 

Here I must say that simple code:

(FName$[1]=":" OR FName$[2]=":")

is absolutely NOT Working!!!

Because of PL65 manner of string nature of compared values.

 

As them represents both addresses and lengthes they do NOT compares identical values at all!

Addr or Len will be different anyway!

 

WRTSTR("FILE") will never give us addr/len such as WRTSTR("F")

Share this post


Link to post
Share on other sites

I used PL65 almost exclusively for years and never realised there was a problem with WRTSTR. I'm wondering whether or not it's poor documentation that's the problem, although BITD I considered the documentation to be pretty good.

 

However, I suspect that WRTSTR was one function that I didn't use that often. I tended to roll my own code, especially for game and demo projects. However, there is one project that I might still have lying around that may have used extensive use of WRTSTR. But then again IIRC use of the library functions caused a noticeable slowdown in writing text to the screen, so I may even have written my own code for that.

Share this post


Link to post
Share on other sites

Hello Tickled_Pink!

 

I must say that documentation of PL65 is very detailed and explicit.

Particularly it means that to find something we need to read all book. :)

 

My personal problem was that I could not realize for a long time that There Is NOT string PROCs in PL65 but only string FUNCs.

Any PROC works with strings by default.

 

Another thing is that we need not $-sign in FUNCs only in 2 cases - while writing compile-time expression and while using dot operator.

 

For fast screen-out I often used line based output with precalculated array of 24 POINTER addresses of screen lines.

Share this post


Link to post
Share on other sites

I was just thinking about it now. Doesn't WRTSTR use the SIO functions in another library file - is it TERMINAL.LIB? That would account for the slowness of the text draw. So thinking about it now I probably did write my own for the project I was working on. I did a writeup on this and a version of the game Loopz that I had been working on for MyAtari magazine years ago. Both being written in PL65.

 

I intend to finish them at some point if I still have the original disks. Life kind of got in the way. Loopz was around 75% complete. The other was a disk cataloguer which had a GUI-like interface insofar as the way that I displayed unavailable menu options greyed out using DLIs.

Share this post


Link to post
Share on other sites

I really love PL65. It's the artifact of langs. Only thinking in it's way we can understand how the langs growth.

 

Even ACTION! is premAtive because of lack of typedef syntax in PL65.

 

YES! It's possible to wright something like Dynamic Memory Allocation in PL65 but ...

 

Its POINTERS are too ancient at all!!!

 

Anyway I love your interest in PL65. ;-)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...