6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed Nov 13, 2024 7:04 am

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Thu Oct 03, 2013 11:16 pm 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
Hi there, the next stage of my little Orwell computer is getting BASIC running on it. After reading the Pagetable blog post on it I decided to go with Microsoft BASIC. It is also in keeping with my whole 80s computer theme.

In addition to the code there I found Grant Searle's version of it he used on his simple 6502 machine. His code is all the relevant bits of the OSI version of BASIC in one file with macros and unnecessary ifdefs removed. I took this code as my start point.

I added in my own IO routines and after a few minor bugs got it working. I can get past the Cold/Warm restart page but then it all goes wonky at the Memory Size prompt. The symptom is odd behaviour in the key values I get returned. For example I can return an 'a' but 'A' comes through as garbage. No matter what I enter here I get a syntax error and the prompt repeats. I think somehow something is getting corrupted. In order to understand what I have been trying to understand the code but something is confusing me.

I believe things are going wrong in the COLD_START code.
Code:
        lda     #<QT_MEMORY_SIZE
        ldy     #>QT_MEMORY_SIZE
        jsr     STROUT
        jsr     NXIN
        stx     TXTPTR
        sty     TXTPTR+1
        JSR     CHRGET
        cmp     #$41
        beq     PR_WRITTEN_BY
        tay
        bne     L40EE
        lda     #<RAMSTART2
        ldy     #>RAMSTART2
        sta     LINNUM
        sty     LINNUM+1
        ldy     #$00
L40D7:
        inc     LINNUM
        bne     L40DD
        inc     LINNUM+1
L40DD:
        lda     #$92 ; 10010010 / 00100100
        sta     (LINNUM),y
        cmp     (LINNUM),y
        bne     L40FA
        asl     a
        sta     (LINNUM),y
        cmp     (LINNUM),y
        beq     L40D7; old: faster
        bne     L40FA
L40EE:
        jsr     CHRGOT
        jsr     LINGET
        tay
        beq     L40FA
        jmp     SYNERR
L40FA:
        lda     LINNUM
        ldy     LINNUM+1
        sta     MEMSIZ
        sty     MEMSIZ+1
        sta     FRETOP
        sty     FRETOP+1


That cmp #$41 is actually a kind of easter egg. An 'A' typed here is supposed to show who wrote the code. But I get garbage not an 'A' at this point.

I have been trying to understand how the jsr CHRGET works. But I don't see how CHRGET is a subroutine? In code it is declared like this:

Code:
CHRGET:
TXTPTR = <(GENERIC_TXTPTR-GENERIC_CHRGET + CHRGET)
CHRGOT = <(GENERIC_CHRGOT-GENERIC_CHRGET + CHRGET)
CHRGOT2 = <(GENERIC_CHRGOT2-GENERIC_CHRGET + CHRGET)
RNDSEED = <(GENERIC_RNDSEED-GENERIC_CHRGET + CHRGET)


That's actually in the zeropage (at $BC).

Later in the actual code there is this:
Code:
GENERIC_CHRGET:
        inc     TXTPTR
        bne     GENERIC_CHRGOT
        inc     TXTPTR+1
GENERIC_CHRGOT:
GENERIC_TXTPTR = GENERIC_CHRGOT + 1
        lda     $EA60
        cmp     #$3A
        bcs     L4058
GENERIC_CHRGOT2:
        cmp     #$20
        beq     GENERIC_CHRGET
        sec
        sbc     #$30
        sec
        sbc     #$D0
L4058:
        rts
GENERIC_RNDSEED:
; random number seed
        .byte   $80,$4F,$C7,$52
GENERIC_CHRGET_END:


I don't understand how this works? How doe we get into that code? I guess TXTPTR is a buffer for the value entered from the keyboard but how does all this get called exactly?

All my code is too big to post and I don't have it online yet but Grant's version is here.

My next thing to try is take all my code out and just hard code things just so I can see if I can get past the memory size/check stage with the standard OSI code. I don't know if any of the above is part of my problem but it would be nice to understand how it works!

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 04, 2013 2:49 am 
Offline

