scu-dsp/advent: use div10_unsigned and unparse_base10 from lib

This commit is contained in:
Zack Buhman 2025-08-12 23:03:08 -05:00
parent 5c1b264b8c
commit 8ee90a535c
16 changed files with 303 additions and 41 deletions

View File

@ -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

View File

@ -0,0 +1,3 @@
mount y .
Y:
dspsim.exe

View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
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");

View File

@ -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');
}
}

View File

@ -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

View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
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");

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
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");

View File

@ -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)

10
scu-dsp/advent/advent.mk Normal file
View File

@ -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)

View File

@ -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

View File

@ -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

12
scu-dsp/scu-dsp.mk Normal file
View File

@ -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 $@

128
scu-dsp/vdp2_text.cpp Normal file
View File

@ -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<uint32_t *>(&_binary_font_hp_100lx_4bit_flip_data_start);
const int size = reinterpret_cast<uint32_t>(&_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;
}
}

3
scu-dsp/vdp2_text.hpp Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void vdp2_text_init();