Monday, November 26, 2018

MC-10 ROM fixes before a release

The bug in the code that converts ASCII to floating point by changing divide by 10 to multiplying by 1/10 is now fixed.  This offered a significant speedup, so I'm happy that code will make it into the release.  That leaves one bug to fix before an official release.  That bug is likely to be in the math library, and I'm pretty sure I know what it is.  Once I get time it shouldn't take too long to fix.  The first release will definitely be a 16K ROM, but an 8K ROM with most of the code may follow if it will fit.  I am not going to fight with it to get that working though.

You can see the bug in my youtube video with the sort comparison.  The gap values are different between the original and new ROM.  That is no longer the case.  FWIW, the the constant for 1/10 was wrong and it was the first thing I checked, so... easy fix.


Thursday, November 22, 2018

Breaking the chains... of the 8K barrier

Only one day after deciding to finally ditch the MC-10 8K ROM limitation, a couple small changes have pushed the new ROM to almost 10% faster than the original, and the actual executable code is smaller.  I simply dumped the valid token check in the main loop and extended the command dispatch table.  Anything invalid jumps strait to SN ERROR, and valid tokens are executed quicker.  The table wastes some space, but there will be less wasted space as I add Extended BASIC commands to the ROM.

This does not include the code that uses multiplication to convert ASCII numbers to binary instead of division, and the code that stores the current line pointer instead of the current line number.

Solitaire Solver, original ROM vs new ROM 

Again... with feeling!

For your viewing pleasure

Wednesday, November 21, 2018

Latest MC-10 ROM snapshot

The video is still uploading, but here is a snapshot of the difference in speed between the original MC-10 ROM and new one on the "Fedora" 3D Plot.  The SIN(), COS(), TAN(), and string compare are faster.
I'd make a video of a large sort to show off the string compare, but it's not as dramatic and would take several minutes to watch.

Friday, November 16, 2018

String variable test/sort code (BASIC)

Here is a little test program I threw together to benchmark the 16 bit string compare code I'm preparing for a future ROM version.  A little bonus here is a sort implementation you may not have seen before.

Back in the 90s I was working on a project I inherited from someone else.  It involved nightly data dumps from a production system to a local server that made the data accessible to customers via modem, using custom software.  The process was rather labor intensive.  The operator had to run the data extraction, ftp the data to a PC, which was then imported by a custom VB application that required multiple starts, executing other program, then continuing, etc...  It was impossible to automate the way it was.
Upon investigation, the original programmer did not know how to implement a sort, so he was using an external utility.   (he also didn't seem to know how to take a shower... but that's another topic)
After a quick search on Yahoo, no VB sorts turned up (I think the search engine was undergoing maintenance), so I threw in a bubble sort and went home.  Some 12 hours later, the sort was still going so I killed it, wrote a more optimal version, and on the first try it took about 18 minutes to sort the 80,000+ records, and it didn't require human intervention so it could be launched automatically. 
Anyway, a more polished version of that sort is below.  This has some optimizations that weren't in the original as it's aimed at the Microsoft BASIC interpreter.

The sort is, at the very least, a really improved version of the bubble sort.  It functions a bit like a comb or shell sort, so I'm not sure what you'd call it.  It's easy to implement, pretty fast, and it's fairly small.  Taking a hint from the comb sort, dividing the gap by two may not be the most efficient, but it works pretty well for something I came up with off the top of my head in my 20s.

The data comes from a list of the 1000 most common surnames, and it is truncated here for space.  The data includes a few other numbers with it that I didn't waste time removing.  With all the additional data, only 894 names fit in memory, but that provides a really good workout for the interpreter and sort.  Sorting takes over 10 minutes on a regular MC-10, but I'm hoping the new string comparison cuts that by at least 20%, which is about what you can expect from unrolling a loop once.



0 I=0:N=1000:C=0:D=0:E=0:NW=0

