6502 TaliForth2 Implementation Questions
6502 TaliForth2 Implementation Questions
After watching some Youtube videos on C64 White Lightning.. I have a new itch..
I have a virtual 6502 machine that I've played around with on Windows. I've made a simple Vic 20 emulator, BBC BASIC emulator and other things.. Now I'm thinking about building a copy of fig-Forth and creating some graphics extensions like you would find in White Lighting (e.g. functions/words that drive the Commodore 64's graphics or call kernel routines).
I've only just downloaded the fig-Forth assembly source. Just wondering if anybody had any hints or pointers on where to start - maybe somewhere there's some notes on how to implement the fig-Forth I/O routines which I need to start with first?
But let's say I get a simple Forth environment working - how would I go about adding a new word/token such as DRAW ? I'm not asking how to implement the specifics of DRAW -just how/where I would add support for the DRAW keyword, how many parameters it would expect to take, what it should return (if anything) and the likes.
I have a virtual 6502 machine that I've played around with on Windows. I've made a simple Vic 20 emulator, BBC BASIC emulator and other things.. Now I'm thinking about building a copy of fig-Forth and creating some graphics extensions like you would find in White Lighting (e.g. functions/words that drive the Commodore 64's graphics or call kernel routines).
I've only just downloaded the fig-Forth assembly source. Just wondering if anybody had any hints or pointers on where to start - maybe somewhere there's some notes on how to implement the fig-Forth I/O routines which I need to start with first?
But let's say I get a simple Forth environment working - how would I go about adding a new word/token such as DRAW ? I'm not asking how to implement the specifics of DRAW -just how/where I would add support for the DRAW keyword, how many parameters it would expect to take, what it should return (if anything) and the likes.
Last edited by SparkyNZ on Mon Feb 24, 2025 9:42 pm, edited 1 time in total.
Re: 6502 fig-Forth Extensions
Fig-Forth requires you to write:
cin - read in one ASCII character from keyboard (expects to block until key available - put char in A register)
cout - write one ASCII character (from A register) to terminal. Note, high bit (bit 7) may be set - best to clear that bit before outputting.
crout - move down to beginning of next line (eg. print linefeed or carriage return/linefeed if using a terminal)
Once you have those three working, you should be able to get an interactive forth prompt. If you hit enter and get OK back then everything is likely working.
I'd recommend starting by writing your words in Forth before you try writing them in assembly. You'll need to know how to access your video hardware. If you want to use C64 hardware (emulated or real) and you are familiar with POKE in basic, you can do that in Forth using the C! word. You also have the equivalent of PEEK with C@Here's an example:
If you are targeting C64, I'd recommend getting a copy of Forth already assembled for that platform (the I/O will be done for you, and you can still POKE (C!) around - it may also have file I/O words available or be able to use blocks on a disk)
Once you get your word (written in Forth) working, then you can add it to the assembly source. You'll need to learn how to access the Forth data stack from assembly, and you'll need to add your word to the vocabulary linked list. When you get that far, let us know and we can help.
cin - read in one ASCII character from keyboard (expects to block until key available - put char in A register)
cout - write one ASCII character (from A register) to terminal. Note, high bit (bit 7) may be set - best to clear that bit before outputting.
crout - move down to beginning of next line (eg. print linefeed or carriage return/linefeed if using a terminal)
Once you have those three working, you should be able to get an interactive forth prompt. If you hit enter and get OK back then everything is likely working.
I'd recommend starting by writing your words in Forth before you try writing them in assembly. You'll need to know how to access your video hardware. If you want to use C64 hardware (emulated or real) and you are familiar with POKE in basic, you can do that in Forth using the C! word. You also have the equivalent of PEEK with C@Here's an example:
Code: Select all
BASIC:
POKE 53281,1 : REM Set background to WHITE
PEEK(53281) : REM Get the current background color
Forth:
1 53281 C! ( Set background to WHITE )
53281 C@ ( Equivalent of PEEK to get background color - value left on stack )Once you get your word (written in Forth) working, then you can add it to the assembly source. You'll need to learn how to access the Forth data stack from assembly, and you'll need to add your word to the vocabulary linked list. When you get that far, let us know and we can help.
Re: 6502 fig-Forth Extensions
SamCoVT wrote:
Once you get your word (written in Forth) working, then you can add it to the assembly source. You'll need to learn how to access the Forth data stack from assembly, and you'll need to add your word to the vocabulary linked list. When you get that far, let us know and we can help.
Re: 6502 fig-Forth Extensions
If your homebrew system has a 65C02 in it, I'll also put in a shameless plug for Tali Forth 2:
https://github.com/SamCoVT/TaliForth2
It's a significantly faster forth than FIG and is generally easy to port to new hardware (see the manual in the docs folder). It does require a 65C02 (won't run on an older 6502).
https://github.com/SamCoVT/TaliForth2
It's a significantly faster forth than FIG and is generally easy to port to new hardware (see the manual in the docs folder). It does require a 65C02 (won't run on an older 6502).
Re: 6502 fig-Forth Extensions
SamCoVT wrote:
If your homebrew system has a 65C02 in it, I'll also put in a shameless plug for Tali Forth 2:
https://github.com/SamCoVT/TaliForth2
It's a significantly faster forth than FIG and is generally easy to port to new hardware (see the manual in the docs folder). It does require a 65C02 (won't run on an older 6502).
https://github.com/SamCoVT/TaliForth2
It's a significantly faster forth than FIG and is generally easy to port to new hardware (see the manual in the docs folder). It does require a 65C02 (won't run on an older 6502).
I'll go clone now and probably have a go at assembling it when I need a break from work next week
Re: 6502 fig-Forth Extensions
If you need any help, there's a Tali-specific thread here you can ask questions in:
viewtopic.php?f=9&t=2926
Note that the thread has been running for 10 years and I'm not the original Tali Forth author, but I am the current maintainer.
You can also create a new thread for your questions if you want. The Forth folks here are helpful and are interested in hearing about whatever you find interesting in your Forthing adventures (even if it's simple).
Tali's build system requires GNU Make and 64tass, with gcc required if you also want to build the simulator it comes with (optional). On Windows, you can use WSL, Cygwin, or MinGW to get Gnu Make and gcc. You could also just download GNU Make for Windows and put it in your path.
Extending Tali Forth is similar to extending FIG Forth, and I'll recommend the same general sequence of writing your words in Forth first, and then translating them to assembly if it makes sense to do that. I think you'll find the source code for Tali is better documented than FIG, which makes that process much easier when it's time.
What Windows app do you use for simulation?
viewtopic.php?f=9&t=2926
Note that the thread has been running for 10 years and I'm not the original Tali Forth author, but I am the current maintainer.
You can also create a new thread for your questions if you want. The Forth folks here are helpful and are interested in hearing about whatever you find interesting in your Forthing adventures (even if it's simple).
Tali's build system requires GNU Make and 64tass, with gcc required if you also want to build the simulator it comes with (optional). On Windows, you can use WSL, Cygwin, or MinGW to get Gnu Make and gcc. You could also just download GNU Make for Windows and put it in your path.
Extending Tali Forth is similar to extending FIG Forth, and I'll recommend the same general sequence of writing your words in Forth first, and then translating them to assembly if it makes sense to do that. I think you'll find the source code for Tali is better documented than FIG, which makes that process much easier when it's time.
What Windows app do you use for simulation?
Re: 6502 fig-Forth Extensions
SamCoVT wrote:
If you need any help, there's a Tali-specific thread here you can ask questions in:
viewtopic.php?f=9&t=2926
..
What Windows app do you use for simulation?
viewtopic.php?f=9&t=2926
..
What Windows app do you use for simulation?
My Windows app is my own creation - it uses the same 6502 CPU source as C65 does so I'm on the same page there. I got as far as loading the tali-blah.bin file into my memory at $8000, setting FFFC and FFFD to point to $8000 and watched it fall over
My app does log disassembly as it executes.. but to be fair, when I saw a load of BRK instructions being executed I figured I must be doing something stupid so I'll come back to it and possibly compare against the C65 app. I had a quick look at the first .asm file I could find but to be fair, I haven't spent enough time with it yet so I couldn't even confirm where the origin is yet.
I can jump across to the other thread if you prefer. I wondered about emailing you because I may have some really silly questions - but happy to use whichever channel is more appropriate.
Re: 6502 fig-Forth Extensions
Silly questions are 100% allowed here, as they often help others who are experiencing the same silly problems. The Tali thread or this thread would be fine for that.
Just FYI, if you want to use this thread, you can rename the entire thread by editing the subject of the very first post. It's not uncommon for threads to longer match their initial title, so that's a good trick to know to make it easier for others to find information.
Starting at $8000 should work as long as your I/O doesn't need any initialization - that's where the word COLD is by default, and that word does a cold start. The expected starting address would be at the label kernel_init, found in your platform file (found in platform/simulator.asm if you are using the platform-py65mon.asm or platform-c65.asm platform files, as they share I/O routines).
There are no BRK instructions in Tali itself except for one in the word BYE, but I believe the unused areas in the bin file are zero filled so those will show up as BRK if you accidentally try to run code there.
Just FYI, if you want to use this thread, you can rename the entire thread by editing the subject of the very first post. It's not uncommon for threads to longer match their initial title, so that's a good trick to know to make it easier for others to find information.
Starting at $8000 should work as long as your I/O doesn't need any initialization - that's where the word COLD is by default, and that word does a cold start. The expected starting address would be at the label kernel_init, found in your platform file (found in platform/simulator.asm if you are using the platform-py65mon.asm or platform-c65.asm platform files, as they share I/O routines).
There are no BRK instructions in Tali itself except for one in the word BYE, but I believe the unused areas in the bin file are zero filled so those will show up as BRK if you accidentally try to run code there.
Re: 6502 fig-Forth Extensions
SamCoVT wrote:
There are no BRK instructions in Tali itself except for one in the word BYE, but I believe the unused areas in the bin file are zero filled so those will show up as BRK if you accidentally try to run code there.
Re: 6502 fig-Forth Extensions
SamCoVT wrote:
SamCoVT wrote:
There are no BRK instructions in Tali itself except for one in the word BYE, but I believe the unused areas in the bin file are zero filled so those will show up as BRK if you accidentally try to run code there.
Re: 6502 fig-Forth Extensions
SamCoVT wrote:
SamCoVT wrote:
There are no BRK instructions in Tali itself
When I implemented my BBC BASIC emulator, I did some horrible things such as watching for jumps to various routines (think they were called OSBYTE and OSWORD if I recall). I'd then call some code in C to massage my ram byte array as necessary, tweak registers etc and return as required. This is more or less the direction I'll be taking with kernel_putc so I can write out provided characters to my screen. So this is totally a dirty hack (for now) but I'll be pretending to be py65mon as far as the code is concerned. Being able to run 6502 code within fake6502 on a Windows machine opens up so much when it comes to watching code. I even went through adding my own comments when I played with BBC BASIC so I could see my comments alongside the executed disassembly with optional registers and memory buffers. I think I added memory labels from .lst files too so I might do the same thing again - ie - assemble the py65mon, import the .lst labels etc.. That's if I really need to - I found py65mon-labelmap.txt which will be of good use. Interesting that it claims kernel_putc starts at $F027.. so maybe I should reassemble given that the .bin file I'm using looks a bit different.
I'll have to read the docs and do my research on how kernel_putc works. I'm guessing that the cold_zp_table contains vectors such as kernel_putc and that's what the rest of the code will use whenever kernel_putc is required. I just need to look through the code and find an example of where output is first done - where the Tali Forth 2 and version date are printed.
Re: 6502 TaliForth2 Implementation Questions
The listing for taliforth-py65mon will end up in the file docs/py65mon-listing.txt and there is a labelmap there too if that's helpful.
The source code for kernel_putc, if you are using the py65mon based binary, will be in platform/simulator.asm
kernel_putc is expecting the character in the A register, and it just writes it to $f001 for the py65mon simulator.
kernel_getc just keeps reading from $f004 until a character arrives, and then returns that in A. It's a blocking routine.
The py65mon simulator will print any character written to $f001 and you can read from $f004 to get a char from the keyboard (the read from $f004 is non-blocking and returns 0 if no character is available).
The c65 simulator works mostly the same with addresses $f001 for printing and $f004 for reading, but reading characters is a bit different between them, so the code for kernel_getc is in the platform file itself (either platform/platform-py65mon.asm or platform/platform-c65.asm). If I recall, the main difference is that the c65 version has code for for the forth word KEY? which can detect if there is a key pressed or not. This is done by implementing (the entirely optional) kernel_kbhit, which returns 0 if no key is pressed and any other value when a key is pressed (it doesn't actually use up the keypress, though). The py65mon cheats a bit for kernel_kbhit by trying to read from $f004 and using a one byte buffer if it accidentally reads a character, and kernel_getc knows to check the buffer first.
The IO routines are placed just a little above that I/O section for those simulators, so I'm not surprised you are seeing addresses like $f022. You are indeed correct that the COLD routine is saving the address of kernel_putc (Tali uses vectored input and output so the user can replace the I/O routines while it is running). Only the vector for output is initialized at first, so that error messages can be printed if something goes wrong. The other vectors are copied in from a table a little later. If you want to see the source code for COLD, it's right at the top of words/all.asm
You're welcome to take a look at the modifications that Patrick put into c65 and yoink any you find useful - the code for Tali and c65 is public domain. I think the only modifications we made to fake65c02.h had to do with unused opcodes using up the correct number of bytes, and that did not affect the running of Tali at all because Tali doesn't have those opcodes and never generates those opcodes. I don't know if those changes made it upstream.
The source code for kernel_putc, if you are using the py65mon based binary, will be in platform/simulator.asm
kernel_putc is expecting the character in the A register, and it just writes it to $f001 for the py65mon simulator.
kernel_getc just keeps reading from $f004 until a character arrives, and then returns that in A. It's a blocking routine.
The py65mon simulator will print any character written to $f001 and you can read from $f004 to get a char from the keyboard (the read from $f004 is non-blocking and returns 0 if no character is available).
The c65 simulator works mostly the same with addresses $f001 for printing and $f004 for reading, but reading characters is a bit different between them, so the code for kernel_getc is in the platform file itself (either platform/platform-py65mon.asm or platform/platform-c65.asm). If I recall, the main difference is that the c65 version has code for for the forth word KEY? which can detect if there is a key pressed or not. This is done by implementing (the entirely optional) kernel_kbhit, which returns 0 if no key is pressed and any other value when a key is pressed (it doesn't actually use up the keypress, though). The py65mon cheats a bit for kernel_kbhit by trying to read from $f004 and using a one byte buffer if it accidentally reads a character, and kernel_getc knows to check the buffer first.
The IO routines are placed just a little above that I/O section for those simulators, so I'm not surprised you are seeing addresses like $f022. You are indeed correct that the COLD routine is saving the address of kernel_putc (Tali uses vectored input and output so the user can replace the I/O routines while it is running). Only the vector for output is initialized at first, so that error messages can be printed if something goes wrong. The other vectors are copied in from a table a little later. If you want to see the source code for COLD, it's right at the top of words/all.asm
You're welcome to take a look at the modifications that Patrick put into c65 and yoink any you find useful - the code for Tali and c65 is public domain. I think the only modifications we made to fake65c02.h had to do with unused opcodes using up the correct number of bytes, and that did not affect the running of Tali at all because Tali doesn't have those opcodes and never generates those opcodes. I don't know if those changes made it upstream.
Re: 6502 fig-Forth Extensions
SparkyNZ wrote:
When I implemented my BBC BASIC emulator, I did some horrible things such as watching for jumps to various routines (think they were called OSBYTE and OSWORD if I recall). I'd then call some code in C to massage my ram byte array as necessary, tweak registers etc and return as required.
That platform loads programs at $a000, so the assembly origin starts there, and there are no vectors at the end because that platform already has them loaded before Tali is loaded.
Re: 6502 TaliForth2 Implementation Questions
SamCoVT wrote:
The listing for taliforth-py65mon will end up in the file docs/py65mon-listing.txt and there is a labelmap there too if that's helpful.
https://imgur.com/XSlZA53
I'm not sure how to upload images on this forum but hopefully you can see something. I'm not sure whether I should be handling line feed/CR myself or not but I'll come back to that tomorrow or the next day
Re: 6502 TaliForth2 Implementation Questions
That looks great. The default behavior of BYE is to run a BRK instruction, and the default ISR vector for BRK instructions (or any interrupts, really) is kernel_init, so the fact it starts over again is expected behavior. You can write a new kernel_bye if you have an OS or monitor you would like to return to, but lots of Tali users just use Tali as their OS. It has an interactive shell, a built in assembler (hidden by default - see the docs for how to enable it), and direct access to the hardware.
How familiar with Forth are you? We handle questions and thoughts from people just getting started all the way through some members that are currently documenting their progress with metacompiling (where you use Forth to compile another Forth). Regardless of your skill level, you will want to check out the Glossary at the back of the manual to see all the words that Tali comes with. Tali is an ANS 2012 forth and you can also check the standard for more information on words at https://forth-standard.org/ (I use the Standard button and the Search function the most, at the top of that site, to find words).
It's best to add images to the forum, when possible, as the external links tend to disappear over time. To add images, make sure you are on the "full editor". The Quick Reply area at the bottom of the thread has a button to launch the full editor. Then, below the editor is an "Upload attachment" area. Choose your file, provide a text description (handy for people who may not be able to see the image), and click "Add the file". This doesn't actually put the image in the post yet, it just uploads it to the server. After you've uploaded at least one image, there will be a new "Attachments" section with a dropdown that lets you pick the image you want and a "Place inline" button to add it to the post. It's handy to upload all of your images one at a time and then add them to your post where you want them. You can click the "Preview" button to see how it's going to look.
Just FYI: There is an occasional issue where sometimes image previews get rotated that I don't have a solution for and most users will understand if that happens. I don't believe it rotates the original image, only the thumbnail preview, and it only happens occasionally.
How familiar with Forth are you? We handle questions and thoughts from people just getting started all the way through some members that are currently documenting their progress with metacompiling (where you use Forth to compile another Forth). Regardless of your skill level, you will want to check out the Glossary at the back of the manual to see all the words that Tali comes with. Tali is an ANS 2012 forth and you can also check the standard for more information on words at https://forth-standard.org/ (I use the Standard button and the Search function the most, at the top of that site, to find words).
It's best to add images to the forum, when possible, as the external links tend to disappear over time. To add images, make sure you are on the "full editor". The Quick Reply area at the bottom of the thread has a button to launch the full editor. Then, below the editor is an "Upload attachment" area. Choose your file, provide a text description (handy for people who may not be able to see the image), and click "Add the file". This doesn't actually put the image in the post yet, it just uploads it to the server. After you've uploaded at least one image, there will be a new "Attachments" section with a dropdown that lets you pick the image you want and a "Place inline" button to add it to the post. It's handy to upload all of your images one at a time and then add them to your post where you want them. You can click the "Preview" button to see how it's going to look.
Just FYI: There is an occasional issue where sometimes image previews get rotated that I don't have a solution for and most users will understand if that happens. I don't believe it rotates the original image, only the thumbnail preview, and it only happens occasionally.
Last edited by SamCoVT on Tue Feb 25, 2025 4:38 pm, edited 1 time in total.