Lazarus

Programming => Packages and Libraries => Topic started by: kveroneau on April 22, 2019, 12:13:17 am

Title: Publishing my very first Lazarus/FPC package today!
Post by: kveroneau on April 22, 2019, 12:13:17 am
So, I think I am finally starting to feel real confident with my ObjectPascal programming skills now.  I have created a couple things, but nothing too substantial.  I do have a programming background, I mostly programmed in Python(and still do), but decided I needed a language which really emphasizes cross-platform, as well FPC/Lazarus really hit that out of the park.  Compared to say Python when you want to put together a GUI application, it can get rather complicated when it comes time to deploying it out to end-users, as you will need to either ship the entire Python runtime, and any Qt/Gtk libraries along with it, and hope that everything just works on the other side.  This also results in a very large distribution as you could imagine.  Lazarus programs tend to be very tight in size and speed, and usually compile with no issues on any OS that Lazarus can run on.  Beautiful!

Anyways, so the FPC Unit, which doesn't technically need Lazarus at all, but I am providing a lpk file for ease of use for both myself and anyone who may wish to use this.  I put together the first pieces of a 65c02 CPU Emulator!  This might at a later date become useful for another interesting ObjectPascal project, P65Pas, an editor and Pascal compiler for the 6502!  I am sure this project could say integrate this 6502 Emulator into their IDE to allow for some basic debugging and such.  Just a thought.

You can find it here on my BitBucket page: https://bitbucket.org/kveroneau/pas6502/src/default/

I also noticed that BitBucket, although supports ObjectPascal as a selectable language, does not highlight files.  This is rather disappointing.

I should also add, that this 6502 Emulator is not cycle accurate, nor does it even take cycles into account.  You may be scratching your head, wondering, why?  The purpose of this 6502 Emulator was not to run retro software, plenty of software packages out on the Internet already do that.  The purpose was to have the 6502 machine code run as fast as possible on whichever host machine it runs on, so that it could act as a Virtual Machine for some other type of program or tool.  Here's a rather basic example, say Castle Game Engine allowed for the loading of external scripts written in either C or Pascal, how could they implement this in the Engine?  You see, plenty of compilers currently exist for the 6502, cc65, and P65Pas.  The 6502 machine code is rather versatile, and new opcodes or IO could be provided to extend the 6502 to allow to perform tasks like real multiplication, and floating point operations.  If you read that last line and are now thinking, the 6502 could never do anything like that, it does not have the opcodes necessary.  That is the common response I hear when people rarely think outside the box.  On the 6502, could you not map IO devices in memory?  Do you not recall the 286 and 386SX processors?  These processors either needed to perform floating point operations in software emulation(emu87 unit), or you needed to have the math co-processor installed on your motherboard.  Now, think of the 6502 like the traditional 286(but emulates faster), could you not map a virtual math co-processor onto your Virtual 6502 to allow it to perform float point calculation?  But lets take this a step further...  If you code the 6502 Virtual Machine in just the right way, your 6502 machine program can actually do anything your host machine can do, as long as you provide an API within the VM code.  Something I recently tested was having virtual addresses mapped in, when the 6502 program counter would JSR to this special address, it basically acted like a cdecl call into my host code, here's an example: https://bitbucket.org/kveroneau/arcvm/src/default/runtime/devices/console.py

When a C function like say "puts('Hello World');" is compiled into assembly, it places a pointer to the string into A and X as a 16-bit word.  And in this situation, instead of puts being a real 6502 function, instead puts in just a pointer to a virtually mapped I/O address.  So when the compiled C code attempts to JSR to the entry point of the puts statement, guess where it goes?  It goes into the Host program, and as you can see in this Python code, I can easily grab the 16-bit pointer to the string, then grab the null-terminated string, and display the text.  When this method call ends, it simulates a RTS, but popping the 16-bit pointer off the stack and setting it to the program counter, and then it resumes the 6502 machine code ending our call into the Host OS.  I was able to go way beyond a simple string of course, I am able to send any data type from C, including custom structs.  This allows the virtual 6502 machine code to access allowed resources on the Host OS, much like how say the Java VM or maybe Qemu permits access to very specific host systems.

