mirror of
https://github.com/danbulant/chip8badapple
synced 2026-06-18 22:21:42 +00:00
correct sprite splitting
This commit is contained in:
parent
f84466c03a
commit
ea272b611f
1 changed files with 62 additions and 35 deletions
97
src/main.rs
97
src/main.rs
|
|
@ -31,10 +31,10 @@ fn main() -> Result<(), ffmpeg_next::Error> {
|
|||
decoder.width(),
|
||||
decoder.height(),
|
||||
// output
|
||||
Pixel::MonoBlack,
|
||||
Pixel::GRAY8,
|
||||
WIDTH as u32,
|
||||
HEIGHT as u32,
|
||||
Flags::BILINEAR
|
||||
Flags::BICUBIC
|
||||
)?;
|
||||
|
||||
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
|
||||
// it uses sprite bank to draw sprites on the screen
|
||||
// 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
|
||||
0x6C,0x01, // 0x202 VC = 1
|
||||
|
||||
|
|
@ -51,32 +51,37 @@ fn main() -> Result<(), ffmpeg_next::Error> {
|
|||
0x00,0xE0, // 0x204 clear screen,
|
||||
0x61,0x00, // 0x206 V1 = 0
|
||||
0x60,0x00, // 0x208 V0 = 0
|
||||
0xD0,0x1F, // 0x20A draw sprite at V0, V1 with height 15
|
||||
0x70,0x08, // 0x20C V0 += 8
|
||||
0x62, 120, // 0x20E V2 = 120
|
||||
0xF2,0x1E, // 0x210 I += V2
|
||||
0x31, 30, // 0x20A if V1 == 30 skip
|
||||
0xD0,0x1F, // 0x20C draw sprite at V0, V1 with height 15
|
||||
0x41, 30, // 0x20E if V1 != 30 skip
|
||||
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
|
||||
0x12,0x0A, // 0x214 goto 0x20A
|
||||
0x71, 15, // 0x216 V1 += 15
|
||||
0x31, 45, // 0x218 if V1 == 45 skip
|
||||
0x12,0x08, // 0x21A goto 0x208
|
||||
0x30,WIDTH, // 0x218 if V0 == WIDTH (64) skip
|
||||
0x12,0x0A, // 0x21A goto 0x20A
|
||||
0x71, 15, // 0x21C V1 += 15
|
||||
0x31, 45, // 0x21E if V1 == 45 skip
|
||||
0x12,0x08, // 0x220 goto 0x208
|
||||
|
||||
// wait for next frame. Delay timer ticks every 1/60th of a second, video is 30fps, hence 2 ticks
|
||||
0x6B,0x02, // 0x21C VB = 2
|
||||
0xFB,0x15, // 0x21E delay timer = VB
|
||||
0xFB,0x07, // 0x220 VB = delay timer
|
||||
0x6B,0x02, // 0x222 VB = 2
|
||||
0xFB,0x15, // 0x224 delay timer = VB
|
||||
0xFB,0x07, // 0x226 VB = delay timer
|
||||
|
||||
0x4B,0x00, // 0x222 if VB != 0 skip
|
||||
0x12,0x22, // 0x224 goto 0x222
|
||||
0x4B,0x00, // 0x228 if VB != 0 skip
|
||||
0x12,0x22, // 0x22A goto 0x222 (repeat wait)
|
||||
|
||||
0x12,0x04, // 0x226 goto 0x204
|
||||
0x12,0x04, // 0x22C goto 0x204
|
||||
// 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
|
||||
];
|
||||
|
||||
// dbg!(&base_rom);
|
||||
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 =
|
||||
|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)?;
|
||||
let data = bw_frame.data(0);
|
||||
// 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
|
||||
];
|
||||
|
||||
for i in 0..8 {
|
||||
for j in 0..3 {
|
||||
sprite_bank[j][i] = data[i * 3 + j];
|
||||
for horizontal_part in 0..8 {
|
||||
for vertical_part in 0..3 {
|
||||
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();
|
||||
file.write_all(format!("P4\n{} {}\n", bw_frame.width(), bw_frame.height()).as_bytes()).unwrap();
|
||||
file.write_all(data).unwrap();
|
||||
// let mut file = File::create(format!("frames/f{}.pbm", frame_index)).unwrap();
|
||||
// file.write_all(format!("P5\n{} {}\n255\n", WIDTH, HEIGHT).as_bytes()).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 sprite in 0..8 {
|
||||
let mut sprite_byte = 0;
|
||||
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();
|
||||
output_file.write_all(&sprite_bank[part][sprite]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue