mirror of
https://github.com/imjasonh/nescript
synced 2026-07-09 01:16:12 +00:00
69 lines
2.5 KiB
Text
69 lines
2.5 KiB
Text
|
|
// sha256/computing_state.ne — runs the SHA-256 block compression.
|
|||
|
|
//
|
|||
|
|
// The compression is split across frames so the main loop keeps
|
|||
|
|
// responding to the NMI handshake. Each frame advances one
|
|||
|
|
// "phase"; every phase does a batch of 4 iterations so the
|
|||
|
|
// whole compression (48 schedule steps + 64 rounds + fold)
|
|||
|
|
// finishes inside ~30 frames — roughly half a second of
|
|||
|
|
// wall-clock wait between pressing Enter and the hash appearing.
|
|||
|
|
//
|
|||
|
|
// Phase map:
|
|||
|
|
// 0..11 schedule W[16..63] in batches of 4 (12 × 4 = 48)
|
|||
|
|
// 12..27 rounds 0..63 in batches of 4 (16 × 4 = 64)
|
|||
|
|
// 28 fold wk[A..H] into h_state, transition to Showing
|
|||
|
|
|
|||
|
|
const SCHED_PHASES: u8 = 12 // 12 × 4 = 48 schedule steps
|
|||
|
|
const ROUND_PHASES: u8 = 16 // 16 × 4 = 64 rounds
|
|||
|
|
const FOLD_PHASE: u8 = 28 // SCHED + ROUND
|
|||
|
|
const BATCH_SIZE: u8 = 4 // iterations per frame
|
|||
|
|
|
|||
|
|
state Computing {
|
|||
|
|
on enter {
|
|||
|
|
// Reset persistent hash state and build the padded
|
|||
|
|
// block from the user's message. Phased work then runs
|
|||
|
|
// on top of the freshly-initialised w[] / h_state /
|
|||
|
|
// wk[A..H].
|
|||
|
|
reset_hash_state()
|
|||
|
|
build_padded_block()
|
|||
|
|
init_abcdefgh()
|
|||
|
|
|
|||
|
|
cp_phase = 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
on frame {
|
|||
|
|
if cp_phase < SCHED_PHASES {
|
|||
|
|
// Each schedule phase handles BATCH_SIZE words.
|
|||
|
|
// First word index for this phase: 16 + phase * 4.
|
|||
|
|
var first_idx: u8 = 16 + (cp_phase << 2)
|
|||
|
|
var step: u8 = 0
|
|||
|
|
while step < BATCH_SIZE {
|
|||
|
|
var i: u8 = first_idx + step
|
|||
|
|
schedule_one(i << 2) // byte offset into w[]
|
|||
|
|
step += 1
|
|||
|
|
}
|
|||
|
|
cp_phase += 1
|
|||
|
|
} else if cp_phase < FOLD_PHASE {
|
|||
|
|
// Round batch. First round for this phase:
|
|||
|
|
// (phase - SCHED_PHASES) * 4.
|
|||
|
|
var first_r: u8 = (cp_phase - SCHED_PHASES) << 2
|
|||
|
|
var step2: u8 = 0
|
|||
|
|
while step2 < BATCH_SIZE {
|
|||
|
|
var r: u8 = first_r + step2
|
|||
|
|
round_one(r << 2) // K/W share byte 4*i
|
|||
|
|
step2 += 1
|
|||
|
|
}
|
|||
|
|
cp_phase += 1
|
|||
|
|
} else {
|
|||
|
|
// Fold a..h into h_state and hand off to Showing.
|
|||
|
|
fold_abcdefgh()
|
|||
|
|
transition Showing
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Draw the input buffer so the user can see what they
|
|||
|
|
// typed while the hash is being computed. The cursor
|
|||
|
|
// sprite is deliberately not drawn here — the keyboard
|
|||
|
|
// is inactive during this phase.
|
|||
|
|
draw_input()
|
|||
|
|
}
|
|||
|
|
}
|