Jump to content
IGNORED

Complete PL65 Manual


spookt

Recommended Posts

Hey - gotta love providence. I was patiently scanning through this a page at a time on my flatbed when guess what rolls up in the office? A brand spanking new colour copier / fax / digital sender / laser printer ! OK, I entrusted the manual to the sheet feed, tapped in my email address and ... presto PDF file. (Well actually 14 PDF files with 10 pages in each - need to find that setting and change it) And no bleed through ! :)

 

So after stitching it together and having made a quick check here at last is the complete PL65 Programming Manual:

 

PL65.pdf

 

Happy reading !

Edited by spookt
  • Like 1
Link to comment
Share on other sites

WOW, this language looks cool! I wish that I had known about this language when it came out!

 

& the editor looks like it would be great...

 

Can someone post the ATR of the last version? I presume that there is a non-copy protected version out there, right?

 

Are there any additional toolkits, user contributed libraries, or example source listings out there?

Link to comment
Share on other sites

I don't believe it. I'm not alone!! :D

 

I've got the original disk and a happied backup somewhere (both still worked last time I tried them). Unfortunately it looked like my parents threw out the manual before I could retrieve it, so I'm sooo happy someone else has scanned it.

 

And how the hell did I miss this old thread? Didn't know that someone had actually cracked PL65, presumably from one of the uncracked/half cracked disk images I posted some time ago?

 

PL65 is my favourite 8-bit language. The compiler is a little slow because it seems to work its way compiling a function/procedure at a time before saving it, producing a compound file as it goes. If anyone could come up with a tool to convert the compound file into one contiguous block so that it could be run from a ROM cart then that would be :cool: 0

 

If anyone seriously wants to have a go at the language and needs any help then feel free to PM me. Although I haven't access to my 8-bits at the minute, I used this language so much that I should be able to remember most of it. It was my first introduction to pointers, long before I came across C/C++. :)

Edited by Tickled_Pink
Link to comment
Share on other sites

@ spookt: Thanks a lot for scanning the manual! I'd never heard of this language before. I assumed I had the disk for it, but alas not to be. Good to see that the program has been cracked already. I didn't catch the thread about that being done before either.

 

The language looks great. On first review, it looks to be much better than Turbo-BASIC XL. No line numbers, PMG Library, Assembly functions, better constructs/functionality, etc.

 

@ Tickled_Pink: In the PL65 Cracked thread, the author of the language claims to have written a defragmenter for the executables. Unfortunately he says, "God knows if you would ever find this".

 

BTW: Now I know why you said, "I can't vote. My primary language has never been any of those." in the Programming Languages Poll. I thought you were making a joke, as I had assumed I hadn't forgotten any major languages (arrogant). You may soon have more company in your language choice. ;)

Edited by MrFish
Link to comment
Share on other sites

@ Tickled_Pink: In the PL65 Cracked thread, the author of the language claims to have written a defragmenter for the executables. Unfortunately he says, "God knows if you would ever find this".

The guy who made the post wasn't the author (and didn't claim to be). I remember writing a letter to Noahsoft once and got a reply from someone with an Eastern European surname.

 

I might have a stab at doing a similar program myself. Wanted to do one for years but never got around to it. As it's all just stripping headers, it can't be too difficult to do.

Link to comment
Share on other sites

I had problems with compiled programs not running with the cracked PL65 version from the other thread.

 

What I found is that there is code (Location $3637) that runs when you press 1 to start the compiler, this code does a checksum of the copy protection code. Since the copy protection code was modifed to bypass the bad sector check the checksum no longer matches. This in turn triggers code at $3649 that XORs the first $80 bytes of the runtime with $AA rendering the compiled program unusable.

 

The version in the attached ATR has all of the code mentioned above removed and produces compiled code that runs now. :)

pl65fix.zip

  • Thanks 1
Link to comment
Share on other sites

I had problems with compiled programs not running with the cracked PL65 version from the other thread.

 

What I found is that there is code (Location $3637) that runs when you press 1 to start the compiler, this code does a checksum of the copy protection code. Since the copy protection code was modifed to bypass the bad sector check the checksum no longer matches. This in turn triggers code at $3649 that XORs the first $80 bytes of the runtime with $AA rendering the compiled program unusable.

 

The version in the attached ATR has all of the code mentioned above removed and produces compiled code that runs now. :)

Yes, compiled programs run now. Great work! Many thanks.

Edited by MrFish
Link to comment
Share on other sites

I had problems with compiled programs not running with the cracked PL65 version from the other thread.

 

What I found is that there is code (Location $3637) that runs when you press 1 to start the compiler, this code does a checksum of the copy protection code. Since the copy protection code was modifed to bypass the bad sector check the checksum no longer matches. This in turn triggers code at $3649 that XORs the first $80 bytes of the runtime with $AA rendering the compiled program unusable.

 

The version in the attached ATR has all of the code mentioned above removed and produces compiled code that runs now. :)

That's great. I suspected that something was affecting the runtime code rather than the user compiled program.

 

