Open GoogleCodeExporter opened 9 years ago
Original comment by kotlin...@gmail.com
on 3 Nov 2012 at 1:42
Original comment by kotlin...@gmail.com
on 10 Nov 2012 at 9:41
Original comment by kotlin...@gmail.com
on 4 Feb 2013 at 2:17
Original comment by kotlin...@gmail.com
on 22 Jun 2013 at 10:27
Probably I will not do it - due to personal lack of interest
Original comment by kotlin...@gmail.com
on 22 Jun 2013 at 10:51
A quick solution
Original comment by stefan.h...@gmail.com
on 22 Jul 2013 at 9:59
Attachments:
Original comment by kotlin...@gmail.com
on 22 Jul 2013 at 10:16
ok... that is not a 100% solution, or? I tried quickly to use it, got the "OK",
but the Forth source files are not loading for me.
Original comment by kotlin...@gmail.com
on 22 Jul 2013 at 10:44
Hm, a C128 solution would be cool!
- 128 KB RAM
- 80 characters
I plan to create a retro 8bit roguelike game and 80 characters would help a lot.
Original comment by marco....@gmail.com
on 2 Aug 2014 at 1:29
Seems to be one at http://forth128.blogspot.se/
Pretty cool! Of course there are some changes since August. Is there any download?
I had the same idea, and got it sort-of working fairly without too many changes; I've put a work-in-progress branch up at https://github.com/rhalkyard/durexforth/tree/c128-port.
So far, both 80 column and 40 column text modes work (including switching between them with escape-X), and it can load and compile source and operate interactively. I've added fast
and slow
words that work like their BASIC 7.0 counterparts, and a fast?
word to return the current fast/slow state. v
and graphics do not work yet, since they have some C64-specific assumptions in them, but those should be fairly easy to overcome. ls
doesn't seem to work either, haven't quite worked out why yet.
Eventually it would be nice to support both the C64 and 128 in a single codebase. Would it be reasonable to add a built-in word to determine the platform that we are running on, so that the same code can do the right thing on both systems?
I also have a Plus/4 sitting around. If I get bored this winter I might try porting to that too ;)
Hi! Wow, that's very exciting and impressive! I had a glance, and at least so far, it looks like not many changes were needed? If it's not more, it would be enough to add an Acme define (if there is none already) to conditionally apply the changes. For $801/$1c01, I think it would be appropriate to add a CONSTANT for that. If more changes are needed, certainly it would not hurt to add a word that identifies the target.
Thank you! I'm impressed with how easy it was to get it working - it's a very easy-to-understand codebase.
v.fs
and gfx.fs
will need to handle RAM/ROM switching differently on the 128, and it might be nice to selectively call fast
in a few places (e.g. when compiling), so it probably would be worthwhile to have a word. Any objections to calling it c128?
?
I'm not fully aware what fast/slow does? I mean... "fast" sounds nicer than "slow" but I suspect there are circumstances when it cannot be used? :-) I read up on "FAST" mode now. Maybe it would be good to have it always on, except when graphics are enabled? Or are there other circumstances where it will not work?
For your question, c128
should be avoided, since there is a naming conflict with the hexadecimal number with the same name. Maybe there is some other way to do it.
It also works in C64 mode, how about "?vdc"?
Pushed a few more changes that got ls
and v
working (though v
only works correctly in 40 column mode).
It also works in C64 mode, how about "?vdc"?
That might be useful to have too, but we will also need to be able to identify a C128 running in native mode. Hopefully most of those checks can be done in fairly low-level code, but, e.g. graphics routines will need to know about the different memory layout and bank controls on the native 128.
The 128's memory layout is kind of awkward for hi-res graphics; you can't use the $C000-$FFFF
VIC bank because $FF00
is a 'magic' address that controls the MMU. Instead, I might try and run the graphics in high RAM; it won't be quite as performant, but it's less awkward than trying to put the bitmap in the middle of everything.
The VDC also has its own unofficial graphics mode that's even higher resolution (640x200 or 640x480 interlaced); might be fun to add support for that sometime too!
EDIT: never mind about my memory layout comment; it is indeed possible to use $C000-$FFFF
for graphics, you just can't have the bitmap at $D000-$FFFF
. gfx.fs
is working with only minor changes, see https://github.com/rhalkyard/durexforth/commit/008477a508d58d048c0a43b5c2269f25278bd5b9. VDC graphics would be nice to have as well though.
In the process of this, I have added some new words [IF]
[ELSE]
and [THEN]
(see https://forth-standard.org/standard/tools/BracketIF) that work like normal if-else-then, but are immediate, so can be used for conditional compilation (like #if
/#ifdef
in C etc.)
This lets us handle the differences between the C64 and C128 at compile time - only the code appropriate to the machine gets compiled, so (aside from the extra dictionary space these words take up) there will be no runtime cost in speed or code size to supporting both systems.
The implementation and some examples in more
and v
are in the following commit, if you would like to take a look:
https://github.com/rhalkyard/durexforth/commit/6759f4c8feb53e1893a31d913f0e06b7f5b28869
I realise that adding these words to the standard environment consumes almost all the remaining cartridge space, but it will make supporting both systems (or potentially, having full-featured and "lite" variants of libraries) much easier.
Humm, yeah I must admit I'm not really a fan of adding [if]
[else]
[then]
words. Most of the times, those words are not really needed and take up space that maybe could be used for something more fun.
Maybe the differing words could be moved out to their own files? Then the problem could even be solved in the Makefile, by having two separate builds for c64 and c128?
That's reasonable; it was fun implementing them anyway, and I think that with how few changes were actually required, your idea is a better one. If you don't mind me doing so, I'll do some refactoring of the makefile to support it.
On the topic of fun things, the 128 version makes playing with graphics a delight - since the VIC and VDC are completely independent, you can leave the VIC in hi-res mode while the interpreter runs on the VDC, so you can interactively play with graphics words and see their effects immediately. It's one thing to do it in an emulator, but there's a certain magic to seeing it on a pair of CRTs connected to a real machine :)
Code-wise, I see only two roadblocks to considering 128 support fully functional.
On the simple side, float.fs still needs to be modified to work with the 128's BASIC routines. I haven't touched it yet because I don't entirely understand how it avoids corrupting the stack - the floating-point accumulators in 128 BASIC are slightly closer to the start of the stack than on the 64, so there would be greater risk of overwriting valid stack values. Some advice on how it works on the 64 would be appreciated.
And then there's a bug that stopped me from sleeping last night. I don't expect you to have an answer for me or anything, but I figure that if I write it all down, it'll at least help me organise my thoughts, and if I'm really lucky, someone smarter than me will see it and have an idea.
On the 128, the first character of the line following an INCLUDE
or REQUIRE
will sometimes get dropped or garbled. It doesn't happen all the time, but it is repeatable and appears to be affected by file size (with the same set of files, it happens at the same place each time, but when file sizes change, it will happen in different places).
The strange thing is, I've spent hours examining the code path where this happens (INCLUDED
-REFILL
-interpret_tib
) and it appears to be making all the right Kernal calls through the official jump table entries, and (aside from needing to call SETBNK
before OPEN
on the 128), should work fine on both the 128 and 64.
If we have some source that looks like this,
...
.( compiling foo...) include foo .( done)
cr here .
...
as far as I can understand it, the sequence of events are as follows:
INCLUDED
saves TIB state and adjusts TIB pointer to preserve any trailing characters, increments file number, and does a standard SETBNK
- SETNAM
- SETLFS
- OPEN
- CHKIN
sequence, consumes the first two characters because we are using the PRG filetype, and then goes into REFILL
- interpret_tib
loop.
REFILL
reads the last line of foo
into the TIB and sets READ_EOF
.
INCLUDED
tail-calls interpret_tib
to interpret the last line of foo
, then returns to the parent's interpret_tib
.
The parent interpret_tib
sees an empty TIB and returns to the REFILL
- interpret_tib
loop.
REFILL
closes foo
, decrements the file number, calls CHKIN
to get input from the parent file, and tail-calls RESTORE_INPUT
to restore the TIB and EOF state.
interpret_tib
interprets the remaining characters (.( done)
) successfully.
REFILL
attempts to read the next line from the parent file into the TIB, but sometimes, instead of cr here .
, it will read something like r here .
or %r here .
('%' is just a stand-in for some garbage character).
It gets even stranger when testing with different drives - with a 1571 the problem is sporadic and almost always manifests as a dropped character rather than a garbled one, but a 1541 will always return a garbage character in this case. I first noticed this running in VICE and wondered if it was an emulator issue, but when I tried it on my real 128 with real drives, the issue manifested in the exact same way.
Until I can get to the bottom of it, this bug is a bit of a showstopper, but it is possible to work around the issue by following each INCLUDE
with a multi-line comment so that a dropped or garbage character won't affect interpretation, like so:
...
include foo (
guard comment )
...
Stepping through with the Vice monitor might be illuminating. Just trying to help you sleep ;)
This may help: https://www.floodgap.com/retrobits/ckb/display.cgi?139
About float.fs: It does not really work on C64 either, so don't worry about it! It's just a fun, undocumented hack. I added a comment to underline that further.
About included
et.c.: Ouch! I've struggled with those kind of problems one a lot myself. It's real tricky. Let me know if I can help somehow.
By the way, what is the exact repro?
About float.fs: It does not really work on C64 either, so don't worry about it! It's just a fun, undocumented hack. I added a comment to underline that further.
Ah, that's good to know. funnily enough, the C128's ability to remap the zero page might make that kind of thing easier to work with - with some clever memory-map juggling we could have almost the whole zero page dedicated to the Forth stack.
About
included
et.c.: Ouch! I've struggled with those kind of problems one a lot myself. It's real tricky. Let me know if I can help somehow.By the way, what is the exact repro?
I've managed to reproduce the issue with a simple program that alternates reading from two different files. The code and a brief writeup are at https://github.com/rhalkyard/c128-chkin-bug. I'll update that repo as I continue to dig into it.
Try using $00 as the secondary address for both files, look for the ASCII value of the byte read in location 512 ($200) after the GET#
Maybe you need to specify drive number when opening the files? I have some vague memory that the C128 is weird or particular about this. Not that it should matter...
On Mon, 14 Dec 2020 at 03:37, Whammo notifications@github.com wrote:
Try using $00 as the secondary address for both files.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jkotlinski/durexforth/issues/95#issuecomment-744129518, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAY34OYMVC62ZWSWHDVRC3DSUV26XANCNFSM4BZPCYMA .
@rhalkyard I think I got it working by calling CLRCHN
before each file switch!
Calling UNTALK
before file switch seems to work equally well. Maybe it's preferable? I have no idea why it is needed at all.
clrchn calls untalk
Ha, I just got there too, and with some messing about with a logic analyzer, I think I've figured out why - sending a new command to the drive is supposed to implicitly UNTALK
it, but because of the way the Fast Serial handshake works on the 128, the drive thinks that the computer is ready for another byte, and then gets interrupted partway through when the computer asserts ATN.
Here's a trace of a CHKIN
without CLRCHN
on a C64 and 1541:
And here's the same thing on a 128 with a 1541 - see how the drive tries to transmit another byte when we release DATA
to start the fast-serial handshake:
It doesn't happen as often with the 1571, but it does still occur (unfortunately PulseView doesn't know how to decode fast serial properly, but you can see the drive sending a byte immediately before we assert ATN):
Explicitly UNTALK
ing the drive before calling OPEN
or CHKIN
gets around the issue because UNTALK
doesn't attempt the fast-serial handshake:
Calling UNTALK
seems preferable to me in case CLRCHN
messes with any output redirection the user might be doing, though I don't know if it really matters.
Thanks so much for your help!
Simply amazing! Soon, the best programming language implementation for the C64 will be the best programming language implementation for the c128! Thank you all!
Sending a new command to the drive is supposed to implicitly
UNTALK
it.
NO!
I don't know where people got that idea -- it never has been true. It isn't implied, it isn't automatic. A program always must call CLRCHN
explicitly. You must disconnect -- explicitly -- from an active file-channel before you do anything with another file.
AND, you must disconnect -- explicitly -- from an active file-channel before you close that file.
That's true for all models of Commodore 8-bit computers and all models of drive units.
If it had happened to work without CLRCHN
, then it was an accident. Don't rely on accidents -- they will bite you in the rear end!
I stand corrected! I can't remember where I picked up that bit of misinformation, but I'd seen it done that way so often, I'd never thought to question it.
Thank you @greg-king5 for sharing knowledge! Much appreciated!
!
@greg-king5 a question about this
"AND, you must disconnect -- explicitly -- from an active file-channel before you close that file."
Just to clarify. First call CLOSE
, then CLRCHN
, is that correct? Like here? https://codebase64.org/doku.php?id=base:reading_a_file_byte-by-byte
"AND, you must disconnect -- explicitly -- from an active file-channel before you close that file."
Just to clarify. First call
CLOSE
, thenCLRCHN
, is that correct? Like here? https://codebase64.org/doku.php?id=base:reading_a_file_byte-by-byte
It's the other way around. You can think of the actions in terms of functional blocks. "Openning a file", "connecting to a file", and "getting/sending bytes" are three blocks. The later blocks should be nested completely inside the earlier blocks. It's similar to nested code blocks in a lot of programming languages, such as C, Python, Java, Ruby.
OPEN ---------------------+
CHKIN/CHKOUT ---------+ |
begin a loop -----+ | |
input or output | | |
end a loop -------+ | |
CLRCHN ---------------+ |
CLOSE --------------------+
Another thing to consider is that people will want to use DurexForth on devices other than Commodore's floppy drives.
There are hard drives and solid state drives. There are devices that plug into an expansion connector, such as IEEE adapters, the Lt. Kernel hard drive, RAM drives, the IDE64 hard drive adapter, and 80-column display adapters. There were switching hubs that allowed a kind of "Network-Attached Storage" (used in business offices and classrooms).
We can't know how those devices will react to a program that takes shortcuts (leaves out a function call), or calls functions in a wrong order. It's best not to take chances.
Further work here: https://github.com/jkotlinski/durexforth/pull/478
Original issue reported on code.google.com by
kotlin...@gmail.com
on 27 Oct 2012 at 11:59