correct sprite splitting

This commit is contained in:
Daniel Bulant 2023-01-26 22:09:58 +01:00
parent f84466c03a
commit ea272b611f

View file

@ -31,10 +31,10 @@ fn main() -> Result<(), ffmpeg_next::Error> {
decoder.width(), decoder.width(),
decoder.height(), decoder.height(),
// output // output
Pixel::MonoBlack, Pixel::GRAY8,
WIDTH as u32, WIDTH as u32,
HEIGHT as u32, HEIGHT as u32,
Flags::BILINEAR Flags::BICUBIC
)?; )?;
let mut frame_index = 0; let mut frame_index = 0;
@ -43,7 +43,7 @@ fn main() -> Result<(), ffmpeg_next::Error> {
// V0=x, V1=y, V10=VA=frame count, V11=VB=delay timer // V0=x, V1=y, V10=VA=frame count, V11=VB=delay timer
// it uses sprite bank to draw sprites on the screen // it uses sprite bank to draw sprites on the screen
// because of frame counting, maximum length is roughly 36.4 minutes (for 30fps) // because of frame counting, maximum length is roughly 36.4 minutes (for 30fps)
let base_rom = [ let base_rom: [u8; 50] = [
0xA3,0x00, // 0x200 I = 0x300 0xA3,0x00, // 0x200 I = 0x300
0x6C,0x01, // 0x202 VC = 1 0x6C,0x01, // 0x202 VC = 1
@ -51,32 +51,37 @@ fn main() -> Result<(), ffmpeg_next::Error> {
0x00,0xE0, // 0x204 clear screen, 0x00,0xE0, // 0x204 clear screen,
0x61,0x00, // 0x206 V1 = 0 0x61,0x00, // 0x206 V1 = 0
0x60,0x00, // 0x208 V0 = 0 0x60,0x00, // 0x208 V0 = 0
0xD0,0x1F, // 0x20A draw sprite at V0, V1 with height 15 0x31, 30, // 0x20A if V1 == 30 skip
0x70,0x08, // 0x20C V0 += 8 0xD0,0x1F, // 0x20C draw sprite at V0, V1 with height 15
0x62, 120, // 0x20E V2 = 120 0x41, 30, // 0x20E if V1 != 30 skip
0xF2,0x1E, // 0x210 I += V2 0xD0,0x12, // 0x210 draw sprite at V0, V1 with height 2
0x70,0x08, // 0x212 V0 += 8
0x62, 120, // 0x214 V2 = 120
0xF2,0x1E, // 0x216 I += V2
0x30, 32, // 0x212 if V0 == 32 skip 0x30,WIDTH, // 0x218 if V0 == WIDTH (64) skip
0x12,0x0A, // 0x214 goto 0x20A 0x12,0x0A, // 0x21A goto 0x20A
0x71, 15, // 0x216 V1 += 15 0x71, 15, // 0x21C V1 += 15
0x31, 45, // 0x218 if V1 == 45 skip 0x31, 45, // 0x21E if V1 == 45 skip
0x12,0x08, // 0x21A goto 0x208 0x12,0x08, // 0x220 goto 0x208
// wait for next frame. Delay timer ticks every 1/60th of a second, video is 30fps, hence 2 ticks // wait for next frame. Delay timer ticks every 1/60th of a second, video is 30fps, hence 2 ticks
0x6B,0x02, // 0x21C VB = 2 0x6B,0x02, // 0x222 VB = 2
0xFB,0x15, // 0x21E delay timer = VB 0xFB,0x15, // 0x224 delay timer = VB
0xFB,0x07, // 0x220 VB = delay timer 0xFB,0x07, // 0x226 VB = delay timer
0x4B,0x00, // 0x222 if VB != 0 skip 0x4B,0x00, // 0x228 if VB != 0 skip
0x12,0x22, // 0x224 goto 0x222 0x12,0x22, // 0x22A goto 0x222 (repeat wait)
0x12,0x04, // 0x226 goto 0x204 0x12,0x04, // 0x22C goto 0x204
// unreachable, for future use // unreachable, for future use
0x12,0x28, // 0x228 goto 0x228 (self jump, our emulator exits) 0x12,0x2E, // 0x22E goto 0x22E (self jump, our emulator exits)
0x00,0x00 // crash if we get here 0x00,0x00 // crash if we get here
]; ];
// dbg!(&base_rom);
output_file.write_all(&base_rom).unwrap(); output_file.write_all(&base_rom).unwrap();
output_file.seek(std::io::SeekFrom::Start(0x300)).unwrap(); output_file.seek(std::io::SeekFrom::Start(0x100)).unwrap();
let mut receive_and_process_decoded_frames = let mut receive_and_process_decoded_frames =
|decoder: &mut ffmpeg_next::decoder::Video| -> Result<(), ffmpeg_next::Error> { |decoder: &mut ffmpeg_next::decoder::Video| -> Result<(), ffmpeg_next::Error> {
@ -86,31 +91,53 @@ fn main() -> Result<(), ffmpeg_next::Error> {
scaler.run(&decoded, &mut bw_frame)?; scaler.run(&decoded, &mut bw_frame)?;
let data = bw_frame.data(0); let data = bw_frame.data(0);
// dbg!(data); // dbg!(data);
let mut sprite_bank: [[u8; 8]; 3] = [ let mut sprite_bank: [[[u8; 15]; 8]; 3] = [
[ [
0; 8 // there are 8 sprites in 64 pixel wide screen [
0; 15 // 15 pixel tall, 8 pixel wide (u8) sprite
]; 8 // there are 8 sprites in 64 pixel wide screen
]; 3 // 3 parts 15 pixels each to fill 32 pixel tall screen ]; 3 // 3 parts 15 pixels each to fill 32 pixel tall screen
]; ];
for i in 0..8 { for horizontal_part in 0..8 {
for j in 0..3 { for vertical_part in 0..3 {
sprite_bank[j][i] = data[i * 3 + j]; let rows = if vertical_part == 2 { 2 } else { 15 };
for row in 0..rows {
// data is 64x32x8bit, we need to split it into 8x15x8bit chunks
for col in 0..8 {
let x = horizontal_part * 8 + col;
let y = vertical_part * 15 + row;
let pixel = data[y as usize * WIDTH as usize + x as usize];
// dbg!(pixel);
if pixel > 30 {
sprite_bank[vertical_part][horizontal_part][row] |= 1 << (7 - col);
}
}
}
} }
} }
let mut file = File::create(format!("frames/f{}.pbm", frame_index)).unwrap(); // let mut file = File::create(format!("frames/f{}.pbm", frame_index)).unwrap();
file.write_all(format!("P4\n{} {}\n", bw_frame.width(), bw_frame.height()).as_bytes()).unwrap(); // file.write_all(format!("P5\n{} {}\n255\n", WIDTH, HEIGHT).as_bytes()).unwrap();
file.write_all(data).unwrap(); // file.write_all(data).unwrap();
for part in 0..3 {
for line in 0..15 {
for sprite in 0..8 {
print!("{:08b} ", sprite_bank[part][sprite][line]);
}
println!();
}
println!();
}
println!();
println!("frame {}", frame_index);
println!();
for part in 0..3 { for part in 0..3 {
for sprite in 0..8 { for sprite in 0..8 {
let mut sprite_byte = 0; output_file.write_all(&sprite_bank[part][sprite]).unwrap();
for pixel in 0..8 {
if sprite_bank[part][sprite] & 1 << (7 - pixel) != 0 {
sprite_byte |= 1 << (7 - pixel);
}
}
output_file.write_all(&[sprite_byte]).unwrap();
} }
} }