@@ -18,6 +18,7 @@ pub fn install_pico8_drawing(ctx: Context) {
1818 ctx. set_global ( "line" , line:: callback ( ctx) ) ;
1919 ctx. set_global ( "spr" , spr:: callback ( ctx) ) ;
2020 ctx. set_global ( "sspr" , sspr:: callback ( ctx) ) ;
21+ ctx. set_global ( "map" , map:: callback ( ctx) ) ;
2122}
2223
2324#[ api_callback]
@@ -62,7 +63,7 @@ pub fn circfill(rt: &mut Runtime, x: Option<i16>, y: Option<i16>, r: Option<P8Nu
6263 if r < p8 ! ( 0 ) { return }
6364
6465 let even_flag = rt. memory . machine_state ( ) . misc_chipset_flags ( ) . contains ( MiscChipsetFeatureFlags :: EVEN_RADIUS_CIRC ) ;
65- let mut painter = rt. memory . painter ( ) ;
66+ let painter = rt. memory . painter ( ) ;
6667
6768 let ( x0, y0) = painter. to_abs ( x, y) ;
6869 let ( x1, y1) = if r. fract ( ) >= p8 ! ( 0.5 ) && even_flag {
@@ -104,7 +105,7 @@ pub fn circ(rt: &mut Runtime, x: Option<i16>, y: Option<i16>, r: Option<P8Num>,
104105 if r < p8 ! ( 0 ) { return }
105106
106107 let even_flag = rt. memory . machine_state ( ) . misc_chipset_flags ( ) . contains ( MiscChipsetFeatureFlags :: EVEN_RADIUS_CIRC ) ;
107- let mut painter = rt. memory . painter ( ) ;
108+ let painter = rt. memory . painter ( ) ;
108109
109110 let ( x0, y0) = painter. to_abs ( x, y) ;
110111 let ( x1, y1) = if r. fract ( ) >= p8 ! ( 0.5 ) && even_flag {
@@ -146,7 +147,7 @@ pub fn ovalfill(rt: &mut Runtime, x0: Option<i16>, y0: Option<i16>, x1: Option<i
146147 let ( x0, x1) = ( x0. min ( x1) , x0. max ( x1) ) ;
147148 let ( y0, y1) = ( y0. min ( y1) , y0. max ( y1) ) ;
148149
149- let mut painter = rt. memory . painter ( ) ;
150+ let painter = rt. memory . painter ( ) ;
150151
151152 let width = ( x1 as i32 - x0 as i32 ) / 2 ;
152153 let height = ( y1 as i32 - y0 as i32 ) / 2 ;
@@ -206,7 +207,7 @@ pub fn oval(rt: &mut Runtime, x0: Option<i16>, y0: Option<i16>, x1: Option<i16>,
206207 let ( x0, x1) = ( x0. min ( x1) , x0. max ( x1) ) ;
207208 let ( y0, y1) = ( y0. min ( y1) , y0. max ( y1) ) ;
208209
209- let mut painter = rt. memory . painter ( ) ;
210+ let painter = rt. memory . painter ( ) ;
210211
211212 let width = ( x1 as i32 - x0 as i32 ) / 2 ;
212213 let height = ( y1 as i32 - y0 as i32 ) / 2 ;
@@ -288,7 +289,7 @@ pub fn line(rt: &mut Runtime, p1: Option<P8Num>, p2: Option<P8Num>, p3: Option<P
288289 _ => unreachable ! ( ) ,
289290 } ;
290291
291- let mut painter = rt. memory . painter ( ) ;
292+ let painter = rt. memory . painter ( ) ;
292293
293294 if y0 == y1 {
294295 painter. paint ( & mut rt. memory , x0..=x1, y0) ;
@@ -346,17 +347,17 @@ pub fn spr(rt: &mut Runtime, n: Option<i16>, x: Option<i16>, y: Option<i16>, w:
346347
347348 let memory = & mut rt. memory ;
348349 let graphics = memory. graphics ( ) ;
349- let painter = graphics. painter ( memory) . sprite_mode ( memory) ;
350350 let sprites = graphics. sprites ( ) ;
351+ let painter = graphics. painter ( memory) . sprite_mode ( memory) ;
351352 let ( x0, y0) = painter. to_abs ( x, y) ;
352353 let x1 = x0 + w - 1 ;
353354 let y1 = y0 + h - 1 ;
354355
355356 match ( flip_x, flip_y) {
356- ( false , false ) => { painter. with_callback ( |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x as i16 - x0) as u8 , ( sy + y as i16 - y0) as u8 ) ) . paint_abs ( memory , x0..=x1 , y0..=y1 ) ; } ,
357- ( true , false ) => { painter. with_callback ( |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x1 - x as i16 ) as u8 , ( sy + y as i16 - y0) as u8 ) ) . paint_abs ( memory , x0..=x1 , y0..=y1 ) ; } ,
358- ( false , true ) => { painter. with_callback ( |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x as i16 - x0) as u8 , ( sy + y1 - y as i16 ) as u8 ) ) . paint_abs ( memory , x0..=x1 , y0..=y1 ) ; } ,
359- ( true , true ) => { painter. with_callback ( |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x1 - x as i16 ) as u8 , ( sy + y1 - y as i16 ) as u8 ) ) . paint_abs ( memory , x0..=x1 , y0..=y1 ) ; } ,
357+ ( false , false ) => { painter. paint_abs_tex ( memory , x0..=x1 , y0..=y1 , |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x as i16 - x0) as u8 , ( sy + y as i16 - y0) as u8 ) ) ; } ,
358+ ( true , false ) => { painter. paint_abs_tex ( memory , x0..=x1 , y0..=y1 , |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x1 - x as i16 ) as u8 , ( sy + y as i16 - y0) as u8 ) ) ; } ,
359+ ( false , true ) => { painter. paint_abs_tex ( memory , x0..=x1 , y0..=y1 , |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x as i16 - x0) as u8 , ( sy + y1 - y as i16 ) as u8 ) ) ; } ,
360+ ( true , true ) => { painter. paint_abs_tex ( memory , x0..=x1 , y0..=y1 , |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x1 - x as i16 ) as u8 , ( sy + y1 - y as i16 ) as u8 ) ) ; } ,
360361 }
361362}
362363
@@ -392,29 +393,27 @@ pub fn sspr(rt: &mut Runtime, sx: i16, sy: i16, sw: i16, sh: i16, mut dx: i16, m
392393 let dxf = ( sw > dw && sw % dw == 0 ) . then_some ( sw / dw) ;
393394 let dyf = ( sh > dh && sh % dh == 0 ) . then_some ( sh / dh) ;
394395
395- painter
396- . with_callback ( |memory : & mut Memory , x, y| {
397- let mut sx = sx0 + sample ( x as i16 - dx0, dw, sw, dxf) ;
398- let mut sy = sy0 + sample ( y as i16 - dy0, dh, sh, dyf) ;
399-
400- if flip_x {
401- sx = sx1. min ( 127 ) - ( sx - sx0. max ( 0 ) )
402- }
403-
404- if flip_y {
405- sy = sy1. min ( 127 ) - ( sy - sy0. max ( 0 ) )
406- }
407-
408- if sx < sx0. max ( 0 ) || sy < sy0. max ( 0 ) || sx > sx1. min ( 127 ) || sy > sy1. min ( 127 ) {
409- return None
410- }
411-
412- let sx = u8:: try_from ( sx) . ok ( ) ?;
413- let sy = u8:: try_from ( sy) . ok ( ) ?;
414-
415- sprites. get_pixel ( memory, sx, sy)
416- } )
417- . paint_abs ( & mut rt. memory , dx0..dx0+dw, dy0..dy0+dh) ;
396+ painter. paint_abs_tex ( & mut rt. memory , dx0..dx0+dw, dy0..dy0+dh, |memory : & mut Memory , x, y| {
397+ let mut sx = sx0 + sample ( x as i16 - dx0, dw, sw, dxf) ;
398+ let mut sy = sy0 + sample ( y as i16 - dy0, dh, sh, dyf) ;
399+
400+ if flip_x {
401+ sx = sx1. min ( 127 ) - ( sx - sx0. max ( 0 ) )
402+ }
403+
404+ if flip_y {
405+ sy = sy1. min ( 127 ) - ( sy - sy0. max ( 0 ) )
406+ }
407+
408+ if sx < sx0. max ( 0 ) || sy < sy0. max ( 0 ) || sx > sx1. min ( 127 ) || sy > sy1. min ( 127 ) {
409+ return None
410+ }
411+
412+ let sx = u8:: try_from ( sx) . ok ( ) ?;
413+ let sy = u8:: try_from ( sy) . ok ( ) ?;
414+
415+ sprites. get_pixel ( memory, sx, sy)
416+ } ) ;
418417}
419418
420419fn sample ( x : i16 , dw : i16 , sw : i16 , factor : Option < i16 > ) -> i16 {
@@ -426,3 +425,88 @@ fn sample(x: i16, dw: i16, sw: i16, factor: Option<i16>) -> i16 {
426425
427426 ret
428427}
428+
429+ #[ api_callback]
430+ pub fn map ( rt : & mut Runtime , mx : Option < i16 > , my : Option < i16 > , dx : Option < i16 > , dy : Option < i16 > , mw : Option < i16 > , mh : Option < i16 > , layer : Option < i16 > ) {
431+ let memory = & mut rt. memory ;
432+ let graphics = memory. graphics ( ) ;
433+ let sprites = graphics. sprites ( ) ;
434+ let map = graphics. map ( memory) ;
435+ let painter = graphics. painter ( memory) . sprite_mode ( memory) ;
436+
437+ let mx = mx. unwrap_or ( 0 ) ;
438+ let my = my. unwrap_or ( 0 ) ;
439+ let dx = dx. unwrap_or ( 0 ) ;
440+ let dy = dy. unwrap_or ( 0 ) ;
441+ let mut mw = mw. map ( |sw| sw. max ( 0 ) as u16 ) . unwrap_or ( map. width ( ) ) ;
442+ let mut mh = mh. map ( |sh| sh. max ( 0 ) as u16 ) . unwrap_or ( map. height ( ) . min ( 0x7FFF ) ) ;
443+
444+ let layer = match layer {
445+ None | Some ( 0 ) => 0xFF ,
446+ Some ( val) => val as u8 ,
447+ } ;
448+
449+ let ( mut x0, mut y0) = painter. to_abs ( dx, dy) ;
450+
451+ let mut mx = if mx < 0 {
452+ x0 = x0. saturating_add ( mx. saturating_neg ( ) . saturating_mul ( 8 ) ) ;
453+ mw = mw. saturating_sub ( mx. saturating_neg ( ) as u16 ) ;
454+ 0
455+ } else {
456+ mx as u16
457+ } ;
458+
459+ let mut my = if my < 0 {
460+ y0 = y0. saturating_add ( my. saturating_neg ( ) . saturating_mul ( 8 ) ) ;
461+ mh = mh. saturating_sub ( my. saturating_neg ( ) as u16 ) ;
462+ 0
463+ } else {
464+ my as u16
465+ } ;
466+
467+ if x0 <= -8 {
468+ let cells = ( x0 / -8 ) as u16 ;
469+ mx = mx. saturating_add ( cells) ;
470+ mw = mw. saturating_sub ( cells) ;
471+ x0 %= 8 ;
472+ }
473+
474+ if y0 <= -8 {
475+ let cells = ( y0 / -8 ) as u16 ;
476+ my = my. saturating_add ( cells) ;
477+ mh = mh. saturating_sub ( cells) ;
478+ y0 %= 8 ;
479+ }
480+
481+ if mx + mw > map. width ( ) {
482+ mw = map. width ( ) . saturating_sub ( mx) ;
483+ }
484+
485+ if my + mh > map. height ( ) {
486+ mh = map. height ( ) . saturating_sub ( my) ;
487+ }
488+
489+ if mw <= 0 || mh <= 0 || x0 >= 128 || y0 >= 128 || mx >= map. width ( ) || my >= map. height ( ) || layer == 0 { return ; }
490+
491+ let mw = mw. min ( 17 ) ;
492+ let mh = mh. min ( 17 ) ;
493+
494+ for cy in 0 ..mh {
495+ for cx in 0 ..mw {
496+ let sprite = map. get_sprite ( memory, mx + cx, my + cy) . unwrap ( ) ;
497+
498+ let [ sx, sy] = sprites. sprite_pos ( sprite) . map ( i16:: from) ;
499+ let sx0 = x0 + cx as i16 * 8 ;
500+ let sy0 = y0 + cy as i16 * 8 ;
501+
502+ if sprite == 0 || layer & memory. sprite_flags ( ) [ sprite] == 0 { continue }
503+
504+ painter. paint_abs_tex (
505+ memory,
506+ sx0..sx0+8 ,
507+ sy0..sy0+8 ,
508+ |memory : & mut Memory , x, y| sprites. get_pixel ( memory, ( sx + x as i16 - sx0) as u8 , ( sy + y as i16 - sy0) as u8 ) ,
509+ ) ;
510+ }
511+ }
512+ }
0 commit comments