diff --git a/c64/day09.asm b/c64/day09.asm new file mode 100644 index 0000000..867aeaa --- /dev/null +++ b/c64/day09.asm @@ -0,0 +1,596 @@ +// vim: filetype=kickass + +* = * "Day 09 Input" +!input: + .import text "../inputs/09" + .byte 0 + +* = * "Day 09 Code" + +day09: +{ +.const buffer = $b000 +.const buffer_end = $bfa0 + +.const input_pointer = $40 // $40..42 +.const atoi_result = $42 // $42..46 +.const buffer_pointer = $46 // $46..48 +.const outer_pointer = $48 // $48..4a +.const middle_pointer = $4a // $4a..4c +.const inner_pointer = $4c // $4c..4e +.const part1 = $4e // $4e..52 + +.const lower_pointer = $52 // $52..54 +.const upper_pointer = $54 // $54..56 +.const sum = $56 // $56..5a + +.const min_value = $5a // $5a..5e +.const max_value = $5e // $5e..62 + + + // XXX I'm using 32 bit integers for this day, even though some + // inputs are 64 bit. Seems like I get away with it though. + move_16_imm($03, !str_title+) + jsr write_string + + move_16_imm(input_pointer, !input-) + move_16_imm(buffer_pointer, buffer) + + ldy #0 +!line: + // 32-bit integer to store the result in. + lda #0 + sta atoi_result + 0 + sta atoi_result + 1 + sta atoi_result + 2 + sta atoi_result + 3 + +!digit: + // Check for the newline character at the end of the line. + lda (input_pointer), y + cmp #'\n' + beq !newline+ + + // Multiply the stored number by 10. + u32_mul10(atoi_result) + + // Subtract '0' from the current digit to convert it to binary. + lda (input_pointer), y + sec + sbc #'0' + + // Add the binary digit to the stored number + i32_add_a(atoi_result) + + y_buf_inc(input_pointer) + jmp !digit- + +!newline: + sty zp_temp + ldy #0 + + lda atoi_result + 0 + sta (buffer_pointer), y + iny + + lda atoi_result + 1 + sta (buffer_pointer), y + iny + + lda atoi_result + 2 + sta (buffer_pointer), y + iny + + lda atoi_result + 3 + sta (buffer_pointer), y + + lda buffer_pointer + clc + adc #4 + sta buffer_pointer + bcc !cc+ + inc buffer_pointer + 1 + !cc: + + ldy zp_temp + + y_buf_inc(input_pointer) + + // Check for the null terminator. + lda (input_pointer), y + beq !done+ + jmp !line- + +!done: + // outer for loop initial value + // outer_pointer = buffer + 25 + lda #<(buffer + 25 * 4) + sta outer_pointer + 0 + lda #>(buffer + 25 * 4) + sta outer_pointer + 1 + + !outer: + + // middle for loop initial value + // middle_pointer = outer_pointer - 25 + sec + lda outer_pointer + 0 + sbc #(25 * 4) + sta middle_pointer + 0 + lda outer_pointer + 1 + sbc #0 + sta middle_pointer + 1 + + // TODO if *middle_pointer > *outer_pointer: continue + + !middle: + + // inner_pointer = middle_pointer + 1 + clc + lda middle_pointer + 0 + adc #(1 * 4) + sta inner_pointer + 0 + lda middle_pointer + 1 + adc #0 + sta inner_pointer + 1 + + !inner: + + // if *inner_pointer + *middle_pointer == *outer_pointer: + // continue 'outer; + + // *atoi_result = *inner_pointer + *middle_pointer + clc + + ldy #0 + lda (inner_pointer), y + adc (middle_pointer), y + sta (atoi_result), y + + iny + lda (inner_pointer), y + adc (middle_pointer), y + sta (atoi_result), y + + iny + lda (inner_pointer), y + adc (middle_pointer), y + sta (atoi_result), y + + iny + lda (inner_pointer), y + adc (middle_pointer), y + sta (atoi_result), y + + // if *atoi_result == *outer_pointer: + ldy #0 + lda (atoi_result), y + cmp (outer_pointer), y + bne !not_equal+ + + iny + lda (atoi_result), y + cmp (outer_pointer), y + bne !not_equal+ + + iny + lda (atoi_result), y + cmp (outer_pointer), y + bne !not_equal+ + + iny + lda (atoi_result), y + cmp (outer_pointer), y + bne !not_equal+ + + // continue 'outer; + jmp !middle_done+ + + !not_equal: + + // inner for loop increment + // *inner_pointer += 1 * 4 + clc + lda inner_pointer + 0 + adc #4 + sta inner_pointer + 0 + bcc !+ + inc inner_pointer + 1 + !: + + // inner for loop conditional + // inner_pointer != outer_pointer + lda inner_pointer + 0 + cmp outer_pointer + 0 + bne !inner- + + lda inner_pointer + 1 + cmp outer_pointer + 1 + bne !inner- + + // for loop increment + // *middle_pointer += 1 * 4 + clc + lda middle_pointer + 0 + adc #4 + sta middle_pointer + 0 + bcc !+ + inc middle_pointer + 1 + !: + + // for loop conditional + // middle_pointer != outer_pointer + lda middle_pointer + 0 + cmp outer_pointer + 0 + bne !middle_continue+ + + lda middle_pointer + 1 + cmp outer_pointer + 1 + bne !middle_continue+ + + jmp !outer_done+ + + !middle_continue: + jmp !middle- + + !middle_done: + + // outer for loop increment + // *outer_pointer += 1 * 4 + clc + lda outer_pointer + 0 + adc #4 + sta outer_pointer + 0 + bcc !+ + inc outer_pointer + 1 + !: + + // outer for loop conditional + // *outer_pointer != $cfa0 + lda outer_pointer + 0 + cmp #$a0 + bne !outer_continue+ + + lda outer_pointer + 1 + cmp #$bf + bne !outer_continue+ + + jmp * + + !outer_continue: + jmp !outer- + + + !outer_done: + + // print (part1 = *outer_pointer) + ldy #0 + lda (outer_pointer), y + sta part1 + 0 + sta udivmod32_dividend + 0 + + iny + lda (outer_pointer), y + sta part1 + 1 + sta udivmod32_dividend + 1 + + iny + lda (outer_pointer), y + sta part1 + 2 + sta udivmod32_dividend + 2 + + iny + lda (outer_pointer), y + sta part1 + 3 + sta udivmod32_dividend + 3 + + jsr print_decimal_u32 + + + lda #0 + sta lower_pointer + 0 + sta upper_pointer + 0 + sta sum + 0 + sta sum + 1 + sta sum + 2 + sta sum + 3 + lda #$b0 + sta lower_pointer + 1 + sta upper_pointer + 1 + + !outer: + !upper: + // while sum < part1 + lda sum + 3 + cmp part1 + 3 + beq !+ // sum[3] == part1[3] + bcc !upper_success+ // sum[3] < part1[3] => sum < part + bcs !lower+ // sum[3] >= part1[3] => sum > part + + !: + lda sum + 2 + cmp part1 + 2 + beq !+ // sum[2] == part1[2] + bcc !upper_success+ // sum[2] < part1[2] => sum < part + bcs !lower+ // sum[2] >= part1[2] => sum > part + + !: + lda sum + 1 + cmp part1 + 1 + beq !+ // sum[1] == part1[1] + bcc !upper_success+ // sum[1] < part1[1] => sum < part + bcs !lower+ // sum[1] >= part1[1] => sum > part + + !: + lda sum + 0 + cmp part1 + 0 + beq !outer_end+ // sum[0] == part1[0] => sum == part + bcs !lower+ // sum[0] >= part1[0] => sum > part + + !upper_success: + // sum += *upper_pointer + ldy #0 + clc + + lda sum + 0 + adc (upper_pointer), y // (upper_pointer) + 0 + sta sum + 0 + iny + + lda sum + 1 + adc (upper_pointer), y // (upper_pointer) + 1 + sta sum + 1 + iny + + lda sum + 2 + adc (upper_pointer), y // (upper_pointer) + 2 + sta sum + 2 + iny + + lda sum + 3 + adc (upper_pointer), y // (upper_pointer) + 3 + sta sum + 3 + + // upper_pointer += 1 * 4; + clc + lda upper_pointer + 0 + adc #4 + sta upper_pointer + 0 + bcc !+ + inc upper_pointer + 1 + !: + + jmp !upper- + + !outer_end: + // Hidden shortcut to outer_end because the jump was too long + jmp !outer_end+ + + !lower: + // while sum > part1 + lda sum + 3 + cmp part1 + 3 + beq !+ // sum[3] == part1[3] + bcc !outer- // sum[3] < part[3] => sum < part + bcs !lower_success+ // sum[3] >= part[3] => sum > part + + !: + lda sum + 2 + cmp part1 + 2 + beq !+ // sum[2] == part1[2] + bcc !outer- // sum[2] < part[2] => sum < part + bcs !lower_success+ // sum[2] >= part[2] => sum > part + + !: + lda sum + 1 + cmp part1 + 1 + beq !+ // sum[1] == part1[1] + bcc !outer- // sum[1] < part[1] => sum < part + bcs !lower_success+ // sum[1] >= part[1] => sum > part + + !: + lda sum + 0 + cmp part1 + 0 + beq !outer_end+ // sum[0] == part1[0] + bcs !outer- // sum[0] < part[0] => sum < part + + !lower_success: + // sum -= *lower_pointer + ldy #0 + sec + + lda sum + 0 + sbc (lower_pointer), y // (lower_pointer) + 0 + sta sum + 0 + iny + + lda sum + 1 + sbc (lower_pointer), y // (lower_pointer) + 1 + sta sum + 1 + iny + + lda sum + 2 + sbc (lower_pointer), y // (lower_pointer) + 2 + sta sum + 2 + iny + + lda sum + 3 + sbc (lower_pointer), y // (lower_pointer) + 3 + sta sum + 3 + + // lower_pointer += 1 * 4; + clc + lda lower_pointer + 0 + adc #4 + sta lower_pointer + 0 + bcc !+ + inc lower_pointer + 1 + !: + + jmp !lower- + !lower_end: + + !outer_end: + + // Find the minimum and maximum values + lda #$ff + sta min_value + 0 + sta min_value + 1 + sta min_value + 2 + sta min_value + 3 + + lda #$00 + sta max_value + 0 + sta max_value + 1 + sta max_value + 2 + sta max_value + 3 + + !loop: + ldy #3 + lda (lower_pointer), y // lower[i] >> 24 + cmp min_value + 3 + beq !+ + bcs !not_less+ + bcc !less+ + !: + dey + lda (lower_pointer), y // lower[i] >> 16 + cmp min_value + 2 + beq !+ + bcs !not_less+ + bcc !less+ + !: + dey + lda (lower_pointer), y // lower[i] >> 8 + cmp min_value + 1 + beq !+ + bcs !not_less+ + bcc !less+ + !: + dey + lda (lower_pointer), y // lower[i] >> 0 + cmp min_value + 0 + bcs !not_less+ + + !less: + + ldy #0 + lda (lower_pointer), y + sta min_value + 0 + iny + + lda (lower_pointer), y + sta min_value + 1 + iny + + lda (lower_pointer), y + sta min_value + 2 + iny + + lda (lower_pointer), y + sta min_value + 3 + + !not_less: + + ldy #3 + lda (lower_pointer), y // lower[i] >> 24 + cmp max_value + 3 + beq !+ + bcc !not_more+ + bcs !more+ + !: + dey + lda (lower_pointer), y // lower[i] >> 16 + cmp max_value + 2 + beq !+ + bcc !not_more+ + bcs !more+ + !: + dey + lda (lower_pointer), y // lower[i] >> 8 + cmp max_value + 1 + beq !+ + bcc !not_more+ + bcs !more+ + !: + dey + lda (lower_pointer), y // lower[i] >> 0 + cmp max_value + 0 + bcc !not_more+ + + !more: + + ldy #0 + lda (lower_pointer), y + sta max_value + 0 + iny + + lda (lower_pointer), y + sta max_value + 1 + iny + + lda (lower_pointer), y + sta max_value + 2 + iny + + lda (lower_pointer), y + sta max_value + 3 + + !not_more: + + clc + lda lower_pointer + 0 + adc #4 + sta lower_pointer + 0 + bcc !+ + inc lower_pointer + 1 + !: + + // for loop condition + // lower_pointer != upper_pointer + cmp upper_pointer + 0 + bne !+ + lda lower_pointer + 1 + cmp upper_pointer + 1 + beq !end+ + !: + + jmp !loop- + + !end: + + clc + lda min_value + 0 + adc max_value + 0 + sta udivmod32_dividend + 0 + + lda min_value + 1 + adc max_value + 1 + sta udivmod32_dividend + 1 + + lda min_value + 2 + adc max_value + 2 + sta udivmod32_dividend + 2 + + lda min_value + 3 + adc max_value + 3 + sta udivmod32_dividend + 3 + + move_16_imm($03, str_part2) + jsr write_string + + jsr print_decimal_u32 + + move_16_imm($03, str_done) + jsr write_string + + jmp * + rts +} + + +!str_title: + .text "# Day 09" + .byte '\n', '\n' + .text "Part 1: " + .byte 0