Page 1 of 3

Easiest BASIC to port?

Posted: Tue Jun 19, 2018 8:39 am
by Atlantis
Currently I work on my first MOS6502 microcomputer. Device is soldered on universal PCB, with a large amount of wire wrapping wire. :) This is kind of recreational project, so I decided to use as many already owned chips as I can. Therefore I am using mainly intel bus compatible chips for I/O. Hardware is working already - I was able to blink a LED with short assembly code. Now I am looking for some kind of BASIC to run on top of that thing. :)

I must clarify one thing. This is not my first vintage CPU project. Earlier I've build 8080 computer, running tiny basic (for now at least, I plan to add some hardware and run CP/M). I know there is a TB version for 6502 too, but I am looking for something better. Floating point and PEEK/POKE support would be nice. And of course simplicity is an important factor - just to set memory settings, write own I/O functions and then compile it, for example with ca65. Could you recommend something?

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 9:05 am
by Chromatix
Around here, EhBASIC seems to be pretty popular. It's designed to be easily ported, and so has relatively few assumptions about RAM layout and I/O capabilities.

If you want to get more ambitious, you could implement enough of Acorn's MOS API to run BBC BASIC or HiBASIC.

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 10:26 am
by BigEd
Welcome, Atlantis! I agree with both of Chromatix' points. Here's a pair of short docs for BBC Basic. (Edit: see also this thread elsewhere)

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 10:40 am
by Atlantis
Could you point me to some working examples? I am quite new to the 6502 assembly, my assembly skills in general are pretty basic for a moment. So I would need some information. For example:

1) What I need to change to run it directly from EPROM?
2) Where should I put my code for sending and receiving UART character?
3) Where should I (in the future) put my code for LOAD and SAVE functions?
4) What I need to modify to fit it inside my memory map?

Memory map in my device is quite straightforward, form 0x0000
32kB - directly addressed RAM with zero page and stack at the beginning
8kB - "window" for additional 32kB of RAM, divided into four switched banks.
4kB - unused (for now)
4kB - space for I/O devices
16kB (from 0xC000) - EPROM

I've found some EhBasic code on GitHub, but it appears to be designed to run on Replica-1, directly from memory.

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 11:20 am
by Chromatix
There's an entire EhBASIC section on this forum; looking through that should give you some ideas.

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 11:38 am
by BigEd
I could be wrong, but I think EhBasic is only going to need a read-character routine and a write-character routine... hmm, no, there might be a keyboard-interrupt (^C) facility and there might be a LOAD and SAVE interface.

There are a few repositories on GitHub: might be worth looking at this one at least:
https://github.com/jefftranter/6502/tre ... sm/ehbasic

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 12:37 pm
by Chromatix
Your first requirement is running from ROM instead of RAM. That should just be a matter of changing the assembly start address - near line 440 in basic.asm:

Code: Select all

Ram_base		= $0400	; start of user RAM (set as needed, should be page aligned)
Ram_top		= $5000	; end of user RAM+1 (set as needed, should be page aligned)

; This start can be changed to suit your system

	.org	$5000

; For convenience, put jump here to reset location so it can be
; run from the load address.

JMP	RES_vec
Given the memory map you provided, I suggest:

Code: Select all

Ram_base		= $0400	; start of user RAM (set as needed, should be page aligned)
Ram_top		= $8000	; end of user RAM+1 (set as needed, should be page aligned)

; This start can be changed to suit your system

	.org	$C000

; For convenience, put jump here to reset location so it can be
; run from the load address.

JMP	RES_vec
You'll also need to jump to the entry point at the beginning of the code somehow - I would put a short initialisation routine in, pointed to by your reset vector, which just sets up the hardware and clears the interrupt flag, then jumps into BASIC. The 6502 has three hardware vectors, one for reset, one for IRQ, and one for NMI. The latter two can minimally point to an RTI instruction, if you don't expect to use interrupts profitably (in which case you should also disconnect the IRQ lines and pull them inactive, or at least set up the hardware in your reset handler so that they never produce interrupts).

Then you need to implement the simple I/O routines that EhBASIC requires. Don't bother loading and saving files to begin with, just read keyboard and write terminal, both over a serial port probably. Any decent serial interface will have a status register to tell you when there's a byte ready to read or space to write one; you MUST respect that or you will find yourself dropping/duplicating characters, but it's very easy to do so.

An example of how to do the above is provided in min_mon.asm.

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 3:30 pm
by Dr Jefyll
Welcome, Atlantis -- nice to have you with us! If you have any photos of your project we'd enjoy seeing them. And/or some further description, if you have time, please. (BTW on this forum photos can be attached to one's post -- no need for a third party host.)

Gosh, Tiny Basic -- that takes me back. In the dim reaches of the 20th century I purchased a copy of TB, which was delivered by mail. The format? Paper tape! For which I was equipped; I had interfaced my KIM-1 to a tape reader someone gave me!

/reminisce :)

-- Jeff

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 5:15 pm
by Klaus2m5
You may also want to take a look at: Create your own Version of Microsoft BASIC for 6502

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 6:32 pm
by Atlantis
Chromatix wrote:
Given the memory map you provided, I suggest:

Code: Select all

Ram_base		= $0400	; start of user RAM (set as needed, should be page aligned)
Ram_top		= $8000	; end of user RAM+1 (set as needed, should be page aligned)

