Orwell load and save working (mostly)!

October 31st, 2013

Today I managed to get my LOAD and SAVE routines working. Took me bloody ages and the issue was one that I’ve been bitten by before (and haven’t learned from obviously).

Save turns out to be trivial due to the way my computer works. I didn’t need to do anything. The way I am implementing these functions (for now) is to simple input and output serial data.

Since my video display works by receiving serial data anyway SAVE was already there. All I need to do is intercept the data as it’s sent.

I already have the 6551 ACIA on the machine to do this so all I had to do was add a level converter (my display adaptor uses TTL levels) then I could feed the same serial data into my PC and capture it in a terminal program.

I knew my desktop had no serial port on the rear panel of the motherboard itself  so I dug about in my box of junk and found a slot plate with a 9 pin socket and a ribbon cable on it. The ribbon didn’t connect the pins through correctly so I rewired the connection on the back of the 9 pin plug. With that all done I turned off my desktop to install the new port. Turns out I didn’t need to. I’d completely forgotten the machine already had one!

So all I had to do then was wire up a serial cable and install PuTTY.

So to SAVE all you do is hook up the terminal software and monitor the COM port. Everything echoed to the screen appears in the terminal window. So to save you can simple type LIST then copy and paste the output from the terminal window.

Typing SAVE doesn’t actually do anything.

LOAD was a bit trickier. What I did was hook into the main loop that reads characters. instead of reading characters from the keyboard I read them in from the serial port.

I implemented a circular buffer as described in Garth’s 6502 primer. I am currently no using any flow control mainly because I don’t quite have my head wrapped around RTS and CTS and DTR and DSR and so on. Everything is running happily at 19200 baud though without it (so far).

To make load work I added in a load_flag. When LOAD is called I set this flag to true and enable interrupts for the serial receiver. Serial data is received in the interupt handler and stored in the circular buffer.

The main  loop of BASIC starts from the RESTART routine. That calls a subroutine called INLIN. This routine looks at each character received and works out what to do with it. Most characters get stored in the input buffer. Some characters have special meanings (@ deletes the line, _ deletes a character, etc). A carriage return triggers the parsing and tokenizing of the line. INLIN calls a subroutine called GETLN which is what actually returns the character.

I added code in GETLN to check if the load flag was set. If it is I get characters out of the serial reciever circular buffer. If not I get characters from the keyboard as usual.

To load something you call LOAD from basic to go into loading mode. Then any characters sent via the serial connection will be read. In the terminal program I simply paste in the characters I want to send and it all gets sent via the serial  connection.

To stop loading I monitor the keyboard for a control-c key press. That is the only keyboard key press that has an effect in load mode otherwise hitting keys while loading might cause data corruption. Monitoring the keyboard only for a control-c should mean sending one via the serial link won’t cause any problems.

So to save simple list the program out then copy the text from the terminal window output.

To load type LOAD from Basic then paste the text of the program to load into the terminal window. The characters are all echoed to the screen so you can see it loading. When it is done hit control-c on the keyboard and you’re back to normal with your program loaded into memory ready to run.

I may need to work out the flow control for sending large amounts of text to it but we shall find that out soon.

The one issue I had getting all this working is the same one that got me before when doing my keyboard routines. Because the original code isn’t very procedural (it jumps about all over the show) sometimes it can be hard to tell what registers are in use.

In this case the circular buffer read routine used the X register to do indexing. Unfortunately the line reading code in INLINE also used the X register to keep track of how many characters have been entered. You have to make sure you preserve the X register when accessing the buffer so you don’t mess up the line reading bits of the code. Writing isn’t so bad since that happens inside the interrupt handler and that stores and restores the registers as a matter of course.

Once I finally worked that out it all started working. I don’t think it’s robust yet but it’s usable!

OK, I was just testing it again now and it isn’t robust. I get overrun errors. But it is ALMOST working.

My first test program I successfully saved and reloaded:

10 PRINT "NON MUSICAL NOISES"
20 FOR I = 40 TO 255
30 POKE 20484, I
35 POKE 24576, I
40 NEXT I
50 FOR I = 255 TO 40 STEP -1
60 POKE 20484, I
65 POKE 24576, I
70 NEXT I
80 GOTO 20

20484 is the low byte of the timer one latch hooked to the piezo. 24576 is the IO port connected to the LEDs.

 

Comments are closed.