Nice to see a few interested people downloading the manual too. :)

 

 

BTW: Can't remember if this is in the manual, but here's a little tip. If you're finding the compilation process a little slow and just want to do some syntax checking, just type in the source filename and press return for all the others the compiler prompts for. That way it'll just read the source, compile it, but won't save anything to disk.

Edited by Tickled_Pink
Link to comment
Share on other sites

  • 5 years later...
  • 1 year later...

I've done a little reversing of the compiler, and it seems it has at least one bad bug. Use of the builtin variables like XSAVE, PUSH etc. will fail because there is a bug in the table scanner, it's off by one. So references to STACK will work, but nothing after that should be found. The compiler code is so odd that I remain convinced that it was written itself in either PL65 or something like it. For sure it was not written in Action!, it doesn't have any of the watermarks you'd see if that was used.

Link to comment
Share on other sites

  • 10 months later...

Hi Friends!

I bring to your kind attention and to your free disposal Memory Allocation Library for PL65 compiler.

It is fully working.

Just to ensure the clarity of the text I added some primitive functions to work with free-list in structs/records oriented manner.
You know of course that PL65 lacks of structs and records.

To my great surprise, this innovation made programming much easier.

Here are the code of library itself and program for debugging.

ALLOC.LIB

!====================================!
! ALLOC.LIB Memory allocation library
!       for PL65 compiler            !
! First-fit algorythm for malloc/free
!------------------------------------!
! by Evgeny Zolotarev (aka 576XE),2017
!====================================!
CONST NULL=0,FRED=1,USED=0
CONST MEMSTART=$4000,MEMEND=$BC00
CONST MEMSIZ=MEMEND-MEMSTART
CONST METALEN=6,BYTSZ=1,INTSZ=2
!------------------------------------!
POINTER gpP INT gpV BASED gpP
POINTER freList
!------------------------------------!
FUNC getFlag(INT adr)
BEGIN gpP=adr END gpV
!------------------------------------!
FUNC getSize(INT adr)
BEGIN gpP=adr+2 END gpV
!------------------------------------!
FUNC getNext(INT adr)
BEGIN gpP=adr+4 END gpV
!------------------------------------!
PROC setFlag(INT adr,flag)
BEGIN gpP=adr gpV=flag END
!------------------------------------!
PROC setSize(INT adr,size)
BEGIN gpP=adr+2 gpV=size END
!------------------------------------!
PROC setNext(INT adr,next)
BEGIN gpP=adr+4 gpV=next END
!------------------------------------!
PROC memInit()
BEGIN
  setFlag(freList,FRED)
  setSize(freList,MEMSIZ-METALEN)
  setNext(freList,NULL)
END
!------------------------------------!
PROC split(POINTER fits INT size)
  POINTER new INT blkSiz
BEGIN
  blkSiz=METALEN+size
  new=fits+blkSiz
  setFlag(new,FRED)
  setSize(new,getSize(fits)-blkSiz)
  setNext(new,getNext(fits))
  setFlag(fits,USED)
  setSize(fits,size)
  setNext(fits,new)
END
!------------------------------------!
FUNC alloc(INT nBytes)
  POINTER curr,result
BEGIN
  IF (getSize(freList)=0) THEN
    memInit()
    WRTLN("Memory initialized") CR()
  ENDIF

  curr=freList
  WHILE ((getSize(curr)<nBytes OR getFlag(curr)=USED) AND getNext(curr)<>NULL) DO
    curr=getNext(curr)
    WRTLN("- Search for fitting block...")
  ENDWHILE

  IF getSize(curr)=nBytes THEN
    setFlag(curr,USED)
    result=curr+METALEN
    WRTLN("+ Exact fitting block allocated")
    RETURN result
  ENDIF

  IF getSize(curr)>nBytes+METALEN THEN
    split(curr,nBytes)
    result=curr+METALEN
    BASE=16
    WRTSTR("Block $") WRITE(result) WRTSTR("-$") WRITE(result+nBytes)
    WRTSTR(" size=") BASE=10 WRITE(getSize(curr)) WRTLN(" allocated")
    RETURN result
  ELSE
    result=NULL
    WRTLN("- No sufficient memory to allocate")
  ENDIF
END result
!------------------------------------!
PROC merge()
  POINTER curr
  INT size,next
BEGIN
  curr=freList
  WHILE getNext(curr)<>NULL DO
    IF (getFlag(curr) AND getFlag(getNext(curr))) THEN
      size=getSize(curr)+getSize(getNext(curr))+METALEN
      setSize(curr,size)
      next=getNext(getNext(curr))
      setNext(curr,next)
    ENDIF
    curr=getNext(curr)
  ENDWHILE
END
!------------------------------------!
PROC free(POINTER ptr)
  POINTER curr
BEGIN
  IF ptr>=MEMSTART AND ptr<=MEMEND THEN
    curr=ptr
    curr=curr-METALEN
    setFlag(curr,FRED)
    merge()
    WRTLN("+ Block freed, space merged")
  ELSE
    WRTLN("Please provide a valid allocated pointer")
  ENDIF
