6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri May 10, 2024 6:10 am

All times are UTC




Post new topic Reply to topic  [ 73 posts ]  Go to page 1, 2, 3, 4, 5  Next
Author Message
PostPosted: Mon Jan 13, 2020 2:31 am 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
I'd like to get TaliForth running on my emulator, but I'm having some trouble getting it to compile. I installed GnuWin32 make and ophis, then changed the makefile to add the full path for ophis. make responds with "Nothing to be done for `all'." I tried adding a comment to taliforth.asm to get make to see the file was updated and changed the boot string in platform\platform-py65mon.asm, but make responds the same. Deleting taliforth-py65mon.bin first then running make results in "*** No rule to make target `taliforth-py65mon.bin', needed by `all'. Stop." Assembling directly with "ophis -c taliforth.c" gives about 20 errors "Undefined or circular dependency for label 'cp'" (also, dp, workword, insrc, cib, ciblen, etc)

Would it be possible to just tell me what python scripts and programs I need to run and in what order to get an updated bin with the code to work on my emulator? Make files have always seemed a bit cryptic to me...


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 13, 2020 12:46 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
It might be that the makefile isn't as it should be, or doesn't match the environment, and I can't help with that, but for reference:
Quote:
make -B
will do all the work which might possibly be needed, as if all sources had recently been touched
Quote:
make -n
will do no work but will tell you the commands it would have run

So, I think,
Quote:
make -B -n
might well give you all the commands you might need, in a useful order.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 13, 2020 6:28 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
Druzyek wrote:
Would it be possible to just tell me what python scripts and programs I need to run and in what order to get an updated bin with the code to work on my emulator? Make files have always seemed a bit cryptic to me...

The command should be (from the main TaliForth2 directory):
Code:
ophis -l docs/py65mon-listing.txt -m docs/py65mon-labelmap.txt -o taliforth-py65mon.bin -c platform/platform-py65mon.asm

The platform file brings in all of the other assembly files, in the correct order, to build the binary. If it worked, you should get a message about "32768 bytes output".

You can probably omit the -l and -m options if you don't need the listing and labelmap. That shortens it down to:
Code:
ophis -o taliforth-py65mon.bin -c platform/platform-py65mon.asm

To do a full rebuild, make runs the following on my system:
Code:
python3 forth_code/forth_to_ophisbin.py -i forth_code/forth_words.fs > forth_words.asc
python3 forth_code/forth_to_ophisbin.py -i forth_code/user_words.fs > user_words.asc
ophis -l docs/py65mon-listing.txt -m docs/py65mon-labelmap.txt -o taliforth-py65mon.bin -c platform/platform-py65mon.asm ;
python3 tools/generate_wordlist.py > docs/WORDLIST.md

I've built Tali2 on Windows, both with and without cygwin, so that should work out-of-the-box once you have python, Ophis, and make intalled. I will try to reproduce your setup and see if I can get the same error you are running into. It sounds like an issue with make, so I'd be interested in the version number you are running ("make --version" should tell you).


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 13, 2020 7:51 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
I can verify that Tali2 does not build on Windows using GnuWin32 make. I usually use cygwin on windows, so that probably broke a while ago and I didn't notice. I've put in an issue ticket on Tali2's github page, and it looks like it's pretty easy to fix so I'll probably do it myself if I have time this weekend. The issue appears to be a semicolon on the end of lines 18 and 24 (just remove it - it's not needed on Linux and just confuses Windows). I also had to change all references of "python3" to "python" as 3.8.1 did not appear to install a "python3.exe".

The above commands should get you going in the meantime. If you don't have a python3.exe executable (it brought up the windows store when I installed 3.8.1 and tried running "python3" on a fresh copy of windows 10), you can change those to just "python" in the above commands.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 14, 2020 2:59 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Thanks for looking into it. I was able to get it to compile with ophis like you showed above.

