A text adventure game for the CX16

DarwinNE

New Member
Sep 19, 2019
12
14
3
Dear all,
watching the CX16 video on Youtube, I was intrigued about the project. Therefore, I downloaded and played a little with the emulator (version 30).
I like the C language and I wandered if I can do something for this neat little platform. I saw that greg-king5 on GitHub created a branch of cc65 that could compile for the cx16 target and I tried to port my Two Days to the Race text adventure game, with success.

commanderX16_two_days.png

The game is freely downloadable (I don't want to spam, just search "Two Days to the Race" and you'll find it easily).

For the moment, it is provided in three distinct files as it has to fit in the lower 32KB of RAM. It would be nice to exploit the paging to let the whole game fit in memory (by the way, the whole game only requires 49KB and it fits in a C64), I may do that in the future. Colour support is very basic for the moment.

I thought it would have been funny to play a small text adventure game on this exciting new project, so I hope you'll appreciate it!

Cheers,
D.
 

x7c

New Member
Sep 15, 2019
5
5
3
I easily found the original version of the game, but is the cx16 port available somewhere?

Edit: Sorry, found it. I'll spam for you :) Here is the page with all the downloads. Got it running on the latest build from source.

Edit 2: Made it to the end of disk 1 (y) Now it's bed time o_O
 
Last edited:

Wertyloo

Member
Sep 15, 2019
72
7
8
put the "engine" part on the lower 48k,and all the data in 8k chunks in the cartridge memory pages at $A000, and switch as its needed
 
  • Like
Reactions: DarwinNE

DarwinNE

New Member
Sep 19, 2019
12
14
3
That's cool, x7c! Glad you play the game.
When you've finished the game, don't hesitate to send me the final password (privately, by PM). I'll add you to the hall of fame on the website.
 

qbradq

New Member
Sep 14, 2019
24
15
3
This is some really cool tech! It is really cool to see a full game running in the X16 emulator. I'm not much on IF but I did try the first disk. I like the writing.
 
  • Like
Reactions: x7c and DarwinNE

Wertyloo

Member
Sep 15, 2019
72
7
8
Thank you for the hint, Wertyloo.
be aware,the ext.2M ram currently on the frontsidebus,so no additional mem-latency while access the $a000 part
so do not copy from $a000 into the lover ram-part,use everithing from here,if you can
$a000 bank-switches have latency! so probably no-no to any time critical "tricks"
 

qbradq

New Member
Sep 14, 2019
24
15
3
be aware,the ext.2M ram currently on the frontsidebus,so no additional mem-latency while access the $a000 part
so do not copy from $a000 into the lover ram-part,use everithing from here,if you can
$a000 bank-switches have latency! so probably no-no to any time critical "tricks"
So bank switching $A000 has latency but reads and writes do not? Do we know the timing on the bank switch latency? I'm planning on storing, like, everything in those pages for a BASIC interpreter I'm writing so not being able to thrash those pages is going to be a deal breaker.
 
May 22, 2019
486
250
43
$a000 bank-switches have latency! so probably no-no to any time critical "tricks"
We don't actually know yet how long it takes to switch banks. And we won't know until the hardware is more mature. Right now, it's not even running at the full 8MHz. The wost case scenario, according to the data sheets I could find, seems to be 1µs, which is 8 clock cycles. That's only 2 machine instructions, and it takes at least that many instructions to actually get back from a bank switch.

My guess is that by the time you have processed enough machine instructions to make use of bank switching, the 6522 will have stabilized the address lines and the bank will be available.

Regardless... keeping related data in upper memory is the smart way to go, and for now you'll need to do a PEEK loop to read the data. Or, since you're using c, you can initialize a pointer into the upper memory region and use printf to output strings. By setting a pointer to the bank select register, you can quickly move to any of the 256 upper memory banks, and you can store an index of all of your room data in the first bank.

I've done a lot of database work (my first real programming job was doing database conversions at the file level - we didn't have a fancy DBMS like SQL), so if you want to collaborate on a data storage system, I'd love to learn about your process and maybe help develop a text adventure engine. One goal I have is to write an RPG using a text interface, kind of like a MUD, but without the MU part. =)
 
  • Like
Reactions: Swift34
May 22, 2019
486
250
43
So bank switching $A000 has latency but reads and writes do not? Do we know the timing on the bank switch latency? I'm planning on storing, like, everything in those pages for a BASIC interpreter I'm writing so not being able to thrash those pages is going to be a deal breaker.
Like I mentioned above, he's speculating. There's no evidence to support this yet, and the only data I can find is an older 6522 data sheet that quotes 1µs to set the output pins.

The bank selection is actually being done by using a 6522 VIA to set the upper address lines of the memory chips. So when you write to the bank select register, this sets the VIA pins to a specific value. So the time it takes to switch banks is equal to the time it takes the 6522 to set the output pins.

This is 1 microsecond, according to the data sheet I found, but that may not be correct for the current generation of VIA.

Even assuming it is 1µs, this is just 2 CPU instructions at 8MHz (most instructions take 4-5 cycles per instruction.) So by the time you swap banks and get back to your code to actually do something useful, that time will have passed. Also, the kernel already has routines for far jumps, including far JSR and RTS. If you use those routines, they handle the bank swapping and will account for any latency.

Regardless, based on these numbers, you just need two machine instructions between the STA that does the bank switch and the first LDA that reads data from the bank. (or STA that writes there.)
 

DarwinNE

New Member
Sep 19, 2019
12
14
3
I've done a lot of database work (my first real programming job was doing database conversions at the file level - we didn't have a fancy DBMS like SQL), so if you want to collaborate on a data storage system, I'd love to learn about your process and maybe help develop a text adventure engine. One goal I have is to write an RPG using a text interface, kind of like a MUD, but without the MU part. =)
It would be very interesting, but for the moment I am quite busy working on a new adventure game, called On the Queen's Footsteps:


There is only one third of the game complete, right now (and I tried to compile it for the Commander X16, too, and it works).

I use a tool that I wrote called AWS2C: https://github.com/DarwinNE/aws2c

This tool is not particularly well programmed, but it is more or less working for my needs. It takes an adventure game written in a format called AWS (more on that later) and spits out a complete C source file that can be compiled on a variety of platforms. The I/O is very simple: basically you just need a function to write a string and one to read a string from keyboard, so the resulting code can be compiled on a pretty limited library. For example, I provided a specific driver to use the VIC20 with a 40 column screen. For the X16, once I had a working C compiler I just had to setup some platform-specific settings in a header file and I got the whole game running in a matter of minutes.

Concerning AWS, it is a format inspired on a very old program called GAC. I wrote here a description of the format: https://github.com/DarwinNE/aws2c/blob/master/AWS_description.md

There is an editor, written by Aristide Torrelli (who ideated the AWS file format), but most of the time I work by editing directly the AWS file and the website is in Italian: http://www.aristidetorrelli.it/aws3/Manuali.html

Coming to the page swap, I thought a little bit about it and the problem is that it is not very easy to handle by keeping a single, portable, generated source file in C. I have a similar problem with the C128 and I've been suggested a possible solution with Cc65 would be to use the Extended Memory technique: https://github.com/cc65/cc65/blob/master/samples/multidemo.c
Otherwise, bank switching can be handled manually as already suggested, by knowing, for example, that the description of the room 23 is contained in bank 44, switch so it is seen at bank $A000 and access it. Some specific settings of AWS2C could possibly implement that.
 

qbradq

New Member
Sep 14, 2019
24
15
3
Like I mentioned above, he's speculating. There's no evidence to support this yet, and the only data I can find is an older 6522 data sheet that quotes 1µs to set the output pins.

The bank selection is actually being done by using a 6522 VIA to set the upper address lines of the memory chips. So when you write to the bank select register, this sets the VIA pins to a specific value. So the time it takes to switch banks is equal to the time it takes the 6522 to set the output pins.

This is 1 microsecond, according to the data sheet I found, but that may not be correct for the current generation of VIA.

Even assuming it is 1µs, this is just 2 CPU instructions at 8MHz (most instructions take 4-5 cycles per instruction.) So by the time you swap banks and get back to your code to actually do something useful, that time will have passed. Also, the kernel already has routines for far jumps, including far JSR and RTS. If you use those routines, they handle the bank swapping and will account for any latency.

Regardless, based on these numbers, you just need two machine instructions between the STA that does the bank switch and the first LDA that reads data from the bank. (or STA that writes there.)
FYI, the current data sheet is at Western Design Center (PDF) . WDC are the OEM for this part (and many other 8-bit ICs in this project). That PDF lists the maximum propagation delay at 60nS when operated at 8MHZ. Add a generous guess at 250nS end-to-end propagation for the SRAMs and that's it. I didn't see any buffer logic between the CPU and SRAMs, maybe I missed it?

I thought you were talking like a lot of time like with a modern MMU. Thank you for the clarification.
 

Wertyloo

Member
Sep 15, 2019
72
7
8
C-like languages are high-level ones, meaning as you use built-in libraryes like malloc, you would only see 1 continous memory space
its hide from you how its "memory-page-ing" under the roof
 

BruceMcF

Active Member
May 19, 2019
139
42
28
Like I mentioned above, he's speculating. There's no evidence to support this yet, and the only data I can find is an older 6522 data sheet that quotes 1µs to set the output pins.

The bank selection is actually being done by using a 6522 VIA to set the upper address lines of the memory chips. So when you write to the bank select register, this sets the VIA pins to a specific value. So the time it takes to switch banks is equal to the time it takes the 6522 to set the output pins.

This is 1 microsecond, according to the data sheet I found, but that may not be correct for the current generation of VIA.
I'm not a hardware guy, but I don't see anything like those numbers in the timing charts of the W65C22S. CF. pages 38 & 40.

The tCPW (Peripheral Data Delay) at 5v+/-5% is 30ns from the falling PHI2 clock edge when the data is latched to the register. So for code in a High RAM segment , a pair of identical parallel set of bank transfer instructions in segment should work just fine to change segments, without requiring any Low RAM code trampoline at all.
 

DarwinNE

New Member
Sep 19, 2019
12
14
3
as you use built-in libraryes like malloc, you would only see 1 continous memory space its hide from you how its "memory-page-ing" under the roof
That would be highly desirable, indeed, but I think the current implementation of Cc65 does not allow that and you'd have to handle things manually.
 

BruceMcF

Active Member
May 19, 2019
139
42
28
That would be highly desirable, indeed, but I think the current implementation of Cc65 does not allow that and you'd have to handle things manually.
Yeah ... given that C malloc lets you see one big address space, it's not unusual if the answer to the situation of "it's hard to make this particular memory available as one big address space" is, "OK, you can't malloc that".
 
May 22, 2019
486
250
43
Yeah ... given that C malloc lets you see one big address space, it's not unusual if the answer to the situation of "it's hard to make this particular memory available as one big address space" is, "OK, you can't malloc that".
Right. But the good news is that you don't really need to malloc it if you're reading from disk. You can use pointers and manually manage upper memory.

I should really start playing around with cc95. Is there a somewhat useful toolchain for Windows, yet? (Of course, ideally I'd love to see it running directly on the CX16.)