What do the operands and symbols mean? Anyone?

Let's talk about anything related to the 6502 microprocessor.
Jmstein7
Posts: 379
Joined: 30 May 2021

What do the operands and symbols mean? Anyone?

Post by Jmstein7 »

Hi. I've been reading through some of the posts on the site, and I can across this document:
http://www.6502.org/source/interpreters/sweet16.htm which has Woz's Sweet16 code in it. Unfortunately, I don't understand some of the operands and directives. Can anyone help?

These are the ones I can't pin down:

Code: Select all

AST  32
No clue here

Code: Select all

SW16D   LDA  >SET           
What does the ">" do, here?

Code: Select all

        LDA  OPTBL-2,Y
Is this "-2" from the value of OPTBL?

Code: Select all

OPTBL   DFB  SET-1          ;1X
BRTBL   DFB  RTN-1          ;0
Again a "-" minus sign. And, what is DFB? What does this all do?

Code: Select all

LD      LDA  R0L,X
BK      EQU  *-1
Another minus sign... and an asterisk?

Thanks in advance to any help you can offer!

Jon
User avatar
BigDumbDinosaur
Posts: 9428
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by BigDumbDinosaur »

Jmstein7 wrote:
Hi. I've been reading through some of the posts on the site, and I can across this document:
http://www.6502.org/source/interpreters/sweet16.htm which has Woz's Sweet16 code in it. Unfortunately, I don't understand some of the operands and directives. Can anyone help?

These are the ones I can't pin down:

Code: Select all

AST  32
No clue here

AST appears to be an assembler pseudo-op. No idea what it does.

Quote:

Code: Select all

SW16D   LDA  >SET           
What does the ">" do, here?

The greater-than symbol usually means to take the most-significant byte of a 16-bit value. It is mostly used with immediate-mode addressing, however.

Quote:

Code: Select all

        LDA  OPTBL-2,Y
Is this "-2" from the value of OPTBL?

Correct. The assembler will subtract 2 from whatever OPTBL represents and use the difference as the base address for the instruction.

Quote:

Code: Select all

OPTBL   DFB  SET-1          ;1X
BRTBL   DFB  RTN-1          ;0
Again a "-" minus sign. And, what is DFB? What does this all do?

DFB is an assembler pseudo-op that likely defines storage. As with AST, DFB is specific to the assembler being used.

Quote:

Code: Select all

LD      LDA  R0L,X
BK      EQU  *-1
Another minus sign... and an asterisk?

The asterisk represents the program counter in almost all 6502 assemblers. Therefore, the symbol BK is being set to the program counter minus 1.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
cjs
Posts: 759
Joined: 01 Dec 2018
Location: Tokyo, Japan
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by cjs »

The source code to which you linked looks a lot like input for Apple's EDASM, though that doesn't have an AST directive. Many pseudo-ops and conventions are common to a lot of assemblers, though, so reading through the EDASM manual would at least give you a fair amount of background for interpreting early assembler listings.

`DFB SET-1` places a byte in memory which is the lower byte of the address of the routine SET, minus 1. He's using this technique to create a lookup table of the start offsets of each routine to interpret a Sweet-16 opcode. He uses only the low byte of the address to save space and time; this is why you see the later comment that that section must reside entirely on one page. (You can see at SW16D where he handles the common high byte.)

Pushing the start address minus one is a common technique you'll see in tables of entry points on the 6502 because they are often used with the very technique you see here: look up the address, push it on the stack, and then RTS to "jump" to it. If you carefully examine what the JSR and RTS instructions do, you'll see that the address on the stack is always one less than the address to which you actually return. It's faster and smaller to pre-calculate the offset minus one than to do this at runtime.
Curt J. Sampson - github.com/0cjs
John West
Posts: 383
Joined: 03 Sep 2002

Re: What do the operands and symbols mean? Anyone?

Post by John West »

I suspect that's Wozniak's own assembler, and it looks a rather idiosyncratic one.
http://www.easy68k.com/paulrsm/6502/SW16RB.TXT has what looks like the same source code with a different (and much more standard) syntax, along with the assembled code.

Code: Select all

LDA >set
becomes

Code: Select all

LDA #SW16PAG
which is the (common) high byte of the addresses of the routines that handle the commands. So > means 'high byte', and there's a # missing because this is definitely an immediate LDA.

A couple of lines later we have

Code: Select all

LDY $0
which (in context) is clearly meant to be an immediate load. Most assemblers would want you to write

Code: Select all

LDY #$0
My guess is that AST reserves a block of zero page memory. Sweet16 needs 32 bytes there.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by BigEd »

I can't figure out what the AST directive could be for! There's a disk sector editor with both source and binary here: http://www.apple-iigs.info/doc/fichiers/poms15.pdf which uses AST 32 more than once in the source, and still I can't imagine. I thought it might be alignment, but it isn't.

Crossed in post: John's idea that AST might allocate some zero page. I can't quite see it, but it's plausible.

Edit: it's for ASTerisks! Print out 32 asterisks in the listing.
John West
Posts: 383
Joined: 03 Sep 2002

Re: What do the operands and symbols mean? Anyone?

Post by John West »

BigEd wrote:
Edit: it's for ASTerisks! Print out 32 asterisks in the listing.
OK, I was NOT expecting that! But of course it is.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by drogon »

Jmstein7 wrote:
Hi. I've been reading through some of the posts on the site, and I can across this document:
http://www.6502.org/source/interpreters/sweet16.htm which has Woz's Sweet16 code in it. Unfortunately, I don't understand some of the operands and directives. Can anyone help?
That listing is sublty different from the one in the original "Red Book" (1978).

See here:
IMG_20210824_103128.jpg
Quote:
These are the ones I can't pin down:

Code: Select all

AST  32
No clue here
My suspicion is that it's simply to place a line of asterisks in the output listing.
Quote:

Code: Select all

OPTBL   DFB  SET-1          ;1X
BRTBL   DFB  RTN-1          ;0
Again a "-" minus sign. And, what is DFB? What does this all do?
DeFine Byte.

The minus sign is simple arithmetic, so place the byte value of the constant SET minus 1 into the output object file. SET is a label and so 16-bits wide, so my suspicion is that the assembler just takes the lower 8-bits.

Hope that helps,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by BigEd »

(There's a general observation here: the operand for any given opcode can always be an expression, even if it's generally just a symbol or a literal. That is, if we first recognise syntax like "opcode (operand),Y" and concentrate on the inner part of the operand. So, adding or subtracting 1 is a simple case, but a complex expression might also appear.)
Jmstein7
Posts: 379
Joined: 30 May 2021

Re: What do the operands and symbols mean? Anyone?

Post by Jmstein7 »

I'm going to re-write it with more contemporary directives and see if I can get it to work, using what you guys have proffered. I'll post the results here. If anyone wants to give it a shot, too, and do the same, I'm curious how it goes. Let me know, and I'll report back, too.

Jon
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by drogon »

Jmstein7 wrote:
I'm going to re-write it with more contemporary directives and see if I can get it to work, using what you guys have proffered. I'll post the results here. If anyone wants to give it a shot, too, and do the same, I'm curious how it goes. Let me know, and I'll report back, too.

Jon
I re-wrote it some time back to remove the position dependence and make it a little faster for a project I was working on at the time (a 'malloc' style memory allocator) Woz was a master of saving space but with that limitation gone in my systems I opted to make it a little faster and possibly easier to read.

Link here: https://project-downloads.drogon.net/misc6502/sw16.tgz

Also a little Larson scanner test program in both sw16 and 6502 to compare...

However it's always a good exercise to do something like this to get a better feel for it.


-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Jmstein7
Posts: 379
Joined: 30 May 2021

Re: What do the operands and symbols mean? Anyone?

Post by Jmstein7 »

The good news: I seem to have gotten Sweet16 working (I think).

The bad news: now my "Frankenstein" mash-up of a monitor isn't working... the XModem receive stopped working, and I can't find the problem.

Can anyone figure this out?

Code: Select all

;-------------------------- The Code ----------------------------
;
; zero page variables (adjust these to suit your needs)
;
;
        .target "65C02"
	*= 	$C000		        ; Start of program (adjust to your needs)
        .setting "HandleLongBranch", true
crc		=	$D8		; CRC lo byte  (two byte variable)
crch		=	$D9		; CRC hi byte  
ptr		=	$DA		; data pointer (two byte variable)
ptrh		=	$DB		;   "    "
blkno		=	$DC		; block number 
retry		=	$DD		; retry counter 
retry2		=	$DE		; 2nd counter
bflag		=	$DF		; block flag 
;
;Monitor Variables
;
IN          = $0200          ;*Input buffer
XAML        = $E4            ;*Index pointers
XAMH        = $E5
STL         = $E6
STH         = $E7
L           = $E8
H           = $E9
YSAV        = $EA
MODE        = $EB
MSGL      = $EC
MSGH      = $ED
;
; non-zero page variables and buffers
;
;
Rbuff		=	$0300      	; temp 132 byte receive buffer 
					;(place anywhere, page aligned)
;
; XMODEM Control Character Constants
SOH		=	$F1		; start block
EOT		=	$F4		; end of text marker
ACK		=	$F6		; good block acknowledged
NAK		=	$F5		; bad block acknowledged
CAN		=	$F8		; cancel (not standard, not supported)
CR		=	$FD		; carriage return
LF		=	$FA		; line feed
ESC		=	$FB		; ESC to exit
;Sweet16 Zero Page Variables
R0L     .EQU  $0
R0H     .EQU  $1
R14H    .EQU  $1D
R15L    .EQU  $1E
R15H    .EQU  $1F
;
 ;-------------------------------
 ACC    .EQU $20
 XREG   .EQU $21
 YREG   .EQU $22
 STATUS .EQU $23
 ;
 SAVE16
    STA ACC
    STX XREG
    STY YREG
    PHP
    PLA
    STA STATUS
    CLD
    RTS
 ;------------------------------
 RESTORE16
    LDA STATUS
    PHA
    LDA ACC
    LDX XREG
    LDY YREG
    PLP
    RTS
;
;^^^^^^^^^^^^^^^^^^^^^^ Start of Program ^^^^^^^^^^^^^^^^^^^^^^
;
; Xmodem/CRC upload routine
; By Daryl Rictor, July 31, 2002
;
; v0.3  tested good minus CRC
; v0.4  CRC fixed!!! init to $0000 rather than $FFFF as stated   
; v0.5  added CRC tables vs. generation at run time
; v 1.0 recode for use with SBC2
; v 1.1 added block 1 masking (block 257 would be corrupted)
        .org $C020          ;jump to address
        JSR  SAVE16         ;PRESERVE 6502 REG CONTENTS
        PLA
        STA  R15L           ;INIT SWEET16 PC
        PLA                 ;FROM RETURN
        STA  R15H           ;ADDRESS
SW16B   JSR  SW16C          ;INTERPRET AND EXECUTE
        JMP  SW16B          ;ONE SWEET16 INSTR.
SW16C   INC  R15L
        BNE  SW16D          ;INCR SWEET16 PC FOR FETCH
        INC  R15H
SW16D   LDA  >SET           ;COMMON HIGH BYTE ">" FOR ALL ROUTINES
        PHA                 ;PUSH ON STACK FOR RTS
        LDY  $0
        LDA  (R15L),Y       ;FETCH INSTR
        AND  $F             ;MASK REG SPECIFICATION
        ASL                 ;DOUBLE FOR TWO BYTE REGISTERS
        TAX                 ;TO X REG FOR INDEXING
        LSR
        EOR  (R15L),Y       ;NOW HAVE OPCODE
        BEQ  TOBR           ;IF ZERO THEN NON-REG OP
        STX  R14H           ;INDICATE "PRIOR RESULT REG"
        LSR
        LSR                 ;OPCODE*2 TO LSB'S
        LSR
        TAY                 ;TO Y REG FOR INDEXING
        LDA  OPTBL-2,Y      ;LOW ORDER ADR BYTE
        PHA                 ;ONTO STACK
        RTS                 ;GOTO REG-OP ROUTINE