'initialize the index array, and read in the names.  Skip the other data.
'scans through the data to determine the array sizes before dimensioning the arrays.
'The most heavily use variables are initialized on the first like to insure they are
' at the start of the variable table
'
10 I=0:J=0:G=0:N=0:Q=0
15 PRINT"SCANNING FOR END OF DATA"
20 READ K$,C,D,E:IF K$<>"" THEN N=N+1:GOTO 20
30 RESTORE
40 DIM A$(N),B(N)
45 PRINT"INITIALIZING ARRAYS"
50 FORI=1TON:READ A$(I),C,D,E:B(I)=I:NEXT
60 PRINT:PRINT N" MOST POPULAR SIR NAMES FROM MOST TO LEAST POPULAR"
70 GOSUB 2000
80 PRINT:PRINT "SORTING"N"NAMES":GOSUB 10000
90 PRINT:PRINT N" MOST POPULAR SIR NAME IN ALPHABETICAL ORDER"
95 GOSUB 2000
96 END


'print out the names based on the array index
2000 FOR I=1 TO N:PRINT A$(B(I))" ";:NEXT:RETURN



'optimized bubble(?) sort.
'Moves data as far as possible with each Middle loop
'Skips data that doesn't need sorted with each new pass on inner loop.
'P = what we divide the array size by to get the gap
'G = the gap
'using nested for loops avoids having to perform a line search that would
'happen with GOTO.  The address is simply pulled off of the stack.
'Using STEP 0 keeps FOR NEXT from changing the variable and the endless loop
'exits once the exit condition is achieved

10000 P=1:FORG=2TO1STEP0:P=P*2:G=INT(N/P):NW=N-G:PRINTG;
10010 FORQ=1TO0STEP0:Q=0:FORI=1TONW
10020 IFA$(B(I))>A$(B(I+G))THENT=B(I):B(I)=B(I+G):B(I+G)=T:Q=I
10030 NEXT:IFQ>0THENNW=Q
10040 NEXT:NEXT:RETURN



'1000 MOST POPULAR SIR NAMES FROM MOST TO LEAST POPULAR

100 DATA SMITH,2501922,1.006,1,JOHNSON,2014470,.81,2,WILLIAMS,1738413,.699,3
101 DATA JONES,1544427,.621,4,BROWN,1544427,.621,5,DAVIS,1193760,.48,6
...


1000 DATA "",0,0,0 :REM END OF DATA MARKER


Warning about using TASM for 6803 development

TASM (the Telmark Assembler, not the other TASM assembler) does not always warn you if if the range of an 8 bit relative branch is exceeded.  You can only detect the wrong code was generated by looking at the .LST file and checking the actual offsets by hand, or once you run the program in the VMC10 emulator, and list file.  Then the emulator will halt of the bad code and tell you in the LST window that the range had been exceeded.  This happened to me on a BRA instruction this morning and made me very unhappy.  

Tuesday, November 13, 2018

SIN() in please! (MC-10 ROM changes)

The new MC-10 ROM has been sitting untouched and incomplete for far too long, so I worked on it a few hours.

A small list of some of the changes that were made.
  1. Miscellaneous fixes such as only adding a colon in front of the ELSE statement during tokenization if the character before it isn't already a colon.  It would add one no matter what before.  The colon is required for the ELSE to work.
  2. A redundant floating point register load was eliminated.
  3. The variable that saves the current line number was changed to the current line pointer.  This was the easiest way to implement the feature, and it only took about an hour.  All that needed changed was the code that sets or reads the variable, and code that needs the current line number.  This will only be faster once I store both, but it was the quickest way to get it working since it didn't require significant stack code changes.  The code that prints the line number on BREAK, now prints the address of the line, but the fix shouldn't be difficult once I have time to work on it.  A side benefit of this change was the elimination of some unnecessary code and it's close to working in 8K again.
  4. The most significant change, is the SIN() function now uses multiply to perform division by 2*Pi using the reciprocal (invert and multiply).  So it multiplies by 1/(2*Pi).  The code works well enough to perform some initial tests, which show this offers a significant speedup.  This also speeds up COS() since that is calculated with SIN(n+(Pi/2)), and TAN() which is calculated with  SIN(n) / COS(n).  The code does not work for all cases though, so there's some work to be done yet, but it works well enough I could make the video below.

This is the previous video showing the speed of the new ROM vs the factory ROM:


This is the ROM with the SIN() code change: