Thursday, September 20, 2012

Wierd "Double Dabble" code.

This code, as the comments suggest, takes 24 bits up to a decimal value of 999,999 and converts it to a base100 code into three bytes. Code assumes it can use local vars starting at address $0000. Assumes it can use .macros from here.

.proc convert_to_base100 ; (addressIN: word, addressOUT: word)

; regx, regy: low, hi, address input (24 bit value up to 999,999) 
; reg a, pla: low high address out
; convert 24 bits to 3 bytes: 10,000s, 1000s, 100s
; double dabble: to correct a single digit, before 
; it is shifted look if it will become a 10. If it was to become 
; a 10 you add 6 to correct before a shift you add 3 for the 
; same result. Adding 3 is done right before the shift would have 
; moved the digit into the correct spot
; 
; so for a value of 100 you add 9C or 4E before the shift
;
; 100 in hex:       64     32
;                +  9C   + 4E
;                -----   -----
;                   100    80  --> shl 1 = 100
;
; add 4E if the value to be shifted once more is >=32hex
;
; 0 - 9 is ten digits, 0 -99 one hundred digits , need to check the 
; hundreds for greater than or equal 32
; 
; 999999 = 00001111   01000010   00111111  4 shifts to discard zeros
; to be shifted into 00000000 00000000  00000000 
; 32 in binary = 00110010  = 6 more shifts before check needed 
; 10 shifts total needed before testing
; 
; 14 more shifts after
;

.struct
 addressIN   .byte 2
 addressOUT   .byte 2
 tempIN    .byte 3
 tempOUT   .byte 3
.endstruct

 
 stx addressIN
 sty addressIN+1
 sta addressOUT
 pla
 sta addressOUT+1
 
 ldy #2
 repeat 
  lda (addressIN),y
  sta tempIN,y
  dey
 until negative
 
 
 lda #0
 sta tempOUT
 sta tempOUT+1
 sta tempOUT+2
 
 clc

 ; 4 shifts to remove zeros
  
  lda tempIN
  rol a   
  rol tempIN + 1
  rol tempIN + 2
  rol a   
  rol tempIN + 1
  rol tempIN + 2
  rol a   
  rol tempIN + 1
  rol tempIN + 2
  rol a   
  rol tempIN + 1
  rol tempIN + 2
 
 
 ldy #4 ; 4 shifts that have to go into OUT
 repeat
  rol a   
  rol tempIN + 1
  rol tempIN + 2
  
  rol tempOUT
  dey
 until zero
 
  ; TWO MORE
  
  lda tempIN + 1
  rol a
  rol tempIN + 2
  
  rol tempOUT
  rol a
  rol tempIN + 2
  
  rol tempOUT
  sta tempIN + 1
 
  
 ; 10 shifts done 
 
 ldx #0
 
 ldy #6
 repeat

  jsr check32
  
  rol tempIN + 1
  rol tempIN + 2
  
  rol tempOUT
  rol tempOUT + 1
  
  dey
 until zero
 
 ; after this next check, byte 1 could hold $80
 ; 6 more shifts to check byte 2 ..don't need to though
 

 ldy #8
 repeat
 
  ldx #1
  jsr check32
  dex
  jsr check32
 
  
  ; clc
  ; rol tempIN
  ; rol tempIN + 1
  rol tempIN + 2
  
  rol tempOUT
  rol tempOUT + 1
  rol tempOUT + 2
  
  
  dey
 until zero
 
 ldy #2
 repeat 
  lda tempOUT,y
  sta (addressOUT),y
  dey
 until negative
 

 rts

 
 check32:
 lda tempOUT,x
 cmp #$32
 if greaterORequal
  ; carry is set
  adc #$4D ; add #$4E
  sta tempOUT,x
 endif
 
 rts
 
 
.endproc

No comments:

Post a Comment