TOBR    INC  R15L
        BNE  TOBR2          ;INCR PC
        INC  R15H
TOBR2   LDA  BRTBL,X        ;LOW ORDER ADR BYTE
        PHA                 ;ONTO STACK FOR NON-REG OP
        LDA  R14H           ;"PRIOR RESULT REG" INDEX
        LSR                 ;PREPARE CARRY FOR BC, BNC.
        RTS                 ;GOTO NON-REG OP ROUTINE
RTNZ    PLA                 ;POP RETURN ADDRESS
        PLA
        JSR  RESTORE16        ;RESTORE 6502 REG CONTENTS
        JMP  (R15L)         ;RETURN TO 6502 CODE VIA PC
SETZ    LDA  (R15L),Y       ;HIGH ORDER BYTE OF CONSTANT
        STA  R0H,X
        DEY
        LDA  (R15L),Y       ;LOW ORDER BYTE OF CONSTANT
        STA  R0L,X
        TYA                 ;Y REG CONTAINS 1
        SEC
        ADC  R15L           ;ADD 2 TO PC
        STA  R15L
        BCC  SET2
        INC  R15H
SET2    RTS
OPTBL   .lobyte  SET-1          ;1X 
BRTBL   .lobyte  RTN-1          ;0
        .lobyte  LD-1           ;2X
        .lobyte  BR-1           ;1
        .lobyte  ST-1           ;3X
        .lobyte  BNC-1          ;2
        .lobyte  LDAT-1         ;4X
        .lobyte  BC-1           ;3
        .lobyte  STAT-1         ;5X
        .lobyte  BP-1           ;4
        .lobyte  LDDAT-1        ;6X
        .lobyte  BM-1           ;5
        .lobyte  STDAT-1        ;7X
        .lobyte  BZ-1           ;6
        .lobyte  POP-1          ;8X
        .lobyte  BNZ-1          ;7
        .lobyte  STPAT-1        ;9X
        .lobyte  BM1-1          ;8
        .lobyte  ADD-1          ;AX
        .lobyte  BNM1-1         ;9
        .lobyte  SUB-1          ;BX
        .lobyte  BK-1           ;A
        .lobyte  POPD-1         ;CX
        .lobyte  RS-1           ;B
        .lobyte  CPR-1          ;DX
        .lobyte  BS-1           ;C
        .lobyte  INR-1          ;EX
        .lobyte  NUL-1          ;D
        .lobyte  DCR-1          ;FX
        .lobyte  NUL-1          ;E
        .lobyte  NUL-1          ;UNUSED
        .lobyte  NUL-1          ;F

; FOLLOWING CODE MUST BE
; CONTAINED ON A SINGLE PAGE!
        .org  $C0B0         ;single page start
        
SET     BPL  SETZ           ;ALWAYS TAKEN
LD      LDA  R0L,X
BK      .EQU *-1           ;"*" refers to the program counter
        STA  R0L
        LDA  R0H,X          ;MOVE RX TO R0
        STA  R0H
        RTS
ST      LDA  R0L
        STA  R0L,X          ;MOVE R0 TO RX
        LDA  R0H
        STA  R0H,X
        RTS
STAT    LDA  R0L
STAT2   STA  (R0L,X)        ;STORE BYTE INDIRECT
        LDY  $0
STAT3   STY  R14H           ;INDICATE R0 IS RESULT NEG
INR     INC  R0L,X
        BNE  INR2           ;INCR RX
        INC  R0H,X
INR2    RTS
LDAT    LDA  (R0L,X)        ;LOAD INDIRECT (RX)
        STA  R0L            ;TO R0
        LDY  $0
        STY  R0H            ;ZERO HIGH ORDER R0 BYTE
        BEQ  STAT3          ;ALWAYS TAKEN
POP     LDY  $0             ;HIGH ORDER BYTE = 0
        BEQ  POP2           ;ALWAYS TAKEN
POPD    JSR  DCR            ;DECR RX
        LDA  (R0L,X)        ;POP HIGH ORDER BYTE @RX
        TAY                 ;SAVE IN Y REG
POP2    JSR  DCR            ;DECR RX
        LDA  (R0L,X)        ;LOW ORDER BYTE
        STA  R0L            ;TO R0
        STY  R0H
POP3    LDY  $0             ;INDICATE R0 AS LAST RESULT REG
        STY  R14H
        RTS
LDDAT   JSR  LDAT           ;LOW ORDER BYTE TO R0, INCR RX
        LDA  (R0L,X)        ;HIGH ORDER BYTE TO R0
        STA  R0H
        JMP  INR            ;INCR RX
STDAT   JSR  STAT           ;STORE INDIRECT LOW ORDER
        LDA  R0H            ;BYTE AND INCR RX. THEN
        STA  (R0L,X)        ;STORE HIGH ORDER BYTE.
        JMP  INR            ;INCR RX AND RETURN
STPAT   JSR  DCR            ;DECR RX
        LDA  R0L
        STA  (R0L,X)        ;STORE R0 LOW BYTE @RX
        JMP  POP3           ;INDICATE R0 AS LAST RESULT REG
DCR     LDA  R0L,X
        BNE  DCR2           ;DECR RX
        DEC  R0H,X
DCR2    DEC  R0L,X
        RTS
SUB     LDY  $0             ;RESULT TO R0
        CPR  SEC            ;NOTE Y REG = 13*2 FOR CPR
        LDA  R0L
        SBC  R0L,X
        STA  R0L,Y          ;R0-RX TO RY
        LDA  R0H
        SBC  R0H,X
SUB2    STA  R0H,Y
        TYA                 ;LAST RESULT REG*2
        ADC  $0             ;CARRY TO LSB
        STA  R14H
        RTS
