Skip to content

Commit 402d9e7

Browse files
committed
Fix the colours in 4bpp mode.
1 parent 43ebc57 commit 402d9e7

File tree

1 file changed

+49
-25
lines changed

1 file changed

+49
-25
lines changed

src/vga/mod.rs

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,19 @@ impl RenderEngine {
470470
//
471471
// two RGB pixels (one pair) per byte eight RGB pixels (four pairs)
472472
// per word
473+
//
474+
// We give the interpolator `palette_ptr` and `chunky_pixels`.
475+
//
476+
// We want to know the corresponding palette addresses for each of
477+
// the eight 4-bit pixels in `chunky_pixels`. For each pixel `p` in
478+
// the 32-bit word `pppppppp` we want `palette_ptr.offset(p)`, which
479+
// is `palette_ptr + (p * 2)`.
480+
//
481+
// The interpolator calculates `palette_ptr + ((w >> 3) & 0b11110)`
482+
// for our left pixel and `palette_ptr + ((w << 1) & 0b11110)` for
483+
// our right pixel so we can pull out two pixels for each
484+
// interpolator write.
485+
let palette_ptr = VIDEO_PALETTE.as_ptr() as *const RGBColour;
473486

474487
// Set up the interpolator. This is safe because core1 has its own.
475488
let sio = unsafe { &*crate::pac::SIO::ptr() };
@@ -481,41 +494,40 @@ impl RenderEngine {
481494
unsafe { w.bits(palette_ptr as u32) };
482495
w
483496
});
484-
// lane0 will pull out the higher of the two 4-bit chunky pixels, but shifted
485-
// by 2 bits to account for the 32-bit palette entry
497+
// lane0 will pull out the palette address of the higher of the two 4-bit chunky pixels in the bottom byte
486498
sio.interp0_ctrl_lane0().write(|w| {
487499
unsafe {
488-
w.shift().bits(4);
489-
w.mask_lsb().bits(2);
490-
w.mask_msb().bits(5);
500+
w.shift().bits(3);
501+
w.mask_lsb().bits(1);
502+
w.mask_msb().bits(4);
491503
}
492504
w
493505
});
494-
// lane1 will pull out the lower of the two 4-bit chunky pixels, but shifted
495-
// by 2 bits to account for the 32-bit palette entry
506+
// lane1 will pull out the palette address of the higher of the two 4-bit chunky pixels in the bottom byte
496507
sio.interp0_ctrl_lane1().write(|w| {
497508
unsafe {
498-
w.shift().bits(0);
499-
w.mask_lsb().bits(2);
500-
w.mask_msb().bits(5);
509+
w.shift().bits(31);
510+
w.mask_lsb().bits(1);
511+
w.mask_msb().bits(4);
501512
}
502513
w
503514
});
504515
let line_start_words = line_start_bytes as *const u32;
505516
let line_len_words = line_len_bytes / 4;
506517
for col in 0..line_len_words {
507518
unsafe {
508-
let chunky_pixels = line_start_words.add(col).read();
519+
let mut chunky_pixels = line_start_words.add(col).read();
520+
521+
// ========================================================
522+
// First byte (containing two 4-bit pixels)
523+
// ========================================================
509524

510-
// First two pixels
511-
// Shift up by 2 bits before we load, to account for the 32
512-
// bit size of each palette entry.
513525
sio.interp0_accum0().write(|w| {
514-
w.bits(chunky_pixels << 2);
526+
w.bits(chunky_pixels);
515527
w
516528
});
517529
sio.interp0_accum1().write(|w| {
518-
w.bits(chunky_pixels << 2);
530+
w.bits(chunky_pixels);
519531
w
520532
});
521533
// now we get the palette address for the left pixel
@@ -527,13 +539,17 @@ impl RenderEngine {
527539
scan_line_buffer_ptr.write(pair);
528540
scan_line_buffer_ptr = scan_line_buffer_ptr.add(1);
529541

530-
// Second two pixels
542+
// ========================================================
543+
// Second byte (containing two 4-bit pixels)
544+
// ========================================================
545+
546+
chunky_pixels >>= 8;
531547
sio.interp0_accum0().write(|w| {
532-
w.bits(chunky_pixels >> 6);
548+
w.bits(chunky_pixels);
533549
w
534550
});
535551
sio.interp0_accum1().write(|w| {
536-
w.bits(chunky_pixels >> 6);
552+
w.bits(chunky_pixels);
537553
w
538554
});
539555
// now we get the palette address for the left pixel
@@ -545,13 +561,17 @@ impl RenderEngine {
545561
scan_line_buffer_ptr.write(pair);
546562
scan_line_buffer_ptr = scan_line_buffer_ptr.add(1);
547563

548-
// Third two pixels
564+
// ========================================================
565+
// Third byte (containing two 4-bit pixels)
566+
// ========================================================
567+
568+
chunky_pixels >>= 8;
549569
sio.interp0_accum0().write(|w| {
550-
w.bits(chunky_pixels >> 14);
570+
w.bits(chunky_pixels);
551571
w
552572
});
553573
sio.interp0_accum1().write(|w| {
554-
w.bits(chunky_pixels >> 14);
574+
w.bits(chunky_pixels);
555575
w
556576
});
557577
// now we get the palette address for the left pixel
@@ -563,13 +583,17 @@ impl RenderEngine {
563583
scan_line_buffer_ptr.write(pair);
564584
scan_line_buffer_ptr = scan_line_buffer_ptr.add(1);
565585

566-
// Fourth two pixels
586+
// ========================================================
587+
// Fourth byte (containing two 4-bit pixels)
588+
// ========================================================
589+
590+
chunky_pixels >>= 8;
567591
sio.interp0_accum0().write(|w| {
568-
w.bits(chunky_pixels >> 22);
592+
w.bits(chunky_pixels);
569593
w
570594
});
571595
sio.interp0_accum1().write(|w| {
572-
w.bits(chunky_pixels >> 22);
596+
w.bits(chunky_pixels);
573597
w
574598
});
575599
// now we get the palette address for the left pixel

0 commit comments

Comments
 (0)