lib.asm
defame-demogroup_c64_sa2019invite/libs/lib.asm


//Make accumulator negative value
.pseudocommand neg {
	clc
	eor #%11111111
	adc #$00
}

//absolute value of the accumulator
.pseudocommand abs {
	cmp #$80
	bmi !skip+
	clc
	eor #%11111111
	adc #$00
!skip:
}

.pseudocommand sadc value {
	clc
	adc value
}

.pseudocommand ssbc value {
	sec
	sbc value
}

/*
.pseudocommand gotoLTZ address {
	bit REG_NEGMASK
	beq address //if negative, skip
}

.pseudocommand gotoGTZ address {
	bit REG_NEGMASK
	bne address //if positive, skip
}

.pseudocommand gotoLTEZ address {
	bit REG_NEGMASK
	beq address //if negative, skip
	cmp #$00
	beq address
}

.pseudocommand gotoGTEZ address {
	bit REG_NEGMASK
	bne address //if positive, skip
	cmp #$00
	beq address
}
*/

/*
// x is number, y is remainder
.pseudocommand div number divisor {
	ldx #$00
	lda #$00
!pass:
	inx 
	clc
	adc divisor
	cmp number
	bcc !pass-
	sec
	sbc number
	tay
}
*/

/*
.pseudocommand smul2 arg {	
	lda arg
	clc
	asl
	bcs !forceNegative+
!forcePositive:
	and #%01111111
	jmp !skip+
!forceNegative:
	ora #%10000000
!skip:
}

.pseudocommand sdiv2 arg {	
	lda arg
	bit REG_NEGMASK
	beq !forceNegative+
!forcePositive:
	clc
	lsr
	jmp !skip+
!forceNegative:
	clc
	eor #%11111111
	adc #$01
	lsr
	clc
	eor #%11111111
	adc #$01
!skip:
}
*/

.pseudocommand mov src:tar {
	lda src
	sta tar
}

.pseudocommand mox src:tar {
	ldx src
	stx tar
}

.pseudocommand moy src:tar {
	ldy src
	sty tar
}

.function _16bit_nextArgument(arg) {
	.if (arg.getType()==AT_IMMEDIATE)
		.return CmdArgument(arg.getType(),>arg.getValue())
	.return CmdArgument(arg.getType(),arg.getValue()+1)
}

.pseudocommand inc16 arg {
	inc arg
	bne over
	inc _16bit_nextArgument(arg)
over:
}
.pseudocommand mov16 src:tar {
	lda src
	sta tar
	lda _16bit_nextArgument(src)
	sta _16bit_nextArgument(tar)
}
.pseudocommand add16 arg1 : arg2 : tar {
	.if (tar.getType()==AT_NONE) .eval tar=arg1
	lda arg1
	adc arg2
	sta tar
	lda _16bit_nextArgument(arg1)
	adc _16bit_nextArgument(arg2)
	sta _16bit_nextArgument(tar)
}

.macro waitX(count) {
	ldx #count
!loop:
	dex
	bne !loop-
}

.macro getRandom(delay) {
	lda #$ff  //; maximum frequency value
	sta $d40e //; voice 3 frequency low byte
	sta $d40f //; voice 3 frequency high byte
	lda #$80  //; noise waveform, gate bit off
	sta $d412 //; voice 3 control register
	ldx #delay
!delay:
	dex
	bne !delay-
	lda $d41b //; get the actual random number
}

.macro setupInterrupt(irq, scanline) {
	sei        //disable maskable IRQs

	lda #$7f
	sta $dc0d  //disable timer interrupts which can be generated by the two CIA chips
	sta $dd0d  //the kernal uses such an interrupt to flash the cursor and scan the keyboard, so we better stop it.

	lda $dc0d  //by reading this two registers we negate any pending CIA irqs.
	lda $dd0d  //if we don't do this, a pending CIA irq might occur after we finish setting up our irq. We don't want that to happen.

	lda #$01   //this is how to tell the VICII to generate a raster interrupt
	sta $d01a

	lda #<scanline   //this is how to tell at which rasterline we want the irq to be triggered
	sta $d012

	lda #>scanline   //as there are more than 256 rasterlines, the topmost bit of $d011 serves as
	beq clear
set:
	lda $d011
	ora #$80
	sta $d011
	jmp cont
clear:
	lda $d011
	and #$7f
	sta $d011
	
cont:
	lda #$35   //we turn off the BASIC and KERNAL rom here
	sta $01    //the cpu now sees RAM everywhere except at $d000-$e000, where still the registers of SID/VICII/etc are visible

	lda #<irq  //this is how we set up
	sta $fffe  //the address of our interrupt code
	lda #>irq
	sta $ffff

	cli        //enable maskable interrupts again
}