ADD     LDA  R0L
        ADC  R0L,X
        STA  R0L            ;R0+RX TO R0
        LDA  R0H
        ADC  R0H,X
        LDY  $0             ;R0 FOR RESULT
        BEQ  SUB2           ;FINISH ADD
BS      LDA  R15L           ;NOTE X REG IS 12*2!
        JSR  STAT2          ;PUSH LOW PC BYTE VIA R12
        LDA  R15H
        JSR  STAT2          ;PUSH HIGH ORDER PC BYTE
BR      CLC
BNC     BCS  BNC2           ;NO CARRY TEST
BR1     LDA  (R15L),Y       ;DISPLACEMENT BYTE
        BPL  BR2
        DEY
BR2     ADC  R15L           ;ADD TO PC
        STA  R15L
        TYA
        ADC  R15H
        STA  R15H
BNC2    RTS
BC      BCS  BR
        RTS
BP      ASL                 ;DOUBLE RESULT-REG INDEX
        TAX                 ;TO X REG FOR INDEXING
        LDA  R0H,X          ;TEST FOR PLUS
        BPL  BR1            ;BRANCH IF SO
        RTS
BM      ASL                 ;DOUBLE RESULT-REG INDEX
        TAX
        LDA  R0H,X          ;TEST FOR MINUS
        BMI  BR1
        RTS
BZ      ASL                 ;DOUBLE RESULT-REG INDEX
        TAX
        LDA  R0L,X          ;TEST FOR ZERO
        ORA  R0H,X          ;(BOTH BYTES)
        BEQ  BR1            ;BRANCH IF SO
        RTS
BNZ     ASL                 ;DOUBLE RESULT-REG INDEX
        TAX
        LDA  R0L,X          ;TEST FOR NON-ZERO
        ORA  R0H,X          ;(BOTH BYTES)
        BNE  BR1            ;BRANCH IF SO
        RTS
BM1     ASL                 ;DOUBLE RESULT-REG INDEX
        TAX
        LDA  R0L,X          ;CHECK BOTH BYTES
        AND  R0H,X          ;FOR $FF (MINUS 1)
        EOR  $FF
        BEQ  BR1            ;BRANCH IF SO
        RTS
BNM1    ASL                 ;DOUBLE RESULT-REG INDEX
        TAX
        LDA  R0L,X
        AND  R0H,X          ;CHECK BOTH BYTES FOR NO $FF
        EOR  $FF
        BNE  BR1            ;BRANCH IF NOT MINUS 1
NUL     RTS
RS      LDX  $18            ;12*2 FOR R12 AS STACK POINTER
        JSR  DCR            ;DECR STACK POINTER
        LDA  (R0L,X)        ;POP HIGH RETURN ADDRESS TO PC
        STA  R15H
        JSR  DCR            ;SAME FOR LOW ORDER BYTE
        LDA  (R0L,X)
        STA  R15L
        RTS
RTN     JMP  RTNZ
;End of Sweet16
;
XModem		jsr	PrintMsg	; send prompt and info
		lda	#$01
		sta	blkno		; set block # to 1
		sta	bflag		; set flag to get address from block 1
StartCrc	lda	#"C"		; "C" start with CRC mode
		jsr	Put_Chr		; send it
		lda	#$FF	
		sta	retry2		; set loop counter for ~3 sec delay
		lda	#$00
            sta	crc
		sta	crch		; init CRC value	
		jsr	GetByte		; wait for input
            bcs	GotByte		; byte received, process it
		bcc	StartCrc	; resend "C"

StartBlk	lda	#$FF		; 
		sta	retry2		; set loop counter for ~3 sec delay
		lda	#$00		;
		sta	crc		;
		sta	crch		; init CRC value	
		jsr	GetByte		; get first byte of block
		bcc	StartBlk	; timed out, keep waiting...
GotByte		cmp	#ESC		; quitting?
                bne	GotByte1	; no
;		lda	#$FE		; Error code in "A" of desired
                rts			; YES - do BRK or change to RTS if desired
GotByte1        cmp	#SOH		; start of block?
		beq	BegBlk		; yes
		cmp	#EOT		;
		bne	BadCrc		; Not SOH or EOT, so flush buffer & send NAK	
		jmp	Done		; EOT - all done!
BegBlk		ldx	#$00
GetBlk		lda	#$ff		; 3 sec window to receive characters
		sta 	retry2		;
GetBlk1		jsr	GetByte		; get next character
		bcc	BadCrc		; chr rcv error, flush and send NAK
GetBlk2		sta	Rbuff,x		; good char, save it in the rcv buffer
		inx			; inc buffer pointer	
		cpx	#$84		; <01> <FE> <128 bytes> <CRCH> <CRCL>
		bne	GetBlk		; get 132 characters
		ldx	#$00		;
		lda	Rbuff,x		; get block # from buffer
		cmp	blkno		; compare to expected block #	
		beq	GoodBlk1	; matched!
		jsr	Print_Err	; Unexpected block number - abort	
		jsr	Flush		; mismatched - flush buffer and then do BRK
;		lda	#$FD		; put error code in "A" if desired
		rts			; unexpected block # - fatal error - BRK or RTS
GoodBlk1	eor	#$ff		; 1's comp of block #
		inx			;
		cmp	Rbuff,x		; compare with expected 1's comp of block #
		beq	GoodBlk2 	; matched!
		jsr	Print_Err	; Unexpected block number - abort	
		jsr 	Flush		; mismatched - flush buffer and then do BRK
;		lda	#$FC		; put error code in "A" if desired
		brk			; bad 1's comp of block#	
GoodBlk2	ldy	#$02		; 
CalcCrc		lda	Rbuff,y		; calculate the CRC for the 128 bytes of data	
		jsr	UpdCrc		; could inline sub here for speed
		iny			;
		cpy	#$82		; 128 bytes
		bne	CalcCrc		;
		lda	Rbuff,y		; get hi CRC from buffer
		cmp	crch		; compare to calculated hi CRC
		bne	BadCrc		; bad crc, send NAK
		iny			;
		lda	Rbuff,y		; get lo CRC from buffer
		cmp	crc		; compare to calculated lo CRC
		beq	GoodCrc		; good CRC
