*************************************************
* code to compute Thue Morse constant to > 10^300000 digits
* Chris Lomont Jul 2007 www.lomont.org
*************************************************

SCREENSIZE	equ	$240
TEMP		equ	$8000+SCREENSIZE	* place to store vars, about 9 bytes
SLOW		equ	0			* define to be 0 or 1 for fast or slow version

	org 	16384
* program start for running mode - on entry U=Y=D=$FFFF and S points past bytes to erase 	
app	pshs	y,d,u		* set 6 bytes
	pshs	y,d,u		* set 6 bytes
	
	ldy	#$8000		* Y holds next digit pos at all times
	clra			* A holds parity - todo use lda for later debugging
	 
* here is the infinite loop - start by computing the next parity
infloop	ldx	#SCREENSIZE+zeros-app	* start past code on page $30
	ldb	#$30
	
	if	SLOW
dly	ldu	#8000		* delay loop in SLOW version
!	leau	-1,u
	cmpu	#0
	bne	<
	endif
	
npage	stb	#$FFA0		* next page in, X must point to start
carry	eora	,x
	inc	,x
	eora	,x+		* A has parity change
	cmpx	#$2000
	beq	bound		* out of bounds
	tst	-1,x		*  
	beq	carry		* we have carry, continue
bound	tst	-1,x
	bne	done
	ldx	#0		* start at top
	incb	
	cmpb	#$40
	blt	npage		* go to next page and continue
	
* at this point, A holds parity in the byte, so pack down to the low bit
done	ldb	#7
	sta	TEMP		* 
!	lsra	
	eora	TEMP
	decb
	bne	<

	ldb	#$30		* prepare to output a digit - text digit 0
	anda	#1		* now A has parity in low bit
	beq	>
	incb			* text digit 1
	
* now write to screen	
!	stb	,y+
	cmpy	#$8000+256	* last digit position on screen
	bge	>		* wraparound - do a page increment		

	if	SLOW 
	ldb	#$2A		* multiply * symbol	
	stb	,y		* show space
	endif
	
	bra	infloop
!	ldy	#$8000		* top digit

	if	SLOW 
	ldb	#$2A		* multiply * symbol	
	stb	,y		* show space
	endif				

** check for pause and do 
!	ldb	$FF00		* read output
*	comb			* reverse bits to high to see what was pressed
*	andb	#$7F		* strip unused high bit, all 0 means no keys down
	incb			* todo - may fail with joysticks?
	bne	<		* loop if key down - 0 bit means not down

* increment page counter
* uses registers B,X
	ldx	#$81FF		* last digit
!	ldb	#$3A		* overflow
	inc	,x
	cmpb	,x		* overflow test
	bgt	infloop		* no overflow, done
	ldb	#$30
	stb	,x
	leax	-1,x
	cmpx	#$8200-32
	bgt	<
	bra	infloop

************ The end of the main application, here is where digits start in memory
zeros	fzb 	10		* zeroed bytes
endapp	fzb	10 			

* NOTE: Fast version gives 
* first counting byte is 02AA on page $30, 
* giving $2000-$02AA+1 + 15*($2000) = 130391 bytes, s0
* this can compute 2^(130391*8) digits, approximately
* 10^314013 digits!
*
* Slow version gives  
* first counting byte is 02BD on page $30, 
* giving $2000-$02BD+1 + 15*($2000) = 130372 bytes, s0
* this can compute 2^(130372*8) digits, approximately
* 10^313967 digits!


******* initial screen **********************************
*****************12345678901234567890123456789012********
msg	fcc	"                                "  * 1	
	fcc	"                                "  * 2 
	fcc	"                                "  * 3 
	fcc	"                                "  * 4 
	fcc	"                                "  * 5 
	fcc	"                                "  * 6 
	fcc	"                                "  * 7 
	fcc	"                                "  * 8 
	fcc	"--------------------------------"  * 9	
	if 	SLOW
	fcc	"Thue-Morse constant to 10^313967"  * 10
	endif
	if 	SLOW=0
	fcc	"Thue-Morse constant to 10^314013"  * 10
	endif
	fcc	"digits in base 2,by Chris Lomont"  * 11
	fcc	"      WWW.LOMONT.ORG, 2007      "  * 12
	fcc	"    A CoCo3 digit record !!!    "  * 13
	fcc	" Press and hold a key to pause. "  * 14
	fcc	" Each page is 256 digits. Page# "  * 15
	fcc	"00000000000000000000000000000000"  * 16
	fcc	"                                "  * 17 
	fcc	"--------------------------------"  * 18	
		

* Steps:
*    1. start initialization - speed, interrupts, mem page, video
*    2. copy program to high memory and jump there
*    3. erase uneeded part of program
*    4. jump to running mode


* entry point for Step 1 and EXEC
entrypt	orcc	#$50		* turn off interrupts
	sta	$FFD9		* high speed poke

	lda	#$68		* 0b0110 1000 = 0x40
	sta	$FF90		* enable MMU, disable GIME interrupts

	lda	#$30		* GIME page $30 - bottom 128K page
	sta	$FFA4		* map to CPU $8000

* copy prog to after video ram and jump there
	ldx	#$8000+SCREENSIZE
	leay	app,pcr
!	lda	,y+
	sta	,x+
	cmpx	#$A000		* plenty of size copied - todo dynamic sized?
	blt	<
	lbra	#begin-app+$8000+SCREENSIZE * jump to start in $8000 block

begin	nop			* after prog copied, jump here, todo - make useful


* prepare keyboard for reading keys
	clr	$FF01		* clear control register A
	clr	$FF03		* clear control register B
	clr	$FF00		* set side PIA0 side A to input
	ldd	#$FF34
	sta	$FF02		* set PIA0 side B to output
	stb	$FF01	
	stb	$FF03
	
	clrb			* ground all bits
	stb	$FF02		* set column strobe
	

* load screen
	ldx	#$8000		* new screen location
	leay	msg,pcr		* get initial screen
msgloop	lda	,y+
!	sta	,x+	
	cmpx	#$8000+SCREENSIZE
	bne	msgloop

* set videopage to $8000
*	sta	$FFC6		* set text screen start to CPU $8000
*	sta	$FFC8		* todo - do after screen drawn there
*	sta	$FFCA
*	sta	$FFCC
*	sta	$FFCE
*	sta	$FFD0
*	sta	$FFD3

* set CoCo3 video mode and text start to $8000 - page $30


* set CoCo3 video mode and text start to $8000 - page $30
	lda	#$26		* 0b0010 0110 - text, color, 12 lines per char 	
	sta	$FF98		* set video mode
	lda	#0		* 0b00000000
	sta	$FF99		* video resolution
	lda	#$00
	sta	$FF9C		* Vertical scroll to 0
	ldd	#$C000		* $60000/8
	std	$FF9D
	
* set white letters on black screen?
	clra			* black
	sta	$FFB0		* background black
	lda	#48		* 48 for CMP, 64 for RGB todo
	sta	$FFB8		* foreground
		

*** clear GIME memory pages $31 through $3F
	lda	#$31		* pages $31-$3F
	ldb	#$FF
clrmem	sta	$FFA0		* map to addresses $0000-$1FFF
	ldx	#0
!	stb	,x+
	cmpx	#$2000
	blt 	<
	inca	
	cmpa	#$40
	blt	clrmem

	lda	#$80	
	tfr	a,dp		* set DP for smaller, faster code

* clear page $30 except for vidmem and program in use, page $30 at $8000 right now
	ldd	#$FFFF		* init some registers
	ldy	#$FFFF
	ldu	#$FFFF
	leas	final,pcr	* prepare for clearing with PSHS
	
	leax	final,pcr	* clear rest of page
!	std	,x++
	cmpx	#$A000		
	blt	<	
	
	
	leax	zeros,pcr	* start clearing here
clrstop	nop
!	std	,x++		* clear
	cmpx	#$8000+SCREENSIZE+clrstop-app
	blt	<
		
	lbra	app		* 3 bytes run the main application
	

final	end	entrypt		* set BASIC exec address


*************************************************
* End of file
*************************************************


