paavohtl Claude Opus 4.6 (1M context) commited on
Commit
59bfee7
Β·
1 Parent(s): c8f62aa

refactor: dispatch via DisplayGfx::*_raw methods in queue_dispatch

Browse files

Replaces the per-case `((*vtable).method)(display, ...)` open-coding
with the auto-generated `DisplayGfx::*_raw` methods produced by
`bind_DisplayGfxVtable!(DisplayGfx, base.vtable)`. The `_raw` methods
do the same `((*(*this).base.vtable).method)(this, args...)` dispatch
under the hood while keeping the noalias-safe raw-pointer signature.

Drops the explicit `vtable: *const DisplayGfxVtable` parameter from
all 14 per-case dispatcher functions and removes the `let vtable =
(*display).base.vtable` setup in the main loop. Net βˆ’34 lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

crates/openwa-core/src/render/queue_dispatch.rs CHANGED
@@ -291,28 +291,27 @@ pub unsafe fn render_drawing_queue(
291
  });
292
 
293
  let clip_ref: &ClipContext = &*clip;
294
- let vtable = (*display).base.vtable;
295
 
296
  // Walk from the highest index downward.
297
  for i in (0..count).rev() {
298
  let cmd = entries[i] as *const u32;
299
  let cmd_type = *cmd;
300
  match cmd_type {
301
- 0 => dispatch_case_0_fill_rect(display, vtable, clip_ref, cmd),
302
- 1 => dispatch_case_1_bitmap_global(display, vtable, cmd),
303
- 2 => dispatch_case_2_textbox_local(display, vtable, clip_ref, cmd),
304
- 3 => dispatch_case_3_via_callback(display, vtable, clip_ref, cmd),
305
- 4 => dispatch_case_4_sprite_global(display, vtable, cmd),
306
- 5 => dispatch_case_5_sprite_local(display, vtable, clip_ref, cmd),
307
- 6 => dispatch_case_6_sprite_offset(display, vtable, clip_ref, cmd),
308
- 7 => dispatch_case_7_polyline(display, vtable, cmd),
309
- 8 => dispatch_case_8_line_strip(display, vtable, clip_ref, cmd),
310
- 9 => dispatch_case_9_polygon(display, vtable, clip_ref, cmd),
311
- 0xA => dispatch_case_a_pixel_strip(display, vtable, clip_ref, cmd),
312
- 0xB => dispatch_case_b_crosshair(display, vtable, clip_ref, cmd),
313
- 0xC => dispatch_case_c_outlined_pixel(display, vtable, clip_ref, cmd),
314
- 0xD => dispatch_case_d_tiled_bitmap(display, vtable, clip_ref, cmd),
315
- 0xE => dispatch_case_e_tiled_terrain(display, vtable, clip_ref, cmd),
316
  _ => { /* unknown command type β€” silently skipped, matching WA */ }
317
  }
318
  }