BadCrc		jsr	Flush		; flush the input port
		lda	#NAK		;
		jsr	Put_Chr		; send NAK to resend block
		jmp	StartBlk	; start over, get the block again			
GoodCrc		ldx	#$02		;
		lda	blkno		; get the block number
		cmp	#$01		; 1st block?
		bne	CopyBlk		; no, copy all 128 bytes
		lda	bflag		; is it really block 1, not block 257, 513 etc.
		beq	CopyBlk		; no, copy all 128 bytes
		lda	Rbuff,x		; get target address from 1st 2 bytes of blk 1
		sta	ptr		; save lo address
		inx			;
		lda	Rbuff,x		; get hi address
		sta	ptr+1		; save it
		inx			; point to first byte of data
		dec	bflag		; set the flag so we won't get another address		
CopyBlk		ldy	#$00		; set offset to zero
CopyBlk3	lda	Rbuff,x		; get data byte from buffer
		sta	(ptr),y		; save to target
		inc	ptr		; point to next address
		bne	CopyBlk4	; did it step over page boundary?
		inc	ptr+1		; adjust high address for page crossing
CopyBlk4	inx			; point to next data byte
		cpx	#$82		; is it the last byte
		bne	CopyBlk3	; no, get the next one
IncBlk		inc	blkno		; done.  Inc the block #
		lda	#ACK		; send ACK
		jsr	Put_Chr		;
		jmp	StartBlk	; get next block
Done		lda	#ACK		; last block, send ACK and exit.
		jsr	Put_Chr		;
		jsr	Flush		; get leftover characters, if any
		jsr	Print_Good	;
		jmp RESET			;can be rts
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;
; subroutines
;
;					;
GetByte		lda	#$00		; wait for chr input and cycle timing loop
		sta	retry		; set low value of timing loop
StartCrcLp	jsr	Get_chr		; get chr from serial port, don't wait 
		bcs	GetByte1	; got one, so exit
		dec	retry		; no character received, so dec counter
		bne	StartCrcLp	;
		dec	retry2		; dec hi byte of counter
		bne	StartCrcLp	; look for character again
		clc			; if loop times out, CLC, else SEC and return
GetByte1	rts			; with character in "A"
;
Flush		lda	#$70		; flush receive buffer
		sta	retry2		; flush until empty for ~1 sec.
Flush1		jsr	GetByte		; read the port
		bcs	Flush		; if chr recvd, wait for another
		rts			; else done
;
PrintMsg	ldx	#$00		; PRINT starting message
PrtMsg1		lda   	Msg,x		
		beq	PrtMsg2			
		jsr	Put_Chr
		inx
		bne	PrtMsg1
PrtMsg2		rts
Msg		.textz	"Begin XMODEM/CRC upload. "
		;.lobyte  	CR, LF
               	;.lobyte   0
;
Print_Err	ldx	#$00		; PRINT Error message
PrtErr1		lda   	ErrMsg,x
		beq	PrtErr2
		jsr	Put_Chr
		inx
		bne	PrtErr1
PrtErr2		rts
ErrMsg		.textz 	"Upload Error!"
		;.lobyte  	CR, LF
                ;.lobyte   0
;
Print_Good	ldx	#$00		; PRINT Good Transfer message
Prtgood1	lda   	GoodMsg,x
		beq	Prtgood2
		jsr	Put_Chr
		inx
		bne	Prtgood1
Prtgood2	rts
GoodMsg		.textz 	"Upload Successful!"
		;.lobyte  	CR, LF
                ;.lobyte   0
;
;
;======================================================================
;  I/O Device Specific Routines
;
;  Two routines are used to communicate with the I/O device.
;
; "Get_Chr" routine will scan the input port for a character.  It will
; return without waiting with the Carry flag CLEAR if no character is
; present or return with the Carry flag SET and the character in the "A"
; register if one was present.
;
; "Put_Chr" routine will write one byte to the output port.  Its alright
; if this routine waits for the port to be ready.  its assumed that the 
; character was send upon return from this routine.
;
; Here is an example of the routines used for a standard 6551 ACIA.
; You would call the ACIA_Init prior to running the xmodem transfer
; routine.
;
VIA_REG     =  $8800
VIA_DATA    =  $8801
VIA_DDRR    =  $8802
VIA_DDRD    =  $8803
VIA_HS      =  $880C
;
PSP_DATA    =  $9000
;
ACIA_Data	=	$8000		; Adjust these addresses to point 
ACIA_Status	=	$8001		; to YOUR 6551!
ACIA_Command	=	$8002		;
ACIA_Control	=	$8003		;
ACIA        = $8000
ACIA_CTRL   = ACIA+3
ACIA_CMD    = ACIA+2
ACIA_SR     = ACIA+1
ACIA_DAT    = ACIA
ACIA_Init      	lda	#$10      ; 115.2k init is #%00010000
               	sta	ACIA_Control   	; control reg 
               	lda	#$C9           	; N parity/echo off/rx int off/ dtr active low
               	sta	ACIA_Command   	; command reg 
                lda   #$99
                sta   VIA_HS
                lda   #$FF
                sta   VIA_DDRR
                sta   VIA_DDRD
                sta   VIA_REG
               	rts                  	; done
;
; input chr from ACIA (no waiting)
;
Get_Chr		clc			; no chr present
               	lda	ACIA_Status     ; get Serial port status
               	and	#$08            ; mask rcvr full bit
              	beq	Get_Chr2	; if not chr, done
               	Lda	ACIA_Data       ; else get chr
	       	sec			; and set the Carry Flag
Get_Chr2    	rts			; done
;
; output to OutPut Port
;
Put_Chr	   	PHA                     ; save registers
Put_Chr1     	lda	ACIA_Status     ; serial port status
              	and	#$10            ; is tx buffer empty
               	beq	Put_Chr1        ; no, go back and test it again
               	PLA                     ; yes, get chr to send
               	sta	ACIA_Data       ; put character to Port
                jsr Delay
               	RTS                     ; done