; This start can be changed to suit your system

	.org	$C000
I assume banked RAM above 0x8000 will be still accessible with PEEK and POKE instructions?
Quote:
vectors, one for reset, one for IRQ, and one for NMI. The latter two can minimally point to an RTI instruction, if you don't expect to use interrupts profitably (in which case you should also disconnect the IRQ lines and pull them inactive, or at least set up the hardware in your reset handler so that they never produce interrupts).
IRQ and NMI pins are pulled high. I am not using them, but there are placeholder subprograms with RTI instruction, pointed by vectors. Of course I am talking about my current led blinking code, but I plan to take similar approach in BASIC. Maybe in the future I will use IQR and/or NMI for I/O handling. Now I just want to have bare minimum done.
Quote:
An example of how to do the above is provided in min_mon.asm.
So, I assume min_mon.asm holds I/O functions?
I am still not sure how to modify it to work with my hardware. I mean I know how to configure, send and receive data with my device. I am just not sure which parts of min_mon.asm should I modify and/or delete. I am still unsure what large parts of code from that file do. ;)
Dr Jefyll wrote:
Welcome, Atlantis -- nice to have you with us! If you have any photos of your project we'd enjoy seeing them. And/or some further description, if you have time, please. (BTW on this forum photos can be attached to one's post -- no need for a third party host.)
I've added some photos. I will try to add some description soon.
It is still work in progress. I am going to add 8042 keyboard controller, maybe some RTC and of course CRT controller on the separate board.

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 6:41 pm
by BigEd
Looks like you might only need to tweak the ACIAin and ACIAout routines to match your hardware:
https://github.com/jefftranter/6502/blo ... on.asm#L81

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 7:14 pm
by Atlantis
BigEd wrote:
Looks like you might only need to tweak the ACIAin and ACIAout routines to match your hardware:
I am just a little bit confused by some "mysterious" routines from min_mon.asm. Things like "LoadFile" or the entire content of the imported "CFFA1_API.s" file.

But I also see there is much simpler alternative - "osi_mon.asm". But there are still some things I am confused by. Like copying IRQ routine to the second page of RAM...

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 8:20 pm
by Chromatix
Perhaps look at the "original" version of min_mon.asm from the source.zip archive. That hasn't been specialised for a particular computer, and so is quite a lot simpler.

The code from RES_vec to LAB_dowarm inclusive is the initialisation code. It copies some indirection vectors and the default IRQ/NMI handlers into RAM (so they can be customised at runtime), then prints the welcome message and asks whether a cold/warm start is needed, waiting for the appropriate input character to choose. A warm start skips the rest of the RAM initialisation, so you can resume editing a crashed program without having to reload/retype it.

Some of the memory locations used here are defined in basic.asm, if you're curious as to where this stuff ends up. This includes a set of five indirection vectors pointing to the screen output, keyboard input, escape check, file load and file save routines. You can dummy out the last three so that they harmlessly do nothing.

Next are the ACIAout and ACIAin routines which serve as terminal I/O. These are what you need to edit first.

The supplied ACIAout has no flow control, so is likely to lose characters if used on a real serial line rather than a software emulator; insert something like:

Code: Select all

    BIT ACIA_STATUS
    BPL ACIAout
…to test bit 7 of the status register and busy-wait until it's set. Use BMI instead to wait for bit 7 clear, BVC for bit 6 set, BVS for bit 6 clear. If other bits needed to be tested, you'll need something slightly more sophisticated. Each UART has its own quirky register layout, but the ones designed for 6502s tend to use bit 7 and 6 for buffer status.

The supplied ACIAin interprets a zero read from the data buffer as "no character", and uses the Carry bit to report that to the caller (who will call again if he wants to wait). A more universal test is, again, to test the status register before attempting to read from the data buffer. Don't forget to clear the accumulator before returning in the "nothing read" case, for consistency.

Following that are the vector table and default IRQ/NMI routines that get copied to RAM by the init routine. After that is a definition of the 6502 hardware vectors.

Re: Easiest BASIC to port?

Posted: Tue Jun 19, 2018 10:33 pm
by Chromatix
Quote:
I assume banked RAM above 0x8000 will be still accessible with PEEK and POKE instructions?
Of course. It's just that EhBASIC doesn't know about the banking mechanism, so it can't safely factor the expanded memory into its own memory management. You are free to write your own programs that are aware of that memory, and even take advantage of the fact that EhBASIC will steer clear of it.

Re: Easiest BASIC to port?

Posted: Wed Jun 20, 2018 7:17 am
by Atlantis
Chromatix wrote:
Perhaps look at the "original" version of min_mon.asm from the source.zip archive. That hasn't been specialised for a particular computer, and so is quite a lot simpler.
Ok, now it looks a little bit clearer. But I still have some questions.

1) Should I also replace basic.asm with the file from source.zip?

2) What to do with this strangely looking code? ca65 does not compile that part...

Code: Select all

	*=	$FF80			; pretend this is in a 1/8K ROM
and

Code: Select all

*=	$FFFA
I assume the second one should be replaced by ".org #FFFA", because it directly precedes declaration of system vectors. But what about the first one? If I define beginning of my EPROM there (which appears to be reasonable thing to do) it will be defined twice. Because .ORG $C000 is already set in basic.asm...