@@ -325,8 +324,11 @@ pub unsafe fn render_drawing_queue(
325
  // Each case body mirrors the corresponding `case N:` arm of WA's
326
  // `RenderDrawingQueue` (0x542350). Field offsets are the `puVar1[N]`
327
  // indices from the decompile (each step = 4 bytes).
328
-
329
- use crate::render::display::vtable::DisplayGfxVtable;
 
 
 
330
 
331
  #[inline]
332
  unsafe fn read_field(cmd: *const u32, idx: usize) -> i32 {
@@ -346,12 +348,7 @@ unsafe fn read_fixed(cmd: *const u32, idx: usize) -> Fixed {
346
  // if !iVar4 break;
347
  // // x/y MIN-corner clamps to keep pixel-perfect rect edges
348
  // vtable[18](this, x1>>16, y1>>16, x2>>16, y2>>16, cmd[2]);
349
- unsafe fn dispatch_case_0_fill_rect(
350
- display: *mut DisplayGfx,
351
- vtable: *const DisplayGfxVtable,
352
- clip: &ClipContext,
353
- cmd: *const u32,
354
- ) {
355
  let mut x1 = Fixed::ZERO;
356
  let mut y1 = Fixed::ZERO;
357
  let mut x2 = Fixed::ZERO;
@@ -398,7 +395,7 @@ unsafe fn dispatch_case_0_fill_rect(
398
  }
399
 
400
  let color = *(cmd.add(2));
401
- ((*vtable).fill_rect)(
402
  display,
403
  x1.to_int(),
404
  y1.to_int(),
@@ -413,11 +410,7 @@ unsafe fn dispatch_case_0_fill_rect(
413
  // vtable[20](this, cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]);
414
  //
415
  // Pure passthrough β€” global bitmaps draw at the supplied world coords.
416
- unsafe fn dispatch_case_1_bitmap_global(
417
- display: *mut DisplayGfx,
418
- vtable: *const DisplayGfxVtable,
419
- cmd: *const u32,
420
- ) {
421
  use crate::bitgrid::DisplayBitGrid;
422
  let x = read_fixed(cmd, 2);
423
  let y = read_fixed(cmd, 3);
@@ -427,7 +420,7 @@ unsafe fn dispatch_case_1_bitmap_global(
427
  let src_w = read_field(cmd, 7);
428
  let src_h = read_field(cmd, 8);
429
  let flags = *(cmd.add(9));
430
- ((*vtable).draw_scaled_sprite)(display, x, y, sprite, src_x, src_y, src_w, src_h, flags);
431
  }
432
 
433
  // ---- case 2: DRAW_TEXTBOX_LOCAL β†’ slot 20 (draw_scaled_sprite) -------------
@@ -437,7 +430,6 @@ unsafe fn dispatch_case_1_bitmap_global(
437
  // `cmd+8` controlling whether the result clamps to the second clip pair.
438
  unsafe fn dispatch_case_2_textbox_local(
439
  display: *mut DisplayGfx,
440
- vtable: *const DisplayGfxVtable,
441
  clip: &ClipContext,
442
  cmd: *const u32,
443
  ) {
@@ -497,7 +489,7 @@ unsafe fn dispatch_case_2_textbox_local(
497
  let src_w = read_field(cmd, 10);
498
  let src_h = read_field(cmd, 11);
499
  let flags = *(cmd.add(12));
500
- ((*vtable).draw_scaled_sprite)(display, x1, y1, sprite, src_x, src_y, src_w, src_h, flags);
501
  }
502
 
503
  // ---- case 3 β†’ slot 21 (draw_via_callback) ----------------------------------
@@ -507,7 +499,6 @@ unsafe fn dispatch_case_2_textbox_local(
507
  // vtable[21](this, x, y, cmd[6], cmd[7], cmd[8]);
508
  unsafe fn dispatch_case_3_via_callback(
509
  display: *mut DisplayGfx,
510
- vtable: *const DisplayGfxVtable,
511
  clip: &ClipContext,
512
  cmd: *const u32,
513
  ) {
@@ -528,22 +519,18 @@ unsafe fn dispatch_case_3_via_callback(
528
  let obj = read_field(cmd, 6) as *mut u8;
529
  let p5 = *(cmd.add(7));
530
  let p6 = *(cmd.add(8));
531
- ((*vtable).draw_via_callback)(display, x, y, obj, p5, p6);
532
  }
533
 
534
  // ---- case 4: DRAW_SPRITE_GLOBAL β†’ slot 19 (blit_sprite) --------------------
535
  //
536
  // vtable[19](this, cmd[2], cmd[3], cmd[4], cmd[5]);
537
- unsafe fn dispatch_case_4_sprite_global(
538
- display: *mut DisplayGfx,
539
- vtable: *const DisplayGfxVtable,
540
- cmd: *const u32,
541
- ) {
542
  let x = read_fixed(cmd, 2);
543
  let y = read_fixed(cmd, 3);
544
  let sprite_flags = *(cmd.add(4));
545
  let palette = *(cmd.add(5));
546
- ((*vtable).blit_sprite)(display, x, y, sprite_flags, palette);
547
  }
548
 
549
  // ---- case 5: DRAW_SPRITE_LOCAL β†’ slot 19 (blit_sprite) ---------------------
@@ -552,7 +539,6 @@ unsafe fn dispatch_case_4_sprite_global(
552
  // vtable[19](this, x, y, cmd[4], cmd[5]);
553
  unsafe fn dispatch_case_5_sprite_local(
554
  display: *mut DisplayGfx,
555
- vtable: *const DisplayGfxVtable,
556
  clip: &ClipContext,
557
  cmd: *const u32,
558
  ) {
@@ -561,7 +547,7 @@ unsafe fn dispatch_case_5_sprite_local(
561
  rq_translate_coordinates(clip, read_fixed(cmd, 2), read_fixed(cmd, 3), &mut x, &mut y);
562
  let sprite_flags = *(cmd.add(4));
563
  let palette = *(cmd.add(5));
564
- ((*vtable).blit_sprite)(display, x, y, sprite_flags, palette);
565
  }
566
 
567
  // ---- case 6: DRAW_SPRITE_OFFSET β†’ slot 19 (blit_sprite) --------------------
@@ -572,7 +558,6 @@ unsafe fn dispatch_case_5_sprite_local(
572
  // screen-space offset sprites.
573
  unsafe fn dispatch_case_6_sprite_offset(
574
  display: *mut DisplayGfx,
575
- vtable: *const DisplayGfxVtable,
576
  clip: &ClipContext,
577
  cmd: *const u32,
578
  ) {
@@ -636,7 +621,7 @@ unsafe fn dispatch_case_6_sprite_offset(
636
 
637
  let sprite_flags = *(cmd.add(7));
638
  let palette = *(cmd.add(8));
639
- ((*vtable).blit_sprite)(display, x, y, sprite_flags, palette);
640
  }
641
 
642
  // ---- case 7 β†’ slot 12 (draw_polyline) --------------------------------------
@@ -645,15 +630,11 @@ unsafe fn dispatch_case_6_sprite_offset(
645
  //
646
  // `cmd[2]` is the vertex count, `cmd[3]` is the color, vertex data
647
  // follows starting at `cmd[4]`.
648
- unsafe fn dispatch_case_7_polyline(
649
- display: *mut DisplayGfx,
650
- vtable: *const DisplayGfxVtable,
651
- cmd: *const u32,
652
- ) {
653
  let points = cmd.add(4) as *mut i32;
654
  let count = read_field(cmd, 2);
655
  let color = *(cmd.add(3));
656
- ((*vtable).draw_polyline)(display, points, count, color);
657
  }
658
 
659
  // ---- case 8: DRAW_LINE_STRIP β†’ slot 14 (draw_line_clipped) -----------------
@@ -663,7 +644,6 @@ unsafe fn dispatch_case_7_polyline(
663
  // `cmd[3]` is the color shared by all segments.
664
  unsafe fn dispatch_case_8_line_strip(
665
  display: *mut DisplayGfx,
666
- vtable: *const DisplayGfxVtable,
667
  clip: &ClipContext,
668
  cmd: *const u32,
669
  ) {
@@ -703,7 +683,7 @@ unsafe fn dispatch_case_8_line_strip(
703
  ) {
704
  break;
705
  }
706
- ((*vtable).draw_line_clipped)(display, x1, y1, x2, y2, color);
707
  x1 = x2;
708
  y1 = y2;
709
  vert = vert.add(3);
@@ -714,12 +694,7 @@ unsafe fn dispatch_case_8_line_strip(
714
  //
715
  // Same shape as case 8 but with two color params (cmd[3], cmd[4]) and the
716
  // first vertex starts at `cmd[5..8]`. Per-segment vertex stride is 3 u32s.
717
- unsafe fn dispatch_case_9_polygon(
718
- display: *mut DisplayGfx,
719
- vtable: *const DisplayGfxVtable,
720
- clip: &ClipContext,
721
- cmd: *const u32,
722
- ) {
723
  let mut x1 = Fixed::ZERO;
724
  let mut y1 = Fixed::ZERO;
725
  let mut scale = Fixed::ZERO;
@@ -755,7 +730,7 @@ unsafe fn dispatch_case_9_polygon(
755
  ) {
756
  break;
757
  }
758
- ((*vtable).draw_line)(display, x1, y1, x2, y2, color1, color2);
759
  x1 = x2;
760
  y1 = y2;
761
  vert = vert.add(3);
@@ -773,7 +748,6 @@ unsafe fn dispatch_case_9_polygon(
773
  // vtable[15](this, x, y, cmd[4], cmd[5], cmd[6], cmd[7]);
774
  unsafe fn dispatch_case_a_pixel_strip(
775
  display: *mut DisplayGfx,
776
- vtable: *const DisplayGfxVtable,
777
  clip: &ClipContext,
778
  cmd: *const u32,
779
  ) {
@@ -788,7 +762,7 @@ unsafe fn dispatch_case_a_pixel_strip(
788
  let dy = read_fixed(cmd, 5);
789
  let count = read_field(cmd, 6);
790
  let color = *(cmd.add(7));
791
- ((*vtable).draw_pixel_strip)(display, x, y, dx, dy, count, color);
792
  }
793
 
794
  // ---- case 0xB: DRAW_CROSSHAIR β†’ slot 16 (draw_crosshair) -------------------
@@ -796,12 +770,7 @@ unsafe fn dispatch_case_a_pixel_strip(
796
  // iVar4 = RQ_ClipCoordinates(this, cmd[4], cmd[5], cmd[6], &x, &y, ..);
797
  // if !iVar4 break;
798
  // vtable[16](this, x>>16, y>>16, cmd[2], cmd[3]);
799
- unsafe fn dispatch_case_b_crosshair(
800
- display: *mut DisplayGfx,
801
- vtable: *const DisplayGfxVtable,
802
- clip: &ClipContext,
803
- cmd: *const u32,
804
- ) {
805
  let mut x = Fixed::ZERO;
806
  let mut y = Fixed::ZERO;
807
  let mut scale = Fixed::ZERO;
@@ -818,7 +787,7 @@ unsafe fn dispatch_case_b_crosshair(
818
  }
819
  let color_fg = *(cmd.add(2));
820
  let color_bg = *(cmd.add(3));
821
- ((*vtable).draw_crosshair)(display, x.to_int(), y.to_int(), color_fg, color_bg);
822
  }
823
 
824
  // ---- case 0xC β†’ slot 17 (draw_outlined_pixel) ------------------------------
@@ -828,7 +797,6 @@ unsafe fn dispatch_case_b_crosshair(
828
  // vtable[17](this, x>>16, y>>16, cmd[2], cmd[3]);
829
  unsafe fn dispatch_case_c_outlined_pixel(
830
  display: *mut DisplayGfx,
831
- vtable: *const DisplayGfxVtable,
832
  clip: &ClipContext,
833
  cmd: *const u32,
834
  ) {
@@ -848,7 +816,7 @@ unsafe fn dispatch_case_c_outlined_pixel(
848
  }
849
  let color_fg = *(cmd.add(2));
850
  let color_bg = read_field(cmd, 3);
851
- ((*vtable).draw_outlined_pixel)(display, x.to_int(), y.to_int(), color_fg, color_bg);
852
  }
853
 
854
  // ---- case 0xD: DRAW_TILED_BITMAP β†’ slot 11 (draw_tiled_bitmap) -------------
@@ -859,7 +827,6 @@ unsafe fn dispatch_case_c_outlined_pixel(
859
  // vtable[11](this, (flag ? 0 : x>>16), y>>16, cmd[4]);
860
  unsafe fn dispatch_case_d_tiled_bitmap(
861
  display: *mut DisplayGfx,
862
- vtable: *const DisplayGfxVtable,
863
  clip: &ClipContext,
864
  cmd: *const u32,
865
  ) {
@@ -881,7 +848,7 @@ unsafe fn dispatch_case_d_tiled_bitmap(
881
  let flag_byte = *(cmd.add(5)) as u8;
882
  let dest_x = if flag_byte != 0 { 0 } else { x.to_int() };
883
  let source = read_field(cmd, 4) as *const TiledBitmapSource;
884
- ((*vtable).draw_tiled_bitmap)(display, dest_x, y.to_int(), source);
885
  }
886
 
887
  // ---- case 0xE β†’ slot 22 (draw_tiled_terrain) -------------------------------
@@ -890,7 +857,6 @@ unsafe fn dispatch_case_d_tiled_bitmap(
890
  // runs the two-clip path with the same flag-byte clamps.
891
  unsafe fn dispatch_case_e_tiled_terrain(
892
  display: *mut DisplayGfx,
893
- vtable: *const DisplayGfxVtable,
894
  clip: &ClipContext,
895
  cmd: *const u32,
896
  ) {
@@ -945,7 +911,7 @@ unsafe fn dispatch_case_e_tiled_terrain(
945
  }
946
  let count = read_field(cmd, 7);
947
  let flags = *(cmd.add(8));
948
- ((*vtable).draw_tiled_terrain)(display, x, y, count, flags);
949
  }
950
 
951
  // =============================================================================
 
291
  });
292
 
293
  let clip_ref: &ClipContext = &*clip;
 
294
 
295
  // Walk from the highest index downward.
296
  for i in (0..count).rev() {
297
  let cmd = entries[i] as *const u32;
298
  let cmd_type = *cmd;
299
  match cmd_type {
300
+ 0 => dispatch_case_0_fill_rect(display, clip_ref, cmd),
301
+ 1 => dispatch_case_1_bitmap_global(display, cmd),
302
+ 2 => dispatch_case_2_textbox_local(display, clip_ref, cmd),
303
+ 3 => dispatch_case_3_via_callback(display, clip_ref, cmd),
304
+ 4 => dispatch_case_4_sprite_global(display, cmd),
305
+ 5 => dispatch_case_5_sprite_local(display, clip_ref, cmd),
306
+ 6 => dispatch_case_6_sprite_offset(display, clip_ref, cmd),
307
+ 7 => dispatch_case_7_polyline(display, cmd),
308
+ 8 => dispatch_case_8_line_strip(display, clip_ref, cmd),
309
+ 9 => dispatch_case_9_polygon(display, clip_ref, cmd),
310
+ 0xA => dispatch_case_a_pixel_strip(display, clip_ref, cmd),
311
+ 0xB => dispatch_case_b_crosshair(display, clip_ref, cmd),
312
+ 0xC => dispatch_case_c_outlined_pixel(display, clip_ref, cmd),
313
+ 0xD => dispatch_case_d_tiled_bitmap(display, clip_ref, cmd),
314
+ 0xE => dispatch_case_e_tiled_terrain(display, clip_ref, cmd),
315
  _ => { /* unknown command type β€” silently skipped, matching WA */ }
316
  }
317
  }
 
324
  // Each case body mirrors the corresponding `case N:` arm of WA's
325
  // `RenderDrawingQueue` (0x542350). Field offsets are the `puVar1[N]`
326
  // indices from the decompile (each step = 4 bytes).
327
+ //
328
+ // Vtable dispatch goes through the auto-generated `DisplayGfx::*_raw`
329
+ // methods (from `bind_DisplayGfxVtable!(DisplayGfx, base.vtable)`),
330
+ // which take a raw `*mut DisplayGfx` to avoid creating `&mut self` β€”
331
+ // see the noalias rule in CLAUDE.md.
332
 
333
  #[inline]
334
  unsafe fn read_field(cmd: *const u32, idx: usize) -> i32 {
 
348
  // if !iVar4 break;
349
  // // x/y MIN-corner clamps to keep pixel-perfect rect edges
350
  // vtable[18](this, x1>>16, y1>>16, x2>>16, y2>>16, cmd[2]);
351
+ unsafe fn dispatch_case_0_fill_rect(display: *mut DisplayGfx, clip: &ClipContext, cmd: *const u32) {
 
 
 
 
 
352
  let mut x1 = Fixed::ZERO;
353
  let mut y1 = Fixed::ZERO;
354
  let mut x2 = Fixed::ZERO;
 
395
  }
396
 
397
  let color = *(cmd.add(2));
398
+ DisplayGfx::fill_rect_raw(
399
  display,
400
  x1.to_int(),
401
  y1.to_int(),
 
410
  // vtable[20](this, cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]);
411
  //
412
  // Pure passthrough β€” global bitmaps draw at the supplied world coords.
413
+ unsafe fn dispatch_case_1_bitmap_global(display: *mut DisplayGfx, cmd: *const u32) {
 
 
 
 
414
  use crate::bitgrid::DisplayBitGrid;
415
  let x = read_fixed(cmd, 2);
416
  let y = read_fixed(cmd, 3);
 
420
  let src_w = read_field(cmd, 7);
421
  let src_h = read_field(cmd, 8);
422
  let flags = *(cmd.add(9));
423
+ DisplayGfx::draw_scaled_sprite_raw(display, x, y, sprite, src_x, src_y, src_w, src_h, flags);
424
  }
425
 
426
  // ---- case 2: DRAW_TEXTBOX_LOCAL β†’ slot 20 (draw_scaled_sprite) -------------
 
430
  // `cmd+8` controlling whether the result clamps to the second clip pair.
431
  unsafe fn dispatch_case_2_textbox_local(
432
  display: *mut DisplayGfx,
 
433
  clip: &ClipContext,
434
  cmd: *const u32,
435
  ) {
 
489
  let src_w = read_field(cmd, 10);
490
  let src_h = read_field(cmd, 11);
491
  let flags = *(cmd.add(12));
492
+ DisplayGfx::draw_scaled_sprite_raw(display, x1, y1, sprite, src_x, src_y, src_w, src_h, flags);
493
  }
494
 
495
  // ---- case 3 β†’ slot 21 (draw_via_callback) ----------------------------------
 
499
  // vtable[21](this, x, y, cmd[6], cmd[7], cmd[8]);
500
  unsafe fn dispatch_case_3_via_callback(
501
  display: *mut DisplayGfx,
 
502
  clip: &ClipContext,
503
  cmd: *const u32,
504
  ) {
 
519
  let obj = read_field(cmd, 6) as *mut u8;
520
  let p5 = *(cmd.add(7));
521
  let p6 = *(cmd.add(8));
522
+ DisplayGfx::draw_via_callback_raw(display, x, y, obj, p5, p6);
523
  }
524
 
525
  // ---- case 4: DRAW_SPRITE_GLOBAL β†’ slot 19 (blit_sprite) --------------------
526
  //
527
  // vtable[19](this, cmd[2], cmd[3], cmd[4], cmd[5]);
528
+ unsafe fn dispatch_case_4_sprite_global(display: *mut DisplayGfx, cmd: *const u32) {
 
 
 
 
529
  let x = read_fixed(cmd, 2);
530
  let y = read_fixed(cmd, 3);
531
  let sprite_flags = *(cmd.add(4));
532
  let palette = *(cmd.add(5));
533
+ DisplayGfx::blit_sprite_raw(display, x, y, sprite_flags, palette);
534
  }
535
 
536
  // ---- case 5: DRAW_SPRITE_LOCAL β†’ slot 19 (blit_sprite) ---------------------
 
539
  // vtable[19](this, x, y, cmd[4], cmd[5]);
540
  unsafe fn dispatch_case_5_sprite_local(
541
  display: *mut DisplayGfx,
 
542
  clip: &ClipContext,
543
  cmd: *const u32,
544
  ) {
 
547
  rq_translate_coordinates(clip, read_fixed(cmd, 2), read_fixed(cmd, 3), &mut x, &mut y);
548
  let sprite_flags = *(cmd.add(4));
549
  let palette = *(cmd.add(5));
550
+ DisplayGfx::blit_sprite_raw(display, x, y, sprite_flags, palette);
551
  }
552
 
553
  // ---- case 6: DRAW_SPRITE_OFFSET β†’ slot 19 (blit_sprite) --------------------
 
558
  // screen-space offset sprites.
559
  unsafe fn dispatch_case_6_sprite_offset(
560
  display: *mut DisplayGfx,
 
561
  clip: &ClipContext,
562
  cmd: *const u32,
563
  ) {
 
621
 
622
  let sprite_flags = *(cmd.add(7));
623
  let palette = *(cmd.add(8));
624
+ DisplayGfx::blit_sprite_raw(display, x, y, sprite_flags, palette);
625
  }
626
 
627
  // ---- case 7 β†’ slot 12 (draw_polyline) --------------------------------------
 
630
  //
631
  // `cmd[2]` is the vertex count, `cmd[3]` is the color, vertex data
632
  // follows starting at `cmd[4]`.
633
+ unsafe fn dispatch_case_7_polyline(display: *mut DisplayGfx, cmd: *const u32) {
 
 
 
 
634
  let points = cmd.add(4) as *mut i32;
635
  let count = read_field(cmd, 2);
636
  let color = *(cmd.add(3));
637
+ DisplayGfx::draw_polyline_raw(display, points, count, color);
638
  }
639
 
640
  // ---- case 8: DRAW_LINE_STRIP β†’ slot 14 (draw_line_clipped) -----------------
 
644
  // `cmd[3]` is the color shared by all segments.
645
  unsafe fn dispatch_case_8_line_strip(
646
  display: *mut DisplayGfx,
 
647
  clip: &ClipContext,
648
  cmd: *const u32,
649
  ) {
 
683
  ) {
684
  break;
685
  }
686
+ DisplayGfx::draw_line_clipped_raw(display, x1, y1, x2, y2, color);
687
  x1 = x2;
688
  y1 = y2;
689
  vert = vert.add(3);
 
694
  //
695
  // Same shape as case 8 but with two color params (cmd[3], cmd[4]) and the
696
  // first vertex starts at `cmd[5..8]`. Per-segment vertex stride is 3 u32s.
697
+ unsafe fn dispatch_case_9_polygon(display: *mut DisplayGfx, clip: &ClipContext, cmd: *const u32) {
 
 
 
 
 
698
  let mut x1 = Fixed::ZERO;
699
  let mut y1 = Fixed::ZERO;
700
  let mut scale = Fixed::ZERO;
 
730
  ) {
731
  break;
732
  }
733
+ DisplayGfx::draw_line_raw(display, x1, y1, x2, y2, color1, color2);
734
  x1 = x2;
735
  y1 = y2;
736
  vert = vert.add(3);
 
748
  // vtable[15](this, x, y, cmd[4], cmd[5], cmd[6], cmd[7]);
749
  unsafe fn dispatch_case_a_pixel_strip(
750
  display: *mut DisplayGfx,
 
751
  clip: &ClipContext,
752
  cmd: *const u32,
753
  ) {
 
762
  let dy = read_fixed(cmd, 5);
763
  let count = read_field(cmd, 6);
764
  let color = *(cmd.add(7));
765
+ DisplayGfx::draw_pixel_strip_raw(display, x, y, dx, dy, count, color);
766
  }
767
 
768
  // ---- case 0xB: DRAW_CROSSHAIR β†’ slot 16 (draw_crosshair) -------------------
 
770
  // iVar4 = RQ_ClipCoordinates(this, cmd[4], cmd[5], cmd[6], &x, &y, ..);
771
  // if !iVar4 break;
772
  // vtable[16](this, x>>16, y>>16, cmd[2], cmd[3]);
773
+ unsafe fn dispatch_case_b_crosshair(display: *mut DisplayGfx, clip: &ClipContext, cmd: *const u32) {
 
 
 
 
 
774
  let mut x = Fixed::ZERO;
775
  let mut y = Fixed::ZERO;
776
  let mut scale = Fixed::ZERO;
 
787
  }
788
  let color_fg = *(cmd.add(2));
789
  let color_bg = *(cmd.add(3));
790
+ DisplayGfx::draw_crosshair_raw(display, x.to_int(), y.to_int(), color_fg, color_bg);
791
  }
792
 
793
  // ---- case 0xC β†’ slot 17 (draw_outlined_pixel) ------------------------------
 
797
  // vtable[17](this, x>>16, y>>16, cmd[2], cmd[3]);
798
  unsafe fn dispatch_case_c_outlined_pixel(
799
  display: *mut DisplayGfx,
 
800
  clip: &ClipContext,
801
  cmd: *const u32,
802
  ) {
 
816
  }
817
  let color_fg = *(cmd.add(2));
818
  let color_bg = read_field(cmd, 3);
819
+ DisplayGfx::draw_outlined_pixel_raw(display, x.to_int(), y.to_int(), color_fg, color_bg);
820
  }
821
 
822
  // ---- case 0xD: DRAW_TILED_BITMAP β†’ slot 11 (draw_tiled_bitmap) -------------
 
827
  // vtable[11](this, (flag ? 0 : x>>16), y>>16, cmd[4]);
828
  unsafe fn dispatch_case_d_tiled_bitmap(
829
  display: *mut DisplayGfx,
 
830
  clip: &ClipContext,
831
  cmd: *const u32,
832
  ) {
 
848
  let flag_byte = *(cmd.add(5)) as u8;
849
  let dest_x = if flag_byte != 0 { 0 } else { x.to_int() };
850
  let source = read_field(cmd, 4) as *const TiledBitmapSource;
851
+ DisplayGfx::draw_tiled_bitmap_raw(display, dest_x, y.to_int(), source);
852
  }
853
 
854
  // ---- case 0xE β†’ slot 22 (draw_tiled_terrain) -------------------------------
 
857
  // runs the two-clip path with the same flag-byte clamps.
858
  unsafe fn dispatch_case_e_tiled_terrain(
859
  display: *mut DisplayGfx,
 
860
  clip: &ClipContext,
861
  cmd: *const u32,
862
  ) {
 
911
  }
912
  let count = read_field(cmd, 7);
913
  let flags = *(cmd.add(8));
914
+ DisplayGfx::draw_tiled_terrain_raw(display, x, y, count, flags);
915
  }
916
 
917
  // =============================================================================