;=========================================================================
;Main Routines/Program
RESET       CLD             ;Clear decimal arithmetic mode.
            CLI
            JSR ACIA_Init        ;* Init ACIA 
         LDA #$0D
         JSR ECHO      ;* New line.
         LDA #<MSG1
         STA MSGL
         LDA #>MSG1
         STA MSGH
         JSR SHWMSG      ;* Show Welcome.
         LDA #$0D
         JSR ECHO      ;* New line.
         LDA #<MSG5
         STA MSGL
         LDA #>MSG5
         STA MSGH
         JSR SHWMSG  
         LDA #$0D
         JSR ECHO      ;* New line.
SOFTRESET   LDA #$9B      ;* Auto escape.
NOTCR       CMP #$88        ;"<-"? * Note this was chaged to $88 which is the back space key.
            BEQ BACKSPACE   ;Yes.
            CMP #$9B        ;ESC?
            BEQ ESCAPE      ;Yes.
            INY             ;Advance text index.
            BPL NEXTCHAR    ;Auto ESC if >127.
ESCAPE      LDA #$DC        ;"\"
            JSR ECHO        ;Output it.
GETLINE     LDA #$8D        ;CR.
            JSR ECHO        ;Output it.
            LDY #$01        ;Initiallize text index.
BACKSPACE   DEY             ;Backup text index.
            BMI GETLINE     ;Beyond start of line, reinitialize.
         LDA #$A0      ;*Space, overwrite the backspaced char.
         JSR ECHO
         LDA #$88      ;*Backspace again to get to correct pos.
         JSR ECHO
NEXTCHAR    LDA ACIA_SR     ;*See if we got an incoming char
            AND #$08        ;*Test bit 3
            BEQ NEXTCHAR    ;*Wait for character
            LDA ACIA_DAT    ;*Load char
         CMP #$60      ;*Is it Lower case
         BMI   CONVERT      ;*Nope, just convert it
         AND #$5F      ;*If lower case, convert to Upper case
CONVERT     ORA #$80        ;*Convert it to "ASCII Keyboard" Input
            STA IN,Y        ;Add to text buffer.
            JSR ECHO        ;Display character.
            CMP #$8D        ;CR?
            BNE NOTCR       ;No.
            LDY #$FF        ;Reset text index.
            LDA #$00        ;For XAM mode.
            TAX             ;0->X.
SETSTOR     ASL             ;Leaves $7B if setting STOR mode.
SETMODE     STA MODE        ;$00 = XAM, $7B = STOR, $AE = BLOK XAM.
BLSKIP      INY             ;Advance text index.
NEXTITEM    LDA IN,Y        ;Get character.
            CMP #$8D        ;CR?
            BEQ GETLINE     ;Yes, done this line.
            CMP #$AE        ;"."?
            BCC BLSKIP      ;Skip delimiter.
            BEQ SETMODE     ;Set BLOCK XAM mode.
            CMP #$BA        ;":"?
            BEQ SETSTOR     ;Yes, set STOR mode.
            CMP #$D2        ;"R"?
            BEQ RUN         ;Yes, run user program.
            CMP #$D8           ;"X"?
            BEQ XModem         ;Yes, run XModem transfer.
            STX L           ;$00->L.
            STX H           ; and H.
            STY YSAV        ;Save Y for comparison.
NEXTHEX     LDA IN,Y        ;Get character for hex test.
            EOR #$B0        ;Map digits to $0-9.
            CMP #$0A        ;Digit?
            BCC DIG         ;Yes.
            ADC #$88        ;Map letter "A"-"F" to $FA-FF.
            CMP #$FA        ;Hex letter?
            BCC NOTHEX      ;No, character not hex.
DIG         ASL
            ASL             ;Hex digit to MSD of A.
            ASL
            ASL
            LDX #$04        ;Shift count.
HEXSHIFT    ASL             ;Hex digit left MSB to carry.
            ROL L           ;Rotate into LSD.
            ROL H           ;Rotate into MSD's.
            DEX             ;Done 4 shifts?
            BNE HEXSHIFT    ;No, loop.
            INY             ;Advance text index.
            BNE NEXTHEX     ;Always taken. Check next character for hex.
NOTHEX      CPY YSAV        ;Check if L, H empty (no hex digits).
         BNE NOESCAPE   ;* Branch out of range, had to improvise...
            JMP ESCAPE      ;Yes, generate ESC sequence.

RUN         JSR ACTRUN      ;* JSR to the Address we want to run.
         JMP   SOFTRESET   ;* When returned for the program, reset monitor.
ACTRUN      JMP (XAML)      ;Run at current XAM index.

NOESCAPE    BIT MODE        ;Test MODE byte.
            BVC NOTSTOR     ;B6=0 for STOR, 1 for XAM and BLOCK XAM
            LDA L           ;LSD's of hex data.
            STA (STL, X)    ;Store at current "store index".
            INC STL         ;Increment store index.
            BNE NEXTITEM    ;Get next item. (no carry).
            INC STH         ;Add carry to 'store index' high order.
TONEXTITEM  JMP NEXTITEM    ;Get next command item.
NOTSTOR     BMI XAMNEXT     ;B7=0 for XAM, 1 for BLOCK XAM.
            LDX #$02        ;Byte count.
SETADR      LDA L-1,X       ;Copy hex data to
            STA STL-1,X     ;"store index".
            STA XAML-1,X    ;And to "XAM index'.
            DEX             ;Next of 2 bytes.
            BNE SETADR      ;Loop unless X = 0.
NXTPRNT     BNE PRDATA      ;NE means no address to print.
            LDA #$8D        ;CR.
            JSR ECHO        ;Output it.
            LDA XAMH        ;'Examine index' high-order byte.
            JSR PRBYTE      ;Output it in hex format.
            LDA XAML        ;Low-order "examine index" byte.
            JSR PRBYTE      ;Output it in hex format.
            LDA #$BA        ;":".
            JSR ECHO        ;Output it.
