From 8ee90a535cd4aa695dd48bb80e0a0f6e2b95a2dc Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Tue, 12 Aug 2025 23:03:08 -0500 Subject: [PATCH] scu-dsp/advent: use div10_unsigned and unparse_base10 from lib --- Makefile | 12 +-- scu-dsp/advent/2020/day1/init.bat | 3 + scu-dsp/advent/2020/day1/input.bin.h | 5 + scu-dsp/advent/2020/day1/loader.cpp | 51 ++++++++++ scu-dsp/advent/2020/day1/runner.asm.m4 | 46 +++++++++ scu-dsp/advent/2020/day1/runner.dsp.h | 5 + scu-dsp/advent/2020/day1/runner.m4.asm | 16 --- scu-dsp/advent/2020/day1/solution.asm | 12 ++- scu-dsp/advent/2020/day1/solution.dsp.h | 5 + scu-dsp/advent/2020/day1/solve.py | 9 ++ scu-dsp/advent/advent.mk | 10 ++ scu-dsp/lib/div10_unsigned.asm | 10 +- scu-dsp/lib/unparse_base10.asm | 17 ++-- scu-dsp/scu-dsp.mk | 12 +++ scu-dsp/vdp2_text.cpp | 128 ++++++++++++++++++++++++ scu-dsp/vdp2_text.hpp | 3 + 16 files changed, 303 insertions(+), 41 deletions(-) create mode 100644 scu-dsp/advent/2020/day1/init.bat create mode 100644 scu-dsp/advent/2020/day1/input.bin.h create mode 100644 scu-dsp/advent/2020/day1/loader.cpp create mode 100644 scu-dsp/advent/2020/day1/runner.asm.m4 create mode 100644 scu-dsp/advent/2020/day1/runner.dsp.h delete mode 100644 scu-dsp/advent/2020/day1/runner.m4.asm create mode 100644 scu-dsp/advent/2020/day1/solution.dsp.h create mode 100644 scu-dsp/advent/2020/day1/solve.py create mode 100644 scu-dsp/advent/advent.mk create mode 100644 scu-dsp/scu-dsp.mk create mode 100644 scu-dsp/vdp2_text.cpp create mode 100644 scu-dsp/vdp2_text.hpp diff --git a/Makefile b/Makefile index 3cc46b2..9ba5182 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST))))) + CFLAGS = -Isaturn -I. -D__saturn__ OPT ?= -O2 LIB = ./saturn @@ -173,14 +175,8 @@ editor/main_saturn.elf: editor/main_saturn.o res/nec.bitmap.bin.o res/nec_bold.b cdc/cdc.elf: cdc/cdc.o saturn/start.o memcpy.o cdc/serial.o -scu-dsp/add.elf: scu-dsp/add.o saturn/start.o cdc/serial.o scu-dsp/input.bin.o - -scu-dsp/div10.elf: scu-dsp/div10.o saturn/start.o cdc/serial.o scu-dsp/div10.dsp.o - -scu-dsp/div10_vdp2.elf: scu-dsp/div10_vdp2.o saturn/start.o cdc/serial.o scu-dsp/div10_vdp2.dsp.o font/hp_100lx_4bit_flip.data.o - -%.dsp: %.asm - ~/scu-dsp-asm/scu-dsp-asm $< $@ +include scu-dsp/scu-dsp.mk +include scu-dsp/advent/advent.mk # clean clean: clean-sh diff --git a/scu-dsp/advent/2020/day1/init.bat b/scu-dsp/advent/2020/day1/init.bat new file mode 100644 index 0000000..3eda4b1 --- /dev/null +++ b/scu-dsp/advent/2020/day1/init.bat @@ -0,0 +1,3 @@ +mount y . +Y: +dspsim.exe diff --git a/scu-dsp/advent/2020/day1/input.bin.h b/scu-dsp/advent/2020/day1/input.bin.h new file mode 100644 index 0000000..29364dc --- /dev/null +++ b/scu-dsp/advent/2020/day1/input.bin.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_scu_dsp_advent_2020_day1_input_bin_start __asm("_binary_scu_dsp_advent_2020_day1_input_bin_start"); +extern uint32_t _binary_scu_dsp_advent_2020_day1_input_bin_end __asm("_binary_scu_dsp_advent_2020_day1_input_bin_end"); +extern uint32_t _binary_scu_dsp_advent_2020_day1_input_bin_size __asm("_binary_scu_dsp_advent_2020_day1_input_bin_size"); diff --git a/scu-dsp/advent/2020/day1/loader.cpp b/scu-dsp/advent/2020/day1/loader.cpp new file mode 100644 index 0000000..d4935fd --- /dev/null +++ b/scu-dsp/advent/2020/day1/loader.cpp @@ -0,0 +1,51 @@ +#include "cdc/serial.h" +#include "scu.h" + +#include "scu-dsp/advent/2020/day1/runner.dsp.h" +#include "scu-dsp/advent/2020/day1/input.bin.h" + +#include "scu-dsp/vdp2_text.hpp" + +void main() +{ + vdp2_text_init(); + + scu.reg.PPAF = 0; // stop execution + scu.reg.PPAF = (1 << 15) | 0; // reset PC + + uint32_t * program = (uint32_t *)&_binary_scu_dsp_advent_2020_day1_runner_dsp_start; + int program_length = ((int)&_binary_scu_dsp_advent_2020_day1_runner_dsp_size) / 4; + + for (int i = 0; i < program_length; i++) { + uint32_t p = program[i]; + scu.reg.PPD = p; + //serial_integer(p, 8, '\n'); + } + + uint32_t * data = (uint32_t *)&_binary_scu_dsp_advent_2020_day1_input_bin_start; + int data_length = ((int)&_binary_scu_dsp_advent_2020_day1_input_bin_size) / 4; + + scu.reg.PDA = 64 * 0; // m0[0] + for (int j = 0; j < 2; j++) { + for (int i = 0; i < data_length; i++) { + uint32_t d = data[i]; + scu.reg.PDD = d; + } + } + + scu.reg.PPAF = (1 << 15) | 0; // reset PC + scu.reg.PPAF = (1 << 16); // execute + + int end_flag = 0; + while (end_flag == 0) { + end_flag = (scu.reg.PPAF >> 18) & 1; + } + + scu.reg.PPAF = 0; + scu.reg.PDA = 64 * 3 + 56; // m3[56] + + serial_string("answer:\n"); + for (int i = 0; i < 8; i++) { + serial_integer(scu.reg.PDD, 8, '\n'); + } +} diff --git a/scu-dsp/advent/2020/day1/runner.asm.m4 b/scu-dsp/advent/2020/day1/runner.asm.m4 new file mode 100644 index 0000000..7ce1213 --- /dev/null +++ b/scu-dsp/advent/2020/day1/runner.asm.m4 @@ -0,0 +1,46 @@ + ;; + ;; runner + ;; + + ;; argument: m0, m1 + include(`solution.asm') + ;; fallthrough: solution in A + + ;; [X ] [Y ] [D1 ] + mov 0,ct2 + mov all,mc2 + + ;; + ;; libraries + ;; + + ;; argument: m2[0] + include(`lib/unparse_base10.asm') + ;; fallthrough: base10 characters in m3[56:63] + + jmp vdp2_display + ;; [X ] [Y ] [D1 ] + mov (64 - 8),ct3 ; delay slot + + ;; argument: Y + include(`lib/div10_unsigned.asm') + ;; return: A + + ;; + ;; transfer to vdp2 + ;; +vdp2_display: + ;; vdp2 address calculation + mvi ((8 * 0x4000 + (64 - 8) * 4 + 0x05e00000) >> 2),wa0 + ;; [X ] [Y ] [D1 ] + ;; end vdp2 address calculation + dma1 mc3,d0,8 +dma_wait: + jmp t0,dma_wait + nop + + ;; + ;; end of program + ;; + endi + nop diff --git a/scu-dsp/advent/2020/day1/runner.dsp.h b/scu-dsp/advent/2020/day1/runner.dsp.h new file mode 100644 index 0000000..8e0af6c --- /dev/null +++ b/scu-dsp/advent/2020/day1/runner.dsp.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_scu_dsp_advent_2020_day1_runner_dsp_start __asm("_binary_scu_dsp_advent_2020_day1_runner_dsp_start"); +extern uint32_t _binary_scu_dsp_advent_2020_day1_runner_dsp_end __asm("_binary_scu_dsp_advent_2020_day1_runner_dsp_end"); +extern uint32_t _binary_scu_dsp_advent_2020_day1_runner_dsp_size __asm("_binary_scu_dsp_advent_2020_day1_runner_dsp_size"); diff --git a/scu-dsp/advent/2020/day1/runner.m4.asm b/scu-dsp/advent/2020/day1/runner.m4.asm deleted file mode 100644 index b51bb74..0000000 --- a/scu-dsp/advent/2020/day1/runner.m4.asm +++ /dev/null @@ -1,16 +0,0 @@ - ;; - ;; transfer to vdp2 - ;; - - ;; vdp2 address calculation - mvi ((8 * 0x4000 + (64 - 8) * 4 + 0x05e00000) >> 2),wa0 - mov 0,ct3 - ;; clr a mov 0,ct3 - ;; add mov alu,a - ;; mov all,wa0 - - ;; end vdp2 address calculation - dma1 mc3,d0,8 -dma_wait: - jmp t0,dma_wait - nop diff --git a/scu-dsp/advent/2020/day1/solution.asm b/scu-dsp/advent/2020/day1/solution.asm index 242c44f..2bad145 100644 --- a/scu-dsp/advent/2020/day1/solution.asm +++ b/scu-dsp/advent/2020/day1/solution.asm @@ -46,7 +46,7 @@ loop_inner: btm ;; increment ct1 (A discarded) - mov mc1,a ; (delay slot) + mov mc1,a ; (delay slot) ;; increment ct0 (A discarded) mov mc0,a @@ -60,11 +60,15 @@ loop_exit_test: mov all,lop ; (delay slot) not_found: - jmp end - clr a ; (delay slot) + jmp return + clr a ; (delay slot) found: ;; [X ] [Y ] [D1 ] mov m1,x mov m0,y clr a mov mul,p add mov alu,a ; (delay slot) -end: +return: + ;;mov 0,ct0 + ;;mov all,mc0 + ;;endi + ;;nop diff --git a/scu-dsp/advent/2020/day1/solution.dsp.h b/scu-dsp/advent/2020/day1/solution.dsp.h new file mode 100644 index 0000000..6e07fe0 --- /dev/null +++ b/scu-dsp/advent/2020/day1/solution.dsp.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_scu_dsp_advent_2020_day1_solution_dsp_start __asm("_binary_scu_dsp_advent_2020_day1_solution_dsp_start"); +extern uint32_t _binary_scu_dsp_advent_2020_day1_solution_dsp_end __asm("_binary_scu_dsp_advent_2020_day1_solution_dsp_end"); +extern uint32_t _binary_scu_dsp_advent_2020_day1_solution_dsp_size __asm("_binary_scu_dsp_advent_2020_day1_solution_dsp_size"); diff --git a/scu-dsp/advent/2020/day1/solve.py b/scu-dsp/advent/2020/day1/solve.py new file mode 100644 index 0000000..158b577 --- /dev/null +++ b/scu-dsp/advent/2020/day1/solve.py @@ -0,0 +1,9 @@ +import sys + +with open(sys.argv[1]) as f: + data = list(map(int, f.read().strip().split())) + +for a in data: + for b in data: + if a + b == 2020: + print(a, b, a * b) diff --git a/scu-dsp/advent/advent.mk b/scu-dsp/advent/advent.mk new file mode 100644 index 0000000..2c01c47 --- /dev/null +++ b/scu-dsp/advent/advent.mk @@ -0,0 +1,10 @@ +DAY1_OBJ = \ + saturn/start.o \ + scu-dsp/advent/2020/day1/loader.o \ + cdc/serial.o \ + scu-dsp/advent/2020/day1/runner.dsp.o \ + scu-dsp/advent/2020/day1/input.bin.o \ + scu-dsp/vdp2_text.o \ + font/hp_100lx_4bit_flip.data.o + +scu-dsp/advent/2020/day1/main.elf: $(DAY1_OBJ) diff --git a/scu-dsp/lib/div10_unsigned.asm b/scu-dsp/lib/div10_unsigned.asm index 083afb9..236cbc0 100644 --- a/scu-dsp/lib/div10_unsigned.asm +++ b/scu-dsp/lib/div10_unsigned.asm @@ -2,9 +2,9 @@ ;; function: div10_unsigned ;; - ;; argument: ry - ;; return: a ← ry / 10 - ;; maximum ry is somewhere between 2 ^ 21 and 2 ^ 22 + ;; argument: y + ;; return: a ← y / 10 + ;; maximum y is somewhere between 2 ^ 21 and 2 ^ 22 div10_unsigned: ;; 1 / 10 * (2 ^ 24) ~= 1677722 = 0x19999a mvi 1677722,rx @@ -29,6 +29,6 @@ div10_unsigned: ;; mask 24 bit result mvi 0xffffff,pl - ;; return to caller ; reset ct0 + ;; return to caller; reset caller's ct2 btm - and mov alu,a mov 0,ct0 + and mov alu,a mov 0,ct2 diff --git a/scu-dsp/lib/unparse_base10.asm b/scu-dsp/lib/unparse_base10.asm index 970fc2d..1a7cb5b 100644 --- a/scu-dsp/lib/unparse_base10.asm +++ b/scu-dsp/lib/unparse_base10.asm @@ -3,10 +3,11 @@ ;; ;; argument: m2[0] - ;; return: base10 + 16 in m3[56 - 63] + ;; return: base10 + 16 in m3[56:63] ;; requires: div10_unsigned + ;; [X ] [Y ] [D1 ] unparse_base10: ;; clear end of m3 mov (64 - 8),ct3 @@ -22,19 +23,19 @@ unparse_base10_loop: ;; [X ] [Y ] [D1 ] mov mc2,y mov 1,lop ; mvi imm,pc delay slot (executed twice) ;; after function return: - mov all,mc0 ; m0[1] (1234) + mov all,mc2 ; m2[1] (1234) mov all,pl ;; mod10: multiply by 10: sl mov alu,a sl mov alu,a sl mov alu,a add mov alu,a - add mov alu,a mov 0,ct0 ; restore ct0 after 'mov all,mc1' + add mov alu,a mov 0,ct2 ; restore ct2 after 'mov all,mc2' ;; a: 12340 - mov mc0,a mov all,pl + mov mc2,a mov all,pl - ;; a: 12345 m0[0] + ;; a: 12345 m2[0] ;; p: 12340 ;; mod10: subtract (a - p) @@ -46,12 +47,12 @@ unparse_base10_loop: add mov alu,a ;; store digit in m3 - mov mc0,p clr a mov all,mc3 ; m0[1] + mov mc2,p clr a mov all,mc3 ; m2[1] ;; p: 1234 ;; a: 0 - add mov alu,a mov 0,ct0 + add mov alu,a mov 0,ct2 ;; a: 1234 jmp nz,unparse_base10_loop - mov all,mc0 ; jmp delay slot + mov all,mc2 ; jmp delay slot diff --git a/scu-dsp/scu-dsp.mk b/scu-dsp/scu-dsp.mk new file mode 100644 index 0000000..047917f --- /dev/null +++ b/scu-dsp/scu-dsp.mk @@ -0,0 +1,12 @@ +scu-dsp/add.elf: scu-dsp/add.o saturn/start.o cdc/serial.o scu-dsp/input.bin.o + +scu-dsp/div10.elf: scu-dsp/div10.o saturn/start.o cdc/serial.o scu-dsp/div10.dsp.o + +scu-dsp/div10_vdp2.elf: scu-dsp/div10_vdp2.o saturn/start.o cdc/serial.o scu-dsp/div10_vdp2.dsp.o font/hp_100lx_4bit_flip.data.o + +%.dsp: %.asm + ~/scu-dsp-asm/scu-dsp-asm $< $@ + +%.asm: %.asm.m4 + m4 -I $(MAKEFILE_PATH)/scu-dsp -I $(dir $<) $< > $@.tmp + mv $@.tmp $@ diff --git a/scu-dsp/vdp2_text.cpp b/scu-dsp/vdp2_text.cpp new file mode 100644 index 0000000..d80eb03 --- /dev/null +++ b/scu-dsp/vdp2_text.cpp @@ -0,0 +1,128 @@ +#include "vdp2.h" +#include "common/vdp2_func.hpp" + +#include "font/hp_100lx_4bit_flip.data.h" + +static void cell_data() +{ + const uint32_t * start = reinterpret_cast(&_binary_font_hp_100lx_4bit_flip_data_start); + const int size = reinterpret_cast(&_binary_font_hp_100lx_4bit_flip_data_size); + + // the start of VRAM-A0 + for (int i = 0; i < (size / 4); i++) { + vdp2.vram.u32[i] = start[i]; + } +} + +static void palette_data() +{ + vdp2.cram.u16[0] = 0x0000; + vdp2.cram.u16[1] = 0xffff; +} + +void vdp2_text_init() +{ + v_blank_in(); + + // DISP: Please make sure to change this bit from 0 to 1 during V blank. + vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE + | TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320); + + /* set the color mode to 5bits per channel, 1024 colors */ + vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024 + | RAMCTL__VRAMD + | RAMCTL__VRBMD + | RAMCTL__RDBSA0__CHARACTER_PATTERN_TABLE // VRAM-A0 0x000000 + | RAMCTL__RDBSA1__PATTERN_NAME_TABLE; // VRAM-A1 0x020000 + + vdp2.reg.VRSIZE = 0; + + /* enable display of NBG0 */ + vdp2.reg.BGON = BGON__R0ON | BGON__R0TPON; + + /* set character format for NBG0 to palettized 16 color + set enable "cell format" for NBG0 + set character size for NBG0 to 1x1 cell */ + vdp2.reg.CHCTLB = CHCTLB__R0CHCN__16_COLOR + | CHCTLB__R0BMEN__CELL_FORMAT + | CHCTLB__R0CHSZ__1x1_CELL; + + /* plane size */ + vdp2.reg.PLSZ = PLSZ__RAPLSZ__1x1 + | PLSZ__RBPLSZ__1x1; + + /* map plane offset + 1-word: value of bit 6-0 * 0x2000 + 2-word: value of bit 5-0 * 0x4000 + */ + // plane_a_offset is at the start of VRAM-A1 + constexpr int plane_a = 8; + constexpr int plane_a_offset = plane_a * 0x4000; + + //constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit) + //constexpr int plane_size = page_size * 1; + + /* cycle pattern table not used for RBG0 ? */ + vdp2.reg.CYCA0 = 0x0F44F99F; + vdp2.reg.CYCA1 = 0x0F44F99F; + vdp2.reg.CYCB0 = 0x0F44F99F; + vdp2.reg.CYCB1 = 0x0F44F99F; + + vdp2.reg.MPOFR = MPOFR__RAMP(0); // bits 8~6 + vdp2.reg.MPABRA = MPABRA__RAMPB(plane_a) | MPABRA__RAMPA(plane_a); // bits 5~0 + vdp2.reg.MPCDRA = MPCDRA__RAMPD(plane_a) | MPCDRA__RAMPC(plane_a); // bits 5~0 + vdp2.reg.MPEFRA = MPEFRA__RAMPF(plane_a) | MPEFRA__RAMPE(plane_a); // bits 5~0 + vdp2.reg.MPGHRA = MPGHRA__RAMPH(plane_a) | MPGHRA__RAMPG(plane_a); // bits 5~0 + vdp2.reg.MPIJRA = MPIJRA__RAMPJ(plane_a) | MPIJRA__RAMPI(plane_a); // bits 5~0 + vdp2.reg.MPKLRA = MPKLRA__RAMPL(plane_a) | MPKLRA__RAMPK(plane_a); // bits 5~0 + vdp2.reg.MPMNRA = MPMNRA__RAMPN(plane_a) | MPMNRA__RAMPM(plane_a); // bits 5~0 + vdp2.reg.MPOPRA = MPOPRA__RAMPP(plane_a) | MPOPRA__RAMPO(plane_a); // bits 5~0 + + vdp2.reg.PNCR = PNCR__R0PNB__2WORD; + + vdp2.reg.RPMD = RPMD__ROTATION_PARAMETER_A; + + //vdp2.reg.RPRCTL = 0; + + vdp2.reg.KTCTL = 0; + + vdp2.reg.KTAOF = 0; + + vdp2.reg.PRIR = 3; + + palette_data(); + cell_data(); + + volatile struct vdp2_rotation_parameter_table * table = (struct vdp2_rotation_parameter_table *)&vdp2.vram.u32[0x4000 / 4]; + table->screen_start_coordinate_xst = 0; + table->screen_start_coordinate_yst = 0; + table->screen_start_coordinate_zst = 0; + table->screen_vertical_coordinate_increment_dxst = 0; + table->screen_vertical_coordinate_increment_dyst = (1 << 16); + table->screen_horizontal_coordinate_increment_dx = (1 << 16); + table->screen_horizontal_coordinate_increment_dy = 0; + table->rotation_matrix_parameter_a = (-1 << 16); + table->rotation_matrix_parameter_b = 0; + table->rotation_matrix_parameter_c = 0; + table->rotation_matrix_parameter_d = 0; + table->rotation_matrix_parameter_e = (1 << 16); + table->rotation_matrix_parameter_f = 0; + table->viewpoint_coordinate_px = 0; + table->viewpoint_coordinate_py = 0; + table->viewpoint_coordinate_pz = 0; + table->center_point_coordinate_px = 0; + table->center_point_coordinate_py = 0; + table->center_point_coordinate_pz = 0; + table->horizontal_shift_mx = 0; + table->horizontal_shift_my = 0; + table->scaling_coefficient_kx = (1 << 16); + table->scaling_coefficient_ky = (1 << 16); + + vdp2.reg.RPTA = (((uint32_t)table) >> 1) & 0x7ffff; + + /* */ + + for (int i = 0; i < 64 * 64; i++) { + vdp2.vram.u32[(plane_a_offset / 4) + i] = ' ' - 0x20; + } +} diff --git a/scu-dsp/vdp2_text.hpp b/scu-dsp/vdp2_text.hpp new file mode 100644 index 0000000..20bf4d2 --- /dev/null +++ b/scu-dsp/vdp2_text.hpp @@ -0,0 +1,3 @@ +#pragma once + +void vdp2_text_init();