The idea here, is that the 6502 machine code can be used like any other bytecode system, but has the advantage of being register-based, pretty darn fast, has tons of useful op-codes, and works great with memory mapped I/O to allow perfect Host OS integration.  Also since the 6502 is really well know, it also has the advantage of attracting talent, and has a really great set of development tools and a full community.  Why write your next in-application scripting environment from scratch.  And yes, I know of the existence of PascalScript to enable one to add in-application scripting into Lazarus programs.  However, I imagine that PascalScript is technically much more complex than a CPU Emulator running machine code.  This can both be an advantage and a disadvantage.  The advantage of course is that it can support some very complex language constructs such as full ObjectPascal syntax, the disadvantage is the lack of complete control.  With a 6502 VM, the entire memory core can be easily dumped, multiple 6502 VMs can run at the same time in a single Pascal program either using a co-operative method, or by multithreading.  Your Host program can create virtual interrupts to signal the 6502 VM, the entire Virtual Machine can be effortlessly suspended to disk and easily resumed at the exact point in time which it was suspended with no negative problems.  And most importantly, a 6502 Virtual Machine can fully create self-modifying code, and you have access to all the VMs heap memory from your Host program.  It may also run a tad faster than PascalScript, but I will need to eventually create benchmarks to determine this.

Anyways, that is where I am at with my current 6502 CPU Emulator code.  I still need to add many features, as this is just it's initial release.
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: avra on April 22, 2019, 08:59:06 am
I do have a programming background, I mostly programmed in Python(and still do), but decided I needed a language which really emphasizes cross-platform, as well FPC/Lazarus really hit that out of the park.  Compared to say Python when you want to put together a GUI application, it can get rather complicated when it comes time to deploying it out to end-users, as you will need to either ship the entire Python runtime, and any Qt/Gtk libraries along with it, and hope that everything just works on the other side.  This also results in a very large distribution as you could imagine.  Lazarus programs tend to be very tight in size and speed, and usually compile with no issues on any OS that Lazarus can run on.  Beautiful!
This is a typical use case we should spread around to attract more Python developers.  8) :-[ 8)

I also noticed that BitBucket, although supports ObjectPascal as a selectable language, does not highlight files.  This is rather disappointing.
I can see highlighting of your code:
https://bitbucket.org/kveroneau/pas6502/src/3b5a8bf9a1fde8e0cc77f08d9579f707aa64f140/cpu6502.pas?at=default&fileviewer=file-view-default
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: kveroneau on April 22, 2019, 06:56:39 pm
I do have a programming background, I mostly programmed in Python(and still do), but decided I needed a language which really emphasizes cross-platform, as well FPC/Lazarus really hit that out of the park.  Compared to say Python when you want to put together a GUI application, it can get rather complicated when it comes time to deploying it out to end-users, as you will need to either ship the entire Python runtime, and any Qt/Gtk libraries along with it, and hope that everything just works on the other side.  This also results in a very large distribution as you could imagine.  Lazarus programs tend to be very tight in size and speed, and usually compile with no issues on any OS that Lazarus can run on.  Beautiful!
This is a typical use case we should spread around to attract more Python developers.  8) :-[ 8)
No harm in trying, it's definately a great selling point for Delphi/Lazarus/FPC that's for sure.  Not many compiled languages can easily claim the same.

I also noticed that BitBucket, although supports ObjectPascal as a selectable language, does not highlight files.  This is rather disappointing.
I can see highlighting of your code:
https://bitbucket.org/kveroneau/pas6502/src/3b5a8bf9a1fde8e0cc77f08d9579f707aa64f140/cpu6502.pas?at=default&fileviewer=file-view-default
Maybe it's my browser setting or something.  But I am glad that third parties looking at the source have no issues.  I have no problems with highlighting on GitHub with ObjectPascal code.

If anyone wants to give my code here a nice code review, that'd be really nice.  I would love to know what I could do better, or what I could optimize.  Although I did use a TStream class, you may also notice that I did not use the existing TMemoryStream class, there's good reason on that decision.  The TMemoryStream class grows as needed, and well...  A 6502 CPU cannot access more than 64k, and I also needed the MMU portion of the code to easily support Memory Mapped I/O, so that a specific page of memory will work much differently than a typical TStream.  However, I still wanted to have some level of TStream compatibility for loading in binary data and such, which is why I made my own subclass.
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: ASBzone on April 22, 2019, 10:37:53 pm
I can see highlighting of your code:
https://bitbucket.org/kveroneau/pas6502/src/3b5a8bf9a1fde8e0cc77f08d9579f707aa64f140/cpu6502.pas?at=default&fileviewer=file-view-default (https://bitbucket.org/kveroneau/pas6502/src/3b5a8bf9a1fde8e0cc77f08d9579f707aa64f140/cpu6502.pas?at=default&fileviewer=file-view-default)

