I’ll have to look more into this FLEX Operating system but did find some games for it:
In transcribing some code from the 6800 to the 6502, this snippet had no obvious direct translation:
1DB7 B6 11CA [4] 04064 ldaa DumpAddr+1 ; Now compare upper nybble of low byte
1DBA 84 F0 [2] 04065 anda #$F0
1DBC F6 11BF [4] 04066 ldab DumpEndAddr+1
1DBF C4 F0 [2] 04067 andb #$F0
1DC1 11 [2] 04068 cba
1DC2 26 06 (1DCA) [4] 04069 bne DumpLineContinue
The 6502 has a single accumulator and there are no operations other than transfer allowed between it and the index registers. Rethinking the properties of numbers yielded this:
0AF0 AD 02BC [4] 01498 lda DumpAddr ; Now compare upper nybble of low byte
0AF3 4D 02B7 [4] 01499 eor DumpEndAddr
0AF6 29 F0 [2] 01500 and #$F0
0AF8 D0 08 (0B02) [2/4] 01501 bne DumpLineContinue
Exclusive oring a number to itself results in zero.
@bill looks like Adafruit is getting in the game with CircuitPython.
Seems to be built on top of micropython.
It has been a long and painful slog, but my emulator finally implements both the officially documented and undocumented behaviors of 6502 decimal mode.
It passes the test program at http://6502.org/tutorials/decimal_mode.html
The code is ugly and the adc and sbc instructions are substantially slower in decimal mode. Thankfully, they are not used often.
When I was talking transcribing 6800 code to the 6502, one of them is the TSC Space Voyage game. It is now running though there are some bugs to chase down…
For Happy Programmer's Day, I worked on transcribing the Space Voyage game to the 8080; it is about one-half done. Then I will do it for the AVR so that it will run on an Arduino.
Space Voyage for the 8080 is now feature complete and is playable.
Several days were needed to chase down a rather obscure bug with the short and long range scans reporting different numbers of stars in a quadrant.
. 00844 * Put Objects in Sector Map
. 00845
.05D3 CE 00DC [3] 00846 PUTINM ldx #SECMAP ; Point to map
.05D6 BD 106B [9] 00847 jsr RANDOM
.05D9 84 0F [2] 00848 anda #$F ; Gen random position
.05DB 97 85 [4] 00849 staa TSAVE1
.05DD BD 031A [9] 00850 jsr FIXXRG ; Find in map
.05E0 E6 00 [5] 00851 ldab 0,X
.05E2 BD 106B [9] 00852 jsr RANDOM ; Gen random X
.05E5 84 03 [2] 00853 anda #3
.05E7 97 81 [4] 00854 staa ASAVE
.05E9 27 05 (05F0)[4] 00855 beq PUTIN2
.05EB 56 [2] 00856 PUTIN1 rorb ; Find X position
.05EC 56 [2] 00857 rorb ; AAA
.05ED 4A [2] 00858 deca
.05EE 26 FB (05EB)[4] 00859 bne PUTIN1
.05F0 C5 03 [2] 00860 PUTIN2 bitb #3 ; Is position empty?
.05F2 26 DF (05D3)[4] 00861 bne PUTINM ; If not, repeat
.05F4 DA 7E [3] 00862 orab MASK
.05F6 96 81 [3] 00863 ldaa ASAVE
.05F8 27 05 (05FF)[4] 00864 beq PUTIN4
.05FA 59 [2] 00865 PUTIN3 rolb ; BBB ; Put object in map
.05FB 59 [2] 00866 rolb
.05FC 4A [2] 00867 deca
.05FD 26 FB (05FA)[4] 00868 bne PUTIN3
.05FF E7 00 [6] 00869 PUTIN4 stab 0,X ; Save it
The original code kept an important bit in the carry flag between points AAA and BBB. The or instruction of the 8080 clears the carry flag, losing that bit.
Also, the 8080 cannot set its condition codes according to the contents of a memory location without loading the byte into the accumulator. Even then, an additional operation is needed such as a compare, and or or which also wipes out the carry flag.
Transcribing to the AVR has been easier. It has 32 registers, half of which has the full power of an accumulator. The only major drawback so far has been the lack of a decimal adjust instruction which the original code uses in several places. So instead of a single instruction, a call to a subroutine is needed.
0003AC 00998 DAA:
0003AC E070 [1] 00999 ldi R23,0 ; Initially no correction factor
01000
0003AD F408=0003AF [1/2] 01001 brcc DAA_NotUCarry ; The add overflowed the upper nybble?
01002
0003AE 6670 [1] 01003 ori R23,$60
01004
0003AF 01005 DAA_NotUCarry:
0003AF F40D=0003B1 [1/2] 01006 brhc DAA_NotLCarry ; The add overflowed the lower nybble?
01007
0003B0 6076 [1] 01008 ori R23,$06
01009
0003B1 01010 DAA_NotLCarry:
0003B1 EA90 [1] 01011 ldi R25,$A0 ; Upper nybble needs correction if over 9
01012
0003B2 2F86 [1] 01013 mov R24,R22 ; Make a scratch copy
01014
0003B3 708F [1] 01015 andi R24,$0F
01016
0003B4 308A [1] 01017 cpi R24,$0A ; Check if lower nybble is out of range
0003B5 F010=0003B8 [1/2] 01018 brcs DAA_CheckUpper
01019
0003B6 6076 [1] 01020 ori R23,$06 ; Correct out of range lower nybble
01021
0003B7 E990 [1] 01022 ldi R25,$90 ; Upper nybble needs correction if over 8
01023 ; with carry from lower nybble
01024
0003B8 01025 DAA_CheckUpper:
0003B8 2F86 [1] 01026 mov R24,R22 ; Make a scratch copy
01027
0003B9 1789 [1] 01028 cp R24,R25 ; Check if upper nybble is out of range
0003BA F008=0003BC [1/2] 01029 brcs DAA_Add
01030
0003BB 6670 [1] 01031 ori R23,$60 ; Correct out of range upper nybble
01032
0003BC 01033 DAA_Add:
0003BC 0F67 [1] 01034 add R22,R23 ; Do decimal adjust
01035
0003BD 9508 [2] 01036 ret
I would love to see a port of this to the Commander X16
Is his goal to run C64 binaries unmodified?
The creator is local. Maybe David @dave can twist his arm to give a talk on it…
It is not compatible with the C64. See the FAQ
From what little I read, the tools generate .PRG files and he claims to support the KERNAL API. So if I build something for the C64, it should run if I do not assume anything about the hardware other than a 6502 processor and RAM in the usual place…
It is actually the 65c02 not the 6502. There are some differences in timing and new opcodes.
As painful as that may be sometimes, I am limiting myself to the NMOS 6502 instructions because those work on all 6502 family machines. I do nothing timing dependent.
I just reacquainted myself with one of the more aggravating limitations of the AVR instruction set. Many processors limit relative branches to between -128 and +127; the AVR limit is -64 and +63.
The AVR addresses program memory (16-bit) using word rather than byte addresses, so the range in bytes is the same as many others, but AVR instructions take up one or two words so that is half the number of instructions.
Brian posted a video SWTPC 6800/6809 Computer Review and History https://www.youtube.com/watch?v=SATjR-MWHDM
Interesting twist. As the AVR version started coming up, it gave drastically different results than the others. The game uses pseudo-random numbers so comparing the versions is difficult.
So I rigged the number generator to start with the same seed for now and discovered to my horror that all four versions differed!
I have never worked at software from this angle before, “port” the code and compare the results to this level of detail.
Some of you may have taken a comparative anatomy or comparative religion class before, but I know of no comparative processors class which goes into much detail. The closest was a microprocessors class which covered the Motorola 6800 for several weeks, then the Zilog Z80 for another several. The lab exercises involved writing several simple programs on both.
An enlightening exercise would be to get a program moderate in size and complexity for one and write equivalent code for another processor.
Hi…I am 44 and from Eastern Europe, so I experienced some of 8-bit computers in late 80’s as a teenager. I have never heard of 8-bit Apple nor S100 computers till few years ago when I started to discover US computers. And I like it much. I built most of the N8VEM boards, SCELBI 8H replica, Cosmac Elf 2000 and SBC6120+IOB6120+FP6120 by Spare Time Gizmos. I used to use CP/M on Z80 Sharp MZ-800 and play games on my friends’ ZX Spectrum, Atari 800XL or Commodore C64. The Sharp MZ-800 is still my favorite computer and there is quite a lot going on here around it. We created some interface replicas and there is Unicard emulating floppy, RAMdisk and Quick Disk interfaces, adding VGA and Ethernet to this old computer.
If you are into replicas, you might be interested in this site: https://obsolescence.wixsite.com/obsolescence
I have some of his kits and they are great.
One of the bugs in the 6502 version of Space Voyage was not in its code but a couple of the obscure forms of the ADC instructions in my emulator was inadvertently ignoring the carry flag…
That subroutine turns out to be flawed. A set carry flag when beginning the adjustment indicates that the preceding add overflowed the upper nybble. The carry flag needs to remain set after the adjustment even if adding the correction factor does not set the carry flag.
Edit: The updated code…
000A24 02159 DAA:
000A24 E070 [1] 02160 ldi R23,0 ; Initially no correction factor
02161
000A25 E0A0 [1] 02162 ldi R26,0 ; Presume carry flag is clear
02163
000A26 F410=000A29 [1/2] 02164 brcc DAA_NotUCarry ; The add overflowed the upper nybble?
02165
000A27 6670 [1] 02166 ori R23,$60 ; Correct upper nybble
02167
000A28 95A3 [1] 02168 inc R26 ; Remember original carry flag
02169
000A29 02170 DAA_NotUCarry:
000A29 F40D=000A2B [1/2] 02171 brhc DAA_NotLCarry ; The add overflowed the lower nybble?
02172
000A2A 6076 [1] 02173 ori R23,$06 ; Correct lower nybble
02174
000A2B 02175 DAA_NotLCarry:
000A2B EA90 [1] 02176 ldi R25,$A0 ; Upper nybble needs correction if over 9
02177
000A2C 2F86 [1] 02178 mov R24,R22 ; Make a scratch copy
02179
000A2D 708F [1] 02180 andi R24,$0F
02181
000A2E 308A [1] 02182 cpi R24,$0A ; Check if lower nybble is out of range
000A2F F010=000A32 [1/2] 02183 brcs DAA_CheckUpper
02184
000A30 6076 [1] 02185 ori R23,$06 ; Correct out of range lower nybble
02186
000A31 E990 [1] 02187 ldi R25,$90 ; Upper nybble needs correction if over 8
02188 ; with carry from lower nybble
02189
000A32 02190 DAA_CheckUpper:
000A32 2F86 [1] 02191 mov R24,R22 ; Make a scratch copy
02192
000A33 1789 [1] 02193 cp R24,R25 ; Check if upper nybble is out of range
000A34 F008=000A36 [1/2] 02194 brcs DAA_Add
02195
000A35 6670 [1] 02196 ori R23,$60 ; Correct out of range upper nybble
02197
000A36 02198 DAA_Add:
000A36 0F67 [1] 02199 add R22,R23 ; Do decimal adjust
02200
000A37 F008=000A39 [1/2] 02201 brcs DAA_Carry ; Done if carry set
02202
000A38 95A6 [1] 02203 lsr R26 ; Restore original carry flag
02204
000A39 02205 DAA_Carry:
000A39 9508 [2] 02206 ret