diff --git a/th04/main/pointnum/add.asm b/th04/main/pointnum/add.asm
new file mode 100644
index 00000000..b6ac63b1
--- /dev/null
+++ b/th04/main/pointnum/add.asm
@@ -0,0 +1,57 @@
+public POINTNUMS_ADD_YELLOW, POINTNUMS_ADD_WHITE
+pointnums_add	proc near
+
+@@number  	= word ptr  4
+@@center_y	= word ptr  6
+@@center_x	= word ptr  8
+
+pointnums_add_yellow:
+	mov	bl, _pointnum_yellow_p
+	inc	_pointnum_yellow_p
+	cmp	bl, (POINTNUM_YELLOW_COUNT - 1)
+	jb	short @@skip_past_white_numbers
+	mov	_pointnum_yellow_p, 0
+
+@@skip_past_white_numbers:
+	xor	bh, bh
+	add	bx, POINTNUM_WHITE_COUNT
+	jmp	short @@add
+
+pointnums_add_white:
+	mov	bl, _pointnum_white_p
+	mov	bh, 0
+	inc	_pointnum_white_p
+	cmp	bl, (POINTNUM_WHITE_COUNT - 1)
+	jb	short @@add
+	mov	_pointnum_white_p, 0
+
+@@add:
+	shl	bx, 4
+	add	bx, offset _pointnums
+	mov	word ptr [bx+pointnum_t.flag], 1	; flag = 1, age = 0
+	push	bp
+	mov	bp, sp
+	mov	ax, [bp+@@center_x]
+	mov	[bx+pointnum_t.PN_center_cur.x], ax
+	mov	ax, [bp+@@center_y]
+	mov	[bx+pointnum_t.PN_center_cur.y], ax
+
+	if GAME eq 5
+		push	si
+		mov	si, bx
+	else
+		mov	[bx+pointnum_t.PN_width], 0
+		mov	al, _pointnum_times_2
+		mov	[bx+pointnum_t.PN_times_2], al
+	endif
+
+	lea	ax, [bx+pointnum_t.PN_digits_lebcd + (POINTNUM_DIGITS - 1)]
+	call	pointnum_digits_set pascal, ax, [bp+@@number]
+	if GAME eq 5
+		mov	[si+pointnum_t.PN_width], ax
+		pop	si
+	endif
+	pop	bp
+	retn	6
+pointnums_add	endp
+	nop
diff --git a/th04/main/pointnum/digits.asm b/th04/main/pointnum/digits.asm
new file mode 100644
index 00000000..8080f71a
--- /dev/null
+++ b/th04/main/pointnum/digits.asm
@@ -0,0 +1,30 @@
+public POINTNUM_DIGITS_SET
+pointnum_digits_set	proc near
+
+@@points    	= word ptr  2
+@@last_digit	= word ptr  4
+
+@@bp equ <bx>
+
+	mov	@@bp, sp
+	mov	dx, ss:[@@bp+@@points]
+	mov	bx, ss:[@@bp+@@last_digit]
+	push	si
+	mov	si, offset _FIVE_DIGIT_POWERS_OF_10 + ((5 - POINTNUM_DIGITS) * word)
+	mov	cx, (POINTNUM_DIGITS - 1)
+
+@@loop:
+	mov	ax, dx
+	xor	dx, dx
+	div	word ptr [si]
+	mov	[bx], al
+
+@@next:
+	dec	bx
+	add	si, word
+	loop	@@loop
+	mov	[bx], dl
+	pop	si
+	retn	4
+pointnum_digits_set	endp
+	nop
diff --git a/th04/main/pointnum/inv_upd.asm b/th04/main/pointnum/inv_upd.asm
index b62bccc4..6486d8d9 100644
--- a/th04/main/pointnum/inv_upd.asm
+++ b/th04/main/pointnum/inv_upd.asm
@@ -1,3 +1,12 @@
+public POINTNUMS_INIT
+pointnums_init	proc near
+	mov	_pointnum_white_p, 0
+	mov	_pointnum_yellow_p, 0
+	retn
+pointnums_init	endp
+	even
+
+
 public POINTNUMS_INVALIDATE
 pointnums_invalidate	proc near
 	push	si
diff --git a/th04/main/pointnum/pointnum.hpp b/th04/main/pointnum/pointnum.hpp
index cd7247f6..badd6ae7 100644
--- a/th04/main/pointnum/pointnum.hpp
+++ b/th04/main/pointnum/pointnum.hpp
@@ -35,7 +35,33 @@ struct pointnum_t {
 };
 
 extern pointnum_t pointnums[POINTNUM_COUNT];
+// Yes, [pointnums] is treated as a ring buffer of white numbers, followed by
+// a ring buffer of yellow numbers.
+extern unsigned char pointnum_yellow_p;
+extern unsigned char pointnum_white_p;
 
+#if GAME == 5
+	// Returns the on-screen width of [number] in pixels.
+	unsigned int pascal near pointnum_digits_set(
+		unsigned char near *last_digit, uint16_t points
+	);
+#else
+	// [times_2] is set to this value for for all newly added point numbers.
+	extern bool pointnum_times_2;
+
+	void pascal near pointnum_digits_set(
+		unsigned char near *last_digit, uint16_t points
+	);
+#endif
+
+int pascal pointnum_add_white(
+	Subpixel center_x, Subpixel center_y, uint16_t points
+);
+int pascal pointnum_add_yellow(
+	Subpixel center_x, Subpixel center_y, uint16_t points
+);
+
+void pascal near pointnums_init(void);
 void pascal near pointnums_invalidate(void);
 void pascal near pointnums_update(void);
 /// ---------
diff --git a/th04/main/pointnum/pointnum[data].asm b/th04/main/pointnum/pointnum[data].asm
new file mode 100644
index 00000000..3cb3f1b4
--- /dev/null
+++ b/th04/main/pointnum/pointnum[data].asm
@@ -0,0 +1,3 @@
+public _pointnum_times_2
+_pointnum_times_2	db 0
+	evendata
diff --git a/th04/main/pointnum/render[bss].asm b/th04/main/pointnum/render[bss].asm
index 1d71465c..aec8d5a7 100644
--- a/th04/main/pointnum/render[bss].asm
+++ b/th04/main/pointnum/render[bss].asm
@@ -1,3 +1,7 @@
+public _pointnum_white_p, _pointnum_yellow_p
+_pointnum_white_p	db ?
+_pointnum_yellow_p	db ?
+
 public _pointnums_alive, _pointnum_first_yellow_alive
 _pointnums_alive	dw	(POINTNUM_COUNT + 1) dup (?)
 _pointnum_first_yellow_alive	dw ?
diff --git a/th04_main.asm b/th04_main.asm
index 4f10a67d..5b272010 100644
--- a/th04_main.asm
+++ b/th04_main.asm
@@ -951,7 +951,7 @@ sub_B1D0	proc near
 		call	sparks_init
 		call	hud_score_put
 		call	sub_15D74
-		call	main_01:sub_BCB2
+		call	main_01:pointnums_init
 		nopcall	main_01:hud_put
 		mov	fp_255AC, offset tiles_render_all
 		call	main_01:tiles_invalidate_reset
@@ -1738,18 +1738,6 @@ nullsub_2	proc far
 		retf
 nullsub_2	endp
 
-; ---------------------------------------------------------------------------
-		nop
-
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_BCB2	proc near
-		mov	byte_2520E, 0
-		mov	byte_2520F, 0
-		retn
-sub_BCB2	endp
-
 ; ---------------------------------------------------------------------------
 		nop
 include th04/main/pointnum/inv_upd.asm
@@ -14199,58 +14187,7 @@ include th04/main/scroll_y_3.asm
 MOTION_UPDATE_DEF 2
 RANDRING_NEXT_DEF 2
 		db    0
-
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_13D90	proc near
-		mov	bl, byte_2520F
-		inc	byte_2520F
-		cmp	bl, (POINTNUM_YELLOW_COUNT - 1)
-		jb	short loc_13DA2
-		mov	byte_2520F, 0
-
-loc_13DA2:
-		xor	bh, bh
-		add	bx, POINTNUM_WHITE_COUNT
-		jmp	short loc_13DBE
-sub_13D90	endp
-
-
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_13DAA	proc near
-		mov	bl, byte_2520E
-		mov	bh, 0
-		inc	byte_2520E
-		cmp	bl, (POINTNUM_WHITE_COUNT - 1)
-		jb	short loc_13DBE
-		mov	byte_2520E, 0
-
-loc_13DBE:
-		shl	bx, 4
-		add	bx, offset _pointnums
-		mov	word ptr [bx+pointnum_t.flag], 1
-		push	bp
-		mov	bp, sp
-		mov	ax, [bp+8]
-		mov	[bx+pointnum_t.PN_center_cur.x], ax
-		mov	ax, [bp+6]
-		mov	[bx+pointnum_t.PN_center_cur.y], ax
-		mov	[bx+pointnum_t.PN_width], 0
-		mov	al, byte_21CC8
-		mov	[bx+pointnum_t.PN_times_2], al
-		lea	ax, [bx+pointnum_t.PN_digits_lebcd + (POINTNUM_DIGITS - 1)]
-		push	ax
-		push	word ptr [bp+4]
-		call	sub_189EE
-		pop	bp
-		retn	6
-sub_13DAA	endp
-
-; ---------------------------------------------------------------------------
-		nop
+include th04/main/pointnum/add.asm
 include th04/math/vector2_near.asm
 		nop
 include th04/main/sparks_add.asm
@@ -22522,32 +22459,7 @@ off_189DE	dw offset loc_1872F
 		dw offset loc_188F6
 		dw offset loc_1894A
 
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_189EE	proc near
-		mov	bx, sp
-		mov	dx, ss:[bx+2]
-		mov	bx, ss:[bx+4]
-		push	si
-		mov	si, 1EB6h
-		mov	cx, 3
-
-loc_189FF:
-		mov	ax, dx
-		xor	dx, dx
-		div	word ptr [si]
-		mov	[bx], al
-		dec	bx
-		add	si, 2
-		loop	loc_189FF
-		mov	[bx], dl
-		pop	si
-		retn	4
-sub_189EE	endp
-
-; ---------------------------------------------------------------------------
-		nop
+include th04/main/pointnum/digits.asm
 
 ; =============== S U B	R O U T	I N E =======================================
 
@@ -24941,8 +24853,8 @@ sub_19F16	endp
 
 sub_19F6E	proc near
 
-var_4		= word ptr -4
-var_2		= word ptr -2
+@@x		= word ptr -4
+@@y		= word ptr -2
 arg_0		= word ptr  4
 
 		enter	4, 0
@@ -24952,21 +24864,20 @@ arg_0		= word ptr  4
 		imul	ax, 1280
 		movzx	eax, ax
 		add	_score_delta, eax
-		mov	byte_21CC8, 0
+		mov	_pointnum_times_2, 0
 		mov	ax, _midboss_pos.cur.x
 		add	ax, (-64 shl 4)
-		mov	[bp+var_2], ax
+		mov	[bp+@@y], ax
 		mov	ax, _midboss_pos.cur.y
 		add	ax, (-64 shl 4)
-		mov	[bp+var_4], ax
+		mov	[bp+@@x], ax
 		xor	di, di
 		jmp	short loc_19FCD
 ; ---------------------------------------------------------------------------
 
 loc_19F9F:
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_2]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@y]
 		mov	si, ax
 		or	si, si
 		jge	short loc_19FB2
@@ -24975,18 +24886,17 @@ loc_19F9F:
 ; ---------------------------------------------------------------------------
 
 loc_19FB2:
-		cmp	si, 1800h
+		cmp	si, (PLAYFIELD_W shl 4)
 		jle	short loc_19FBB
-		mov	si, 1800h
+		mov	si, (PLAYFIELD_W shl 4)
 
 loc_19FBB:
 		push	si
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_4]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@x]
 		push	ax
-		push	500h
-		call	sub_13D90
+		push	1280
+		call	pointnums_add_yellow
 		inc	di
 
 loc_19FCD:
@@ -25005,8 +24915,8 @@ sub_19F6E	endp
 
 sub_19FD8	proc near
 
-var_4		= word ptr -4
-var_2		= word ptr -2
+@@y		= word ptr -4
+@@x		= word ptr -2
 arg_0		= word ptr  4
 
 		enter	4, 0
@@ -25016,21 +24926,20 @@ arg_0		= word ptr  4
 		imul	ax, 1280
 		movzx	eax, ax
 		add	_score_delta, eax
-		mov	byte_21CC8, 0
+		mov	_pointnum_times_2, 0
 		mov	ax, _boss_pos.cur.x
 		add	ax, (-64 shl 4)
-		mov	[bp+var_2], ax
+		mov	[bp+@@x], ax
 		mov	ax, _boss_pos.cur.y
 		add	ax, (-64 shl 4)
-		mov	[bp+var_4], ax
+		mov	[bp+@@y], ax
 		xor	di, di
 		jmp	short loc_1A037
 ; ---------------------------------------------------------------------------
 
 loc_1A009:
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_2]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@x]
 		mov	si, ax
 		or	si, si
 		jge	short loc_1A01C
@@ -25039,18 +24948,17 @@ loc_1A009:
 ; ---------------------------------------------------------------------------
 
 loc_1A01C:
-		cmp	si, 1800h
+		cmp	si, (PLAYFIELD_W shl 4)
 		jle	short loc_1A025
-		mov	si, 1800h
+		mov	si, (PLAYFIELD_W shl 4)
 
 loc_1A025:
 		push	si
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_4]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@y]
 		push	ax
-		push	500h
-		call	sub_13D90
+		push	1280
+		call	pointnums_add_yellow
 		inc	di
 
 loc_1A037:
@@ -29314,7 +29222,7 @@ bullets_update	proc far
 @@patnum		= byte ptr -9
 var_8		= word ptr -8
 var_6		= word ptr -6
-var_4		= word ptr -4
+@@points		= word ptr -4
 var_2		= word ptr -2
 
 		push	bp
@@ -29594,7 +29502,7 @@ loc_1CB44:
 		idiv	bx
 		add	al, PAT_BULLET_KILL
 		mov	[bp+@@patnum], al
-		mov	[bp+var_4], 1
+		mov	[bp+@@points], 1
 		mov	[bp+var_6], 1
 		mov	al, _rank
 		mov	ah, 0
@@ -29605,17 +29513,17 @@ loc_1CB44:
 		jmp	cs:off_1CC29[bx]
 
 loc_1CB71:
-		mov	[bp+var_8], 3E8h
+		mov	[bp+var_8], 1000
 		jmp	short loc_1CB84
 ; ---------------------------------------------------------------------------
 
 loc_1CB78:
-		mov	[bp+var_8], 640h
+		mov	[bp+var_8], 1600
 		jmp	short loc_1CB84
 ; ---------------------------------------------------------------------------
 
 loc_1CB7F:
-		mov	[bp+var_8], 7D0h
+		mov	[bp+var_8], 2000
 
 loc_1CB84:
 		mov	_popup_bonus, 0
@@ -29639,21 +29547,18 @@ loc_1CB91:
 ; ---------------------------------------------------------------------------
 
 loc_1CBB7:
-		movzx	eax, [bp+var_4]
+		movzx	eax, [bp+@@points]
 		add	_popup_bonus, eax
 		add	_score_delta, eax
-		push	[si+bullet_t.pos.cur.x]
-		push	[si+bullet_t.pos.cur.y]
-		push	[bp+var_4]
-		call	sub_13DAA
+		call	pointnums_add_white pascal, [si+bullet_t.pos.cur.x], [si+bullet_t.pos.cur.y], [bp+@@points]
 		mov	ax, [bp+var_6]
-		add	[bp+var_4], ax
+		add	[bp+@@points], ax
 		add	[bp+var_6], 3
-		mov	ax, [bp+var_4]
+		mov	ax, [bp+@@points]
 		cmp	ax, [bp+var_8]
 		jbe	short loc_1CBEA
 		mov	ax, [bp+var_8]
-		mov	[bp+var_4], ax
+		mov	[bp+@@points], ax
 
 loc_1CBEA:
 		mov	[si+bullet_t.flag], 2
@@ -31634,14 +31539,14 @@ include th04/main/item/miss_add.asm
 
 sub_1DBAE	proc near
 
-var_1		= byte ptr -1
+@@yellow		= byte ptr -1
 arg_0		= word ptr  4
 
 		enter	2, 0
 		push	si
 		push	di
 		mov	di, [bp+arg_0]
-		mov	[bp+var_1], 0
+		mov	[bp+@@yellow], 0
 		mov	al, [di+0Eh]
 		mov	ah, 0
 		mov	bx, ax
@@ -31673,13 +31578,13 @@ loc_1DC04:
 		cmp	_power_overflow_level, 42
 		jb	short loc_1DC19
 		mov	_power_overflow_level, 42
-		mov	[bp+var_1], 1
+		mov	[bp+@@yellow], 1
 
 loc_1DC19:
 		mov	bx, _power_overflow_level
 		add	bx, bx
 		mov	si, POWER_OVERFLOW_BONUS[bx]
-		cmp	byte_21CC8, 0
+		cmp	_pointnum_times_2, 0
 		jz	loc_1DD93
 		inc	byte_23660
 		jmp	loc_1DD93
@@ -31688,13 +31593,13 @@ loc_1DC19:
 loc_1DC33:
 		cmp	word ptr [di+4], 340h
 		jg	short loc_1DC58
-		mov	si, 1400h
+		mov	si, 5120
 		mov	al, byte_23660
 		add	al, 4
 		mov	byte_23660, al
 		inc	_total_max_valued_point_items_collected
-		mov	[bp+var_1], 1
-		cmp	byte_21CC8, 0
+		mov	[bp+@@yellow], 1
+		cmp	_pointnum_times_2, 0
 		jz	short loc_1DC7B
 		add	al, 4
 		jmp	short loc_1DC78
@@ -31705,13 +31610,13 @@ loc_1DC58:
 		cwd
 		sub	ax, dx
 		sar	ax, 1
-		mov	dx, 0CE4h
+		mov	dx, 3300
 		sub	dx, ax
 		mov	si, dx
 		mov	al, byte_23660
 		add	al, 2
 		mov	byte_23660, al
-		cmp	byte_21CC8, 0
+		cmp	_pointnum_times_2, 0
 		jz	short loc_1DC7B
 		add	al, 2
 
@@ -31743,7 +31648,7 @@ loc_1DC9A:
 		mov	al, byte_23660
 		add	al, 2
 		mov	byte_23660, al
-		cmp	byte_21CC8, 0
+		cmp	_pointnum_times_2, 0
 		jz	loc_1DD93
 		add	al, 2
 		mov	byte_23660, al
@@ -31783,15 +31688,15 @@ loc_1DD09:
 loc_1DD25:
 		cmp	_power_overflow_level, 42
 		jnz	short loc_1DD93