Likewise...
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: kveroneau on April 23, 2019, 05:09:13 am
Just added a major update this evening(at least in my timezone)...

Firstly there's a new markdown document: https://bitbucket.org/kveroneau/pas6502/src/default/USAGE.md

Also, it's now finally usable!  You can load in a binary file, or hand assemble using the setB and setW method calls.

BRK or the $fffe vector by default points to $fff0 which has an ObjectPascal callback to default_BRK, which sets FRunning:=False, so guess what?  The IO Map Callback system is now functional!  You can map in ObjectPascal functions into the $ff00-$fff9 IO space, and when your code does a JSR to this callback address, your ObjectPascal function will take over and do what it has to do.  If your function sets the Result to True, meaning it was handled, the code then simulates a RTS and resumes back to your 6502 machine code.  How swell is that?

Furthermore, if you make programs in cc65, there are some special method calls you can use to access the cc65 stack and pop pointers from it, so if you perform a C function call in cc65, it is fully possible for your ObjectPascal callback to properly read in the parameters sent in from the C function call and perform the actions and then safely return back to where the C function was called.  I will be publishing samples of this in action at some point soon, as it really highlights how powerful this interactivity can be.  Once I figure out how P65Pas works and how it does system calls, be on the lookout for this being fully supported as well.  So your 6502 Pascal code can call your x86/ARM ObjectPascal code with ease.
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: Edson on June 14, 2019, 04:37:53 am
Ineresting project.

I will be publishing samples of this in action at some point soon, as it really highlights how powerful this interactivity can be.  Once I figure out how P65Pas works and how it does system calls, be on the lookout for this being fully supported as well. 

P65Pas use the JSR instruction to call subroutines. And has several ways for passing parameters:

* Common functions (Or procedures): The compiler doesn't use stack. It uses global variables that are reused according to some diabolic algorithm.  It's projected to use stack (not implemented) only when a procedure/function is part of a recursive circle.
* Functions with REGISTER parameters: This is a fast and short way to pass parameters to functions. Currently only register A can be used as parameter, but it's projected to use X and Y register too.
* INLINE Functions: P65Pas define INLINE functions in a particular way. In this case parameters are passed according teh definition of the INLINE function and the JSR instruction is not used. Not complete implemented in the current version.

System fucntions are some other category of functions. They are defined "ad hoc". Usually they are INLINE but can use JSR or REGISTER parameters.
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: marcov on June 14, 2019, 10:25:54 am
Forgive me if this is wrong, my last C=64 work is almost 30 years old (1990/1991)

I think one should model some zeropage places (like $F8) as volatile registers. This way far (16-bit) pointers are passed there, and directly available to load via lda ($f8), and you don't eat up two precious registers to pass a VAR value ?
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: Edson on June 14, 2019, 04:51:19 pm
Forgive me if this is wrong, my last C=64 work is almost 30 years old (1990/1991)

I think one should model some zeropage places (like $F8) as volatile registers. This way far (16-bit) pointers are passed there, and directly available to load via lda ($f8), and you don't eat up two precious registers to pass a VAR value ?

Short pointers is not implemented yet in P65Pas. Poniters is still in development. But the compiler knows how to address zero-page registers. This code:

Code: Pascal  [Select][+][-]
  1. var
  2.   zeropag: byte absolute $F8;  
  3. begin
  4.   zeropag := $ff;
  5. end.

Will generate:

Code: Pascal  [Select][+][-]
  1.     processor 6502
  2. ;===Blocks of Code===
  3.             ORG $0000
  4.       $0000 4C 03 00 JMP $0003
  5. __main_program__:
  6.       $0003 A9 FF    LDA #$FF
  7.       $0005 85 F8    STA $F8
  8. ;--------------------
  9.       END

Using the zero page form of STA.

No need to specify VOLATILE by now. Compiler optimization consider all RAM is volatile. Probably I will be implementing it later.

Variables are placed by default in the position where all program start. (ORG = )

P65Pas doesn't know wich parts of the Zero page are free, because P65Pas is a 6502 compiler, not a Commodore compiler. Atari or Apple have different memory map in zero page.

Knowing specific free memory blocks is work of libraries not of the compiler. For example, the unit Commodore.pas define code start at $800, but the programmer is free to map some variables in other places.
Title: Re: Publishing my very first Lazarus/FPC package today!
Post by: julkas on June 14, 2019, 08:22:00 pm
@kveroneau Good project. Go on!
Regards.

P.S. Why on BitBucket?
TinyPortal © 2005-2018