Would it be possible to comment out some of the words I don't need and recompile to make the binary smaller? Would I need to edit the word lists too to get that to work? The closest I can get to a rommable version might be a cut down version of the runtime and having my emulator supply bytes from a file every time TaliForth requests a key press. Maybe it would make sense to keep the full version to develop interactively and have a reduced version to switch to that just reads from a file and executes.

In case it's useful, make is 3.81. I tried running make -B and it shows the line "python3 tools/generate_wordlist.py > docs/WORDLIST.md" with error 9009. Typing python gets me a python prompt but python3 opens a browser window to install Python from the Windows store but doesn't print anything to the console.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 14, 2020 9:54 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
Druzyek wrote:
Would it be possible to comment out some of the words I don't need and recompile to make the binary smaller? Would I need to edit the word lists too to get that to work? The closest I can get to a rommable version might be a cut down version of the runtime and having my emulator supply bytes from a file every time TaliForth requests a key press. Maybe it would make sense to keep the full version to develop interactively and have a reduced version to switch to that just reads from a file and executes.


The default image is a complete 32K ROM meant for simulating in py65mon. There is some unused space in that ROM (see the "filler" value when you assemble it), but it generates from $8000 all the way through the reset/IRQ vectors ending at $ffff. I believe the steckschwein folks modified their platform file to not generate the vectors at the end of the memory space, and their image is only about 22K. That allows them to load it into RAM to run it, using loading facilities in their existing kernel.

To make things smaller, you should be able to remove the assembler, disassembler, and "ed" editor (not to be confused with the "editor" for working with blocks). I'll have to try doing that to see what the instructions are. Those three things live in separate asm files (bought in from the taliforth.asm file), but you will need to remove the headers for all of those words in headers.asm (this is a singly linked list where each "nt" (name token) links to the next word in the list). There are actually four wordlists - a root wordlist, the main forth wordlist, an editor wordlist (for the block editor), and an assembler wordlist.

To remove the assembler, for example, you would comment out the .require "assembler.asm" in taliforth.asm, then go into headers.asm and search for ASSEMBLER-WORDLIST. You should leave the "assembler_dictionary_start:" so it resolves somewhere else in the code, but you don't care what it resolves to as it won't be used anymore. You can then comment out from nt_asm_adc_h: through the end of the file.