-		mov	si, 0A00h
-		mov	[bp+var_1], 1
+		mov	si, 2560
+		mov	[bp+@@yellow], 1
 		jmp	short loc_1DD93
 ; ---------------------------------------------------------------------------
 
 loc_1DD35:
 		les	bx, _resident
 		inc	es:[bx+resident_t.rem_bombs]
-		mov	si, 64h	; 'd'
+		mov	si, 100
 		call	sub_EFA1
 		jmp	short loc_1DD93
 ; ---------------------------------------------------------------------------
@@ -31819,10 +31724,10 @@ loc_1DD7B:
 		call	sub_11DE6
 
 loc_1DD90:
-		mov	si, 64h	; 'd'   ; jumptable 0001CCD9 case 696
+		mov	si, 100	; jumptable 0001CCD9 case 696
 
 loc_1DD93:
-		cmp	byte_21CC8, 0
+		cmp	_pointnum_times_2, 0
 		jnz	short loc_1DDA0
 		movzx	eax, si
 		jmp	short loc_1DDA8
@@ -31835,20 +31740,14 @@ loc_1DDA0:
 
 loc_1DDA8:
 		add	_score_delta, eax
-		cmp	[bp+var_1], 0
+		cmp	[bp+@@yellow], 0
 		jnz	short loc_1DDBF
-		push	word ptr [di+2]
-		push	word ptr [di+4]
-		push	si
-		call	sub_13DAA
+		call	pointnums_add_white pascal, word ptr [di+2], word ptr [di+4], si
 		jmp	short loc_1DDC9
 ; ---------------------------------------------------------------------------
 
 loc_1DDBF:
-		push	word ptr [di+2]
-		push	word ptr [di+4]
-		push	si
-		call	sub_13D90
+		call	pointnums_add_yellow pascal, word ptr [di+2], word ptr [di+4], si
 
 loc_1DDC9:
 		cmp	byte_23660, 20h	; ' '
@@ -31961,12 +31860,12 @@ items_update	proc far
 		mov	si, offset _items
 		cmp	byte_236E0, 0
 		jz	short loc_1DE74
-		mov	byte_21CC8, 1
+		mov	_pointnum_times_2, 1
 		jmp	short loc_1DE79
 ; ---------------------------------------------------------------------------
 
 loc_1DE74:
-		mov	byte_21CC8, 0
+		mov	_pointnum_times_2, 0
 
 loc_1DE79:
 		xor	di, di
@@ -31985,7 +31884,7 @@ loc_1DE7E:
 loc_1DE90:
 		cmp	byte_236E0, 0
 		jz	short loc_1DEC6
-		mov	byte_21CC8, 1
+		mov	_pointnum_times_2, 1
 		mov	[si+item_t.pulled_to_player], 1
 		mov	ax, _player_pos.cur.y
 		sub	ax, [si+item_t.pos.cur.y]
@@ -32066,7 +31965,7 @@ loc_1DF4E:
 		cmp	di, ITEM_COUNT
 		jl	loc_1DE7E
 		call	item_splashes_update
-		mov	byte_21CC8, 0
+		mov	_pointnum_times_2, 0
 		pop	di
 		pop	si
 		leave
@@ -36325,8 +36224,7 @@ off_21CBA	dd aSt00_map
 					; "ST00.MAP"
 aSt00_map	db 'ST00.MAP',0
 		db 0
-byte_21CC8	db 0
-		db 0
+include th04/main/pointnum/pointnum[data].asm
 include th04/sprites/pointnum.asm
 		db  18h
 		db  3Ch	; <
@@ -36964,8 +36862,6 @@ word_25107	dw ?
 word_25109	dw ?
 		db    ?	;
 include th02/math/randring[bss].asm
-byte_2520E	db ?
-byte_2520F	db ?
 include th04/main/pointnum/render[bss].asm
 include th04/main/sparks_add[bss].asm
 include th04/main/item/splashes[bss].asm
diff --git a/th05/main/pointnum/digits.asm b/th05/main/pointnum/digits.asm
new file mode 100644
index 00000000..4db6f18d
--- /dev/null
+++ b/th05/main/pointnum/digits.asm
@@ -0,0 +1,46 @@
+public POINTNUM_DIGITS_SET
+pointnum_digits_set	proc near
+
+@@points    	= word ptr  4
+@@last_digit	= word ptr  6
+
+@@bp equ <bp>
+@@ret equ <bp>
+
+	push	bp
+	mov	@@bp, sp
+	mov	dx, ss:[@@bp+@@points]
+	mov	bx, ss:[@@bp+@@last_digit]
+	push	si
+	xor	@@ret, @@ret
+	mov	si, offset _FIVE_DIGIT_POWERS_OF_10 + ((5 - POINTNUM_DIGITS) * word)
+	mov	cx, (POINTNUM_DIGITS - 1)
+
+@@loop:
+	mov	ax, dx
+	xor	dx, dx
+	div	word ptr [si]
+	mov	[bx], al
+	or	al, al
+	jz	short @@next
+	or	@@ret, @@ret
+	jnz	short @@next
+	mov	@@ret, cx
+
+@@next:
+	dec	bx
+	add	si, word
+	loop	@@loop
+	mov	[bx], dl
+
+	; +1 for the last digit written in the instruction above, +1 for the
+	; trailing 0.
+	add	bp, 2
+
+	shl	bp, 3	; * NUMERAL_W
+	mov	ax, bp
+	pop	si
+	pop	bp
+	retn	4
+pointnum_digits_set	endp
+	nop
diff --git a/th05_main.asm b/th05_main.asm
index d58a65d0..fa1058c3 100644
--- a/th05_main.asm
+++ b/th05_main.asm
@@ -1096,7 +1096,7 @@ sub_B55A	proc near
 		call	sub_C473
 		call	sparks_init
 		call	hud_score_put
-		call	sub_C29E
+		call	pointnums_init
 		nopcall	hud_put
 		mov	fp_23F5A, offset tiles_render_all
 		call	tiles_invalidate_reset
@@ -1970,18 +1970,6 @@ include th04/main/bullet/pellet_r.asm
 include th04/main/spark_render.asm
 include th04/main/sparks.asm
 include th04/main/item/splash_dot_render.asm
-
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_C29E	proc near
-		mov	byte_24064, 0
-		mov	byte_24065, 0
-		retn
-sub_C29E	endp
-
-; ---------------------------------------------------------------------------
-		nop
 include th04/main/pointnum/inv_upd.asm
 include th05/main/pointnum/render.asm
 include th04/main/pointnum/num_put.asm
@@ -12600,59 +12588,7 @@ off_1575F	dw offset loc_15388
 RANDRING_NEXT_DEF 2
 		db 0
 include th04/main/gather_point_render.asm
-
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_1586E	proc near
-		mov	bl, byte_24065
-		inc	byte_24065
-		cmp	bl, (POINTNUM_YELLOW_COUNT - 1)
-		jb	short loc_15880
-		mov	byte_24065, 0
-
-loc_15880:
-		xor	bh, bh
-		add	bx, POINTNUM_WHITE_COUNT
-		jmp	short loc_1589C
-sub_1586E	endp
-
-
-; =============== S U B	R O U T	I N E =======================================
-
-
-sub_15888	proc near
-		mov	bl, byte_24064
-		mov	bh, 0
-		inc	byte_24064
-		cmp	bl, (POINTNUM_WHITE_COUNT - 1)
-		jb	short loc_1589C
-		mov	byte_24064, 0
-
-loc_1589C:
-		shl	bx, 4
-		add	bx, offset _pointnums
-		mov	word ptr [bx+pointnum_t.flag], 1
-		push	bp
-		mov	bp, sp
-		mov	ax, [bp+8]
-		mov	[bx+pointnum_t.PN_center_cur.x], ax
-		mov	ax, [bp+6]
-		mov	[bx+pointnum_t.PN_center_cur.y], ax
-		push	si
-		mov	si, bx
-		lea	ax, [bx+pointnum_t.PN_digits_lebcd + (POINTNUM_DIGITS - 1)]
-		push	ax
-		push	word ptr [bp+4]
-		call	sub_1F9BA
-		mov	[si+pointnum_t.PN_width], ax
-		pop	si
-		pop	bp
-		retn	6
-sub_15888	endp
-
-; ---------------------------------------------------------------------------
-		nop
+include th04/main/pointnum/add.asm
 
 ; =============== S U B	R O U T	I N E =======================================
 
@@ -14823,7 +14759,7 @@ sub_16F05	endp
 
 sub_16F54	proc near
 
-var_3		= byte ptr -3
+@@yellow		= byte ptr -3
 var_2		= word ptr -2
 arg_0		= word ptr  4
 
@@ -14831,7 +14767,7 @@ arg_0		= word ptr  4
 		push	si
 		push	di
 		mov	di, [bp+arg_0]
-		mov	[bp+var_3], 0
+		mov	[bp+@@yellow], 0
 		mov	al, [di+0Eh]
 		mov	ah, 0
 		mov	bx, ax
@@ -14863,7 +14799,7 @@ loc_16FAA:
 		cmp	_power_overflow_level, 42
 		jb	short loc_16FD1
 		mov	_power_overflow_level, 42
-		mov	[bp+var_3], 1
+		mov	[bp+@@yellow], 1
 		cmp	byte_2264E, 0
 		jnz	short loc_16FD1
 		cmp	_dream, 128
@@ -14888,7 +14824,7 @@ loc_16FE3:
 		sub	dx, ax
 		add	dx, 0FC80h
 		mov	[bp+var_2], dx
-		mov	si, 1400h
+		mov	si, 5120
 		jmp	short loc_1700C
 ; ---------------------------------------------------------------------------
 
@@ -14919,7 +14855,7 @@ loc_1703E:
 
 loc_17043:
 		inc	_total_max_valued_point_items_collected
-		mov	[bp+var_3], 1
+		mov	[bp+@@yellow], 1
 		jmp	short loc_1705C
 ; ---------------------------------------------------------------------------
 
@@ -14928,7 +14864,7 @@ loc_1704D:
 		cwd
 		sub	ax, dx
 		sar	ax, 1
-		mov	dx, 0AF0h
+		mov	dx, 2800
 		sub	dx, ax
 		mov	si, dx
 
@@ -14949,8 +14885,8 @@ loc_17074:
 loc_1707F:
 		cmp	_dream, 128
 		jb	short loc_1708F
-		mov	si, 3200h
-		mov	[bp+var_3], 1
+		mov	si, 12800
+		mov	[bp+@@yellow], 1
 		jmp	short loc_17097
 ; ---------------------------------------------------------------------------
 
@@ -15003,8 +14939,8 @@ loc_170F2:
 loc_1710E:
 		cmp	_power_overflow_level, 42
 		jnz	short loc_17174
-		mov	si, 0A00h
-		mov	[bp+var_3], 1
+		mov	si, 2560
+		mov	[bp+@@yellow], 1
 		jmp	short loc_17174
 ; ---------------------------------------------------------------------------
 
@@ -15043,20 +14979,14 @@ loc_17171:
 loc_17174:
 		movzx	eax, si
 		add	_score_delta, eax
-		cmp	[bp+var_3], 0
+		cmp	[bp+@@yellow], 0
 		jnz	short loc_1718F
-		push	word ptr [di+2]
-		push	word ptr [di+4]
-		push	si
-		call	sub_15888
+		call	pointnums_add_white pascal, word ptr [di+2], word ptr [di+4], si
 		jmp	short loc_17199
 ; ---------------------------------------------------------------------------
 
 loc_1718F:
-		push	word ptr [di+2]
-		push	word ptr [di+4]
-		push	si
-		call	sub_1586E
+		call	pointnums_add_yellow pascal, word ptr [di+2], word ptr [di+4], si
 
 loc_17199:
 		cmp	byte_225CC, 20h	; ' '
@@ -15357,32 +15287,31 @@ sub_17354	endp
 
 sub_173AC	proc near
 
-var_4		= word ptr -4
-var_2		= word ptr -2
+@@y		= word ptr -4
+@@x		= word ptr -2
 arg_0		= word ptr  4
 
 		enter	4, 0
 		push	si
 		push	di
 		mov	ax, [bp+arg_0]
-		imul	ax, 500h
+		imul	ax, 1280
 		movzx	eax, ax
 		add	_score_delta, eax
 		mov	byte_21762, 0
 		mov	ax, _midboss_pos.cur.x
-		add	ax, 0FC00h
-		mov	[bp+var_2], ax
+		add	ax, (-64 shl 4)
+		mov	[bp+@@x], ax
 		mov	ax, _midboss_pos.cur.y
-		add	ax, 0FC00h
-		mov	[bp+var_4], ax
+		add	ax, (-64 shl 4)
+		mov	[bp+@@y], ax
 		xor	di, di
 		jmp	short loc_1740B
 ; ---------------------------------------------------------------------------
 
 loc_173DD:
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_2]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@x]
 		mov	si, ax
 		or	si, si
 		jge	short loc_173F0
@@ -15391,18 +15320,17 @@ loc_173DD:
 ; ---------------------------------------------------------------------------
 
 loc_173F0:
-		cmp	si, 1800h
+		cmp	si, (PLAYFIELD_W shl 4)
 		jle	short loc_173F9
-		mov	si, 1800h
+		mov	si, (PLAYFIELD_W shl 4)
 
 loc_173F9:
 		push	si
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_4]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@y]
 		push	ax
-		push	500h
-		call	sub_1586E
+		push	1280
+		call	pointnums_add_yellow
 		inc	di
 
 loc_1740B:
@@ -15421,8 +15349,8 @@ sub_173AC	endp
 
 sub_17416	proc near
 
-var_4		= word ptr -4
-var_2		= word ptr -2
+@@y		= word ptr -4
+@@x		= word ptr -2
 arg_0		= word ptr  4
 
 		enter	4, 0
@@ -15434,18 +15362,17 @@ arg_0		= word ptr  4
 		mov	byte_21762, 0
 		mov	ax, _boss_pos.cur.x
 		add	ax, (-64 shl 4)
-		mov	[bp+var_2], ax
+		mov	[bp+@@x], ax
 		mov	ax, _boss_pos.cur.y
 		add	ax, (-64 shl 4)
-		mov	[bp+var_4], ax
+		mov	[bp+@@y], ax
 		xor	di, di
 		jmp	short loc_17476
 ; ---------------------------------------------------------------------------
 
 loc_17448:
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_2]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@x]
 		mov	si, ax
 		or	si, si
 		jge	short loc_1745B
@@ -15454,18 +15381,17 @@ loc_17448:
 ; ---------------------------------------------------------------------------
 
 loc_1745B:
-		cmp	si, 1800h
+		cmp	si, (PLAYFIELD_W shl 4)
 		jle	short loc_17464
-		mov	si, 1800h
+		mov	si, (PLAYFIELD_W shl 4)
 
 loc_17464:
 		push	si
-		push	800h
-		call	randring2_next16_mod
-		add	ax, [bp+var_4]
+		call	randring2_next16_mod pascal, (128 shl 4)
+		add	ax, [bp+@@y]
 		push	ax
-		push	3E8h
-		call	sub_1586E
+		push	1000
+		call	pointnums_add_yellow
 		inc	di
 
 loc_17476:
@@ -16048,7 +15974,7 @@ sub_17C04	proc far
 @@patnum		= byte ptr -9
 var_8		= word ptr -8
 var_6		= word ptr -6
-var_4		= word ptr -4
+@@points		= word ptr -4
 var_2		= word ptr -2
 
 		push	bp
@@ -16353,17 +16279,17 @@ loc_17EC3:
 		idiv	bx
 		add	al, PAT_BULLET_KILL
 		mov	[bp+@@patnum], al
-		mov	[bp+var_4], 1
+		mov	[bp+@@points], 1
 		mov	[bp+var_6], 1
 		cmp	_rank, RANK_EXTRA
 		jnz	short loc_17EE9
-		mov	ax, 640h
+		mov	ax, 1600
 		jmp	short loc_17EFA
 ; ---------------------------------------------------------------------------
 
 loc_17EE9:
-		push	(3C0h shl 16) or 500h
-		push	(500h shl 16) or 500h
+		push	( 960 shl 16) or 1280
+		push	(1280 shl 16) or 1280
 		call	select_for_rank
 
 loc_17EFA:
@@ -16389,21 +16315,18 @@ loc_17F0B:
 ; ---------------------------------------------------------------------------
 
 loc_17F31:
-		movzx	eax, [bp+var_4]
+		movzx	eax, [bp+@@points]
 		add	_popup_bonus, eax
 		add	_score_delta, eax
-		push	[si+bullet_t.pos.cur.x]
-		push	[si+bullet_t.pos.cur.y]
-		push	[bp+var_4]
-		call	sub_15888
+		call	pointnums_add_white pascal, [si+bullet_t.pos.cur.x], [si+bullet_t.pos.cur.y], [bp+@@points]
 		mov	ax, [bp+var_6]
-		add	[bp+var_4], ax
+		add	[bp+@@points], ax
 		add	[bp+var_6], 3
-		mov	ax, [bp+var_4]
+		mov	ax, [bp+@@points]
 		cmp	ax, [bp+var_8]
 		jbe	short loc_17F64
 		mov	ax, [bp+var_8]
-		mov	[bp+var_4], ax
+		mov	[bp+@@points], ax
 
 loc_17F64:
 		mov	[si+bullet_t.flag], 2
@@ -29246,51 +29169,7 @@ midboss5_update	endp
 
 ; ---------------------------------------------------------------------------
 		db 0
-
-; =============== S U B	R O U T	I N E =======================================
-
-; Attributes: bp-based frame
-
-sub_1F9BA	proc near
-
-arg_0		= word ptr  4
-arg_2		= word ptr  6
-
-		push	bp
-		mov	bp, sp
-		mov	dx, [bp+arg_0]
-		mov	bx, [bp+arg_2]
-		push	si
-		xor	bp, bp
-		mov	si, 1FBCh
-		mov	cx, 4
-
-loc_1F9CC:
-		mov	ax, dx
-		xor	dx, dx
-		div	word ptr [si]
-		mov	[bx], al
-		or	al, al
-		jz	short loc_1F9DE
-		or	bp, bp
-		jnz	short loc_1F9DE
-		mov	bp, cx
-
-loc_1F9DE:
-		dec	bx
-		add	si, 2
-		loop	loc_1F9CC
-		mov	[bx], dl
-		add	bp, 2
-		shl	bp, 3
-		mov	ax, bp
-		pop	si
-		pop	bp
-		retn	4
-sub_1F9BA	endp
-
-; ---------------------------------------------------------------------------
-		nop
+include th05/main/pointnum/digits.asm
 include th05/main/hud/number_put.asm
 
 ; =============== S U B	R O U T	I N E =======================================
@@ -30174,8 +30053,6 @@ byte_23F5E	db ?
 		db    ?	;
 word_23F60	dw ?
 include th02/math/randring[bss].asm
-byte_24064	db ?
-byte_24065	db ?
 include th04/main/pointnum/render[bss].asm
 byte_2429A	db ?
 byte_2429B	db ?