diff --git a/Makefile b/Makefile index 620bcb2..cb3dbc1 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ all: m4 < $< > $@ %.bin: %.asm - $(HOME)/6502-asm/main $< $@ + $(HOME)/6502-asm/main $^ $@ %.rom: %.bin python $(HOME)/6502-asm/link.py $< $@ @@ -17,6 +17,8 @@ all: clean: rm -f *.bin *.rom +aoc/2020/day1/solution.bin: aoc/2020/day1/solution.asm aoc/mul24.asm aoc/hex.asm aoc/lcd.asm aoc/2020/day1/input.bin + .SUFFIXES: .INTERMEDIATE: .PRECIOUS: %.bin %.rom %.asm diff --git a/aoc/2020/day1/solution.asm b/aoc/2020/day1/solution.asm new file mode 100644 index 0000000..53468c9 --- /dev/null +++ b/aoc/2020/day1/solution.asm @@ -0,0 +1,101 @@ + ;; uint16_t * input; + ;; uint8_t * input_len = 0; + ;; uint16_t * input_j = 2; + ;; uint16_t * input_k = 4; + ;; uint8_t * k_index = 1; + BRA r :reset ; RESB + NOP i ; IRQB + + ;; reset stack +reset: LDX # ff + TXS i + + ;; *input_k = input + LDA # :_bin_aoc/2020/day1/input_start_l + STA zp 4 + LDA # :_bin_aoc/2020/day1/input_start_h + STA zp 5 + + ;; *input_len = _bin_aoc/2020/day1/input_size / 2 + LDA # :_bin_aoc/2020/day1/input_size_h + LSR A + LDA # :_bin_aoc/2020/day1/input_size_l + ROR A + STA zp 0 + + ;; *k_index = *input_len + STA zp 1 + + +_day1_loopx: LDA # :_bin_aoc/2020/day1/input_start_l ;; + STA zp 2 ;; + LDA # :_bin_aoc/2020/day1/input_start_h ;; + STA zp 3 ;; *input_j = input + LDA zp 0 ;; (input_size) + TAX i ;; X = *input_len + +_day1_loop: CLC i ;; /* 16-bit addition+comparison (lower byte) */ + LDY # 0 ;; + LDA (zp),y 2 ;; + ADC (zp),y 4 ;; A = ((uint8_t *)(*input_j))[0] + ((uint8_t *)(*input_k))[0] + PHP s ;; + CMP # e4 ;; + BNE r :_day1_next ;; if (A != 0xE4) goto _next + + PLP s ;; /* 16-bit addition+comparison (upper byte) */ + LDY # 1 ;; + LDA (zp),y 2 ;; + ADC (zp),y 4 ;; A = ((uint8_t *)(*input_j))[1] + ((uint8_t *)(*input_k))[1] + CMP # 07 ;; + BEQ r :_day1_found ;; if (A == 0x07) goto _found + +_day1_next: CLC i ;; + LDA zp 2 ;; + ADC # 2 ;; + STA zp 2 ;; + LDA zp 3 ;; + ADC # 0 ;; + STA zp 3 ;; *input_j = *input_j + 2 + DEX i ;; + BNE r :_day1_loop ;; if (--X != 0) goto _loop + + CLC i ;; + LDA zp 4 ;; + ADC # 2 ;; + STA zp 4 ;; + LDA zp 5 ;; + ADC # 0 ;; + STA zp 5 ;; *input_k = *input_k + 2 + LDY zp 1 ;; + DEY i ;; + STY zp 1 ;; *k_index = k_index - 1; + BNE r :_day1_loopx ;; if (*k_index != 0) goto _loopx + +_day1_notfound: BRA r :_day1_notfound + +_day1_found: LDX # 8 + LDY # 0 ;; copy **input_j and **input_k to mul24 `a` and `b` arguments + LDA (zp),y 2 ;; + STA zp,x 0 ;; + LDA (zp),y 4 ;; + STA zp,x 3 ;; + ;; + LDY # 1 ;; + LDA (zp),y 2 ;; + STA zp,x 1 ;; + LDA (zp),y 4 ;; + STA zp,x 4 ;; + ;; + LDA # 0 ;; + STA zp,x 2 ;; + STA zp,x 5 ;; + + JSR a :mul24 + + JSR a :lcd_reset + + LDX # 10 + LDY # 3 + JSR a :lcd_hex + +_day1_stop: BRA r :_day1_stop diff --git a/aoc/hex.asm b/aoc/hex.asm new file mode 100644 index 0000000..80283cd --- /dev/null +++ b/aoc/hex.asm @@ -0,0 +1,39 @@ +;; +;; +;; args: +;; X: zero page offset +;; Y: length +lcd_hex: NOP i + + ;; top nib +_hex_loop: LDA zp,x 0 + LSR A + LSR A + LSR A + LSR A + CMP # a + BCS r :_hex_nib0_af +_hex_nib0_09: CLC i + ADC # 30 + BRA r :_hex_nib0_out +_hex_nib0_af: CLC i + ADC # 37 +_hex_nib0_out: JSR a :lcd_w_rs1 + + ;; bottom nib + LDA zp,x 0 + AND # f + CMP # a + BCS r :_hex_nib1_af +_hex_nib1_09: CLC i + ADC # 30 + BRA r :_hex_nib1_out +_hex_nib1_af: CLC i + ADC # 37 +_hex_nib1_out: JSR a :lcd_w_rs1 + + DEX i + DEY i + BNE r :_hex_loop + + RTS s diff --git a/aoc/lcd.asm.in b/aoc/lcd.asm.in new file mode 100644 index 0000000..d75c193 --- /dev/null +++ b/aoc/lcd.asm.in @@ -0,0 +1,85 @@ +include(`common.m4') + +;;; begin lcd_reset + ;; Set pins 0-2 on Port A to Output +lcd_reset: LDA # %00000111 + STA a DDRA + + ;; Function Set: + ;; D7 D6 D5 D4 D3 D2 D1 D0 + ;; 0 0 1 B L F x x + ;; (Bits 8/4, Lines 2/1, Font 5x11/5x8) + LDA # %00111000 + JSR a :lcd_w_rs0 + + ;; Clear Display: + ;; D7 D6 D5 D4 D3 D2 D1 D0 + ;; 0 0 0 0 0 0 0 1 + LDA # %00000001 + JSR a :lcd_w_rs0 + + ;; Entry Mode Set: + ;; D7 D6 D5 D4 D3 D2 D1 D0 + ;; 0 0 0 0 0 1 I/D S + ;; (Increment/Decrement, Shift) + LDA # %00000110 + JSR a :lcd_w_rs0 + + ;; Display ON/OFF: + ;; D7 D6 D5 D4 D3 D2 D1 D0 + ;; 0 0 0 0 0 D C B + ;; (Display, Cursor, Blink) + LDA # %00001110 + JSR a :lcd_w_rs0 + + RTS s +;;; end lcd_reset + + + ;; write "instruction" +lcd_w_rs0: JSR a :lcd_wait + + STA a PORTB + LDA # 0 + STA a PORTA + LDA # hh(L_E) + STA a PORTA + LDA # 0 + STA a PORTA + RTS s + + ;; write "data" to lcd +lcd_w_rs1: JSR a :lcd_wait + + STA a PORTB + LDA # hh(L_RS) + STA a PORTA + LDA # hh(L_RS|L_E) + STA a PORTA + LDA # hh(L_RS) + STA a PORTA + RTS s + +;;; begin lcd_wait +lcd_wait: PHA s + + LDA # %00000000 ;; Set pins 0-7 on Port B to Input + STA a DDRB + +_lcd_wait: LDA # hh(L_RW) + STA a PORTA + LDA # hh(L_E|L_RW) + STA a PORTA + LDA a PORTB + AND # %10000000 + BNE r :_lcd_wait + + LDA # hh(L_RW) + STA a PORTA + + LDA # %11111111 ;; Set pins 0-7 on Port B to Output + STA a DDRB + + PLA s + RTS s +;;; end lcd_wait diff --git a/aoc/mul24.asm b/aoc/mul24.asm new file mode 100644 index 0000000..ec4cf07 --- /dev/null +++ b/aoc/mul24.asm @@ -0,0 +1,46 @@ +;; multiply two 24-bit operands; 24-bit product +;; +;; r = a * b +;; +;; args: +;; X: zero page offset +;; uint24_t * a = [0, 1, 2] +;; uint24_t * b = [3, 4, 5] +;; uint24_t * r = [6, 7, 8] + +mul24: LDA # 0 + STA zp,x 6 + STA zp,x 7 + STA zp,x 8 + +_mul24_loop: LDA zp,x 0 ;; while (a) { + ORA zp,x 1 ;; + ORA zp,x 2 ;; + BEQ r :_mul24_ret ;; + + LDA # 1 ;; if (a & 1) + AND zp,x 0 ;; + BEQ r :_mul24_nand_1 ;; + + CLC i ;; r += b; + LDA zp,x 3 ;;; 7..0 + ADC zp,x 6 ;; + STA zp,x 6 ;; + LDA zp,x 4 ;;; 15..8 + ADC zp,x 7 ;; + STA zp,x 7 ;; + LDA zp,x 5 ;;; 23..16 + ADC zp,x 8 ;; + STA zp,x 8 ;; + +_mul24_nand_1: LSR zp,x 2 ;; a >>= 1 + ROR zp,x 1 ;; + ROR zp,x 0 ;; + + ASL zp,x 3 ;; b <<= 1 + ROL zp,x 4 ;; + ROL zp,x 5 ;; + + JMP a :_mul24_loop ;; } + +_mul24_ret: RTS s ;; return; diff --git a/wink.asm.in b/wink.asm.in index 3eea2d8..2de5fc0 100644 --- a/wink.asm.in +++ b/wink.asm.in @@ -1,6 +1,9 @@ ; -*-asm-*- include(`common.m4') + BRA r :reset ; RESB + NOP i ; IRQ + ;; reset stack reset: LDX # ff TXS i