You should also remove the forth word that invokes this wordlist (only needed because you've eliminated an entire wordlist. Search for "nt_assembler_wordlist:". You'll actually be editing nt_root_wordlist so it doesn't link to nt_assembler_wordlist anymore. In the "nt_root_wordlist:" header, change the very first item after .word from "nt_assembler_wordlist" to "nt_editor_wordlist".

You should now be able to reassemble without the assembler being installed.

If you want to remove further words, you can pick and choose from the words in native_words.asm and then "unlink" their header entry by making the previous entry skip over them. Then you can comment out their header as well.

I'll give this a try and make sure it works as I explained it, but feel free to give a holler if you get stuck or break something.

Druzyek wrote:
In case it's useful, make is 3.81. I tried running make -B and it shows the line "python3 tools/generate_wordlist.py > docs/WORDLIST.md" with error 9009. Typing python gets me a python prompt but python3 opens a browser window to install Python from the Windows store but doesn't print anything to the console.


I had this odd behavior as well. Apparently the python3 thing is kinda linux-only, but windows captures trying to run python or python3 and redirects you to the MS store. Installing the latest python 3 on Windows only installs python.exe but not python3.exe, so that remains redirected. Python is still a bit of a mess with their v2 vs v3, and it's been like that for years now.

I've updated the Makefile and issued a pull request to the Tali2 project, but it might be a bit before scotws can take a look at it. You can snag just the Makefile from https://github.com/SamCoVT/TaliForth2/t ... m/Makefile if you'd like to use make.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 14, 2020 9:57 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
(As of very recently, python2 is no longer maintained, so it's become reasonable for 'python' to mean 'python3' - which is not to say that everything everywhere will still work. We've had a long time to make the adjustment, but many of us haven't.)


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 15, 2020 1:03 am 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
I've made a quick attempt to "smallerize" Tali2 by removing the assembler, disassembler, wordlist support, and the editor "ed". It drops from around 22K to less than 10K in size. I made a branch in my repository if you want to check it out: https://github.com/SamCoVT/TaliForth2/t ... smalltali2

Please note that the binary is still 32K because the platform/platform-py65mon.asm file still has an ".org $8000" at the beginning, and at the end it advances to $fffa to place the reset/interrupt vectors. Also beware that there are a couple of ".advance" directives in the middle of the code (to $e000 for platform_bye: and to $f010 for the IO routines. You can adjust these for wherever you want the code to live.

The expectation is that you will make a new platform-xxxx.asm file in the platform folder for your specific hardware or simulator and put your initialization and I/O routines there. You can take a look at the existing files there for examples.

If you can provide some more details on what you're interested in doing and what hardware/simulator you are working with, I can probably provide more specific help.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 15, 2020 9:07 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Quote:
I've made a quick attempt to "smallerize" Tali2
Awesome! Thanks a lot for doing this. I think this will be a big help. Is there a good place in ram or zero page where I can steal a few bytes to keep track of the cursor position?

I'm trying to get it running on my JavaScript emulator in order to port a simple game I made to see how Forth compares to CC65 and writing assembly with macros. The setup is four 16k banks with the lowest one mapped to ram, the middle two normally mapped to screen memory and code in the top 16k. The CC65 version came out to 27k, so some graphics and other stuff are in a second bank which gets copied to RAM at startup before the screen is needed then banked out so the address space can be used for the screen. Hopefully I can devise something similar for Forth.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 15, 2020 10:13 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
Druzyek wrote:
Awesome! Thanks a lot for doing this. I think this will be a big help. Is there a good place in ram or zero page where I can steal a few bytes to keep track of the cursor position?

Yes. Everything beyond $80 (it says $78 in the platform file, but skip a couple of bytes just in case of a Forth stack underflow) is reserved for you to use as you see fit. You should be able to use those without being disturbed.
Quote:
I'm trying to get it running on my JavaScript emulator in order to port a simple game I made to see how Forth compares to CC65 and writing assembly with macros.
That sounds super exciting. I'll be interested in seeing what you discover. Tali2 is definitely a bit fat to fit in 16K (it was designed for fitting in 24K so a user could have 8K for their own kernal and fit it all in a 32K ROM) The smallerized version is under 10K, so that should fit. You'll need to make your own platform file (start with platform-py65mon.asm in the platform folder, copy it to a new platform-xxxx.asm file and add your initialization and I/O routines).

Just FYI, you *might* want the assembler (you can easily mix assembly and forth words in Tali2) and remove some of the other words instead. If that ends up being the case, let me know.

Quote:
The setup is four 16k banks with the lowest one mapped to ram, the middle two normally mapped to screen memory and code in the top 16k. The CC65 version came out to 27k, so some graphics and other stuff are in a second bank which gets copied to RAM at startup before the screen is needed then banked out so the address space can be used for the screen. Hopefully I can devise something similar for Forth.

16K of RAM should be way more than enough for Forth, as most of the dictionary and starting words live in ROM. Make sure to adjust the ".org" label at the beginning of the platform file (you probably want $c000 to start in the last 16K bank) and the ram_end label (currently "$8000-1, you want "$4000-1" to only use RAM in the first 16K) in that same file. Your I/O routines looks similar enough to what py65mon uses that it might be as simple as changing the address that is read or written for I/O. Don't forget to update the kernel_id string at the bottom of the platform file.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jan 16, 2020 10:12 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
Great. I got everything working. The character data and drawing code is about 1k. It fits into 16k with your cut down version with about 700 bytes to spare. Is the extra 5k of data in addition to the 9k or so of code word lists and stuff?

Quote:
Just FYI, you *might* want the assembler (you can easily mix assembly and forth words in Tali2) and remove some of the other words instead.
The extra code space might be more valuable for this project. Seems like I could cross assemble instead and store the entry points in a table then use Forth to jump into assembly, but I haven't tried yet.

Quote:
16K of RAM should be way more than enough for Forth, as most of the dictionary and starting words live in ROM
Hopefully the code and graphics data will both fit. Hmm, could I change the dictionary pointer to compile some words to a different 16k bank and run the code from there that doesn't access the screen which uses the same 16k bank? That worked really well in CC65.


Attachments:
File comment: CC65 version of Robot Game running on JavaScript emulator
RobotGame1.PNG
RobotGame1.PNG [ 22.86 KiB | Viewed 2857 times ]
File comment: Tali Forth 2 running on JavaScript emulator
TaliForth2.png
TaliForth2.png [ 19.66 KiB | Viewed 2857 times ]
Top
 Profile  
Reply with quote  
PostPosted: Fri Jan 17, 2020 3:38 am 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
Druzyek wrote:
Great. I got everything working. The character data and drawing code is about 1k. It fits into 16k with your cut down version with about 700 bytes to spare. Is the extra 5k of data in addition to the 9k or so of code word lists and stuff?
Congratulations getting things working! Your robot game looks interesting, but I can see why you need so much space. I can take a look at the bonus 5K (probably tomorrow). I suspect there are some strings that you could do without.

Quote:
Seems like I could cross assemble instead and store the entry points in a table then use Forth to jump into assembly, but I haven't tried yet.
Yes, you should be able to do that. Place an address on the stack and use the word EXECUTE and it will jsr there.

Quote:
Quote:
16K of RAM should be way more than enough for Forth, as most of the dictionary and starting words live in ROM
Hopefully the code and graphics data will both fit. Hmm, could I change the dictionary pointer to compile some words to a different 16k bank and run the code from there that doesn't access the screen which uses the same 16k bank? That worked really well in CC65.
That is a very interesting thought. There are some issues to deal with, but I'm leaning towards "probably". Also, it's Forth, so really the answer is "of course".
When Tali compiles, it places the header and code together in the dictionary, which grows up from the bottom of RAM. The headers don't have to be with the code, through, and indeed they are not in the words in ROM. I suspect you'd have to rewrite : to make that work, but it's a possibility.

Another possibility would be to use wordlists (might need to put back a few select words that I removed - Tali still has the functionality but not the words to control wordlists). You could create a new wordlist, make it the current wordlist (the one new words will go into), save the current value of CP (the compiler pointer) into a variable that lives in the bottom 16K, map the page you want to use into one of your upper 16K blocks, move CP point into that page, and then start defining new words. Once all of the words you want have been compiled, you can put CP back where it used to live, make the "Forth" wordlist the current wordlist again, and then you just need to make sure you remove the new wordlist out of the search order before you unmap that page (so that Forth doesn't go looking for any headers in that page). You could technically make a new wordlist for every 16K page you wanted to compile new words into.

Are you familiar with CREATE and DOES> in Forth? You could certainly make a new defining word that will do all of this switching around when compiling the words and can also switch things around when running them. I'll have to think on it a while to see if I can see exactly how that would work. Making new defining words is still a bit mind-bending for me.


Top
 Profile  
Reply with quote  
PostPosted: Fri Jan 17, 2020 10:01 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 247
The 5K was indeed wordlist headers and strings. If you want to pull my recent commits to the example/smalltali2 branch, I've removed the second editor, the environment? word which used a lot of strings, and all of the block words. It's now about 14K combined code+data.

I also put back just enough wordlist words and tested moving the compiler pointer around - it seems to work. You have "wordlist" which creates a new wordlist and gives you the number (make sure you save this immediately - using the word again will reserve ANOTHER wordlist). I normally put it in a constant like so:
Code:
wordlist constant mywordlist


The compiler pointer is in zero page address 0. You can "move" it by just storing into location zero:
Code:
hex 4000 0 ! ( move compiler pointer to $4000 )
I recommend saving the original value of cp (the word "here" puts the current value on the stack) into a variable kept in the unpaged low RAM so that you can put it back when you are done.

Here is my sample run in the simulator.
Code:
wordlist constant mywordlist  \ Make a new wordlist  ok
mywordlist forth-wordlist 2 set-order \ Add the new wordlist to the search order  ok
mywordlist set-current \ Make the new wordlist the one words compile into  ok
here . 1047 \ See where CP is now.  ok
4000 0 ! \ Change it to $4000  ok
here . 4000 \ Check that it changed OK.  ok
: new-word ." This word lives higher in memory" ;  ok

\ Once you are done defining words:
1047 0 ! \ Put the original CP value back  ok
forth-wordlist set-current \ Make the Forth wordlist the compiling wordlist ok
forth-wordlist 1 set-order \ Remove the new wordlist from the search order ok
\ Now it's OK to swap that memory out.
\ The words in that wordlist are "hidden" and will not be
\ searched or used until you put mywordlist back in the search order.


Once the words have been compiled into memory, you only need to use the "set-order" word to change the search order. Make sure the correct memory page is there before adjusting the search order, and put it back to just the forth-wordlist before changing it to another page. You can check out https://forth-standard.org/standard/search for info on these words. I didn't put back words like get-current and order that let you see what's currently set for values, but you can uncomment them (in native_words.asm and headers.asm) if you want them.


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 21, 2020 7:13 am 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
After a lot of fiddling, I got it to work. Thanks for the even smaller version. The extra 1.6k in ROM is VERY useful.

One thing that threw me was that the Undefined word error only shows part of the word. If you enter "bar" for example and it's not defined it shows ">r< Undefined word" instead of >bar<. I thought maybe the pointer to the input buffer was getting scrambled somehow switching between the banks.

ram_end had to be moved from $4000-1 to $C000-1 since otherwise moving the cp to $4000 would give an out of memory error. cp_end is now also $C000-1. hist_buff changed from ram_end-$03ff to $4000-$03ff so it won't point to the banked memory (I recognized the problem when I got lots of colored dots on the screen :D ) Hmm, how exactly does hist_buff work? Do I need all 8 buffers?

Here's what I have so far. Please let me know what I can improve.
Code:
hex

\ Variables stored in zero page
0 constant cp
86 constant bank_mode         \ whether bank 2 points to code or screen memory
88 constant cp_save            \ copy of normal cp
8A constant cp_banked         \ copy of second cp in bank 2

\ Hardware specific
FFE1 constant bank2_register   \ 0x4000-0x7FFF
1 constant bank_gen_ram2      \ banked code goes here (bank 2)
4 constant bank_gfx_ram1      \ upper half of screen (bank 2)

: bank2 bank2_register c! ;

wordlist constant mywordlist

: setup 4000 cp_banked !   \ cp for banked code ;
: startup decimal CR CR CR 4000 here - u. hex ." bytes RAM left" ;

: EnableBankROM
   bank_mode @ 0= if
      mywordlist forth-wordlist 2 set-order
      mywordlist set-current
      here cp_save !
      cp_banked @ cp !
      bank_gen_ram2 bank2
      1 bank_mode !
   then
;

: EnableGfxRAM
   bank_mode @ 0<> if
      here cp_banked !
      cp_save @ cp !
      forth-wordlist set-current
      forth-wordlist 1 set-order
      bank_gfx_ram1 bank2
      0 bank_mode !
   then
;


setup
startup

: foo ." foo!" ;
foo                  \ Success
EnableBankROM
: bar ." bar!" ;
foo bar               \ Success
EnableGfxRAM
foo bar               \ bar not found as expected
EnableBankROM
foo bar               \ Success


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 21, 2020 6:54 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
I think mod may be wrong. Here is some test output:
Code:
13 5 mod . 3  ok
-13 5 mod . -3  ok
13 -5 mod . 3  ok
-13 -5 mod . -3  ok

It should be this (confirmed in Gforth):
Code:
13 5 mod . 3  ok
-13 5 mod . 2  ok
13 -5 mod . -2  ok
-13 -5 mod . -3  ok

-x/y = -(x/y) but -x mod y != -(x mod y)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 73 posts ]  Go to page 1, 2, 3, 4, 5  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: