Jump to content


Super Administrators
  • Posts

  • Joined

  • Last visited

  • Days Won


Posts posted by TomXP411

  1. On 11/25/2022 at 12:52 PM, neutrino said:

    Perhaps an idea to implement "seek()" in the Kernal? Basic?

    No. That's not how Commodore disk access works, and it never has been. There's a perfectly accessible method of doing so already, by sending a command on the command channel. 

    The whole design of Commodore's disk system is for the disk drive to handle the complex side of the operation, and for the computer itself to just provide a dumb communication channel, so aside from the basic I/O commands (LOAD, SAVE, OPEN, PRINT#, INPUT#, GET), there is no need or expectation of things like record handling for REL files, seeking in sequential files, or things on the printers, like changing fonts or printing bitmapped graphics. That's why the command channel exists - to allow the I/O device to handle those things on its own, without needing a command for everything on the host system.

    If you need a "Seek" command in BASIC, you can implement it as a subroutine. If you need a SEEK command in machine language, you an implement it as a subroutine. If you need a seek command in C or Pascal... you can implement it as subroutines. There's no need to add device-specific commands to the KERNAL or BASIC, since once you start down that path, it never ends.

  2. When you print the quote symbol, it activates "control character mode", where cursor movements, colors, and so on, are printed in reverse text like you see above. 

    The fix for this is to print a second quote, then DEL it, or you can print a return (don't put the comma at the end) and use LOCATE to position the cursor each time through the loop. 

    DEL should be 20, so you can try something like this...

    PRINT CHR$(X+Y);CHR$(X+Y);CHR$(20),

    Here's a complete program that uses this:
    10 CLS
    20 C=32
    30 FOR Y=1 TO 16
    40 FOR X=1 TO 70 STEP 8
    60 IF C<100 THEN PRINT" ";
    70 PRINT C;CHR$(C);CHR$(C);CHR$(20);"  ";
    80 C=C+1:IF C>127 THEN END
    90 NEXT X
    100 PRINT
    110 NEXT Y

    And here's a program that uses LOCATE:

    10 CLS
    20 C=32
    30 FOR Y=1 TO 16
    40 FOR X=1 TO 70 STEP 8
    50 LOCATE Y,X
    60 IF C<100 THEN PRINT" ";
    70 PRINT C;CHR$(C);
    80 C=C+1:IF C>127 THEN PRINT:END
    90 NEXT X,Y



  3. Yup. The correct answer is "Don't do that." Because the addresses change with each build of the ROMs. 

    If you feel you must do that, you'll have to look through the "SYM" files for the CHANNL symbol to get the correct value, then update that value for each version of the ROM. As you can imagine, that's an exercise in frustration. It's better to, as you suggested, use the OPEN and INPUT# commands if you don't want the question mark.


  4. On 11/22/2022 at 1:29 PM, kaos said:

    Whoaaa... I just read through the C64 DOS commands, and the KERNAL API, and it seems it does not have a concept of a file seek position..? Weird!

    One always has to load/save an entire file??

    Nope. There is a special file type on CBM DOS known as the "REL" file. This allows you to specify a record size and seek to specific records within a file. It's super awkward, and it would have made more sense just to implement a byte position command at the beginning, but trust computer engineers to make things more complicated than needed, for no real reason but that they can. 


    • Thanks 1
  5. On 11/21/2022 at 8:32 AM, neutrino said:

    Where does one get these Z-files? are they copyrighted?

    Just like anything else.. you start with a search engine and look for "interactive fiction" or "z-machine" games. 

    And yes - they are Copyrighted. All computer code is Copyrighted by default. However, like any other type of computer programs, some people give away their IF games for free, and others charge for it. There's quite a large community of Interactive Fiction developers out there - you just have to go take a look for it.

    • Like 1
  6. On 11/21/2022 at 1:30 AM, idea1407a said:

    Will we see Z-machine in the Commander X16? I wouldn't mind seeing it. \

    Should we have Z-machine for the X16? And as an added question, should we have CP/M on the X16?

    Z-Machine interpreters are available for the 6502, but I only know about a couple of generic ones (as opposed to ones bundled with things like Zork.) I haven't heard of anyone implementing one for Commander yet, but you can look at projects like Zeugma, The Å-machine, or Ozmoo as a starting point. 

    And no, you can't run CP/M on the Commander X16.  You can make an operating system similar to CP/M, but there are a lot of differences between the 8080 and 6502 CPU that mean any port of CP/M is going to take a lot of liberties with how things work... and even if you did create a CP/M port for 6502, it's not going to run 8080 or Z80 CP/M software. It would require any application software to also be ported similarly. 

    If you're going to go to all the effort to convert a piece of software to 6502, it makes more sense to simply port it to KERNAL, rather than trying to make it run on CP/M.

    • Like 1
  7. On 11/20/2022 at 8:13 PM, svenvandevelde said:

    So what is about this jsrfar?

    JSRFAR does basically the same thing your code does, it's just more complicated because it needs to be more general purpose. 

    Your code works fine for one address, but when you need to JSR to different addresses, you duplicate a lot of code by repeating the stack push/pull every time. However, for performance, you may need to do just that.

    • Thanks 1
  8. On 11/7/2022 at 2:50 PM, kaos said:

    The code for this is in basic/code17.s

    Making it honor the RAM bank setting results in slightly faster BASIC execution.

    That's good to know, thank you. I guess the question is, how does URAMB get set? I should go look that up. If it's just a POKE, that will work fine for simple stuff - but it's still not going to work well for storing and retrieving strings and floats. 

    I've been thinking about writing some helper routines for BASIC programs to use banked RAM; they would basically (no pun intended) be the commands I already mentioned, but implemented as machine language subroutines. It's not as user friendly to see things like
    POKE $400,$05: POKE $401,$10: POKE $402,$A3 : SYS $410
    but that would have the same effect as something like
    BANK 5: A$=SPEEK$($A310)


  9. On 11/7/2022 at 12:19 PM, Guybrush said:

    @TomXP411 I was referring to @kaos's post about RAM pages, not ROM pages.

    @kaos I would like to think that people writing the BASIC ROM have already thought about this. I might be wrong, but anyone worth their salt as a programmer should have thought of that.

    JSRFAR works for RAM and ROM, but going up-thread, the conversation seems to actually be related to reading and writing from banks, not executing code in banked RAM.

    I entered an issue 3 years ago for this in the CX16 ROM Git. Here are some of the things I asked for:

    1. A BANK command that would set the default bank for subsequent reads and writes
    2. that PEEK and POKE honor the selected bank
    3. A 16-bit integer PEEKI and POKEI
    4. A 40-bit float PEEKF and POKEF
    5. String PEEKS and POKES. (1 byte length, followed by the string data). 

    Combined, all these would give you the ability to work natively in banked memory in BASIC. It would work really well for things like text adventure games, for example, 

    If someone wants to pick up that ball and run with it, I'm sure Mike wouldn't mind. There's already been a lot of community involvement in the ROM, and anyone who can fix issues from the ROM is appreciated. 

    The actual issue is here:

  10. On 11/7/2022 at 11:25 AM, Guybrush said:

    Any ROM code executing (be it an interrupt routine or KERNAL routine called from BASIC) should always push the current RAM page on stack and pop it back when it's done.

    This is not a multi-core system, there's always only one thread executing, so there's no danger of conflict.

    There is a JSRFAR routines to facilitate that. Those routines live in low, unbanked RAM, and can be called at any time to execute code in another ROM or RAM bank. 

    https://github.com/commanderx16/x16-docs/blob/master/X16 Reference - 04 - KERNAL.md#function-name-JSRFAR


    • Like 1
  11. On 11/5/2022 at 3:37 PM, kaos said:

    I have been at this for a bit too long..

    I have been writing this function for a while, that performs I/O to the VRAM.


    It overwrites a portion of its code, depending on if the user wants the READ or WRITE function.

    The high byte of @vram_write and @vram_read are almost certainly in the same page, which means that overwriting this will not be needed. (See code.)

    Not overwriting the high byte of the address would make the function 12 bytes shorter (!!!)

    One way to do it is ofc to just make sure it gets loaded on the same page, by using either .align (which would totally undo the effort of space-saving) or otherwise manually making sure the code gets loaded to a suitable RAM space.

    But another way would be to use a an .IF statement. Something like this:

    But alas, this does not work. It seems ca65 requires the arguments to be constants, and not addresses of labels.

    Does anyone know how to write this .IF-statement?

    Or something similar maybe, whatever that does it...




    I found another solution to this problem, that makes the question obsolete. Just use BRA @vram_write instead of JSR ... relative addressing solves it. Derp.

    But it would be nice to be able to make .IF-statements based on address values anyways. So if anyone knows, plz elaborate 🙂

    I'm just going to say "there's a reason I don't use CA65". 

    Have you looked at other macro assemblers, such as Kick ASM or 64TASS? if 64TASS supports what you're trying to do, that's truly the simplest assembler to install and use.

  12. On 10/31/2022 at 1:48 PM, JPage said:

    Hello again!

    I have two small questions that, once again, I can't seem to find answers for and since you fine folk here were so helpful last time...

    I know that RESTORE moves the "pointer" back to the start of all DATA values. The way I was planning to use DATA this wouldn't be "useful" for me as I would need to jump around in the DATA quite a bit. So I wrote a subroutine that reads all the data but only pulls out the data between a start/end point (which you define before the GOSUB command (make the start and end points the same to pull only a single value)) then RESTORES at the end of the subroutine. It works well but I was wondering how "expensive" this is (performance wise). I might eventually have thousands of data points in there that it would loop over regularly! I did some small tests (up to 20 to 30 data points) and it's lightning fast but I wanted to ask if this was good practice before I spend the time typing all those DATA values into the code!

    I want to move a ball (single character CHR$(113)) around the screen. I have this working (using locate) but it removes any characters that it overlaps with! I was envisioning using VPEEK to see what character is in the next space the ball will occupy, then store that character's code, so I can put it back when the ball moves on! I know $B000 (45056) is the top/left corner (locate 1,1) of the screen but I can't seem to make hide nor hair of what position 1,2 would be (and so on). I thought perhaps it was $B001 (45057) but that doesn't work. I just don't understand the memory address stuff I guess. I was hoping somebody could explain that to a five year old for me? Or maybe suggest a better way of doing what I'm trying to do? (I would also like to use this "peeking" into the next spot to work as boundaries as well).

    I thank you in advance for any insight/advice!

    The READ statement is pretty slow. For large data sets (ie: thousands) I'd suggest reading from a file, instead, and using the Position (aka Seek) command (discussed in other threads here) to select the data you need to read.

    As to moving a ball around... there is only one possible character in each screen cell, and when you replace it, you replace it - no "overlap" possible within one frame buffer. However, there are two separate layers. If you enable the second layer, you can put background stuff in the rear layer and put your moving ball in the front layer.

    Or you can use a sprite. Moving the sprite around is cheaper than clearing and replacing a screen character, and sprites are naturally designed to overlap text or bitmap graphics. 


    • Thanks 1
  13. On 10/31/2022 at 1:20 PM, neutrino said:

    -30 dB yikes..

    Are loop antennas with diameters in the meter range also that bad?

    If your antenna is 1 meter across, and the wavelength you're working is 80 meters, you can do the math.

    There's a reason antennas are built around quarter-wave segments. Anything smaller than that is going to quickly lose performance. However, a meter wide antenna is certainly going to perform better than one that's 1cm wide. As to how much better... you'd have to go look at the specifications for various commercial loop antennas. (I don't rely on people posting their hobby antennas, since most of them don't seem to provide hard numbers.)


    • Like 2
  14. On 10/31/2022 at 11:32 AM, neutrino said:

    How many times worse are loopstick antennas vs long wire antenna circa?

    It's not a simple answer, but within certain limits. a bigger antenna gathers more energy than a smaller antenna. If size wasn't important, AM radio towers would not be hundreds of feet tall. 

    Without giving you a layman's class in antenna design, the length of a resonant half-wave dipole at 1MHz is 468 feet. That bar antenna is about 3 inches long. So that little bar antenna is only able to collect 3/468 (or 1/156) as much energy as the half wave antenna. Expressed in dB (the standard for radio), this ends up being something like a -21dB difference. However, I'm guessing that difference is actually more extreme, and the fact that the antenna is not tuned will make it even worse. You're probably talking -30dB or worse, compared to the dipole. I would be unsurprised to see a gain figure of -40 or -50dBi on that antenna.

    30dB of gain or attenuation is a huge amount in radio. That's the difference between 1 watt and 1000 watts, or 1 watt and 0.001 watts. For a radio antenna, a 30dB loss is unforgiveable. 

    Those ferrite coil antennas are useful for picking up stations that broadcast with hundreds of kilowatts of power from less than 50 miles away, but not for picking up stations hundreds or thousands of miles away. On a good night, I've talked to Australia and over the pole to Europe on 100 watts. That bar antenna won't even hear a 50,000 watt transmitter in the next county. 



    • Like 2
  15. On 10/31/2022 at 8:37 AM, neutrino said:

    Perhaps try a loopstick antenna instead?

    The radio waves consist of electro-magnetic waves. And if the electrical waves are really long then it might be more practical to utilize a loopstick antenna to use the magnetic part instead for better coupling to the wave.



    Loop antennas or "bar antennas" used on portable AM radios are nowhere near as efficient as long wire antenna. I've been a ham for a bit now, and I can tell you firsthand, that an outdoor dipole at 1/2 the wavelength of the transmitting station does a much better job receiving a signal than a loop or compromise antenna. 

    On 10/30/2022 at 11:10 AM, Travis Bryant moore said:

    Well I do live near the Appalachian mountains. Maybe my body was a 2nd ground. My antenna was around 30ft long. Aldo found this. http://www.arrl.org/files/file/Technology/tis/info/pdf/culter.pdf

    Your body acting as the ground is a super common occurrence when an antenna system is not balanced (ie: has at least as much ground plane as radiator, for verticals, or has an equal length negative pole for horizontals.) 

    In the case of crystal radios, where you're trying to pick up AM broadcast or shortwave signals, you usually want a horizontal antenna, and some sort of grounding system. 

    As to the mystery radio: I'm unclear what you are trying to do. The "mystery" radio is just a crystal set without a ground. A transistor radio is not a crystal radio, since crystal radios don't use batteries or transistors. If you're asking whether a transistor radio can effectively operate with a long wire, ungrounded antenna system: yes it can. I have done so, to good effect. You never want to transmit with an untuned, ungrounded long wire, but for listening to broadcasts, you can basically just connect any long piece of wire to an AM receiver and go crazy, extending it until you get a clear signal of whatever you're trying to listen to. Personally, I have a wire strung around the sunshade on the deck outside my room... I ran coax out through the wall, then ran the center along the beams. It does a good job of picking up all the local radio stations, although not so much with things like WWV (mostly because I'm surrounded by mountains on 3 sides.) 


    • Like 2
  16. On 10/30/2022 at 11:10 AM, Ed Minchau said:

    The banks are switched by setting the bank value in location 0000 for the RAM bank and 0001 for the ROM bank.  The STA command for zero page takes three cycles, and loading the accumulator with a byte in immediate mode is two cycles, so around five cycles total. Way more in BASIC, of course.

    Can we even trust a bank switch in BASIC? I believe RAM Bank 0 gets used by the KERNAL, so I haven't bothered using the banks for anything... especially since PEEK and POKE is actually slower than file I/O, if you optimize things correctly. 

  17. From @Kevin Williams, via Discord:

    Hey everyone.  It's taking a bit longer than I planned, but here is the current state of the X16 Developer Board.  I'm still routing it and I do need to nudge a few things around and stuff can happen, but this is more or less the layout I'll be going with.  It is a little different than Proto 3, and perhaps a bit more than planned which is part of the reason it has been taking longer.  For one, after adding Wavicle's clock stretching circuit, I felt the urge to revisit some of my decoding logic and was able to simplify it a little and move some things around.  I undid a part of my logic (interestingly, something Adrian and I added) that was incompatible with the clock stretching and wound up saving another IC.  But then, I subsequently put another IC on the board for another feature, ROM carts.  A total of 2MB of RAM is accessible via 256 'pages' of 8k each in the HI-RAM area.  The ROM functionally works the same, but we only have 512k onboard and a 16k window.  We could theoretically support up to 4MB of ROM with this arrangement but, 512k is probably more than enough.  Looking down the road however, David suggested moving these pins to the bus so we could later support a cartridge.  I did quite a bit of shuffling of pins on the bus and managed to squeeze everything we wanted in there, for the most part.  I'm sure some may disagree, but 60 pins are all we have.  Some other parts have been moved to hopefully optimize the audio ground paths, as well as other ground considerations.  Pretty happy with it, but the board is pretty crowded now.

    Some other notes and changes:

    I decided not to change the expansion port.  I intentionally picked 60 pins on Proto 3 because it's uncommon and a lot of pins.  This prevents A2 & ISA cards and I think none of the console carts will fit in here, maybe Famicom?  But hey, it is its own thing, so please, only X16 stuff!  I'm thinking about printing it on the production PCB.
    Added a ton of UGLY TVS Diodes for port protection.  I think they will be a little less ugly in real-life, but safety third, or something.
    Added a relay on the audio circuit to mute it on reset or power off.  The caps on the opamps make a squeal when powering off, and the YM tends to squeal a hair too, so I wanted it to mute to prevent spurious noise.  I know a relay may be annoying, but it truly is the best ‘invisible’ mute circuit in my opinion.
    I moved the ATX power connector to a more traditional location on the side of the board.  IE, a more traditional location.
    The last big one, was something I wanted to add, which is an audio-option header.  I haven’t labeled much of anything in this pic yet, but the header directly to the left of the power connector is meant for an add-on audio board.  Directly to the right of the connector are several on-board jumper pads which can be cut, and optional PCBs can be designed to do some cool stuff.  We don’t really have a volume control, except via SW, but this header has the VERA, YM & BUS audio input pins individual addressable, the output opamp is still there, as well as the i2c pins.  So you could get an i2c variable pot to set volumes, with code!  You could also add effects, and all manner of cool stuff!  Or leave it alone and it still works as it did originally.
    I’m probably forgetting something, but that is the bulk of it.  It’s a daunting board to layout, and it takes a ton of optimization.  However, I really want the dev board to be as close to the prod as possible to make sure we work out any issues now before we start making a TON more. 

    Take care everyone and thanks for your involvement.  I truly will be the software available which makes this machine successful, and I have high hopes for what we can achieve, it’s really the best DIY made in many years in my opinion.  Yes, I am biased, but I do think it’s true in this case


    • Like 9
    • Thanks 1
  18. On 10/27/2022 at 10:38 AM, tmo said:

    nice @TomXP411! 🙂

    I tried my best to get the folks to get me a computer (of any kind) starting in the late-80s', and it was a no-go (most likely due to price + I was very young). So, it wasn't until 97/98 that I got a Gateway 2000 (or, everyone in the household had one to share).

    Do you remember what you paid for the VIC-20? I'm curious what they went for when they were "new".

    I think I paid $79 for mine. The VIC-20 had been out for a couple of years, by that point, and the Commodore 64 had also come out, so the VIC-20's price was lower, thanks to the bigger C64 being on the market.


    • Like 1
  19. I was 10 years old, and my elementary school added something new to the school library: several Commodore 64 and VIC-20 computers. 

    I sat down at one, picked up the manual, and started following the directions to write a program. I was hooked. That night, I told my parents I wanted a computer. They told me "well, you can buy your own, if you can earn the money."

    Which I did. It took me some time, but by the end of the school year, I had the money to purchase my very own Commodore VIC-20 computer. The folks took mercy on me and pitched in for the cassette recorder and TV set, although the TV eventually took over as the living room TV when the old one finally died...

    I've been hooked ever since.

    • Like 1
  20. On 10/26/2022 at 11:44 AM, JPage said:

    So the OPEN is what I would use to accomplish what I'm trying to do?

    Do I need an SD card attached to do this (meaning I can't "open" from the hard drive the SD card is required? is it because the c64 didn't have a HD so it's spoofing the SD card as a floppy drive)?

    Please forgive my utter ignorance on how these things work! I'm an old-dog learning some new tricks 😄

    Yes, yes, and that's fine - we were all there once. 

    You need to OPEN a file to write to it in one program (with PRINT#) and then read from another program with INPUT# or GET#. 

    And don't forget to CLOSE it when you're done. 

    This example shows how to save a sequential file, then re-open it and even move the read pointer around to read specific bits of data.


    • Thanks 1
  21. If OPEN is locking up the emulator, you probably don't have an SD image attached. 

    I use a batch file to start up my emulator, with the following command line:

    x16emu.exe -scale 2 -echo -sdcard ..\sdcard.img -rtc

    The Scale parameter should be obvious.
    -echo causes text printed in the emulator to also be echoed on the console. This is useful for extracting BASIC programs by printing them to the console with -echo and LISTing them in the emulator.
    -sdcard is the useful parameter here. This lets you specify a filename of a disk image that contains the SD card contents. The emulator comes with the sdcard.img file, which you can copy if you want additional storage space. It's probably wise to create one for each project you're working on. 
    -rtc turns on the real time clock, which the Commander can use to keep TI$ current.

  22. On 10/22/2022 at 2:35 AM, voidstar said:

    I was experimenting with the WiModem232 on the CoCo1... Without the RS232 Pak, the built in serial connection could only do 1200 baud.   That was surprising since the PET could manage 2400 baud.

    Adding the RS232 Pak on the CoCo (which connects thru the cartridge port), then it could handle 9600 baud.


    With the 8MHz X16, I'm not sure what the difference will be (between some onboard emulation versus some solution as a cartridge).

    The Commodore 64 User port could handle bit-banged serial at up to 2400 bits per second, and the 6551 used in the Swiftlink cartridge can run at 19.2K (or faster if externally clocked.)

    The Commander is 8x faster, so you should be able to manage about 19.2K bit-banged and the full 115.2K with a 65C51N. 


  • Create New...

Important Information

Please review our Terms of Use