.macro startInterrupt() {
	pha
	txa
	pha
	tya
	pha

	lda #$ff   //this is the orthodox and safe way of clearing the interrupt condition of the VICII.
	sta $d019
}

.macro doubleIRQ(rasterline) {
	// rasterline is the y pos of the raster of the 1st of 2 double irq lines
////////////////////// Stabalize me baby
	:mov #<!irq2+: $fffe
	inc $d012
	
	tsx
	cli
	//these nops never really finish due to the raster IRQ triggering again
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
//---------------------------------------------------------------------------------------------------------------------
!irq2:
	txs
	ldx #$08
	dex
	bne *-1
	bit $ea
	nop

	lda #rasterline+1
	cmp $d012
	beq !cont+
!cont:	//////////////////////	the raster is now stable! \o/
}

.macro endInterrupt() {
	pla
	tay        //restore register Y from stack (remember stack is FIFO: First In First Out)
	pla
	tax        //restore register X from stack
	pla        //restore register A from stack
	rti
}

.macro fill_1K(val, mem) {
	ldx #$00
	lda #val
loop:
	sta mem,x
	sta mem+$100,x
	sta mem+$200,x
	sta mem+$300,x
	dex
	bne loop
}

.macro fill_2K(val, mem) {
	ldx #$00
	lda #val
loop:
	sta mem,x
	sta mem+$100,x
	sta mem+$200,x
	sta mem+$300,x
	sta mem+$400,x
	sta mem+$500,x
	sta mem+$600,x
	sta mem+$700,x
	dex
	bne loop
}

.macro fill_4K(val, mem) {
	ldx #$00
	lda #val
loop:
	sta mem,x
	sta mem+$100,x
	sta mem+$200,x
	sta mem+$300,x
	sta mem+$400,x
	sta mem+$500,x
	sta mem+$600,x
	sta mem+$700,x
	sta mem+$800,x
	sta mem+$900,x
	sta mem+$a00,x
	sta mem+$b00,x
	sta mem+$c00,x
	sta mem+$d00,x
	sta mem+$e00,x
	sta mem+$f00,x
	dex
	bne loop
}

.macro fill_8K(val, mem) {
	ldx #$00
	lda #val
loop:
	sta mem,x
	sta mem+$100,x
	sta mem+$200,x
	sta mem+$300,x
	sta mem+$400,x
	sta mem+$500,x
	sta mem+$600,x
	sta mem+$700,x
	sta mem+$800,x
	sta mem+$900,x
	sta mem+$a00,x
	sta mem+$b00,x
	sta mem+$c00,x
	sta mem+$d00,x
	sta mem+$e00,x
	sta mem+$f00,x
	sta mem+$1000,x
	sta mem+$1100,x
	sta mem+$1200,x
	sta mem+$1300,x
	sta mem+$1400,x
	sta mem+$1500,x
	sta mem+$1600,x
	sta mem+$1700,x
	sta mem+$1800,x
	sta mem+$1900,x
	sta mem+$1a00,x
	sta mem+$1b00,x
	sta mem+$1c00,x
	sta mem+$1d00,x
	sta mem+$1e00,x
	sta mem+$1f00,x
	dex
	bne loop
}

.macro setBank(bank) {
	lda $dd00
	and #%11111100
	ora #[3-bank] 
	sta $dd00
}

.macro setD018bmp(screen, bmp) {
	lda #[[screen*16]+[bmp*8]]
	sta $d018
}

.macro setD018char(screen, char) {
	lda #[[screen*16]+[char*2]]
	sta $d018
}

.macro setD011(bmp, rsel, yscroll) {
	lda $d011
	and #%11010000
	ora #[bmp*32] + [[rsel^1]*8] + yscroll
	sta $d011
}

.macro setD016(mcol, csel, xscroll) {
	lda $d016
	and #%11100000
	ora #[mcol*16] + [[csel^1]*8] + xscroll
	sta $d016	
}

//new ones added from Kick src
.function screenToD018(addr) {
	.return ((addr&$3fff)/$400)<<4
}
.function charsetToD018(addr) {
	.return ((addr&$3fff)/$800)<<1
}
.function toD018(screen, charset) {
	.return screenToD018(screen) | charsetToD018(charset)
}

.function toSpritePtr(addr) {
	.return (addr&$3fff)/$40
}

//sinus libs
.function sinus(i, amplitude, center, noOfSteps) {
	.return round(center+amplitude*sin(toRadians(i*360/noOfSteps)))	
}

.function cosinus(i, amplitude, center, noOfSteps) {
	.return round(center+amplitude*cos(toRadians(i*360/noOfSteps)))	
}

