NES 64: Commodore 64 KERNAL + BASIC port

A place where you can keep others updated about your NES-related projects through screenshots, videos or information in general.

Moderator: Moderators

Post Reply
calcwatch
Posts: 3
Joined: Tue Feb 15, 2022 6:07 am
Contact:

NES 64: Commodore 64 KERNAL + BASIC port

Post by calcwatch »

Hi everyone,

I'm new to these forums, but I've been messing around with 6502 assembly for decades...

A few years ago, I got the crazy idea to try porting the Commodore 64 KERNAL and BASIC ROMs to the NES, since their CPUs are mostly the same. But I gave up when things got complicated with the PPU. Then a couple weeks ago, I saw that someone ported it to the Atari 1200XL, so I decided I'd give it another shot. This time, I was able to make a (mostly) working system. :)

Here are some videos of it in action:
  1. Booting up, running BASIC, and showing tab stop and scrolling support: https://www.youtube.com/watch?v=G2APi8KVKGc
  2. Running a benchmark maze generator program: https://www.youtube.com/watch?v=ETx8FjbXT_0
  3. Running a benchmark that calls a machine language subroutine: https://www.youtube.com/watch?v=CrPb3mq1qwM
  4. Writing to the APU to play a C major scale: https://www.youtube.com/watch?v=KKzs_-WQxlI
I can't test it on hardware, but it seems fine in emulation. Since it requires Family BASIC keyboard support, I think I'm limited to just FCEUX and BizHawk, though I can't get BizHawk's keyboard support working at all. FCEUX 2.6.2 seems a bit buggy too, so I had to write some workarounds for it.

UPDATE: I've published the code and a prebuilt ROM on GitHub. Check it out here: https://github.com/calcwatch/nes64

I'm also not sure about publishing the code for the project. Though it seems that nobody cares about the various disassemblies already floating around github...


Implementation Details
I went with the MMC5 mapper so that I could use ExRAM for the text screen, and not worry as much about reading/writing bytes in the PPU. The KERNAL an BASIC ROM are 8 kB each, so I put them in the last two banks ($C000-$FFFF), and filled the other banks with PRG RAM ($6000-$BFFF). The first byte of OS RAM is reserved, and the rest is available to BASIC. Hence the "24,575 bytes free" in the splash screen: $C000 - $6001 = $5FFF = 24,575.

The CHR ROM just contains the default all-caps character set from the C64.

I disabled all the mapper's interrupts except for the raster one, which the OS uses for keyboard scans, etc.

Because it's using the MMC5, it gets an 8-bit-to-16-bit multiplier for free. I tested it, and it works, but I can't find a practical use for it. (Not that this project has any practically uses! :lol: )

The original code comes from a heavily annotated disassembly I found on github. I needed to make some minor changes to get it assembled with ca65, mostly adding colons after labels. To free up space for new code, I removed pieces related to datacassettes, modems, RS232 devices and color RAM.

Caveats / Future Work
FCEUX only seems to support the shift key for letters. E.g., "shift+A" works, but "shift+1" doesn't register as a keypress. So there's no way to type "!", or most other symbols you'd need for BASIC. However, control key combos work, so I made the keyboard code act as if control were the same as shift.

The C64 text screen is 40 columns by 25 rows. I changed it to 32x30, which is fine for emulators, but I realize it's outside what TVs would display. (Family BASIC's text screen is just 28x24.) Shrinking it further would require substantial code changes to ignore the screen RAM bytes before and after each screen line.

So that's all I have now. I hope you enjoyed the writeup! I still can't believe that it works at all. :D
Last edited by calcwatch on Sun Feb 20, 2022 1:36 am, edited 1 time in total.
djmips
Posts: 2
Joined: Mon May 28, 2012 6:28 pm

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by djmips »

Very fun. Thanks for sharing. How much further will you take this? Do you have sprite examples?
Drag
Posts: 1615
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by Drag »

That's really neat! It goes to show that a good kernal plus BASIC can turn most things into a computer. :D
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by Oziphantom »

If one was to do this for "reals", you would port it to the FDS, it has 32K of RAM that you can use, and a disk drive for IO.

But yes a 1.8mhz CPU with no "bad lines and a smaller screen" beats the raw C64. But a C128 in C64 mode with "fast" enabled then disabled should beat the NES.
calcwatch
Posts: 3
Joined: Tue Feb 15, 2022 6:07 am
Contact:

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by calcwatch »

djmips wrote: Tue Feb 15, 2022 1:44 pm Very fun. Thanks for sharing. How much further will you take this? Do you have sprite examples?
Thanks! I'm not sure; I think I have most of the easy-to-implement stuff done already, though it could be cleaner. If people want to run this on real hardware, fixing the text window size should come next.

It starts up with sprites disabled, but you can turn them on with POKE 8193, 30. Manipulating them would have to be done in assembly unfortunately, because there's no way to guarantee the POKE commands happen during the vblank. Even just modifying the palette seems to require assembly; when I tried with POKEs, I got palette and screen corruption. Maybe the PPU isn't expecting such long delays between writes?
Oziphantom wrote: Wed Feb 16, 2022 1:16 am If one was to do this for "reals", you would port it to the FDS, it has 32K of RAM that you can use, and a disk drive for IO.
Hmm, I hadn't thought of making it an FDS image, but I don't think I'd gain more RAM that way. My understanding is that the FDS BIOS takes up $E000-$FFFF, and then I'd need to load the 16 kB of KERNAL and BASIC into RAM at $A000-$DFFF, leaving just 16 kB free. And the disk drive only does sequential writes like a tape drive, so that would make supporting it interesting. Anyway, the MMC5 supports 64 kB RAM with bank switching, so if someone really needs extra memory, it's there.
Oziphantom wrote: Wed Feb 16, 2022 1:16 am But yes a 1.8mhz CPU with no "bad lines and a smaller screen" beats the raw C64. But a C128 in C64 mode with "fast" enabled then disabled should beat the NES.
True, and it's certainly no match for a C64 with a Super CPU. I just threw the benchmarks in to compare to this Atari 64 video. No disrespect intended for the C64 :)
shiny
Posts: 26
Joined: Fri Sep 05, 2008 3:39 am

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by shiny »

I have some Famiclones with the keyboard in the attic, I might try this with an Everdrive
..jpg
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by Oziphantom »

another annoying thing about poke is it does (zp),y which can give you read/write modify glitches, for example you can't poke a VDC register on the C128 for this reason, this would also potentially cause issues with scroll registers.
calcwatch
Posts: 3
Joined: Tue Feb 15, 2022 6:07 am
Contact:

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by calcwatch »

shiny wrote: Thu Feb 17, 2022 9:10 am I have some Famiclones with the keyboard in the attic, I might try this with an Everdrive
..jpg
Cool, I'd love to know if it works!

I've just posted the code and the first release ROM on Github: https://github.com/calcwatch/nes64
Oziphantom wrote: Thu Feb 17, 2022 9:30 am another annoying thing about poke is it does (zp),y which can give you read/write modify glitches, for example you can't poke a VDC register on the C128 for this reason, this would also potentially cause issues with scroll registers.
Interesting, I had no idea. As an experiment, I modified the `POKE` code to write and call a subroutine in RAM that would call `STA` without indirection, but it still caused glitches in the PPU.
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: NES 64: Commodore 64 KERNAL + BASIC port

Post by Individualised »

Having a lot of fun with this. One thing I noticed however is that you can't have BASIC lines that span multiple visual lines. On the C64, BASIC lines can be up to 80 characters, but if you type a BASIC line more than 32 characters here, it will think the next visual line is another BASIC line and will give a syntax error.
Post Reply