PRDATA      LDA #$A0        ;Blank.
            JSR ECHO        ;Output it.
            LDA (XAML,X)    ;Get data byte at 'examine index".
            JSR PRBYTE      ;Output it in hex format.
XAMNEXT     STX MODE        ;0-> MODE (XAM mode).
            LDA XAML
            CMP L           ;Compare 'examine index" to hex data.
            LDA XAMH
            SBC H
            BCS TONEXTITEM  ;Not less, so no more data to output.
            INC XAML
            BNE MOD8CHK     ;Increment 'examine index".
            INC XAMH
MOD8CHK     LDA XAML        ;Check low-order 'exainine index' byte
            AND #$0F        ;For MOD 8=0 ** changed to $0F to get 16 values per row **
            BPL NXTPRNT     ;Always taken.
PRBYTE      PHA             ;Save A for LSD.
            LSR
            LSR
            LSR             ;MSD to LSD position.
            LSR
            JSR PRHEX       ;Output hex digit.
            PLA             ;Restore A.
PRHEX       AND #$0F        ;Mask LSD for hex print.
            ORA #$B0        ;Add "0".
            CMP #$BA        ;Digit?
            BCC ECHO        ;Yes, output it.
            ADC #$06        ;Add offset for letter.
ECHO        PHA             ;*Save A
            AND #$7F        ;*Change to "standard ASCII"
            STA ACIA_DAT    ;*Send it.
            jsr Delay       ; try delay
WAIT       LDA ACIA_SR     ;*Load status register for ACIA
            AND #$10        ;*Mask bit 4.
            BEQ    WAIT    ;*ACIA not done yet, wait.
            PLA             ;*Restore A
            RTS             ;*Done, over and out...

SHWMSG      LDY #$0
PRINT      LDA (MSGL),Y
         BEQ DONEX
         JSR ECHO
         INY 
         BNE PRINT
DONEX      RTS 
;Interrupt Service Routines
IRQ_ISA     SEI
            PHA
            PHX
            PHY
            ;actual routine
            PLY
            PLX
            PLA
            CLI
            RTI
;
NMI_ISA     SEI
            PHA
            PHX
            PHY
            ;actual routine
            PLY
            PLX
            PLA
            CLI
            RTI
;=========================================================================
;
;
;  CRC subroutines 
;
;
UpdCrc		eor 	crc+1 		; Quick CRC computation with lookup tables
       		tax		 	; updates the two bytes at crc & crc+1
       		lda 	crc		; with the byte send in the "A" register
       		eor 	CRCHI,X
       		sta 	crc+1
      	 	lda 	CRCLO,X
       		sta 	crc
       		rts
;
; The following tables are used to calculate the CRC for the 128 bytes
; in the xmodem data blocks.  You can use these tables if you plan to 
; store this program in ROM.  If you choose to build them at run-time, 
; then just delete them and define the two labels: crclo & crchi.
;
; low byte CRC lookup table (should be page aligned)
		*= $ED00
crclo
 .lobyte $00,$21,$42,$63,$84,$A5,$C6,$E7,$08,$29,$4A,$6B,$8C,$AD,$CE,$EF
 .lobyte $31,$10,$73,$52,$B5,$94,$F7,$D6,$39,$18,$7B,$5A,$BD,$9C,$FF,$DE
 .lobyte $62,$43,$20,$01,$E6,$C7,$A4,$85,$6A,$4B,$28,$09,$EE,$CF,$AC,$8D
 .lobyte $53,$72,$11,$30,$D7,$F6,$95,$B4,$5B,$7A,$19,$38,$DF,$FE,$9D,$BC
 .lobyte $C4,$E5,$86,$A7,$40,$61,$02,$23,$CC,$ED,$8E,$AF,$48,$69,$0A,$2B
 .lobyte $F5,$D4,$B7,$96,$71,$50,$33,$12,$FD,$DC,$BF,$9E,$79,$58,$3B,$1A
 .lobyte $A6,$87,$E4,$C5,$22,$03,$60,$41,$AE,$8F,$EC,$CD,$2A,$0B,$68,$49
 .lobyte $97,$B6,$D5,$F4,$13,$32,$51,$70,$9F,$BE,$DD,$FC,$1B,$3A,$59,$78
 .lobyte $88,$A9,$CA,$EB,$0C,$2D,$4E,$6F,$80,$A1,$C2,$E3,$04,$25,$46,$67
 .lobyte $B9,$98,$FB,$DA,$3D,$1C,$7F,$5E,$B1,$90,$F3,$D2,$35,$14,$77,$56
 .lobyte $EA,$CB,$A8,$89,$6E,$4F,$2C,$0D,$E2,$C3,$A0,$81,$66,$47,$24,$05
 .lobyte $DB,$FA,$99,$B8,$5F,$7E,$1D,$3C,$D3,$F2,$91,$B0,$57,$76,$15,$34
 .lobyte $4C,$6D,$0E,$2F,$C8,$E9,$8A,$AB,$44,$65,$06,$27,$C0,$E1,$82,$A3
 .lobyte $7D,$5C,$3F,$1E,$F9,$D8,$BB,$9A,$75,$54,$37,$16,$F1,$D0,$B3,$92
 .lobyte $2E,$0F,$6C,$4D,$AA,$8B,$E8,$C9,$26,$07,$64,$45,$A2,$83,$E0,$C1
 .lobyte $1F,$3E,$5D,$7C,$9B,$BA,$D9,$F8,$17,$36,$55,$74,$93,$B2,$D1,$F0 

; hi byte CRC lookup table (should be page aligned)
		*= $EE00
crchi
 .lobyte $00,$10,$20,$30,$40,$50,$60,$70,$81,$91,$A1,$B1,$C1,$D1,$E1,$F1
 .lobyte $12,$02,$32,$22,$52,$42,$72,$62,$93,$83,$B3,$A3,$D3,$C3,$F3,$E3
 .lobyte $24,$34,$04,$14,$64,$74,$44,$54,$A5,$B5,$85,$95,$E5,$F5,$C5,$D5
 .lobyte $36,$26,$16,$06,$76,$66,$56,$46,$B7,$A7,$97,$87,$F7,$E7,$D7,$C7
 .lobyte $48,$58,$68,$78,$08,$18,$28,$38,$C9,$D9,$E9,$F9,$89,$99,$A9,$B9
 .lobyte $5A,$4A,$7A,$6A,$1A,$0A,$3A,$2A,$DB,$CB,$FB,$EB,$9B,$8B,$BB,$AB
 .lobyte $6C,$7C,$4C,$5C,$2C,$3C,$0C,$1C,$ED,$FD,$CD,$DD,$AD,$BD,$8D,$9D
 .lobyte $7E,$6E,$5E,$4E,$3E,$2E,$1E,$0E,$FF,$EF,$DF,$CF,$BF,$AF,$9F,$8F
 .lobyte $91,$81,$B1,$A1,$D1,$C1,$F1,$E1,$10,$00,$30,$20,$50,$40,$70,$60
 .lobyte $83,$93,$A3,$B3,$C3,$D3,$E3,$F3,$02,$12,$22,$32,$42,$52,$62,$72
 .lobyte $B5,$A5,$95,$85,$F5,$E5,$D5,$C5,$34,$24,$14,$04,$74,$64,$54,$44
 .lobyte $A7,$B7,$87,$97,$E7,$F7,$C7,$D7,$26,$36,$06,$16,$66,$76,$46,$56
 .lobyte $D9,$C9,$F9,$E9,$99,$89,$B9,$A9,$58,$48,$78,$68,$18,$08,$38,$28
 .lobyte $CB,$DB,$EB,$FB,$8B,$9B,$AB,$BB,$4A,$5A,$6A,$7A,$0A,$1A,$2A,$3A
 .lobyte $FD,$ED,$DD,$CD,$BD,$AD,$9D,$8D,$7C,$6C,$5C,$4C,$3C,$2C,$1C,$0C
 .lobyte $EF,$FF,$CF,$DF,$AF,$BF,$8F,$9F,$6E,$7E,$4E,$5E,$2E,$3E,$0E,$1E 
;
; End of File
;*****************************************************
;	Delay
;
;	Delay For 65535 Cycles 
;
;*****************************************************
Delay
		phx
		phy
		ldy #$8F ; restore to #$00
AL2		ldx #$05 ; restore to #$00
AL1		dex
		bne AL1
		dey
		bne AL2
		ply
		plx
		rts
;
MSG1      .textz "Welcome to JSMON 2.0."
MSG2      .textz "Start Intel Hex Transfer."
MSG3      .textz "Intel Hex Imported."
MSG4      .textz "Intel Hex Imported with  error."
MSG5      .textz "Sweet16 Enabled at JSR $C020" ;modify accordingly
                .ORG    $FFFA
NMI_VEC         .word   NMI_ISA         ;IRQ vector
RESET_VEC       .word   RESET           ;RESET vector $C33F
IRQ_VEC         .word   IRQ_ISA         ;IRQ vector
Jmstein7
Posts: 379
Joined: 30 May 2021

Re: What do the operands and symbols mean? Anyone?

Post by Jmstein7 »

Wow. Still no luck. This will drive me bonkers.
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by 8BIT »

These are values, not addresses. It looks like you changed them thinking they were zero page addresses.

Code: Select all

SOH		=	$01		; start block
EOT		=	$04		; end of text marker
ACK		=	$06		; good block acknowleged
NAK		=	$15		; bad block acknowleged
CAN		=	$18		; cancel (not standard, not supported)
CR		 =	13
LF		 =	10
ESC      =   27       ; ESC to exit
I did not look over the rest of the code.

Daryl
Please visit my website -> https://sbc.rictor.org/
Jmstein7
Posts: 379
Joined: 30 May 2021

Re: What do the operands and symbols mean? Anyone?

Post by Jmstein7 »

8BIT wrote:
These are values, not addresses. It looks like you changed them thinking they were zero page addresses.

Code: Select all

SOH		=	$01		; start block
EOT		=	$04		; end of text marker
ACK		=	$06		; good block acknowleged
NAK		=	$15		; bad block acknowleged
CAN		=	$18		; cancel (not standard, not supported)
CR		 =	13
LF		 =	10
ESC      =   27       ; ESC to exit
I did not look over the rest of the code.

Daryl
Daryl, I'm a BIG fan of your work! The XModem problem seems to be fixed. Now let's see if I can get Sweet16 fully operational.

Jon

edit: now XModem works but Sweet16 doesn't. Hmmmm... :lol:
edit2: I wish there was a "smacking my forehead" emoji here :lol:
User avatar
cjs
Posts: 759
Joined: 01 Dec 2018
Location: Tokyo, Japan
Contact:

Re: What do the operands and symbols mean? Anyone?

Post by cjs »

John West wrote:
I suspect that's Wozniak's own assembler, and it looks a rather idiosyncratic one.
http://www.easy68k.com/paulrsm/6502/SW16RB.TXT has what looks like the same source code with a different (and much more standard) syntax, along with the assembled code.
That's a great find; it appears to be a machine-readable version of the listing from the original 1977-11 BYTE article by Wozniak.

The 6502.org page appears to be a reformatted copy of a file called sweet16.txt that dates back to at least 2000. That contains the material from the 1979 Call-A.P.P.L.E. Woz Pak II (which includes a version of Woz's article without source code and another article on Sweet 16 by Dick Sedgewick), bits of other documentation, and a different (and much worse) version of the source code. It's not only been reworked for whatever strange assembler doesn't use `#` to indicate immediate addressing, but also has at least two typos (loss of the SW16 entry point label and indentation of the CPR label). It does, however, add the "Following code must be contained on a single page!" comment.

My recommendation for anybody playing with this is to use the SW16RB.TXT listing and just trim off the address and data columns at the left.
Curt J. Sampson - github.com/0cjs
Post Reply