END
!====================================!
! End of Library
ENDFILE

ALLOC.PRG

INCLUDE TERMINAL.LIB
INCLUDE ALLOC.LIB

MAIN()
  POINTER p,r,k
  POINTER q,w
BEGIN
  freList=MEMSTART

  p=alloc(100*INTSZ)
  q=alloc(250*BYTSZ)
  r=alloc(1000*INTSZ)

  free(p)
  w=alloc(700)

  free(r)
  k=alloc(500*INTSZ)

  CR() WRTLN("Allocation and deallocation")
  WRTLN("are done successfully!")
END

And here is the result of allocations and deallocations of memory with related atr.

ALLOC in use

post-20208-0-98889100-1497942453_thumb.png

PL65 Compiler SpDOSx33a 360.atr

 

There is no simple way without using of monitor to find the beginning of heap, but you can use an arbitrary value after looking at XREF table.

 

You can freely delete debugging messages, of course

Best wishes from Moscow.
ez

  • Like 2
Link to comment
Share on other sites

  • 3 years later...

Hello, friends.

Recently I wrote simple bank-switching routine in PL/65.

!====================================!
! BANKS.PRG                          !
!   Using 130XE Extended Banks in    !
!     PL65 Programming Language      !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2020 !
!====================================!
INCLUDE TERMINAL.LIB

!- CONSTANTS & VARIABLES:
BYTE PORTB=$D301
INT bkNum

!- DUMMY array representing ---------!
!- selected BANKs slice ------------!
BYTE bkMem[$4000]=$4000

!- Bank Selector Values -------------!
!- Emulator ONLY(Sic.) Atari 576XE --!
BYTE bkSel[33]
DATA $91,
  $81,$83,$85,$87,$89,$8B,$8D,$8F,
  $A1,$A3,$A5,$A7,$A9,$AB,$AD,$AF,
  $C1,$C3,$C5,$C7,$C9,$CB,$CD,$CF,
  $E1,$E3,$E5,$E7,$E9,$EB,$ED,$EF;

! String VAR  to store in all BANKS
STRING inp$[4+27]
  DATA "==> User DATA from Bank #00";

! Set string as VAR for appending
STRING out$[4+27]
  DATA "                           ";

!- PROCEDURES:
!- Clear Screen Procedure -----------!
PROC clrScr()
  CONST clr=255
BEGIN WRTSTR(CHR$(125)) END

!- Wait for Any Key Pressed ---------!
PROC anyKey()
  CONST none=255
  BYTE CH=764
BEGIN
  WRTSTR("Wait for a Key...") CR()
  WHILE CH=none DO ENDWHILE
  CH=none
END

!- Place bkSel Tags into PORTB ------!
PROC setBank(INT bkNum)
  CONST bkMask=%10010001 BYTE bkTag
BEGIN
  bkTag=bkSel[bkNum]
  LDA PORTB AND bkMask OR bkTag STA PORTB
END

!- Writes to Bank -------------------!
PROC writBk()
BEGIN
  FOR bkNum=1 TO 32 DO
    WRTSTR("Writing to BANK #") WRITE(bkNum) CR()
    IF bkNum<10 THEN
      inp$[25,25]=STR$(0) inp$[26,26]=STR$(bkNum)
    ELSE inp$[25]=STR$(bkNum) ENDIF
    out$=inp$
    setBank(bkNum)
    MOVE(.out,LEN(out$),.bkMem)
  NEXT
END

!- Reads from Bank ------------------!
PROC readBk()
BEGIN
  FOR bkNum=1 TO 32 DO
    WRTSTR("Reading BANK #") WRITE(bkNum) CR()
    setBank(bkNum)
    MOVE(.bkMem,LEN(out$),.out)
    WRTSTR(out$) CR()
  NEXT
END

!------------------------------------!
MAIN()
BEGIN
  clrScr() anyKey() writBk()
  anyKey() clrScr() readBk()
END
! >>> EOF <<< !

This routine uses 576KiB RAM extension scheme of
emulator ONLY!

XRAM.thumb.png.f7ea6dac835f9a90fdf2399cca25ade6.png
It works perfectly while traversing EXTMEM only i.e. [1..32]

working.thumb.png.662af684d704ee83b34a7898fbf8ccff.png
but if I try to traverse from MAIN bank to EXTMEM [0..32]
it simply clears the screen for a moment and skips one
or two strings of output or crashes.

writebad.thumb.png.b94528dac9a181f3524fc65cf9e15281.png

readBad.thumb.png.1ba1dc937632579574183f71d2f10c42.png

Nevertheless the DATA in all banks stays written firmly.
I can see it reading emulator's monitor.

Monitor.thumb.png.5030efdf84c1d228dde602e3a543d1e4.png
The routine itself is clear and understandable but I still
can not glue what's wrong.

PL65 SD_X33A.atr

Obviously you can use all codes at your disposal :)

zen

Edited by 576XE
  • Like 1
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...