Page 2 of 3

Re: Easiest BASIC to port?

Posted: Wed Jun 20, 2018 7:24 am
by Chromatix
The .ORG directive does not mean "this is the unique beginning of the binary object". It means "place the next instruction at a specific address". Padding is automatically inserted as required.

Re: Easiest BASIC to port?

Posted: Thu Jun 21, 2018 7:01 pm
by Atlantis
I added my own IO subroutines. Also I modified Makefile to generate hex file with objcopy.
It assembles without error, but there is something weird with my assembled code.
Previously I was using web based asm80.com tool to assemble my (much simpler) code and it was fine. While loading hex file to my programmer software, I had to manually set the shift by entering the beginning address (0x0C000). After that code was loaded at the beginning of, then there was several kB of empty space (0xFF) and at the very end RES, NMI and IRQ vectors were placed.

When I tried to do the same with assembled basic, nothing happened. I still had empty space, filled with "FF". So, I tried to load hex without setting shift. It worked. Kind of. The code was placed at the beginning of memory, but vectors were glued to it, without empty space between them and the code. So real vectors were just set to 0xFFFF...

Of course it doesn't work after burning on EPROM.

UPDATE: I also tried to manually transfer vectors to the end of memory. It partially worked. It asked me about cold or warm start, then displayed welcome message with bunch of random characters (but without amount of memory). I was able to write for a while, but on average every second character was skipped and hitting ENTER was causing reset. Then it stopped working at all.
There mus be something wrong...

My code, as well as assembled bin and hex files are in attached src.zip file.

Re: Easiest BASIC to port?

Posted: Thu Jun 21, 2018 10:46 pm
by /RESET
Hi!

I am using ACME (https://sourceforge.net/projects/acme-crossass/) assembler and threw your sources at it. After some minor adjustments (see sources attached), it assembled a binary.

I did run the command without the Makefile.

Code: Select all

acme -f plain -o b.bin min_mon.asm 
As ACME does not produce HEX files, you've to run a bin2hex tool for this ...

Code: Select all

bin2hex.py --offset=0xc000 b.bin b.hex
This is what the start of the hex file looks like ...

Code: Select all

:10C000004C28E8A004B9F9E09900038810F7A2FFD2
:10C0100086889AA94C85A1A21CBDFDE095BBCAD01B
:10C02000F8A212BD1AE19500CA10F8A90085DC85B6
:10C03000DF85B28567A90E8564A90385A0A26886FD
:10C04000652095C8A92DA0E120D6C82043C286C38B
:10C0500084C420C200D01FA000E611D008E612A5BB
:10C0600012C980F01DA9559111D111D0150A911155
:10C07000D111F0E5D00C20A9D9A5ACC998B0A22067
:10C08000FAD4A511A412C001909785858486858174
:10C090008482A000A2048479867A989179E6792036
...
... and the upper end looks like this ...

Code: Select all

...
:10FFD0000000000000000000000000000000000021
:10FFE0000000000000000000000000000000000011
:10FFF00000000000000000000000170328E80D03C7
:00000001FF
Regards!

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 5:37 am
by Atlantis
I've noticed one more thing. There is only one ".org" statement in file basic.asm.
It means the code was made to be run from from RAM and in my case there are variables in the EPROM address space!
I see there is a lot of constants defined at the end of this file. But I suppose there are also some variables intertwined with them, that should be stored in RAM. Could you help me sort it out?
Maybe somebody already made an EPROM friendly version of this code?

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 6:25 am
by Klaus2m5
There is no further .org statemant in EhBASIC because all RAM usage is declared as direct addresses!

Code: Select all

; zero page use ..

LAB_WARM          = $00       ; BASIC warm start entry point
Wrmjpl            = LAB_WARM+1; BASIC warm start vector jump low byte
Wrmjph            = LAB_WARM+2; BASIC warm start vector jump high byte

Usrjmp            = $0A       ; USR function JMP address
Usrjpl            = Usrjmp+1  ; USR function JMP vector low byte
Usrjph            = Usrjmp+2  ; USR function JMP vector high byte
Nullct            = $0D       ; nulls output after each line
TPos              = $0E       ; BASIC terminal position byte
TWidth            = $0F       ; BASIC terminal width byte
Iclim             = $10       ; input column limit
Itempl            = $11       ; temporary integer low byte
Itemph            = Itempl+1  ; temporary integer high byte
; and so on ...

; absolute addresses in RAM start here

ccflag            = $0200     ; BASIC CTRL-C flag, 00 = enabled, 01 = dis
ccbyte            = ccflag+1  ; BASIC CTRL-C byte
ccnull            = ccbyte+1  ; BASIC CTRL-C byte timeout

VEC_CC            = ccnull+1  ; ctrl c check vector

VEC_IN            = VEC_CC+2  ; input vector
VEC_OUT           = VEC_IN+2  ; output vector
VEC_LD            = VEC_OUT+2 ; load vector
VEC_SV            = VEC_LD+2  ; save vector

; Ibuffs can now be anywhere in RAM, ensure that the max length is < $80,
; the input buffer must not cross a page boundary and must not overlap with
; program RAM pages!

;Ibuffs            = IRQ_vec+$14
Ibuffs            = VEC_SV+$16
                              ; start of input buffer after IRQ/NMI code
Ibuffe            = Ibuffs+$47; end of input buffer

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

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 7:09 am
by Atlantis
Ok. Then any idea why ca65 and ld65 are not able to build this project correctly in my case?
I've tried to replace objcopy in my Makefile with bin2hex.py, introducing shift:

Code: Select all

./bin2hex.py --offset=0xc000 basic.bin basic.hex
Now my basic.hex file starts correctly:

Code: Select all

:10C00000A004B9F6E09900028810F7A2FF86889A8A
:10C01000A94C85A1A21CBDFAE095BBCAD0F8A2121A
:10C02000BD17E19500CA10F8A90085DC85DF85B24F
But unfortunately vectors are still just "glued" to the end of a code, without empty space between them:

Code: Select all

:10E8B000684241534943205B435D6F6C642F5B5753
:0DE8C0005D61726D203F00170225E80D021A
:00000001FF



There must be something wrong with linker, because min_mon.lst file lists vectors correctly:

Code: Select all

00E8C7  1               .org    $FFFA
00FFFA  1
00FFFA  1  17 02                .word   NMI_vec         ; NMI vector
00FFFC  1  25 E8                .word   RES_vec         ; RESET vector
00FFFE  1  0D 02                .word   IRQ_vec         ; IRQ vector
I suspect this is not the only problem, because as I said - I manually transferred vectors where they belong and code started, but was highly unstable and not even remotely usable...

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 8:43 am
by BigEd
Yes, it does look like two problems...

I see Jeff's Makefile feeds the basic.map file created by cc65 into ld65 - did you do that?

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 8:48 am
by Atlantis
BigEd wrote:
Yes, it does look like two problems...

I see Jeff's Makefile feeds the basic.map file created by cc65 into ld65 - did you do that?
Yes, I am using basically the same Makefile. With slight modification for generating hex file instead of mon file:

Code: Select all

# Adjust the run address to match the .org in the source code
all: basic.hex

basic.hex: basic.bin
	./bin2hex.py --offset=0xc000 basic.bin basic.hex

basic.bin: basic.o
	ld65 -t none -vm -m basic.map -o basic.bin basic.o

basic.o: basic.asm min_mon.asm
	ca65 -g -l min_mon.lst --feature labels_without_colons -o basic.o min_mon.asm

clean:
	$(RM) *.o *.lst *.map *.bin *.hex

distclean: clean
UPDATE

I see basic.map file is not generated by ca65 during creation of basic.o.
It only appears in the directory when ld65 is called to create basic.bin. So it is created by the linker.


UPDATE2

I also tried to follow /RESETs suggestion to use ACME assembler. Hex looks fine indeed.
I will try to burn EPROM when I get back home.

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 9:17 am
by BigEd
Ah, right. It's odd that Jeff's build process presumably works. Perhaps it has no gaps between the basic, the monitor, and the vectors??

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 5:17 pm
by Atlantis
It turns out that after compiling it wits ACME I still suffers the same issues as before.
BASIC asks me if I want to perform cold or warm boot. Then displays welcome message, without memory info but with bunch of random characters. On average every second typed character is ignored. And when I press enter, welcome message is printed again, so I it impossible to even test one line of BASIC code...
There must be some separate issue. Where to look? It doesn't look for hardware issue, does it?

UPDATE:
Is it possible that this kind of behavior is caused by using TAX and TXA inside TX routine, for saving accumulator while checking UART status register? Is X register used somewhere else? I will try use stack instead.

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 5:45 pm
by BigEd
What kind of diagnostic kit do you have, or could you get your hands on? A cheap 16-channel USB logic analyser would be a big help, for example.

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 5:46 pm
by Chromatix
I certainly wouldn't rule out hardware at this stage. The symptoms look consistent with the sort of hardware faults that usually show up on a homebrew machine. It's really common to have subtle timing or power faults, especially when you're trying to interface chips from two different bus families.

The clincher would be to drop your ROM image into a software emulator that matches your hardware configuration, and see how that behaves.

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 6:48 pm
by Dr Jefyll
Chromatix wrote:
I certainly wouldn't rule out hardware at this stage.
I agree. However, there's also this:
Atlantis wrote:
Is it possible that this kind of behavior is caused by using TAX and TXA inside TX routine, for saving accumulator while checking UART status register?
To me that also sounds possible.
Quote:
Is X register used somewhere else? I will try use stack instead.
Saving X to the stack is a little awkward if you are using the old NMOS 6502. A CMOS (65C02) will have PHX and PLX instructions available, but an NMOS 6502 will not.

Instead you could put this...

Code: Select all

PHA   ;save A first
TXA   ;then save
PHA   ;X
... at the beginning of your TX routine and also put this...

Code: Select all

PLA   ;restore...
TAX   ;X
PLA   ;then restore A last.
... at the end.

Edit: Oops - this won't work if A already has something you need in it.
-- Jeff

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 6:58 pm
by Chromatix
Looking at the photo on the first page, I see "MOS 6502AD" - so an old NMOS chip.

He's only using the X register to save A, so just use PHA instead of TAX, and PLA instead of TXA.

Re: Easiest BASIC to port?

Posted: Fri Jun 22, 2018 7:09 pm
by /RESET
Hi,

a quick look into the source code around line 7800 shows that the line endings are not consistent. Several $0A without preceding $0D. Also the "garbage" in the terminal seems pretty constant to be anything random.

Code: Select all

LAB_MSZM
	!raw	$0D,$0A,"Memory size ",$00

LAB_SMSG
	!raw	" Bytes free",$0D,$0A,$0A
	!raw	"Enhanced BASIC 2.22",$0A,$00
May it be that the terminal client software get's confused about the missing $0D characters causing that garbage to appear?

Couldn't hurt to fix those text constants an give it a try.

Regards.
Atlantis wrote:
It turns out that after compiling it wits ACME I still suffers the same issues as before.
BASIC asks me if I want to perform cold or warm boot. Then displays welcome message, without memory info but with bunch of random characters. On average every second typed character is ignored. And when I press enter, welcome message is printed again, so I it impossible to even test one line of BASIC code...
There must be some separate issue. Where to look? It doesn't look for hardware issue, does it?

UPDATE:
Is it possible that this kind of behavior is caused by using TAX and TXA inside TX routine, for saving accumulator while checking UART status register? Is X register used somewhere else? I will try use stack instead.