Joined: Sun Jul 28, 2013 12:59 am
Posts: 235
What's going on is actually kind of cute... Or perhaps cutesy. GENERIC_CHRGET through GENERIC_CHRGET_END is copied to the zpage at some point during startup (the code wouldn't work, otherwise). The definitions for CHRGET, TXTPTR, CHRGOT, CHRGOT2, and RNDSEED are all defined as zero-page locations, all relative to CHRGET (the + CHRGET term at the end of most of the definitions) based on the displacement of the GENERIC_ version of the symbol relative to GENERIC_CHRGET. This allows for a default value to be seeded for the random number seed, and the CHRGET routine itself gets to use LDA absolute to read characters, with the absolute address in the instruction being stored at TXTPTR, which is a speed optimization.

Now that I've seen this trick I'm going to have to think carefully about if I can (or want) to use it in my own software.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 04, 2013 4:30 am 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
nyef wrote:
What's going on is actually kind of cute... Or perhaps cutesy. GENERIC_CHRGET through GENERIC_CHRGET_END is copied to the zpage at some point during startup (the code wouldn't work, otherwise). The definitions for CHRGET, TXTPTR, CHRGOT, CHRGOT2, and RNDSEED are all defined as zero-page locations, all relative to CHRGET (the + CHRGET term at the end of most of the definitions) based on the displacement of the GENERIC_ version of the symbol relative to GENERIC_CHRGET. This allows for a default value to be seeded for the random number seed, and the CHRGET routine itself gets to use LDA absolute to read characters, with the absolute address in the instruction being stored at TXTPTR, which is a speed optimization.

Now that I've seen this trick I'm going to have to think carefully about if I can (or want) to use it in my own software.


Ah, the moving is done in the code just above that I posted above. In the cold start routine which makes perfect sense of course. Has to be done once!

Code:
COLD_START:
        ldx     #$FF
        stx     CURLIN+1
        txs
        lda     #<COLD_START
        ldy     #>COLD_START
        sta     GORESTART+1
        sty     GORESTART+2
        sta     GOSTROUT+1
        sty     GOSTROUT+2
        lda     #<AYINT
        ldy     #>AYINT
        sta     GOAYINT
        sty     GOAYINT+1
        lda     #<GIVAYF
        ldy     #>GIVAYF
        sta     GOGIVEAYF
        sty     GOGIVEAYF+1
        lda     #$4C
        sta     GORESTART
        sta     GOSTROUT
        sta     JMPADRS
        sta     USR
        lda     #<IQERR
        ldy     #>IQERR
        sta     USR+1
        sty     USR+2
        lda     #WIDTH
        sta     Z17
        lda     #WIDTH2
        sta     Z18
        ldx     #GENERIC_CHRGET_END-GENERIC_CHRGET
L4098:
        lda     GENERIC_CHRGET-1,x
        sta     CHRGET-1,x
        dex
        bne     L4098
        txa
        sta     SHIFTSIGNEXT
        sta     LASTPT+1
        sta     Z15
        sta     POSX
        pha
        sta     Z14
        lda     #$03
        sta     DSCLEN
        lda     #$2C
        sta     LINNUM+1
        jsr     CRDO
        ldx     #TEMPST
        stx     TEMPPT
        lda     #<QT_MEMORY_SIZE
        ldy     #>QT_MEMORY_SIZE


