Sweet 16 for MAC/65 Atari 8bit#

General Information

Author: Steve "Woz" Wozniak
Assembler: Mac/65
Published: 1977

see also Original Sweet 16

This is a port of the Sweet 16 interpreter to the 8bit ATARI.

Diffs#

  • The ATARI uses the zero page registers at $E0-$FF instead of $00-$1F
  • the "save" and "restore" routines are not in ROM, but in the source

Mac/65 Source #

1010 ***************************
1020 *								 *
1030 * APPLE II PSEUDO MACHINE *
1040 *		  INTERPRETER		*
1050 *								 *
1060 * COPYRIGHT (C) 1977		*
1070 * APPLE COMPUTER INC.	  *
1080 *								 *
1090 * STEVE WOZNIAK			  *
1100 *								 *
1110 ***************************
1120 * TITLE: SWEET 16 INTERPRETER
1130 ;
1131	  *=  $7889
1132 ;
1140 R0L =	$E0
1150 R0H =	$E1
1160 R14H =  $FD
1170 R15L =  $FE
1180 R15H =  $FF
1190 ;
1220 ;
1230 ; PRESERVE 6502 REG CONTENT
1240 ;
1250 SW16 JSR SAVE
1260 ;
1270 ; INIT SWEET16 PC
1280 ; FROM RETURN ADDRESS
1290 ;
1300 SW16A PLA 
1310	  STA R15L
1320	  PLA 
1330	  STA R15H
1340 ;
1350 ; INTERPRET AND EXECUTE
1360 ; ONE SWEET16 INSTRUCTION
1370 ;
1380 SW16B JSR SW16C
1390	  JMP SW16B
1400 ;
1410 ; INCREMENT SWEET16 PC
1420 ; FOR FETCH
1430 ;
1440 SW16C INC R15L
1450	  BNE SW16D
1460	  INC R15H
1470 ;
1480 ; COMMON HIG BZTE FOR ALL
1490 ; ROUTINES, PUSH ON STACK FOR
1500 ; RTS
1510 SW16D LDA  # >SET
1520	  PHA 
1530 ;
1540 ; FETCH INSTRUCTION
1550 ;
1560	  LDY #$00
1570	  LDA (R15L),Y
1580 ;
1590 ; MASK REGISTER SPECIFICATION
1600 ;
1610	  AND #$0F
1620 ;
1630 ; DOUBLE FOR TWO BYTE REGISTERS
1640 ;
1650	  ASL A
1660 ;
1670 ; TO X REGISTER FOR INDEXING
1680 ;
1690	  TAX 
1700	  LSR A
1710 ;
1720 ; NOW HAVE OPCODE
1730 ;
1740	  EOR (R15L),Y
1750 ;
1760 ; IF ZERO THEN NO REG OPCODE
1770 ;
1780	  BEQ TOBR
1790 ;
1800 ; INDICATE PRIOR RESULT REG
1810 ;
1820	  STX R14H
1830 ;
1840 ; OPCODE * 2 TO LSB'S
1850 ;
1860	  LSR A
1870	  LSR A
1880	  LSR A
1890 ;
1900 ; TO Y REGISTER FOR INDEXING
1910 ;
1920	  TAY 
1930 ;
1940 ; LOW ORDER ADR BYTE ON STACK
1950 ;
1960	  LDA OPTBL-2,Y
1970	  PHA 
1980 ;
1990 ; GOTO REG-OPCODE ROUTINE
2000 ;
2010	  RTS 
2020 ;
2030 ; INCREMENT PC
2040 ;
2050 TOBR
2051	  INC R15L
2060	  BNE TOBR2
2070	  INC R15H
2080 ;
2090 ; LOW ORDER ADR BYTE ONTO
2100 ; STACK FOR NON-REG OPCODE
2110 ;
2120 TOBR2 LDA BRTBL,X
2130	  PHA 
2140 ;
2150 ; PRIOR RESULT REG INDEX
2160 ;
2170	  LDA R14H
2180 ;
2190 ; PREPARE CARRY FOR BC. BNC.
2200 ;
2210	  LSR A
2220 ;
2230 ; GOTO NON-REG OPCODE ROUTINE
2240 ;
2250	  RTS 
2260 ;
2270 ; RETURN TO 6502 MODE ROUTINE
2280 ;
2290 ; POP RETURN ADDRESS
2300 ;
2310 RTNZ PLA 
2320	  PLA 
2330 ;
2340 ; RESTORE 6502 REG CONTENT
2350 ;
2360	  JSR RESTORE
2370 ;
2380 ; RETURN TO 6502 CODE VIA PC
2390 ;
2400	  JMP (R15L)
2410 ;
2420 ; SET REGISTER ROUTINE
2430 ;
2440 ; GET HIGH BYTE OF CONSTANT
2450 ;
2460 SETZ LDA (R15L),Y
2470	  STA R0H,X
2480	  DEY 
2490 ;
2500 ; GET LOW BYTE OF CONSTANT
2510 ;
2520	  LDA (R15L),Y
2530	  STA R0L,X
2540 ;
2550 ; Y REG CONTAINS 1
2560 ;
2570	  TYA 
2580 ;
2590 ; ADD 2 TO PC
2600 ;
2610	  SEC 
2620	  ADC R15L
2630	  STA R15L
2640	  BCC SET2
2650	  INC R15H
2660 SET2 RTS 
2670 ;
2680 ; OPCODE TABLE
2690 ;
2700 OPTBL .BYTE  <SET-1 ; 1X
2710 BRTBL .BYTE  <RTN-1 ; 0
2720	  .BYTE  <LD-1 ; 2X
2730	  .BYTE  <BR-1 ; 1
2740	  .BYTE  <ST-1 ; 3X
2750	  .BYTE  <BNC-1 ; 2
2760	  .BYTE  <LDAT-1 ; 4X
2770	  .BYTE  <BC-1 ; 3
2780	  .BYTE  <STAT-1 ; 5X
2790	  .BYTE  <BP-1 ; 4
2800	  .BYTE  <LDDAT-1 ; 6X
2810	  .BYTE  <BM-1 ; 5
2820	  .BYTE  <STDAT-1 ; 7X
2830	  .BYTE  <BZ-1 ; 6
2840	  .BYTE  <POP-1 ; 8X
2850	  .BYTE  <BNZ-1 ; 7
2860	  .BYTE  <STPAT-1 ; 9X
2870	  .BYTE  <BM1-1 ; 8
2880	  .BYTE  <ADD-1 ; AX
2890	  .BYTE  <BNM1-1 ; 9
2900	  .BYTE  <SUB-1 ; BX
2910	  .BYTE  <BK-1 ; A
2920	  .BYTE  <POPD-1 ; CX
2930	  .BYTE  <RS-1 ; B
2940	  .BYTE  <CPR-1 ; DX
2950	  .BYTE  <BS-1 ; C
2960	  .BYTE  <INR-1 ; EX
2970	  .BYTE  <NUL-1 ; D
2980	  .BYTE  <DCR-1 ; FX
2990	  .BYTE  <NUL-1 ; E
3000	  .BYTE  <NUL-1 ; UNUSED
3010	  .BYTE  <NUL-1 ; F
3020 ;
3030 ; THE FOLLOWING CODE MUST
3040 ; BE CONTAINED IN A SINGLE PAGE
3050 ;
3060 SET
3061	  JMP SETZ	 ; ALWAYS
3070 LD
3071	  LDA R0L,X
3080 BK  =	LD+1
3090	  STA R0L
3100 ;
3110 ; MOV RX TO R0
3120 ;
3130	  LDA R0H,X
3140	  STA R0H
3150	  RTS 
3160 ;
3170 ST  LDA R0L
3180 ;
3190 ; MOV R0 TO RX
3200 ;
3210	  STA R0L,X
3220	  LDA R0H
3230	  STA R0H,X
3240	  RTS 
3250 ;
3260 ; STORE BYTE INDEIRECT
3270 ;
3280 STAT LDA R0L
3290 STAT2 STA (R0L,X)
3300	  LDY #$00
3310 ;
3320 ; INDICATE R0 IS RESULT NEG
3330 ;
3340 STAT3 STY R14H
3350 INR INC R0L,X
3360	  BNE INR2	 ; INC RX
3370	  INC R0H,X
3380 INR2 RTS 
3390 ;
3400 ; LOAD INDIRECT (RX) TO R0
3410 ;
3420 LDAT LDA (R0L,X)
3430	  STA R0L
3440 ;
3450 ; ZERO HIGH ORDER R0 BYTE
3460 ;
3470	  LDY #$00
3480	  STY R0H
3490	  BEQ STAT3	; ALWAYS
3500 ;
3510 ; HIGH ORDER BYTE = 0
3520 ;
3530 POP LDY #$00
3540	  BEQ POP2	 ; ALWAYS
3550 POPD JSR DCR	 ; DECR RX
3560 ;
3570 ; POP HIGH ORDER BYTE @RX
3580 ; AND SAV IN Y REG
3590 ;
3600	  LDA (R0L,X)
3610	  TAY 
3620 POP2 JSR DCR	 ; DECR RX
3630 ;
3640 ; LOW ORDER BYTE TO R0
3650 ;
3660	  LDA (R0L,X)
3670	  STA R0L
3680	  STY R0H
3690 ;
3700 ; INDICATE R0 AS LAST RES. REG
3710 ;
3720 POP3 LDY #$00
3730	  STY R14H
3740	  RTS 
3750 ;
3760 ; LOW ORDER BYTE TO R0, INC RX
3770 ;
3780 LDDAT JSR LDAT
3790 ;
3800 ; HIGH ORDER BYTE TO R0
3810	  LDA (R0L,X)
3820	  STA R0H
3830	  JMP INR	  ; INC RX
3840 ;
3850 ; STORE INDIRECT LOW ORDER
3860 ; BYTE AND INC RX THEN
3870 ; STORE HIGH  ORDER BYTE,
3880 ; INC RX AND RETURN
3890 ;
3900 STDAT JSR LDAT
3910	  LDA R0H
3920	  STA (R0L,X)
3930	  JMP INR
3940 STPAT JSR DCR	; DEC RX
3950	  LDA R0L
3960 ;
3970 ; STORE R0 LOW BYTE @RX
3980 ;
3990	  STA (R0L,X)
4000 ;
4010 ; INDICATE R0 AS LAST RES REG
4020 ;
4030	  JMP POP3
4040 ;
4050 DCR LDA R0L,X
4060	  BNE DCR2	 ; DEC RX
4070	  DEC R0H,X
4080 DCR2 DEC R0L,X
4090	  RTS 
4100 ;
4110 ; RESULT TO R0
4120 ;
4130 SUB LDY #$00
4140 ;
4150 ; NOTE Y REG = 13 * 2 FOR CPR
4160 ;
4170 CPR SEC 
4180	  LDA R0L
4190	  SBC R0L,X
4200	  STA R0L,Y	; RY=R0-RX
4210	  LDA R0H
4220	  SBC R0H,X
4230 SUB2 STA R0H,Y
4240 ;
4250 ; LAST RESULT REG * 2
4260 ;
4270	  TYA
4280 ;
4290 ; CARRY TO LSB
4300 ;
4310	  ADC #$00
4320	  STA R14H
4330	  RTS 
4340 ;
4350 ADD LDA R0L
4360	  ADC R0L,X
4370	  STA R0L	  ; R0=RX+R0
4380	  LDA R0H
4390	  ADC R0H,X
4400 ;
4410 ; R0 FOR RESULT
4420 ;
4430	  LDY #$00
4440 ; FINISH ADD
4450	  BEQ SUB2
4460 ;
4470 ; NOTE X REG IS 12 * 2 !
4480 ;
4490 BS  LDA R15L
4500 ;
4510 ; PUSH LOW PC BYTE VIA R12
4520 ;
4530	  JSR STAT2
4540	  LDA R15H
4550 ;
4560 ; PUSH HIGH PC BYTE
4570 ;
4580	  JSR STAT2
4590 BR  CLC 
4600 BNC BCS BNC2	 ; NO CARRY TEST
4610 ;
4620 ; DISPLACEMENT BYTE
4630 ;
4640 BR1 LDA (R15L),Y
4650	  BPL BR2
4660	  DEY 
4670 ;
4680 ; ADD TO PC
4690 ;
4700 BR2 ADC R15L
4710	  STA R15L
4720	  TYA 
4730	  ADC R15H
4740	  STA R15H
4750 BNC2 RTS 
4760 BC  BCS BR
4770	  RTS 
4780 ;
4790 ; DOUBLE RESULT REG INDEX
4800 ;
4810 BP  ASL A
4820 ;
4830 ; TO X REG FOR INDEX
4840 ;
4850	  TAX 
4860 ; TEST FOR PLUS, BRANCH IF SO
4870 ;
4880	  LDA R0H,X
4890	  BPL BR1
4900	  RTS 
4910 ;
4920 ; DOUBLE RESULT REG INDEX
4930 ;
4940 BM  ASL A
4950	  TAX 
4960 ;
4970 ; TEST FOR MINUS
4980 ;
4990	  LDA R0H,X
5000	  BMI BR1
5010	  RTS 
5020 ;
5030 ; DOUBLE RESULT REG INDEX
5040 ;
5050 BZ  ASL A
5060	  TAX 
5070 ;
5080 ; TEST FOR ZERO (BOTH BYTES)
5090 ;
5100	  LDA R0L,X
5110	  ORA R0H,X
5120	  BEQ BR1
5130	  RTS 
5140 ;
5150 ; DOUBLE RESULT REG INDEX
5160 ;
5170 BNZ ASL A
5180	  TAX 
5190 ;
5200 ; TEST FOR NON-ZERO (BOTH)
5210 ;
5220	  LDA R0L,X
5230	  ORA R0H,X
5240	  BNE BR1
5250	  RTS 
5260 ;
5270 ; DOUBLE RESULT REG INDEX
5280 ;
5290 BM1 ASL A
5300	  TAX 
5310 ;
5320 ; TEST FOR $FF (-1) BOTH BYTES
5330 ;
5340	  LDA R0L,X
5350	  AND R0H,X
5360	  EOR #$FF
5370	  BEQ BR1
5380	  RTS 
5390 ;
5400 ; DOUBLE RESULT REG
5410 ;
5420 BNM1 ASL A
5430	  TAX 
5440 ;
5450 ; TEST FOR NO $FF
5460 ;
5470	  LDA R0L,X
5480	  AND R0H,X
5490	  EOR #$FF
5500	  BNE BR1
5510 NUL RTS 
5520 ; 12*2 FOR R12 AS STACK POINTER
5530 ;
5540 RS  LDX #$18
5550 ;
5560 ; DECR STACK POINTER
5570 ;
5580	  JSR DCR
5590 ;
5600 ; POP HIGHRETURN ADDRESS TO PC
5610 ;
5620	  LDA (R0L,X)
5630	  STA R15H
5640 ;
5650 ; SAME WITH LOW ORDER BYTE
5660 ;
5670	  JSR DCR
5680	  LDA (R0L,X)
5690	  STA R15L
5700	  RTS 
5710 RTN JMP RTNZ
5720 ;------------------------------
5730 SAVE
5740	  STA ACC
5750	  STX XREG
5760	  STY YREG
5770	  PHP 
5780	  PLA 
5790	  STA STATUS
5800	  CLD 
5810	  RTS 
5820 ;------------------------------
5830 RESTORE LDA STATUS
5840	  PHA 
5850	  LDA ACC
5860	  LDX XREG
5870	  LDY YREG
5880	  PLP 
5890	  RTS 
5900 ;-------------------------------
5910 ACC .BYTE 0
5920 XREG .BYTE 0
5930 YREG .BYTE 0
5940 STATUS .BYTE 0

5950 ;------------------------------
5960 TEST
5970	  JSR SW16A
5980	  .BYTE $11,$00,$F0 ; SET R1
5990	  .BYTE $12,$00,$40 ; SET R2
6000	  .BYTE $13,$00,$02 ; SET R3
6010	  .BYTE $41	; LD @R1
6020	  .BYTE $52	; ST @R2
6030	  .BYTE $F3	; DCR R3
6040	  .BYTE $07,$FB ; BNZ -4
6050	  .BYTE $00	; RTN
6060	  RTS 
6070 ;------------------------------