Makes more sense now (although I still don't 100% follow). I still have issues with my code. I did try moving my variables to another part of memory well away from the ZP stuff but still the same issue. I did verify my actual key scan is returning the correct key though. Will keep digging!

Thanks!

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 04, 2013 8:51 am 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
Well, I finally worked out my bug. The line reading code uses X to keep track of where it is up to on the input buffer. There is a check to make sure that X hasn't fallen off the end of the line in which case the last character isn't added to the buffer. Unfortunately my keyboard scanning code also uses X. I use it as an offset into my key matrix look up table. The matrix isn't in any sensible order from a character point of view.

What was happening was certain characters were causing me to use an X offset into my lookup table that changed X enough that the character wasn't being stored in the line buffer. That's why some characters worked fine but not others with no obvious pattern.

Fixed by preserving X before I use it of course then restoring it later.

And that worked! I can now boot up and get into BASIC. It runs the memory check and so on. I can enter lines but so far can't run anything. It just says 'OK'. Typing 'LIST' returns nothing but 'OK'. Next issue to work out.

The other thing I need to do is add in support for my alpha lock key as using shift to type everything in upper case is annoying!

Image

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 04, 2013 1:36 pm 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 410
Location: Minnesota
Or you could change the keyboard lookup table.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 04, 2013 7:27 pm 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
Well, the lookup table directly maps to how the matrix is laid out to make decoding it in software easy. I scan the rows and read the columns in one byte at a time so it makes the lookup easy. I can just say something like key position = (row * 8) + column to find the key. Now I save X before mucking with it it's all fine. It just took me a bit of digging in the OSI code to realise they were using it too. Debugging like this is a great way to learn what their code is doing of course.

I now have alpha working and commands are working (I can poke into my debug buffer and light up LEDs and "? FRE(0)" returns correctly) but remembering of line numbers isn't working for some reason. It's not storing my lines of code. No errors though.

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 27, 2013 10:00 am 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
Well, finally I can report success! I now (after weeks of debugging) have Microsoft BASIC running on my Orwell machine.

Many times I was going to post here for help but in the end I kept plugging away. I wrote routines to dump out what was in memory. I compared my code to the original OSI code, original Applesoft code, whatever other versions of the code I could find. I even downloaded an OSI machine emulator so I could see what it's memory looked like. I have a much better (but not complete) understanding of how OSI BASIC works now.

In the end my bug was simple. The code to check for control-c seems broken. It calls into ISCNTC routine then no matter what it just runs into the stop code. So the effect on any LIST or RUN command was as if control-C was hit right away. Interestingly the code on PageTable seems to note this in the comments in the osi_iscntc.s file (wish I'd seen that weeks ago!). I started my code from the version Grant Searle has on his site. His code seems to just run into stop too. I changed mine so if control-c isn't hit it just returns and keeps going. Maybe I am missing something subtle here but it seems to be working for me now.

A few things that really helped were http://www.osiweb.org/manuals/basicnotes.pdf and http://www.osiweb.org/misc/OSI%20ROM%20Basic%20Datasheet%20from%20Aardvark%201979.pdf. Those notes really explain how some things are done (like the line parsing and program storing in memory).

Still a lot to do. I want to keep studying the code and, more importantly, comment it. I'll never remember how it works otherwise. I need to come up with some load/save routines. And I need to keep working on my Eagle layout for a real circuit board for the thing.

But I can now start reviewing all my 80s Usborne books and actually use the machine to enter in all the program listings now.

This has been bugging me for so long now it's really a relief to finally get it working. I've literally been losing sleep over it.

Here are some pictures:

Image

Image

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 27, 2013 10:47 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Very nice! Make a note in your copy book.


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 27, 2013 7:23 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8483
Location: Midwestern USA
Simon wrote:
Well, finally I can report success!...Here are some pictures:

Image

Ah, I see what was causing your problem. Not enough red wire on the breadboard! :lol:

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Oct 27, 2013 9:11 pm 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
BigDumbDinosaur wrote:
Ah, I see what was causing your problem. Not enough red wire on the breadboard! :lol:

Ha! I could fix that! But now I need to sort out a real PCB for it I think. And I might add a power on reset circuit.

I spent ages last night after I got it running just writing small BASIC programs poking memory to make the piezo make silly noises. I am using a VIA to do my keyboard matrix scanning and since PB7 was unused for that I figured I might as well use it for something!

Is it enough to put 0 into the timer one latch to stop it or do you actually need to disable it?

Funny thing is I remember the first thing I did with my Vic 20 (first machine way back when) was the little programs in the manual to make noises.

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 28, 2013 8:25 pm 
Offline

Joined: Mon Mar 25, 2013 9:26 pm
Posts: 183
Location: Germany
Cool. Ehat kind of keyboard you are using? It looks really small but with "normal" sized keys. I have recycled an old C64 keyboard, but on yours there are the mostly needed characters. The C64 keyboard has only a lot of specific graphic symbols that do not need.

Mario.

_________________
How should I know what I think, until I hear what I've said.


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 28, 2013 8:55 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Looks like http://www.oldcomputermuseum.com/ti_994a.html


Top
 Profile  
Reply with quote  
PostPosted: Mon Oct 28, 2013 10:49 pm 
Offline

Joined: Mon Apr 16, 2007 6:04 am
Posts: 155
Location: Auckland, New Zealand
BigEd wrote:

Exactly right! I got it off eBay a while ago. Apparently RadioShack sold them years ago as a surplus part. Mine came with the original packaging! It's a very nice little keyboard actually. Proper keys! Lovely to type on but compact.

Simon

_________________
My 6502 related blog: http://www.asciimation.co.nz/bb/category/6502-computer


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: