Initial commit
This commit is contained in:
959
backends/graphics/atari/atari-c2p-asm.S
Normal file
959
backends/graphics/atari/atari-c2p-asm.S
Normal file
@@ -0,0 +1,959 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY| without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../platform/atari/symbols.h"
|
||||
|
||||
| C2P by Mikael Kalms (public domain)
|
||||
| See https://github.com/Kalmalyzer/kalms-c2p
|
||||
|
||||
.globl SYM(asm_c2p1x1_8)
|
||||
.globl SYM(asm_c2p1x1_8_tt)
|
||||
.globl SYM(asm_c2p1x1_8_rect)
|
||||
.globl SYM(asm_c2p1x1_4)
|
||||
.globl SYM(asm_c2p1x1_4_rect)
|
||||
|
||||
|
||||
.text
|
||||
|
||||
| void asm_c2p1x1_8(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
|
||||
SYM(asm_c2p1x1_8):
|
||||
#ifdef __FASTCALL__
|
||||
| a0: chunky
|
||||
move.l a1,d0 | chunky end
|
||||
move.l 4(sp),a1 | screen
|
||||
#else
|
||||
move.l (4,sp),a0 | chunky
|
||||
move.l (8,sp),d0 | chunky end
|
||||
move.l (12,sp),a1 | screen
|
||||
#endif
|
||||
movem.l d2-d7/a2-a6,-(sp)
|
||||
move.l d0,a2
|
||||
move.l #0x0f0f0f0f,d4
|
||||
move.l #0x00ff00ff,d5
|
||||
move.l #0x55555555,d6
|
||||
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d3
|
||||
|
||||
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
|
||||
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
|
||||
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
|
||||
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d1
|
||||
move.l d3,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d2,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d2
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d1,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d1
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
bra.s c2p1x1_8_start
|
||||
|
||||
c2p1x1_8_pix16:
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d3
|
||||
|
||||
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
|
||||
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
|
||||
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
|
||||
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #4,d7
|
||||
move.l a3,(a1)+
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d1
|
||||
move.l d3,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d2,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d2
|
||||
move.l a4,(a1)+
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
move.l a5,(a1)+
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d1,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d1
|
||||
move.l a6,(a1)+
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
c2p1x1_8_start:
|
||||
move.l d2,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d0,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d0
|
||||
add.l d7,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d1,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d1
|
||||
add.l d7,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
|
||||
| a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
|
||||
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.w d2,d7
|
||||
move.w d0,d2
|
||||
swap d2
|
||||
move.w d2,d0
|
||||
move.w d7,d2
|
||||
move.w d3,d7
|
||||
move.w d1,d3
|
||||
swap d3
|
||||
move.w d3,d1
|
||||
move.w d7,d3
|
||||
|
||||
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
|
||||
| c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
|
||||
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d0,d7
|
||||
and.l #0x33333333,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d1,d7
|
||||
and.l #0x33333333,d7
|
||||
eor.l d7,d1
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7 a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6
|
||||
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
|
||||
| a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5 a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4
|
||||
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
|
||||
|
||||
swap d0
|
||||
swap d1
|
||||
swap d2
|
||||
swap d3
|
||||
|
||||
move.l d0,a6
|
||||
move.l d2,a5
|
||||
move.l d1,a4
|
||||
move.l d3,a3
|
||||
|
||||
cmp.l a0,a2
|
||||
bne c2p1x1_8_pix16
|
||||
|
||||
move.l a3,(a1)+
|
||||
move.l a4,(a1)+
|
||||
move.l a5,(a1)+
|
||||
move.l a6,(a1)+
|
||||
|
||||
movem.l (sp)+,d2-d7/a2-a6
|
||||
rts
|
||||
|
||||
|
||||
| void asm_c2p1x1_8_tt(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen, uint32 screenPitch);
|
||||
SYM(asm_c2p1x1_8_tt):
|
||||
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
|
||||
|
||||
#ifdef __FASTCALL__
|
||||
| a0: chunky
|
||||
move.l a1,a2 | a2: chunky end
|
||||
move.l (11*4+4,sp),a1 | a1: screen
|
||||
| d0.l: screen pitch (double width)
|
||||
#else
|
||||
move.l (11*4+4,sp),a0 | a0: chunky
|
||||
move.l (11*4+8,sp),a2 | a2: chunky end
|
||||
move.l (11*4+12,sp),a1 | a1: screen
|
||||
move.l (11*4+16,sp),d0 | d0.l: screen pitch (double width)
|
||||
#endif
|
||||
move.l sp,old_sp
|
||||
|
||||
move.l d0,screen_pitch
|
||||
|
||||
lsr.l #1,d0
|
||||
lea (a1,d0.l),a7 | a7: end of first dst line
|
||||
|
||||
move.l d0,screen_offset
|
||||
|
||||
move.l #0x0f0f0f0f,d4
|
||||
move.l #0x00ff00ff,d5
|
||||
move.l #0x55555555,d6
|
||||
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d3
|
||||
|
||||
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
|
||||
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
|
||||
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
|
||||
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d1
|
||||
move.l d3,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d2,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d2
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d1,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d1
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
bra.s c2p1x1_8_tt_start
|
||||
|
||||
c2p1x1_8_tt_pix16:
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d3
|
||||
|
||||
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
|
||||
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
|
||||
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
|
||||
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #4,d7
|
||||
move.l a3,(a1)+
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d1
|
||||
move.l d3,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d2,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d2
|
||||
move.l a4,(a1)+
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
move.l a5,(a1)+
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d1,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d1
|
||||
move.l a6,(a1)+
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
cmp.l a1,a7 | end of dst line?
|
||||
bne.s c2p1x1_8_tt_start
|
||||
|
||||
add.l (screen_offset,pc),a1
|
||||
add.l (screen_pitch,pc),a7
|
||||
|
||||
c2p1x1_8_tt_start:
|
||||
move.l d2,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d0,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d0
|
||||
add.l d7,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d1,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d1
|
||||
add.l d7,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
|
||||
| a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
|
||||
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.w d2,d7
|
||||
move.w d0,d2
|
||||
swap d2
|
||||
move.w d2,d0
|
||||
move.w d7,d2
|
||||
move.w d3,d7
|
||||
move.w d1,d3
|
||||
swap d3
|
||||
move.w d3,d1
|
||||
move.w d7,d3
|
||||
|
||||
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
|
||||
| c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
|
||||
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d0,d7
|
||||
and.l #0x33333333,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d1,d7
|
||||
and.l #0x33333333,d7
|
||||
eor.l d7,d1
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7 a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6
|
||||
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
|
||||
| a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5 a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4
|
||||
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
|
||||
|
||||
swap d0
|
||||
swap d1
|
||||
swap d2
|
||||
swap d3
|
||||
|
||||
move.l d0,a6
|
||||
move.l d2,a5
|
||||
move.l d1,a4
|
||||
move.l d3,a3
|
||||
|
||||
cmp.l a0,a2
|
||||
bne c2p1x1_8_tt_pix16
|
||||
|
||||
move.l a3,(a1)+
|
||||
move.l a4,(a1)+
|
||||
move.l a5,(a1)+
|
||||
move.l a6,(a1)+
|
||||
|
||||
move.l old_sp,sp
|
||||
movem.l (sp)+,d2-d7/a2-a6
|
||||
rts
|
||||
|
||||
|
||||
| void asm_c2p1x1_8_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
|
||||
SYM(asm_c2p1x1_8_rect):
|
||||
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
|
||||
|
||||
#ifdef __FASTCALL__
|
||||
| a0: chunky
|
||||
move.l a1,chunky_end
|
||||
| d0.l: chunky width
|
||||
move.l (11*4+4,sp),a1 | a1: screen
|
||||
exg d1,d2 | d2.l: chunky pitch
|
||||
| d1.l: screen pitch
|
||||
#else
|
||||
move.l (11*4+4,sp),a0 | a0: chunky
|
||||
move.l (11*4+8,sp),chunky_end
|
||||
move.l (11*4+12,sp),d0 | d0.l: chunky width
|
||||
move.l (11*4+16,sp),d2 | d2.l: chunky pitch
|
||||
move.l (11*4+20,sp),a1 | a1: screen
|
||||
move.l (11*4+24,sp),d1 | d1.l: screen pitch
|
||||
#endif
|
||||
move.l sp,old_sp
|
||||
|
||||
lea (a0,d0.l),a2 | a2: end of first src line
|
||||
lea (a1,d0.l),a7 | a7: end of first dst line
|
||||
|
||||
move.l d1,screen_pitch
|
||||
|
||||
sub.l d0,d1
|
||||
move.l d1,screen_offset
|
||||
|
||||
move.l d2,chunky_pitch
|
||||
|
||||
sub.l d0,d2
|
||||
move.l d2,chunky_offset
|
||||
|
||||
move.l #0x0f0f0f0f,d4
|
||||
move.l #0x00ff00ff,d5
|
||||
move.l #0x55555555,d6
|
||||
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d3
|
||||
|
||||
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
|
||||
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
|
||||
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
|
||||
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d1
|
||||
move.l d3,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d2,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d2
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d1,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d1
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
bra.s c2p1x1_8_rect_start
|
||||
|
||||
c2p1x1_8_rect_pix16:
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d3
|
||||
|
||||
| a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
|
||||
| e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
|
||||
| i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
|
||||
| m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #4,d7
|
||||
move.l a3,(a1)+
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d1
|
||||
move.l d3,d7
|
||||
lsr.l #4,d7
|
||||
eor.l d2,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d2
|
||||
move.l a4,(a1)+
|
||||
lsl.l #4,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 b7b6b5b4f7f6f5f4 c7c6c5c4g7g6g5g4 d7d6d5d4h7h6h5h4
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i7i6i5i4m7m6m5m4 j7j6j5j4n7n6n5n4 k7k6k5k4o7o6o5o4 l7l6l5l4p7p6p5p4
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
move.l a5,(a1)+
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d1,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d1
|
||||
move.l a6,(a1)+
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
cmp.l a1,a7 | end of dst line?
|
||||
bne.s c2p1x1_8_rect_start
|
||||
|
||||
add.l (screen_offset,pc),a1
|
||||
add.l (screen_pitch,pc),a7
|
||||
|
||||
c2p1x1_8_rect_start:
|
||||
move.l d2,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d0,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d0
|
||||
add.l d7,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d1,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d1
|
||||
add.l d7,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
|
||||
| a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
|
||||
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.w d2,d7
|
||||
move.w d0,d2
|
||||
swap d2
|
||||
move.w d2,d0
|
||||
move.w d7,d2
|
||||
move.w d3,d7
|
||||
move.w d1,d3
|
||||
swap d3
|
||||
move.w d3,d1
|
||||
move.w d7,d3
|
||||
|
||||
| a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
|
||||
| c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4
|
||||
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.l d2,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d0,d7
|
||||
and.l #0x33333333,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d2
|
||||
move.l d3,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d1,d7
|
||||
and.l #0x33333333,d7
|
||||
eor.l d7,d1
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d3
|
||||
|
||||
| a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7 a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6
|
||||
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
|
||||
| a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5 a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4
|
||||
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
|
||||
|
||||
swap d0
|
||||
swap d1
|
||||
swap d2
|
||||
swap d3
|
||||
|
||||
move.l d0,a6
|
||||
move.l d2,a5
|
||||
move.l d1,a4
|
||||
move.l d3,a3
|
||||
|
||||
cmp.l a0,a2 | end of src line?
|
||||
bne c2p1x1_8_rect_pix16
|
||||
|
||||
cmp.l (chunky_end,pc),a2
|
||||
beq.s c2p1x1_8_rect_done
|
||||
|
||||
add.l (chunky_offset,pc),a0
|
||||
add.l (chunky_pitch,pc),a2
|
||||
|
||||
bra c2p1x1_8_rect_pix16
|
||||
|
||||
c2p1x1_8_rect_done:
|
||||
move.l a3,(a1)+
|
||||
move.l a4,(a1)+
|
||||
move.l a5,(a1)+
|
||||
move.l a6,(a1)+
|
||||
|
||||
move.l old_sp,sp
|
||||
movem.l (sp)+,d2-d7/a2-a6
|
||||
rts
|
||||
|
||||
|
||||
| void asm_c2p1x1_4(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
|
||||
SYM(asm_c2p1x1_4):
|
||||
#ifdef __FASTCALL__
|
||||
| a0: chunky
|
||||
move.l a1,d0 | chunky end
|
||||
move.l 4(sp),a1 | screen
|
||||
#else
|
||||
move.l (4,sp),a0 | chunky
|
||||
move.l (8,sp),d0 | chunky end
|
||||
move.l (12,sp),a1 | screen
|
||||
#endif
|
||||
movem.l d2-d7/a2-a6,-(sp)
|
||||
move.l d0,a2
|
||||
move.l #0x33333333,d4
|
||||
move.l #0x00ff00ff,d5
|
||||
move.l #0x55555555,d6
|
||||
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d3
|
||||
lsl.l #4,d0
|
||||
lsl.l #4,d1
|
||||
or.l d2,d0
|
||||
or.l d3,d1
|
||||
bra.s c2p1x1_4_start
|
||||
|
||||
c2p1x1_4_pix16:
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d3
|
||||
lsl.l #4,d0
|
||||
lsl.l #4,d1
|
||||
move.l a5,(a1)+
|
||||
or.l d2,d0
|
||||
or.l d3,d1
|
||||
move.l a6,(a1)+
|
||||
|
||||
c2p1x1_4_start:
|
||||
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d1
|
||||
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d0,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d0
|
||||
add.l d7,d7
|
||||
eor.l d7,d1
|
||||
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
|
||||
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.w d1,d7
|
||||
move.w d0,d1
|
||||
swap d1
|
||||
move.w d1,d0
|
||||
move.w d7,d1
|
||||
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
|
||||
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d1
|
||||
|
||||
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
|
||||
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
|
||||
|
||||
swap d0
|
||||
swap d1
|
||||
|
||||
move.l d1,a5
|
||||
move.l d0,a6
|
||||
|
||||
cmp.l a0,a2
|
||||
bne.s c2p1x1_4_pix16
|
||||
|
||||
move.l a5,(a1)+
|
||||
move.l a6,(a1)+
|
||||
|
||||
movem.l (sp)+,d2-d7/a2-a6
|
||||
rts
|
||||
|
||||
|
||||
| void asm_c2p1x1_4_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
|
||||
SYM(asm_c2p1x1_4_rect):
|
||||
movem.l d2-d7/a2-a6,-(sp) | 6 + 5 = 11 longs
|
||||
|
||||
#ifdef __FASTCALL__
|
||||
| a0: chunky
|
||||
move.l a1,chunky_end
|
||||
| d0.l: chunky width
|
||||
move.l (11*4+4,sp),a1 | a1: screen
|
||||
exg d1,d2 | d2.l: chunky pitch
|
||||
| d1.l: screen pitch
|
||||
#else
|
||||
move.l (11*4+4,sp),a0 | a0: chunky
|
||||
move.l (11*4+8,sp),chunky_end
|
||||
move.l (11*4+12,sp),d0 | d0.l: chunky width
|
||||
move.l (11*4+16,sp),d2 | d2.l: chunky pitch
|
||||
move.l (11*4+20,sp),a1 | a1: screen
|
||||
move.l (11*4+24,sp),d1 | d1.l: screen pitch
|
||||
#endif
|
||||
move.l sp,old_sp
|
||||
|
||||
move.l d0,d3 | d3.l: screen width
|
||||
lsr.l #1,d3 |
|
||||
|
||||
lea (a0,d0.l),a2 | a2: end of first src line
|
||||
lea (a1,d3.l),a7 | a7: end of first dst line
|
||||
|
||||
move.l d1,screen_pitch
|
||||
|
||||
sub.l d3,d1
|
||||
move.l d1,screen_offset
|
||||
|
||||
move.l d2,chunky_pitch
|
||||
|
||||
sub.l d0,d2
|
||||
move.l d2,chunky_offset
|
||||
|
||||
move.l #0x33333333,d4
|
||||
move.l #0x00ff00ff,d5
|
||||
move.l #0x55555555,d6
|
||||
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d3
|
||||
lsl.l #4,d0
|
||||
lsl.l #4,d1
|
||||
or.l d2,d0
|
||||
or.l d3,d1
|
||||
bra.s c2p1x1_4_rect_start
|
||||
|
||||
c2p1x1_4_rect_pix16:
|
||||
move.l (a0)+,d0
|
||||
move.l (a0)+,d2
|
||||
move.l (a0)+,d1
|
||||
move.l (a0)+,d3
|
||||
lsl.l #4,d0
|
||||
lsl.l #4,d1
|
||||
move.l a5,(a1)+
|
||||
or.l d2,d0
|
||||
or.l d3,d1
|
||||
move.l a6,(a1)+
|
||||
|
||||
cmp.l a1,a7 | end of dst line?
|
||||
bne.s c2p1x1_4_rect_start
|
||||
|
||||
add.l (screen_offset,pc),a1
|
||||
add.l (screen_pitch,pc),a7
|
||||
|
||||
c2p1x1_4_rect_start:
|
||||
|
||||
| a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
|
||||
| i3i2i1i0m3m2m1m0 j3j2j1j0n3n2n1n0 k3k2k1k0o3o2o1o0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #8,d7
|
||||
eor.l d0,d7
|
||||
and.l d5,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #8,d7
|
||||
eor.l d7,d1
|
||||
|
||||
| a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
|
||||
| b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #1,d7
|
||||
eor.l d0,d7
|
||||
and.l d6,d7
|
||||
eor.l d7,d0
|
||||
add.l d7,d7
|
||||
eor.l d7,d1
|
||||
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1
|
||||
| a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.w d1,d7
|
||||
move.w d0,d1
|
||||
swap d1
|
||||
move.w d1,d0
|
||||
move.w d7,d1
|
||||
|
||||
| a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0
|
||||
| c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0
|
||||
|
||||
move.l d1,d7
|
||||
lsr.l #2,d7
|
||||
eor.l d0,d7
|
||||
and.l d4,d7
|
||||
eor.l d7,d0
|
||||
lsl.l #2,d7
|
||||
eor.l d7,d1
|
||||
|
||||
| a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
|
||||
| a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
|
||||
|
||||
swap d0
|
||||
swap d1
|
||||
|
||||
move.l d1,a5
|
||||
move.l d0,a6
|
||||
|
||||
cmp.l a0,a2 | end of src line?
|
||||
bne.s c2p1x1_4_rect_pix16
|
||||
|
||||
cmp.l (chunky_end,pc),a2
|
||||
beq.s c2p1x1_4_rect_done
|
||||
|
||||
add.l (chunky_offset,pc),a0
|
||||
add.l (chunky_pitch,pc),a2
|
||||
|
||||
bra.s c2p1x1_4_rect_pix16
|
||||
|
||||
c2p1x1_4_rect_done:
|
||||
move.l a5,(a1)+
|
||||
move.l a6,(a1)+
|
||||
|
||||
move.l old_sp,sp
|
||||
movem.l (sp)+,d2-d7/a2-a6
|
||||
rts
|
||||
|
||||
|
||||
| place it within reach of 32K (PC relative)
|
||||
screen_pitch:
|
||||
ds.l 1
|
||||
screen_offset:
|
||||
ds.l 1
|
||||
chunky_pitch:
|
||||
ds.l 1
|
||||
chunky_offset:
|
||||
ds.l 1
|
||||
chunky_end:
|
||||
ds.l 1
|
||||
|
||||
.bss
|
||||
.even
|
||||
|
||||
old_sp: ds.l 1
|
||||
88
backends/graphics/atari/atari-c2p-asm.h
Normal file
88
backends/graphics/atari/atari-c2p-asm.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_C2P_ASM_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_C2P_ASM_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into eight bitplanes.
|
||||
* Optimized for surface-to-surface copy with the same pitch.
|
||||
*
|
||||
* @param pChunky chunky buffer start
|
||||
* @param pChunkyEnd chunky buffer end (past-the-end iterator)
|
||||
* @param pScreen bitplane screen start
|
||||
*/
|
||||
void asm_c2p1x1_8(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
|
||||
|
||||
/**
|
||||
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into eight bitplanes.
|
||||
* Optimized for surface-to-surface copy with the double screen pitch (typically 320x480).
|
||||
*
|
||||
* @param pChunky chunky buffer start
|
||||
* @param pChunkyEnd chunky buffer end (past-the-end iterator)
|
||||
* @param pScreen bitplane screen start
|
||||
* @param screenPitch bitplane screen width (in bytes)
|
||||
*/
|
||||
void asm_c2p1x1_8_tt(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen, uint32 screenPitch);
|
||||
|
||||
/**
|
||||
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into eight bitplanes.
|
||||
* Optimized for arbitrary rectangle position and dimension (16px aligned).
|
||||
*
|
||||
* @param pChunky chunky buffer at rectangle's [X1, Y1] position
|
||||
* @param pChunkyEnd chunky buffer at rectangle's [X2, Y2] position (included)
|
||||
* @param chunkyWidth rectangle width
|
||||
* @param chunkyPitch chunky buffer width (in bytes)
|
||||
* @param pScreen bitplane screen at rectangle's [X1, Y1] position
|
||||
* @param screenPitch bitplane screen width (in bytes)
|
||||
*/
|
||||
void asm_c2p1x1_8_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
|
||||
|
||||
/**
|
||||
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into four bitplanes.
|
||||
* Optimized for surface-to-surface copy with the same pitch.
|
||||
*
|
||||
* @param pChunky chunky buffer start
|
||||
* @param pChunkyEnd chunky buffer end (past-the-end iterator)
|
||||
* @param pScreen bitplane screen start
|
||||
*/
|
||||
void asm_c2p1x1_4(const byte *pChunky, const byte *pChunkyEnd, byte *pScreen);
|
||||
|
||||
/**
|
||||
* Chunky to planar conversion routine. Converts a chunky (byte) buffer into four bitplanes.
|
||||
* Optimized for arbitrary rectangle position and dimension (16px aligned).
|
||||
*
|
||||
* @param pChunky chunky buffer at rectangle's [X1, Y1] position
|
||||
* @param pChunkyEnd chunky buffer at rectangle's [X2, Y2] position (included)
|
||||
* @param chunkyWidth rectangle width
|
||||
* @param chunkyPitch chunky buffer width (in bytes)
|
||||
* @param pScreen bitplane screen at rectangle's [X1, Y1] position
|
||||
* @param screenPitch bitplane screen width (in bytes)
|
||||
*/
|
||||
void asm_c2p1x1_4_rect(const byte *pChunky, const byte *pChunkyEnd, uint32 chunkyWidth, uint32 chunkyPitch, byte *pScreen, uint32 screenPitch);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
320
backends/graphics/atari/atari-cursor.cpp
Normal file
320
backends/graphics/atari/atari-cursor.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "atari-cursor.h"
|
||||
|
||||
#include "atari-supervidel.h"
|
||||
#include "atari-surface.h"
|
||||
//#include "backends/platform/atari/atari-debug.h"
|
||||
|
||||
bool Cursor::_globalSurfaceChanged;
|
||||
|
||||
byte Cursor::_palette[256*3];
|
||||
|
||||
const byte *Cursor::_buf;
|
||||
int Cursor::_width;
|
||||
int Cursor::_height;
|
||||
int Cursor::_hotspotX;
|
||||
int Cursor::_hotspotY;
|
||||
uint32 Cursor::_keycolor;
|
||||
|
||||
Graphics::Surface Cursor::_surface;
|
||||
Graphics::Surface Cursor::_surfaceMask;
|
||||
|
||||
Cursor::~Cursor() {
|
||||
_savedBackground.free();
|
||||
// beware, called multiple times (they have to be destroyed before
|
||||
// AtariSurfaceDeinit() is called)
|
||||
if (_surface.getPixels())
|
||||
_surface.free();
|
||||
if (_surface.getPixels())
|
||||
_surfaceMask.free();
|
||||
}
|
||||
|
||||
void Cursor::update() {
|
||||
if (!_buf) {
|
||||
_outOfScreen = true;
|
||||
_savedRect = _alignedDstRect = Common::Rect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_visible || (!_positionChanged && !_surfaceChanged))
|
||||
return;
|
||||
|
||||
_srcRect = Common::Rect(_width, _height);
|
||||
|
||||
_dstRect = Common::Rect(
|
||||
_x - _hotspotX, // left
|
||||
_y - _hotspotY, // top
|
||||
_x - _hotspotX + _width, // right
|
||||
_y - _hotspotY + _height); // bottom
|
||||
|
||||
_outOfScreen = !_boundingSurf->clip(_srcRect, _dstRect);
|
||||
|
||||
if (!_outOfScreen) {
|
||||
assert(_srcRect.width() == _dstRect.width());
|
||||
assert(_srcRect.height() == _dstRect.height());
|
||||
|
||||
const int dstBitsPerPixel = _screenSurf->getBitsPerPixel();
|
||||
const int xOffset = (_screenSurf->w - _boundingSurf->w) / 2;
|
||||
|
||||
// non-direct rendering never uses 4bpp but maybe in the future ...
|
||||
_savedRect = AtariSurface::alignRect(
|
||||
_dstRect.left * dstBitsPerPixel / 8, // fake 4bpp by 8bpp's x/2
|
||||
_dstRect.top,
|
||||
_dstRect.right * dstBitsPerPixel / 8, // fake 4bpp by 8bpp's width/2
|
||||
_dstRect.bottom);
|
||||
|
||||
// this is used only in flushBackground() for comparison with rects
|
||||
// passed by Screen::addDirtyRect (aligned and shifted by the same offset)
|
||||
_alignedDstRect = AtariSurface::alignRect(
|
||||
_dstRect.left + xOffset,
|
||||
_dstRect.top,
|
||||
_dstRect.right + xOffset,
|
||||
_dstRect.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::updatePosition(int deltaX, int deltaY) {
|
||||
//atari_debug("Cursor::updatePosition: %d, %d", deltaX, deltaX);
|
||||
|
||||
if (deltaX == 0 && deltaY == 0)
|
||||
return;
|
||||
|
||||
_x += deltaX;
|
||||
_y += deltaY;
|
||||
|
||||
if (_x < 0)
|
||||
_x = 0;
|
||||
else if (_x >= _boundingSurf->w)
|
||||
_x = _boundingSurf->w - 1;
|
||||
|
||||
if (_y < 0)
|
||||
_y = 0;
|
||||
else if (_y >= _boundingSurf->h)
|
||||
_y = _boundingSurf->h - 1;
|
||||
|
||||
_positionChanged = true;
|
||||
}
|
||||
|
||||
/* static */ void Cursor::setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor) {
|
||||
if (w == 0 || h == 0 || buf == nullptr) {
|
||||
_buf = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
_buf = (const byte *)buf;
|
||||
_width = w;
|
||||
_height = h;
|
||||
_hotspotX = hotspotX;
|
||||
_hotspotY = hotspotY;
|
||||
_keycolor = keycolor;
|
||||
|
||||
_globalSurfaceChanged = true;
|
||||
}
|
||||
|
||||
/* static */ void Cursor::setPalette(const byte *colors, uint start, uint num) {
|
||||
memcpy(&_palette[start * 3], colors, num * 3);
|
||||
|
||||
_globalSurfaceChanged = true;
|
||||
}
|
||||
|
||||
/* static */ void Cursor::convertSurfaceTo(const Graphics::PixelFormat &format) {
|
||||
static int rShift, gShift, bShift;
|
||||
static int rMask, gMask, bMask;
|
||||
|
||||
const int cursorWidth = g_hasSuperVidel ? _width : ((_width + 15) & (-16));
|
||||
const int cursorHeight = _height;
|
||||
const bool isCLUT8 = format.isCLUT8();
|
||||
|
||||
if (_surface.w != cursorWidth || _surface.h != cursorHeight || _surface.format != format) {
|
||||
if (!isCLUT8 && _surface.format != format) {
|
||||
rShift = format.rLoss - format.rShift;
|
||||
gShift = format.gLoss - format.gShift;
|
||||
bShift = format.bLoss - format.bShift;
|
||||
|
||||
rMask = format.rMax() << format.rShift;
|
||||
gMask = format.gMax() << format.gShift;
|
||||
bMask = format.bMax() << format.bShift;
|
||||
}
|
||||
|
||||
// always 8-bit as this is both 8-bit src and 4-bit dst for C2P
|
||||
_surface.create(cursorWidth, cursorHeight, format);
|
||||
assert(_surface.pitch == _surface.w);
|
||||
// always 8-bit or 1-bit
|
||||
_surfaceMask.create(g_hasSuperVidel ? _surface.w : _surface.w / 8, _surface.h, PIXELFORMAT_CLUT8);
|
||||
_surfaceMask.w = _surface.w;
|
||||
}
|
||||
|
||||
const byte *src = _buf;
|
||||
byte *dst = (byte *)_surface.getPixels();
|
||||
byte *dstMask = (byte *)_surfaceMask.getPixels();
|
||||
uint16 *dstMask16 = (uint16 *)_surfaceMask.getPixels();
|
||||
const int dstPadding = _surface.w - _width;
|
||||
|
||||
uint16 mask16 = 0xffff;
|
||||
uint16 invertedBit = 0x7fff;
|
||||
|
||||
for (int j = 0; j < _height; ++j) {
|
||||
for (int i = 0; i < _width; ++i) {
|
||||
const uint32 color = *src++;
|
||||
|
||||
if (color != _keycolor) {
|
||||
if (!isCLUT8) {
|
||||
// Convert CLUT8 to RGB332/RGB121 palette
|
||||
*dst++ = ((_palette[color*3 + 0] >> rShift) & rMask)
|
||||
| ((_palette[color*3 + 1] >> gShift) & gMask)
|
||||
| ((_palette[color*3 + 2] >> bShift) & bMask);
|
||||
} else {
|
||||
*dst++ = color;
|
||||
}
|
||||
|
||||
if (g_hasSuperVidel)
|
||||
*dstMask++ = 0xff;
|
||||
else
|
||||
mask16 &= invertedBit;
|
||||
} else {
|
||||
*dst++ = 0x00;
|
||||
|
||||
if (g_hasSuperVidel)
|
||||
*dstMask++ = 0x00;
|
||||
}
|
||||
|
||||
if (!g_hasSuperVidel && invertedBit == 0xfffe) {
|
||||
*dstMask16++ = mask16;
|
||||
mask16 = 0xffff;
|
||||
}
|
||||
|
||||
// ror.w #1,invertedBit
|
||||
invertedBit = (invertedBit >> 1) | (invertedBit << (sizeof (invertedBit) * 8 - 1));
|
||||
}
|
||||
|
||||
if (dstPadding) {
|
||||
assert(!g_hasSuperVidel);
|
||||
|
||||
// this is at most 15 pixels
|
||||
memset(dst, 0x00, dstPadding);
|
||||
dst += dstPadding;
|
||||
|
||||
*dstMask16++ = mask16;
|
||||
mask16 = 0xffff;
|
||||
invertedBit = 0x7fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect Cursor::flushBackground(const Common::Rect &alignedRect, bool directRendering) {
|
||||
if (_savedRect.isEmpty())
|
||||
return _savedRect;
|
||||
|
||||
if (!alignedRect.isEmpty() && alignedRect.contains(_alignedDstRect)) {
|
||||
// better would be _visibilityChanged but update() ignores it
|
||||
_positionChanged = true;
|
||||
|
||||
_savedRect = Common::Rect();
|
||||
} else if (alignedRect.isEmpty() || alignedRect.intersects(_alignedDstRect)) {
|
||||
// better would be _visibilityChanged but update() ignores it
|
||||
_positionChanged = true;
|
||||
|
||||
if (directRendering)
|
||||
restoreBackground();
|
||||
else
|
||||
return _alignedDstRect;
|
||||
}
|
||||
|
||||
return Common::Rect();
|
||||
}
|
||||
|
||||
void Cursor::saveBackground() {
|
||||
if (_savedRect.isEmpty())
|
||||
return;
|
||||
|
||||
// as this is used only for direct rendering, we don't need to worry about offsettedSurf
|
||||
// having different dimensions than the source surface
|
||||
const Graphics::Surface &dstSurface = *_screenSurf;
|
||||
|
||||
//atari_debug("Cursor::saveBackground: %d %d %d %d", _savedRect.left, _savedRect.top, _savedRect.width(), _savedRect.height());
|
||||
|
||||
// save native bitplanes or pixels, so it must be a Graphics::Surface to copy from
|
||||
if (_savedBackground.w != _savedRect.width()
|
||||
|| _savedBackground.h != _savedRect.height()
|
||||
|| _savedBackground.format != dstSurface.format) {
|
||||
_savedBackground.create(_savedRect.width(), _savedRect.height(), dstSurface.format);
|
||||
}
|
||||
|
||||
_savedBackground.copyRectToSurface(dstSurface, 0, 0, _savedRect);
|
||||
}
|
||||
|
||||
void Cursor::draw() {
|
||||
AtariSurface &dstSurface = *_screenSurf;
|
||||
const int dstBitsPerPixel = dstSurface.getBitsPerPixel();
|
||||
|
||||
//atari_debug("Cursor::draw: %d %d %d %d", _dstRect.left, _dstRect.top, _dstRect.width(), _dstRect.height());
|
||||
|
||||
if (_globalSurfaceChanged) {
|
||||
convertSurfaceTo(dstSurface.format);
|
||||
|
||||
if (!g_hasSuperVidel) {
|
||||
// C2P in-place
|
||||
AtariSurface surf;
|
||||
surf.w = _surface.w;
|
||||
surf.h = _surface.h;
|
||||
surf.pitch = _surface.pitch * dstBitsPerPixel / 8; // 4bpp is not byte per pixel anymore
|
||||
surf.setPixels(_surface.getPixels());
|
||||
surf.format = _surface.format;
|
||||
|
||||
surf.copyRectToSurface(
|
||||
_surface,
|
||||
0, 0,
|
||||
Common::Rect(_surface.w, _surface.h));
|
||||
}
|
||||
|
||||
_globalSurfaceChanged = false;
|
||||
}
|
||||
|
||||
dstSurface.drawMaskedSprite(
|
||||
_surface, _surfaceMask, *_boundingSurf,
|
||||
_dstRect.left, _dstRect.top,
|
||||
_srcRect);
|
||||
|
||||
_visibilityChanged = _positionChanged = _surfaceChanged = false;
|
||||
}
|
||||
|
||||
void Cursor::restoreBackground() {
|
||||
if (_savedRect.isEmpty())
|
||||
return;
|
||||
|
||||
assert(_savedBackground.getPixels());
|
||||
|
||||
//atari_debug("Cursor::restoreBackground: %d %d %d %d", _savedRect.left, _savedRect.top, _savedRect.width(), _savedRect.height());
|
||||
|
||||
// as this is used only for direct rendering, we don't need to worry about offsettedSurf
|
||||
// having different dimensions than the source surface
|
||||
Graphics::Surface &dstSurface = *_screenSurf->surfacePtr();
|
||||
|
||||
// restore native bitplanes or pixels, so it must be a Graphics::Surface to copy to
|
||||
dstSurface.copyRectToSurface(
|
||||
_savedBackground,
|
||||
_savedRect.left, _savedRect.top,
|
||||
Common::Rect(_savedBackground.w, _savedBackground.h));
|
||||
|
||||
_savedRect = Common::Rect();
|
||||
}
|
||||
140
backends/graphics/atari/atari-cursor.h
Normal file
140
backends/graphics/atari/atari-cursor.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_CURSOR_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_CURSOR_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
class AtariSurface;
|
||||
|
||||
// Global state consists of:
|
||||
// - palette (used for the overlay only atm)
|
||||
// - shape (surface, dimensions, hotspot, keycolor)
|
||||
// - visibility
|
||||
// These always get updates by ScummVM, no need to differentiate between engines and the overlay.
|
||||
|
||||
struct Cursor {
|
||||
~Cursor();
|
||||
|
||||
void reset(AtariSurface* screenSurf, const Graphics::Surface *boundingSurf) {
|
||||
_screenSurf = screenSurf;
|
||||
_boundingSurf = boundingSurf;
|
||||
|
||||
_positionChanged = true;
|
||||
_surfaceChanged = true;
|
||||
_visibilityChanged = false;
|
||||
|
||||
_savedRect = _alignedDstRect = Common::Rect();
|
||||
}
|
||||
|
||||
// updates outOfScreen OR srcRect/dstRect (only if visible/needed)
|
||||
void update();
|
||||
|
||||
// visibility
|
||||
bool setVisible(bool visible) {
|
||||
if (_visible == visible) {
|
||||
return _visible;
|
||||
}
|
||||
|
||||
bool last = _visible;
|
||||
|
||||
_visible = visible;
|
||||
|
||||
_visibilityChanged = true;
|
||||
|
||||
return last;
|
||||
}
|
||||
void setSurfaceChanged() {
|
||||
_surfaceChanged = true;
|
||||
}
|
||||
|
||||
// position
|
||||
Common::Point getPosition() const {
|
||||
return Common::Point(_x, _y);
|
||||
}
|
||||
void setPosition(int x, int y) {
|
||||
//atari_debug("Cursor::setPosition: %d, %d", x, y);
|
||||
|
||||
if (_x == x && _y == y)
|
||||
return;
|
||||
|
||||
_x = x;
|
||||
_y = y;
|
||||
|
||||
_positionChanged = true;
|
||||
}
|
||||
void updatePosition(int deltaX, int deltaY);
|
||||
|
||||
// surface
|
||||
static void setSurface(const void *buf, int w, int h, int hotspotX, int hotspotY, uint32 keycolor);
|
||||
static void setPalette(const byte *colors, uint start, uint num);
|
||||
|
||||
bool isVisible() const {
|
||||
return !_outOfScreen && _visible;
|
||||
}
|
||||
bool isChanged() const {
|
||||
return _positionChanged || _surfaceChanged || _visibilityChanged;
|
||||
}
|
||||
|
||||
Common::Rect flushBackground(const Common::Rect &alignedRect, bool directRendering);
|
||||
void saveBackground();
|
||||
void draw();
|
||||
|
||||
private:
|
||||
static void convertSurfaceTo(const Graphics::PixelFormat &format);
|
||||
void restoreBackground();
|
||||
|
||||
AtariSurface *_screenSurf;
|
||||
const Graphics::Surface *_boundingSurf = nullptr;
|
||||
|
||||
bool _positionChanged = false;
|
||||
bool _surfaceChanged = false;
|
||||
bool _visibilityChanged = false;
|
||||
|
||||
bool _visible = false;
|
||||
int _x = 0;
|
||||
int _y = 0;
|
||||
bool _outOfScreen = true;
|
||||
Common::Rect _srcRect;
|
||||
Common::Rect _dstRect;
|
||||
|
||||
Graphics::Surface _savedBackground;
|
||||
Common::Rect _savedRect;
|
||||
Common::Rect _alignedDstRect;
|
||||
|
||||
// related to 'surface'
|
||||
static bool _globalSurfaceChanged;
|
||||
|
||||
static byte _palette[256*3];
|
||||
|
||||
static const byte *_buf;
|
||||
static int _width;
|
||||
static int _height;
|
||||
static int _hotspotX;
|
||||
static int _hotspotY;
|
||||
static uint32 _keycolor;
|
||||
|
||||
static Graphics::Surface _surface;
|
||||
static Graphics::Surface _surfaceMask;
|
||||
};
|
||||
|
||||
#endif // BACKENDS_GRAPHICS_ATARI_CURSOR_H
|
||||
510
backends/graphics/atari/atari-graphics-asm.S
Normal file
510
backends/graphics/atari/atari-graphics-asm.S
Normal file
@@ -0,0 +1,510 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY| without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../platform/atari/symbols.h"
|
||||
|
||||
.global SYM(asm_draw_4bpl_sprite)
|
||||
.global SYM(asm_draw_8bpl_sprite)
|
||||
|
||||
.text
|
||||
|
||||
skip_first_pix16:
|
||||
dc.b 0
|
||||
skip_last_pix16:
|
||||
dc.b 0
|
||||
|
||||
| extern void asm_draw_4bpl_sprite(uint16 *dstBuffer, const uint16 *srcBuffer, const uint16 *srcMask,
|
||||
| uint destX, uint destY, uint dstPitch, uint srcPitch, uint w, uint h,
|
||||
| bool skipFirstPix16, bool skipLastPix16);
|
||||
SYM(asm_draw_4bpl_sprite):
|
||||
movem.l d2-d7/a2,-(sp) | 7 longs
|
||||
|
||||
#ifdef __FASTCALL__
|
||||
move.l a0,a2 | a2: dstBuffer
|
||||
| a1: srcBuffer
|
||||
move.l (4+7*4,sp),a0 | a0: srcMask
|
||||
| d0.w: destX
|
||||
| d1.w: destY
|
||||
move.l d2,d3 | d3.w: dstPitch
|
||||
move.l (8+7*4,sp),d4 | d4.w: srcPitch
|
||||
move.l (12+7*4,sp),d6 | d6.w: w
|
||||
move.l (16+7*4,sp),d7 | d7.w: h
|
||||
tst.l (20+7*4,sp) | skipFirstPix16?
|
||||
sne skip_first_pix16
|
||||
tst.l (24+7*4,sp) | skipLastPix16?
|
||||
sne skip_last_pix16
|
||||
#else
|
||||
move.l (4+7*4,sp),a2 | a2: dstBuffer
|
||||
move.l (8+7*4,sp),a1 | a1: srcBuffer
|
||||
move.l (12+7*4,sp),a0 | a0: srcMask
|
||||
move.l (16+7*4,sp),d0 | d0.w: destX
|
||||
move.l (20+7*4,sp),d1 | d1.w: destY
|
||||
move.l (24+7*4,sp),d3 | d3.w: dstPitch
|
||||
move.l (28+7*4,sp),d4 | d4.w: srcPitch
|
||||
move.l (32+7*4,sp),d6 | d6.w: w
|
||||
move.l (36+7*4,sp),d7 | d7.w: h
|
||||
tst.l (40+7*4,sp) | skipFirstPix16?
|
||||
sne skip_first_pix16
|
||||
tst.l (44+7*4,sp) | skipLastPix16?
|
||||
sne skip_last_pix16
|
||||
#endif
|
||||
|
||||
| Draws a 4 bitplane sprite at any position on screen.
|
||||
| (c) 1999 Pieter van der Meer (EarX)
|
||||
|
|
||||
| INPUT: d0.w: x position of sprite on screen (left side)
|
||||
| d1.w: y position of sprite on screen (top side)
|
||||
| d6.w: number of 16pixel X blocks to do
|
||||
| d7.w: number of Y lines to to
|
||||
| a0: address of maskdata
|
||||
| a1: address of bitmapdata
|
||||
| a2: screen start address
|
||||
|
||||
move.w d0,d2 | / Calculate the
|
||||
andi.w #0b111111110000,d0 | | number of bits
|
||||
sub.w d0,d2 | \ to shift right.
|
||||
lsr.w #1,d0 | / Add x-position to
|
||||
adda.w d0,a2 | \ screenaddress.
|
||||
mulu.w d3,d1 | / Add y-position to
|
||||
adda.l d1,a2 | \ screenaddress.
|
||||
lsr.w #1,d6
|
||||
sub.w d6,d3 | / Prepare offset to next
|
||||
ext.l d3 | \ destination line.
|
||||
sub.w d6,d4 | / Prepare offset to next
|
||||
ext.l d4 | \ source line.
|
||||
subq.w #1,d7 | Adjust for dbra.
|
||||
lsr.w #3,d6 | d6.w: w/16
|
||||
subq.w #1,d6 | Adjust for dbra.
|
||||
move.w d6,d5 | Backup xloopcount in d5.w.
|
||||
|
||||
tst.b (skip_first_pix16,pc)
|
||||
jeq 1f
|
||||
subq.w #1,d5
|
||||
1:
|
||||
tst.b (skip_last_pix16,pc)
|
||||
jeq 2f
|
||||
subq.w #1,d5
|
||||
2:
|
||||
sprite4_yloop:
|
||||
move.w d5,d6 | Restore xloop counter.
|
||||
|
||||
tst.b (skip_first_pix16,pc)
|
||||
jeq 1f
|
||||
|
||||
moveq #16,d1
|
||||
sub.w d2,d1
|
||||
|
||||
moveq #0xffffffff,d0 | Prepare for maskshifting.
|
||||
move.w (a0)+,d0 | Get 16pixel mask in d0.w.
|
||||
rol.l d1,d0 | Shift it!
|
||||
addq.l #8,a2
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 0.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 1.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 2.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 3.
|
||||
subq.l #8,a2 | Return to blockstart.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 0.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 1.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 2.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 3.
|
||||
|
||||
subq.l #8,a2
|
||||
|
||||
1: tst.w d6
|
||||
jmi sprite4_xloop_done
|
||||
|
||||
sprite4_xloop:
|
||||
moveq #0xffffffff,d0 | Prepare for maskshifting.
|
||||
move.w (a0)+,d0 | Get 16pixel mask in d0.w.
|
||||
ror.l d2,d0 | Shift it!
|
||||
and.w d0,(a2)+ | Mask bitplane 0.
|
||||
and.w d0,(a2)+ | Mask bitplane 1.
|
||||
and.w d0,(a2)+ | Mask bitplane 2.
|
||||
and.w d0,(a2)+ | Mask bitplane 3.
|
||||
swap d0 | Get overspill in loword.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 0.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 1.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 2.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 3.
|
||||
lea (-16,a2),a2 | Return to blockstart.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 0.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,6(a2) | Paint overspill bitplane 0.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 1.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,6(a2) | Paint overspill bitplane 1.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 2.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,6(a2) | Paint overspill bitplane 2.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 3.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,6(a2) | Paint overspill bitplane 3.
|
||||
|
||||
dbra d6,sprite4_xloop | Loop until blocks done.
|
||||
|
||||
sprite4_xloop_done:
|
||||
tst.b (skip_last_pix16,pc)
|
||||
jeq 1f
|
||||
|
||||
moveq #0xffffffff,d0 | Prepare for maskshifting.
|
||||
move.w (a0)+,d0 | Get 16pixel mask in d0.w.
|
||||
ror.l d2,d0 | Shift it!
|
||||
and.w d0,(a2)+ | Mask bitplane 0.
|
||||
and.w d0,(a2)+ | Mask bitplane 1.
|
||||
and.w d0,(a2)+ | Mask bitplane 2.
|
||||
and.w d0,(a2)+ | Mask bitplane 3.
|
||||
subq.l #8,a2 | Return to blockstart.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 0.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 1.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 2.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 3.
|
||||
|
||||
1: move.l d4,d0
|
||||
asr.l #2,d0
|
||||
adda.l d0,a0
|
||||
adda.l d4,a1
|
||||
adda.l d3,a2 | Goto next screenline.
|
||||
dbra d7,sprite4_yloop | Loop until lines done.
|
||||
|
||||
movem.l (sp)+,d2-d7/a2
|
||||
rts
|
||||
|
||||
| extern void asm_draw_8bpl_sprite(uint16 *dstBuffer, const uint16 *srcBuffer, const uint16 *srcMask,
|
||||
| uint destX, uint destY, uint dstPitch, uint srcPitch, uint w, uint h,
|
||||
| bool skipFirstPix16, bool skipLastPix16);
|
||||
SYM(asm_draw_8bpl_sprite):
|
||||
movem.l d2-d7/a2,-(sp) | 7 longs
|
||||
|
||||
#ifdef __FASTCALL__
|
||||
move.l a0,a2 | a2: dstBuffer
|
||||
| a1: srcBuffer
|
||||
move.l (4+7*4,sp),a0 | a0: srcMask
|
||||
| d0.w: destX
|
||||
| d1.w: destY
|
||||
move.l d2,d3 | d3.w: dstPitch
|
||||
move.l (8+7*4,sp),d4 | d4.w: srcPitch
|
||||
move.l (12+7*4,sp),d6 | d6.w: w
|
||||
move.l (16+7*4,sp),d7 | d7.w: h
|
||||
tst.l (20+7*4,sp) | skipFirstPix16?
|
||||
sne skip_first_pix16
|
||||
tst.l (24+7*4,sp) | skipLastPix16?
|
||||
sne skip_last_pix16
|
||||
#else
|
||||
move.l (4+7*4,sp),a2 | a2: dstBuffer
|
||||
move.l (8+7*4,sp),a1 | a1: srcBuffer
|
||||
move.l (12+7*4,sp),a0 | a0: srcMask
|
||||
move.l (16+7*4,sp),d0 | d0.w: destX
|
||||
move.l (20+7*4,sp),d1 | d1.w: destY
|
||||
move.l (24+7*4,sp),d3 | d3.w: dstPitch
|
||||
move.l (28+7*4,sp),d4 | d4.w: srcPitch
|
||||
move.l (32+7*4,sp),d6 | d6.w: w
|
||||
move.l (36+7*4,sp),d7 | d7.w: h
|
||||
tst.l (40+7*4,sp) | skipFirstPix16?
|
||||
sne skip_first_pix16
|
||||
tst.l (45+7*4,sp) | skipLastPix16?
|
||||
sne skip_last_pix16
|
||||
#endif
|
||||
move.w d0,d2 | / Calculate the
|
||||
andi.w #0b111111110000,d0 | | number of bits
|
||||
sub.w d0,d2 | \ to shift right.
|
||||
adda.w d0,a2 | Add x-position to screenaddress.
|
||||
mulu.w d3,d1 | / Add y-position to
|
||||
adda.l d1,a2 | \ screenaddress.
|
||||
sub.w d6,d3 | / Prepare offset to next
|
||||
ext.l d3 | \ destination line.
|
||||
sub.w d6,d4 | / Prepare offset to next
|
||||
ext.l d4 | \ source line.
|
||||
subq.w #1,d7 | Adjust for dbra.
|
||||
lsr.w #4,d6 | d6.w: w/16
|
||||
subq.w #1,d6 | Adjust for dbra.
|
||||
move.w d6,d5 | Backup xloopcount in d5.w.
|
||||
|
||||
tst.b (skip_first_pix16,pc)
|
||||
jeq 1f
|
||||
subq.w #1,d5
|
||||
1:
|
||||
tst.b (skip_last_pix16,pc)
|
||||
jeq 2f
|
||||
subq.w #1,d5
|
||||
2:
|
||||
sprite8_yloop:
|
||||
move.w d5,d6 | Restore xloop counter.
|
||||
|
||||
tst.b (skip_first_pix16,pc)
|
||||
jeq 1f
|
||||
|
||||
moveq #16,d1
|
||||
sub.w d2,d1
|
||||
|
||||
moveq #0xffffffff,d0 | Prepare for maskshifting.
|
||||
move.w (a0)+,d0 | Get 16pixel mask in d0.w.
|
||||
rol.l d1,d0 | Shift it!
|
||||
lea (16,a2),a2
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 0.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 1.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 2.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 3.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 4.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 5.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 6.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 7.
|
||||
lea (-16,a2),a2 | Return to blockstart.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 0.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 1.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 2.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 3.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 4.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 5.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 6.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
rol.l d1,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint overspill bitplane 7.
|
||||
|
||||
lea (-16,a2),a2
|
||||
|
||||
1: tst.w d6
|
||||
jmi sprite8_xloop_done
|
||||
|
||||
sprite8_xloop:
|
||||
moveq #0xffffffff,d0 | Prepare for maskshifting.
|
||||
move.w (a0)+,d0 | Get 16pixel mask in d0.w.
|
||||
ror.l d2,d0 | Shift it!
|
||||
and.w d0,(a2)+ | Mask bitplane 0.
|
||||
and.w d0,(a2)+ | Mask bitplane 1.
|
||||
and.w d0,(a2)+ | Mask bitplane 2.
|
||||
and.w d0,(a2)+ | Mask bitplane 3.
|
||||
and.w d0,(a2)+ | Mask bitplane 4.
|
||||
and.w d0,(a2)+ | Mask bitplane 5.
|
||||
and.w d0,(a2)+ | Mask bitplane 6.
|
||||
and.w d0,(a2)+ | Mask bitplane 7.
|
||||
swap d0 | Get overspill in loword.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 0.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 1.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 2.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 3.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 4.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 5.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 6.
|
||||
and.w d0,(a2)+ | Mask overspill bitplane 7.
|
||||
lea (-32,a2),a2 | Return to blockstart.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 0.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 0.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 1.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 1.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 2.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 2.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 3.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 3.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 4.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 4.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 5.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 5.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 6.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 6.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 7.
|
||||
swap d0 | Get overspill in loword.
|
||||
or.w d0,14(a2) | Paint overspill bitplane 7.
|
||||
|
||||
dbra d6,sprite8_xloop | Loop until blocks done.
|
||||
|
||||
sprite8_xloop_done:
|
||||
tst.b (skip_last_pix16,pc)
|
||||
jeq 1f
|
||||
|
||||
moveq #0xffffffff,d0 | Prepare for maskshifting.
|
||||
move.w (a0)+,d0 | Get 16pixel mask in d0.w.
|
||||
ror.l d2,d0 | Shift it!
|
||||
and.w d0,(a2)+ | Mask bitplane 0.
|
||||
and.w d0,(a2)+ | Mask bitplane 1.
|
||||
and.w d0,(a2)+ | Mask bitplane 2.
|
||||
and.w d0,(a2)+ | Mask bitplane 3.
|
||||
and.w d0,(a2)+ | Mask bitplane 4.
|
||||
and.w d0,(a2)+ | Mask bitplane 5.
|
||||
and.w d0,(a2)+ | Mask bitplane 6.
|
||||
and.w d0,(a2)+ | Mask bitplane 7.
|
||||
lea (-16,a2),a2 | Return to blockstart.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 0.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 1.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 2.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 3.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 4.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 5.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 6.
|
||||
|
||||
moveq #0,d0 | Prepare for bitmapshifting.
|
||||
move.w (a1)+,d0 | Get bitplaneword in d0.w.
|
||||
ror.l d2,d0 | Shift it.
|
||||
or.w d0,(a2)+ | Paint bitplane 7.
|
||||
|
||||
1: move.l d4,d0
|
||||
asr.l #3,d0
|
||||
adda.l d0,a0
|
||||
adda.l d4,a1
|
||||
adda.l d3,a2 | Goto next screenline.
|
||||
dbra d7,sprite8_yloop | Loop until lines done.
|
||||
|
||||
movem.l (sp)+,d2-d7/a2
|
||||
rts
|
||||
68
backends/graphics/atari/atari-graphics-asm.h
Normal file
68
backends/graphics/atari/atari-graphics-asm.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_ASM_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_ASM_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
* Copy 4bpl sprite into 4bpl buffer. Sprite's width must be multiply of 16.
|
||||
*
|
||||
* @param dstBuffer destination buffer (four bitplanes)
|
||||
* @param srcBuffer source buffer (four bitplanes)
|
||||
* @param srcMask source mask (one bitplane)
|
||||
* @param destX sprite's X position (in pixels)
|
||||
* @param destY sprite's Y position (in pixels)
|
||||
* @param dstPitch destination buffer's pitch (in bytes)
|
||||
* @param srcPitch source buffer's pitch (in bytes)
|
||||
* @param w sprite's width (in pixels)
|
||||
* @param h sprite's height (in pixels)
|
||||
* @param skipFirstPix16 do not write first 16 pixels
|
||||
* @param skipLastPix16 do not write last 16 pixels
|
||||
*/
|
||||
void asm_draw_4bpl_sprite(uint16 *dstBuffer, const uint16 *srcBuffer, const uint16 *srcMask,
|
||||
uint destX, uint destY, uint dstPitch, uint srcPitch, uint w, uint h,
|
||||
bool skipFirstPix16, bool skipLastPix16);
|
||||
/**
|
||||
* Copy 8bpl sprite into 8bpl buffer. Sprite's width must be multiply of 16.
|
||||
*
|
||||
* @param dstBuffer destination buffer (eight bitplanes)
|
||||
* @param srcBuffer source buffer (eight bitplanes)
|
||||
* @param srcMask source mask (one bitplane)
|
||||
* @param destX sprite's X position (in pixels)
|
||||
* @param destY sprite's Y position (in pixels)
|
||||
* @param dstPitch destination buffer's pitch (in bytes)
|
||||
* @param srcPitch source buffer's pitch (in bytes)
|
||||
* @param w sprite's width (in pixels)
|
||||
* @param h sprite's height (in pixels)
|
||||
* @param skipFirstPix16 do not write first 16 pixels
|
||||
* @param skipLastPix16 do not write last 16 pixels
|
||||
*/
|
||||
void asm_draw_8bpl_sprite(uint16 *dstBuffer, const uint16 *srcBuffer, const uint16 *srcMask,
|
||||
uint destX, uint destY, uint dstPitch, uint srcPitch, uint w, uint h,
|
||||
bool skipFirstPix16, bool skipLastPix16);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1153
backends/graphics/atari/atari-graphics.cpp
Normal file
1153
backends/graphics/atari/atari-graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
213
backends/graphics/atari/atari-graphics.h
Normal file
213
backends/graphics/atari/atari-graphics.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_H
|
||||
|
||||
#include "backends/graphics/graphics.h"
|
||||
#include "common/events.h"
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "atari-cursor.h"
|
||||
#include "atari-pendingscreenchanges.h"
|
||||
#include "atari-screen.h"
|
||||
#include "atari-supervidel.h"
|
||||
|
||||
#define MAX_HZ_SHAKE 16 // Falcon only
|
||||
#define MAX_V_SHAKE 16
|
||||
|
||||
class AtariGraphicsManager final : public GraphicsManager, Common::EventObserver {
|
||||
friend class PendingScreenChanges;
|
||||
|
||||
public:
|
||||
AtariGraphicsManager();
|
||||
virtual ~AtariGraphicsManager();
|
||||
|
||||
bool hasFeature(OSystem::Feature f) const override;
|
||||
void setFeatureState(OSystem::Feature f, bool enable) override;
|
||||
bool getFeatureState(OSystem::Feature f) const override;
|
||||
|
||||
const OSystem::GraphicsMode *getSupportedGraphicsModes() const override {
|
||||
static const OSystem::GraphicsMode graphicsModes[] = {
|
||||
{ "direct", "Direct rendering", kDirectRendering },
|
||||
{ "single", "Single buffering", kSingleBuffering },
|
||||
{ "triple", "Triple buffering", kTripleBuffering },
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
return graphicsModes;
|
||||
}
|
||||
int getDefaultGraphicsMode() const override { return kTripleBuffering; }
|
||||
bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
|
||||
int getGraphicsMode() const override { return _currentState.mode; }
|
||||
|
||||
void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) override;
|
||||
|
||||
int getScreenChangeID() const override { return 0; }
|
||||
|
||||
void beginGFXTransaction() override;
|
||||
OSystem::TransactionError endGFXTransaction() override;
|
||||
|
||||
int16 getHeight() const override { return _currentState.height; }
|
||||
int16 getWidth() const override { return _currentState.width; }
|
||||
void setPalette(const byte *colors, uint start, uint num) override;
|
||||
void grabPalette(byte *colors, uint start, uint num) const override;
|
||||
void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
Graphics::Surface *lockScreen() override;
|
||||
void unlockScreen() override;
|
||||
void fillScreen(uint32 col) override;
|
||||
void fillScreen(const Common::Rect &r, uint32 col) override;
|
||||
void updateScreen() override;
|
||||
void setShakePos(int shakeXOffset, int shakeYOffset) override;
|
||||
void setFocusRectangle(const Common::Rect& rect) override {}
|
||||
void clearFocusRectangle() override {}
|
||||
|
||||
void showOverlay(bool inGUI) override;
|
||||
void hideOverlay() override;
|
||||
bool isOverlayVisible() const override { return _overlayState == kOverlayVisible; }
|
||||
Graphics::PixelFormat getOverlayFormat() const override;
|
||||
void clearOverlay() override;
|
||||
void grabOverlay(Graphics::Surface &surface) const override;
|
||||
void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||
int16 getOverlayHeight() const override { return 480; }
|
||||
int16 getOverlayWidth() const override { return _vgaMonitor ? 640 : 640*1.2; }
|
||||
|
||||
bool showMouse(bool visible) override;
|
||||
void warpMouse(int x, int y) override;
|
||||
void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor,
|
||||
bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override;
|
||||
void setCursorPalette(const byte *colors, uint start, uint num) override;
|
||||
|
||||
Common::Point getMousePosition() const {
|
||||
if (isOverlayVisible()) {
|
||||
return _screen[kOverlayBuffer]->cursor.getPosition();
|
||||
} else {
|
||||
// kFrontBuffer is always up to date
|
||||
return _screen[kFrontBuffer]->cursor.getPosition();
|
||||
}
|
||||
}
|
||||
void updateMousePosition(int deltaX, int deltaY);
|
||||
|
||||
bool notifyEvent(const Common::Event &event) override;
|
||||
Common::Keymap *getKeymap() const;
|
||||
|
||||
private:
|
||||
enum {
|
||||
kUnknownMode = -1,
|
||||
kDirectRendering = 0,
|
||||
kSingleBuffering = 1,
|
||||
kTripleBuffering = 3
|
||||
};
|
||||
|
||||
enum CustomEventAction {
|
||||
kActionToggleAspectRatioCorrection = 100,
|
||||
};
|
||||
|
||||
void allocateSurfaces();
|
||||
void freeSurfaces();
|
||||
|
||||
#ifndef DISABLE_FANCY_THEMES
|
||||
int16 getMaximumScreenHeight() const { return 480; }
|
||||
int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 640 : 640*1.2); }
|
||||
#else
|
||||
int16 getMaximumScreenHeight() const { return _tt ? 480 : 240; }
|
||||
int16 getMaximumScreenWidth() const { return _tt ? 320 : (_vgaMonitor ? 320 : 320*1.2); }
|
||||
#endif
|
||||
|
||||
void addDirtyRectToScreens(const Graphics::Surface &dstSurface,
|
||||
int x, int y, int w, int h, bool directRendering);
|
||||
bool updateScreenInternal(Screen *dstScreen, const Graphics::Surface *srcSurface);
|
||||
void copyRectToAtariSurface(AtariSurface &dstSurface,
|
||||
const byte *buf, int pitch, int x, int y, int w, int h);
|
||||
|
||||
bool isOverlayDirectRendering() const {
|
||||
#ifndef DISABLE_FANCY_THEMES
|
||||
// see osystem_atari.cpp
|
||||
extern bool g_gameEngineActive;
|
||||
#endif
|
||||
// overlay is direct rendered if in the launcher or if game is directly rendered
|
||||
// (on SuperVidel we always want to use _overlaySurface as source for background pixels)
|
||||
return !g_hasSuperVidel
|
||||
#ifndef DISABLE_FANCY_THEMES
|
||||
&& (!g_gameEngineActive || _currentState.mode == kDirectRendering)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
Graphics::Surface *lockOverlay();
|
||||
|
||||
bool _vgaMonitor = true;
|
||||
bool _tt = false;
|
||||
|
||||
struct GraphicsState {
|
||||
GraphicsState()
|
||||
: inTransaction(false)
|
||||
, mode(kUnknownMode)
|
||||
, width(0)
|
||||
, height(0)
|
||||
, format(Graphics::PixelFormat()) {
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return mode != kUnknownMode && width > 0 && height > 0 && format.bytesPerPixel != 0;
|
||||
}
|
||||
|
||||
bool inTransaction;
|
||||
int mode;
|
||||
int width;
|
||||
int height;
|
||||
Graphics::PixelFormat format;
|
||||
};
|
||||
GraphicsState _pendingState;
|
||||
GraphicsState _currentState;
|
||||
|
||||
// feature flags
|
||||
bool _aspectRatioCorrection = false;
|
||||
|
||||
PendingScreenChanges _pendingScreenChanges;
|
||||
|
||||
enum {
|
||||
kFrontBuffer = 0,
|
||||
kBackBuffer1 = 1,
|
||||
kBackBuffer2 = 2,
|
||||
kOverlayBuffer = 3,
|
||||
kBufferCount
|
||||
};
|
||||
Screen *_screen[kBufferCount] = {};
|
||||
|
||||
Graphics::Surface _chunkySurface;
|
||||
Graphics::Surface _chunkySurfaceOffsetted;
|
||||
|
||||
enum {
|
||||
kOverlayVisible,
|
||||
kOverlayIgnoredHide,
|
||||
kOverlayHidden
|
||||
};
|
||||
int _overlayState = kOverlayHidden;
|
||||
bool _ignoreHideOverlay = true;
|
||||
Graphics::Surface _overlaySurface;
|
||||
bool _ignoreCursorChanges = false;
|
||||
|
||||
Palette _palette;
|
||||
Palette _overlayPalette;
|
||||
};
|
||||
|
||||
#endif
|
||||
157
backends/graphics/atari/atari-pendingscreenchanges.cpp
Normal file
157
backends/graphics/atari/atari-pendingscreenchanges.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "atari-pendingscreenchanges.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <mint/falcon.h>
|
||||
|
||||
#include "backends/platform/atari/atari-debug.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "atari-graphics.h"
|
||||
#include "atari-supervidel.h"
|
||||
|
||||
void PendingScreenChanges::queueAll() {
|
||||
_changes |= kAll;
|
||||
|
||||
if (_manager->_tt)
|
||||
_changes &= ~kAspectRatioCorrection;
|
||||
}
|
||||
|
||||
/*
|
||||
* VsetRGB() - stores the palette in a buffer and process it in the nearest non-locked VBL
|
||||
* EsetPalette() - immediatelly applies the palette
|
||||
* (V)SetScreen() - immediatelly sets physbase/logbase but explicitly calls Vsync() for resolution changes
|
||||
* VsetMode() - explicitly calls Vsync()
|
||||
*/
|
||||
|
||||
void PendingScreenChanges::applyBeforeVblLock(const Screen &screen) {
|
||||
_mode = screen.mode; // avoid modifying 'Screen' content
|
||||
_resetSuperVidel = false;
|
||||
|
||||
_aspectRatioCorrectionYOffset.second = false;
|
||||
_setScreenOffsets.second = false;
|
||||
_shrinkVidelVisibleArea.second = false;
|
||||
|
||||
if (_changes & kAspectRatioCorrection) {
|
||||
processAspectRatioCorrection(screen);
|
||||
_changes &= ~kAspectRatioCorrection;
|
||||
}
|
||||
|
||||
_switchToBlackPalette = (_changes & kVideoMode) || _resetSuperVidel;
|
||||
|
||||
if (_changes & kVideoMode) {
|
||||
processVideoMode(screen);
|
||||
// don't reset kVideoMode yet
|
||||
}
|
||||
}
|
||||
|
||||
void PendingScreenChanges::applyAfterVblLock(const Screen &screen) {
|
||||
// VBL doesn't process new palette nor screen address updates
|
||||
// if _changes & kVideoMode then the Vsync handler has just returned
|
||||
|
||||
if (_changes & kShakeScreen) {
|
||||
_setScreenOffsets = std::make_pair(true, true);
|
||||
_changes &= ~kShakeScreen;
|
||||
}
|
||||
|
||||
// restore current (kVideoMode) or set new (kPalette) palette
|
||||
if (_changes & (kVideoMode | kPalette)) {
|
||||
if (_switchToBlackPalette || (_changes & kPalette)) {
|
||||
// Set the palette as fast as possible. Vsync() is a big no-no, updateScreen() and
|
||||
// therefore this function can be called multiple times per frame. In this case,
|
||||
// EsetPalette() will set the colours immediately (oops) but VsetRGB() is fine:
|
||||
// it will be set as soon as VBL is unlocked again.
|
||||
if (_manager->_tt) {
|
||||
EsetPalette(0, screen.palette->entries, screen.palette->tt);
|
||||
} else {
|
||||
VsetRGB(0, screen.palette->entries, screen.palette->falcon);
|
||||
}
|
||||
}
|
||||
|
||||
_changes &= ~(kVideoMode | kPalette);
|
||||
}
|
||||
|
||||
assert(_changes == kNone);
|
||||
}
|
||||
|
||||
void PendingScreenChanges::processAspectRatioCorrection(const Screen &screen) {
|
||||
assert(!_manager->_tt);
|
||||
assert(_mode != -1);
|
||||
|
||||
if (_manager->_aspectRatioCorrection && _manager->_currentState.height == 200 && !_manager->isOverlayVisible()) {
|
||||
// apply machine-specific aspect ratio correction
|
||||
if (!_manager->_vgaMonitor) {
|
||||
_mode &= ~PAL;
|
||||
// 60 Hz
|
||||
_mode |= NTSC;
|
||||
_changes |= kVideoMode;
|
||||
} else {
|
||||
_aspectRatioCorrectionYOffset =
|
||||
std::make_pair((screen.surf->h - 2*MAX_V_SHAKE - screen.offsettedSurf->h) / 2, true);
|
||||
_shrinkVidelVisibleArea = std::make_pair(true, true);
|
||||
}
|
||||
} else {
|
||||
// reset back to default mode
|
||||
if (!_manager->_vgaMonitor) {
|
||||
_mode &= ~NTSC;
|
||||
// 50 Hz
|
||||
_mode |= PAL;
|
||||
_changes |= kVideoMode;
|
||||
} else {
|
||||
_aspectRatioCorrectionYOffset = std::make_pair(0, true);
|
||||
_shrinkVidelVisibleArea = std::make_pair(false, true);
|
||||
|
||||
if (g_hasSuperVidel)
|
||||
_resetSuperVidel = true;
|
||||
|
||||
// kPendingVideoMode will reset the shrunken Videl area
|
||||
_changes |= kVideoMode;
|
||||
}
|
||||
}
|
||||
|
||||
// for VsetMode() and/or _aspectRatioCorrectionYOffset
|
||||
_setScreenOffsets = std::make_pair(true, true);
|
||||
}
|
||||
|
||||
void PendingScreenChanges::processVideoMode(const Screen &screen) {
|
||||
// changing video mode implies an additional Vsync(): there's no way to change resolution
|
||||
// and set new screen address (and/or shake offsets etc) in one go
|
||||
if (screen.rez != -1) {
|
||||
static uint16 black[256];
|
||||
EsetPalette(0, screen.palette->entries, black);
|
||||
|
||||
// unfortunately this reinitializes VDI, too
|
||||
Setscreen(SCR_NOCHANGE, SCR_NOCHANGE, screen.rez);
|
||||
} else if (_mode != -1) {
|
||||
static _RGB black[256];
|
||||
VsetRGB(0, screen.palette->entries, black);
|
||||
|
||||
// VsetMode() must be called before the VBL s_ stuff is set as
|
||||
// it resets all hz/v, scrolling and line width registers
|
||||
if (_resetSuperVidel)
|
||||
VsetMode(SVEXT | SVEXT_BASERES(0) | COL80 | BPS8C); // resync to proper 640x480
|
||||
|
||||
atari_debug("VsetMode: %04x", _mode);
|
||||
VsetMode(_mode);
|
||||
}
|
||||
}
|
||||
111
backends/graphics/atari/atari-pendingscreenchanges.h
Normal file
111
backends/graphics/atari/atari-pendingscreenchanges.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_PENDINGSCREENCHANGES_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_PENDINGSCREENCHANGES_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
class AtariGraphicsManager;
|
||||
class AtariSurface;
|
||||
class Screen;
|
||||
|
||||
class PendingScreenChanges {
|
||||
public:
|
||||
PendingScreenChanges(const AtariGraphicsManager *manager)
|
||||
: _manager(manager) {
|
||||
}
|
||||
|
||||
void clearTransaction() {
|
||||
_changes &= ~kTransaction;
|
||||
}
|
||||
|
||||
void setScreenSurface(AtariSurface *surface) {
|
||||
_surface = surface;
|
||||
}
|
||||
|
||||
void queueVideoMode() {
|
||||
_changes |= kVideoMode;
|
||||
}
|
||||
void queueAspectRatioCorrection() {
|
||||
_changes |= kAspectRatioCorrection;
|
||||
}
|
||||
void queuePalette() {
|
||||
_changes |= kPalette;
|
||||
}
|
||||
void queueShakeScreen() {
|
||||
_changes |= kShakeScreen;
|
||||
}
|
||||
void queueAll();
|
||||
|
||||
int get() const {
|
||||
return _changes;
|
||||
}
|
||||
bool empty() const {
|
||||
return _changes == kNone;
|
||||
}
|
||||
|
||||
AtariSurface *screenSurface() const {
|
||||
return _surface;
|
||||
}
|
||||
const std::pair<int, bool>& aspectRatioCorrectionYOffset() const {
|
||||
return _aspectRatioCorrectionYOffset;
|
||||
}
|
||||
const std::pair<bool, bool>& screenOffsets() const {
|
||||
return _setScreenOffsets;
|
||||
}
|
||||
const std::pair<bool, bool>& shrinkVidelVisibleArea() const {
|
||||
return _shrinkVidelVisibleArea;
|
||||
}
|
||||
|
||||
void applyBeforeVblLock(const Screen &screen);
|
||||
void applyAfterVblLock(const Screen &screen);
|
||||
|
||||
private:
|
||||
void processAspectRatioCorrection(const Screen &screen);
|
||||
void processVideoMode(const Screen &screen);
|
||||
|
||||
enum Change {
|
||||
kNone = 0,
|
||||
kVideoMode = 1<<0,
|
||||
kAspectRatioCorrection = 1<<1,
|
||||
kPalette = 1<<2,
|
||||
kShakeScreen = 1<<3,
|
||||
kTransaction = kVideoMode | kAspectRatioCorrection,
|
||||
kAll = kTransaction | kPalette | kShakeScreen
|
||||
};
|
||||
int _changes = kNone;
|
||||
|
||||
const AtariGraphicsManager *_manager;
|
||||
|
||||
AtariSurface *_surface = nullptr;
|
||||
|
||||
int _mode;
|
||||
bool _resetSuperVidel;
|
||||
bool _switchToBlackPalette;
|
||||
|
||||
// <value, set> ... std::optional would be so much better!
|
||||
std::pair<int, bool> _aspectRatioCorrectionYOffset;
|
||||
std::pair<bool, bool> _setScreenOffsets;
|
||||
std::pair<bool, bool> _shrinkVidelVisibleArea;
|
||||
};
|
||||
|
||||
#endif // ATARI-PENDINGSCREENCHANGES_H
|
||||
170
backends/graphics/atari/atari-screen.cpp
Normal file
170
backends/graphics/atari/atari-screen.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "atari-screen.h"
|
||||
|
||||
#include <mint/falcon.h>
|
||||
|
||||
#include "atari-graphics.h" // MAX_HZ_SHAKE, MAX_V_SHAKE
|
||||
#include "atari-supervidel.h" // g_hasSuperVidel
|
||||
//#include "backends/platform/atari/atari-debug.h"
|
||||
|
||||
Screen::Screen(bool tt, int width, int height, const Graphics::PixelFormat &format, const Palette *palette_)
|
||||
: palette(palette_)
|
||||
, _tt(tt) {
|
||||
|
||||
#ifdef USE_SUPERVIDEL
|
||||
if (g_hasSuperVidel) {
|
||||
surf.reset(new SuperVidelSurface(
|
||||
width + 2 * MAX_HZ_SHAKE,
|
||||
height + 2 * MAX_V_SHAKE,
|
||||
format));
|
||||
_offsettedSurf.reset(new SuperVidelSurface());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
surf.reset(new AtariSurface(
|
||||
width + (_tt ? 0 : 2 * MAX_HZ_SHAKE),
|
||||
height + 2 * MAX_V_SHAKE,
|
||||
format));
|
||||
_offsettedSurf.reset(new AtariSurface());
|
||||
}
|
||||
|
||||
_offsettedSurf->create(
|
||||
*surf,
|
||||
Common::Rect(
|
||||
Common::Point(
|
||||
(surf->w - width) / 2, // left
|
||||
(surf->h - height) / 2), // top
|
||||
width, height));
|
||||
}
|
||||
|
||||
void Screen::reset(int width, int height, const Graphics::Surface &boundingSurf) {
|
||||
clearDirtyRects();
|
||||
|
||||
rez = -1;
|
||||
mode = -1;
|
||||
|
||||
const int bitsPerPixel = surf->getBitsPerPixel();
|
||||
|
||||
// erase old screen
|
||||
_offsettedSurf->fillRect(_offsettedSurf->getBounds(), 0);
|
||||
|
||||
if (_tt) {
|
||||
if (width <= 320 && height <= 240) {
|
||||
surf->w = 320;
|
||||
surf->h = 240 + 2 * MAX_V_SHAKE;
|
||||
surf->pitch = 2 * surf->w * bitsPerPixel / 8;
|
||||
rez = kRezValueTTLow;
|
||||
} else {
|
||||
surf->w = 640;
|
||||
surf->h = 480 + 2 * MAX_V_SHAKE;
|
||||
surf->pitch = surf->w * bitsPerPixel / 8;
|
||||
rez = kRezValueTTMid;
|
||||
}
|
||||
} else {
|
||||
mode = VsetMode(VM_INQUIRE) & PAL;
|
||||
|
||||
if (VgetMonitor() == MON_VGA) {
|
||||
mode |= VGA | (bitsPerPixel == 4 ? BPS4 : (g_hasSuperVidel ? BPS8C : BPS8));
|
||||
|
||||
if (width <= 320 && height <= 240) {
|
||||
surf->w = 320;
|
||||
surf->h = 240;
|
||||
mode |= VERTFLAG | COL40;
|
||||
} else {
|
||||
surf->w = 640;
|
||||
surf->h = 480;
|
||||
mode |= COL80;
|
||||
}
|
||||
} else {
|
||||
mode |= TV | (bitsPerPixel == 4 ? BPS4 : BPS8);
|
||||
|
||||
if (width <= 320 && height <= 200) {
|
||||
surf->w = 320;
|
||||
surf->h = 200;
|
||||
mode |= COL40;
|
||||
} else if (width <= 320*1.2 && height <= 200*1.2) {
|
||||
surf->w = 320*1.2;
|
||||
surf->h = 200*1.2;
|
||||
mode |= OVERSCAN | COL40;
|
||||
} else if (width <= 640 && height <= 400) {
|
||||
surf->w = 640;
|
||||
surf->h = 400;
|
||||
mode |= VERTFLAG | COL80;
|
||||
} else {
|
||||
surf->w = 640*1.2;
|
||||
surf->h = 400*1.2;
|
||||
mode |= VERTFLAG | OVERSCAN | COL80;
|
||||
}
|
||||
}
|
||||
|
||||
surf->w += 2 * MAX_HZ_SHAKE;
|
||||
surf->h += 2 * MAX_V_SHAKE;
|
||||
surf->pitch = surf->w * bitsPerPixel / 8;
|
||||
}
|
||||
|
||||
_offsettedSurf->create(
|
||||
*surf,
|
||||
Common::Rect(
|
||||
Common::Point(
|
||||
(surf->w - width) / 2, // left
|
||||
(surf->h - height) / 2), // top
|
||||
width, height));
|
||||
|
||||
cursor.reset(_offsettedSurf.get(), &boundingSurf);
|
||||
cursor.setPosition(boundingSurf.w / 2, boundingSurf.h / 2);
|
||||
}
|
||||
|
||||
void Screen::addDirtyRect(const Graphics::Surface &srcSurface, int x, int y, int w, int h, bool directRendering) {
|
||||
if (fullRedraw)
|
||||
return;
|
||||
|
||||
if ((w == srcSurface.w && h == srcSurface.h)
|
||||
|| dirtyRects.size() == 128) { // 320x200 can hold at most 250 16x16 rectangles
|
||||
//atari_debug("addDirtyRect[%d]: purge %d x %d", (int)dirtyRects.size(), srcSurface.w, srcSurface.h);
|
||||
|
||||
dirtyRects.clear();
|
||||
// even if srcSurface.w != _offsettedSurf.w, alignRect would lead to the same result
|
||||
dirtyRects.insert(_offsettedSurf->getBounds());
|
||||
|
||||
cursor.reset(_offsettedSurf.get(), &srcSurface);
|
||||
|
||||
fullRedraw = true;
|
||||
} else {
|
||||
// x,y are relative to srcSurface but screen's width is always aligned to 16 bytes
|
||||
// so both dirty rects and cursor must be drawn in screen coordinates
|
||||
const int xOffset = (_offsettedSurf->w - srcSurface.w) / 2;
|
||||
|
||||
const Common::Rect alignedRect = AtariSurface::alignRect(x + xOffset, y, x + xOffset + w, y + h);
|
||||
|
||||
dirtyRects.insert(alignedRect);
|
||||
|
||||
// Check whether the cursor background intersects the dirty rect. Has to be done here,
|
||||
// before the actual drawing (especially in case of direct rendering). There's one more
|
||||
// check in AtariGraphicsManager::updateScreenInternal for the case when there are no
|
||||
// dirty rectangles but the cursor itself has changed.
|
||||
const Common::Rect cursorBackgroundRect = cursor.flushBackground(alignedRect, directRendering);
|
||||
if (!cursorBackgroundRect.isEmpty()) {
|
||||
dirtyRects.insert(cursorBackgroundRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
backends/graphics/atari/atari-screen.h
Normal file
99
backends/graphics/atari/atari-screen.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_SCREEN_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_SCREEN_H
|
||||
|
||||
#include <unordered_set>
|
||||
#include <mint/ostruct.h> // _RGB
|
||||
|
||||
#include "common/ptr.h"
|
||||
|
||||
#include "atari-cursor.h"
|
||||
#include "atari-surface.h"
|
||||
|
||||
template<>
|
||||
struct std::hash<Common::Rect>
|
||||
{
|
||||
std::size_t operator()(Common::Rect const& rect) const noexcept
|
||||
{
|
||||
return 31 * (31 * (31 * rect.left + rect.top) + rect.right) + rect.bottom;
|
||||
}
|
||||
};
|
||||
|
||||
class Palette {
|
||||
public:
|
||||
void clear() {
|
||||
memset(_data, 0, sizeof(_data));
|
||||
entries = 0;
|
||||
}
|
||||
|
||||
uint16 *const tt = reinterpret_cast<uint16*>(_data);
|
||||
_RGB *const falcon = reinterpret_cast<_RGB*>(_data);
|
||||
|
||||
int entries = 0;
|
||||
|
||||
private:
|
||||
byte _data[256*4] = {};
|
||||
};
|
||||
|
||||
struct Screen {
|
||||
using DirtyRects = std::unordered_set<Common::Rect>;
|
||||
|
||||
Screen(bool tt, int width, int height, const Graphics::PixelFormat &format, const Palette *palette);
|
||||
|
||||
void reset(int width, int height, const Graphics::Surface &boundingSurf);
|
||||
// must be called before any rectangle drawing
|
||||
void addDirtyRect(const Graphics::Surface &srcSurface, int x, int y, int w, int h, bool directRendering);
|
||||
|
||||
void clearDirtyRects() {
|
||||
dirtyRects.clear();
|
||||
fullRedraw = false;
|
||||
}
|
||||
|
||||
Common::ScopedPtr<AtariSurface> surf;
|
||||
const Palette *palette;
|
||||
DirtyRects dirtyRects;
|
||||
bool fullRedraw = false;
|
||||
|
||||
Cursor cursor;
|
||||
|
||||
int rez = -1;
|
||||
int mode = -1;
|
||||
const Common::ScopedPtr<AtariSurface> &offsettedSurf = _offsettedSurf;
|
||||
|
||||
private:
|
||||
static constexpr size_t ALIGN = 16; // 16 bytes
|
||||
|
||||
enum SteTtRezValue {
|
||||
kRezValueSTLow = 0, // 320x200@4bpp, ST palette
|
||||
kRezValueSTMid = 1, // 640x200@2bpp, ST palette
|
||||
kRezValueSTHigh = 2, // 640x400@1bpp, ST palette
|
||||
kRezValueTTLow = 7, // 320x480@8bpp, TT palette
|
||||
kRezValueTTMid = 4, // 640x480@4bpp, TT palette
|
||||
kRezValueTTHigh = 6 // 1280x960@1bpp, TT palette
|
||||
};
|
||||
|
||||
bool _tt;
|
||||
Common::ScopedPtr<AtariSurface> _offsettedSurf;
|
||||
};
|
||||
|
||||
#endif // BACKENDS_GRAPHICS_ATARI_SCREEN_H
|
||||
67
backends/graphics/atari/atari-supervidel.cpp
Normal file
67
backends/graphics/atari/atari-supervidel.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "atari-supervidel.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
bool g_hasSuperVidel = false;
|
||||
|
||||
#ifdef USE_SUPERVIDEL
|
||||
|
||||
#ifdef USE_SV_BLITTER
|
||||
int g_superVidelFwVersion = 0;
|
||||
const byte *g_blitMask = nullptr;
|
||||
|
||||
static bool isSuperBlitterLocked;
|
||||
|
||||
void SyncSuperBlitter() {
|
||||
// if externally locked, let the owner decide when to sync (unlock)
|
||||
if (isSuperBlitterLocked)
|
||||
return;
|
||||
|
||||
// while FIFO not empty...
|
||||
if (g_superVidelFwVersion >= 9)
|
||||
while (!(*SV_BLITTER_FIFO & 1));
|
||||
// while busy blitting...
|
||||
while (*SV_BLITTER_CONTROL & 1);
|
||||
}
|
||||
#endif // USE_SV_BLITTER
|
||||
|
||||
void LockSuperBlitter() {
|
||||
#ifdef USE_SV_BLITTER
|
||||
assert(!isSuperBlitterLocked);
|
||||
|
||||
isSuperBlitterLocked = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnlockSuperBlitter() {
|
||||
#ifdef USE_SV_BLITTER
|
||||
assert(isSuperBlitterLocked);
|
||||
|
||||
isSuperBlitterLocked = false;
|
||||
if (g_hasSuperVidel)
|
||||
SyncSuperBlitter();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // USE_SUPERVIDEL
|
||||
70
backends/graphics/atari/atari-supervidel.h
Normal file
70
backends/graphics/atari/atari-supervidel.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#ifdef USE_SUPERVIDEL
|
||||
|
||||
// bits 26:0
|
||||
#define SV_BLITTER_SRC1 ((volatile long *)0x80010058)
|
||||
#define SV_BLITTER_SRC2 ((volatile long *)0x8001005C)
|
||||
#define SV_BLITTER_DST ((volatile long *)0x80010060)
|
||||
// The amount of bytes that are to be copied in a horizontal line, minus 1
|
||||
#define SV_BLITTER_COUNT ((volatile long *)0x80010064)
|
||||
// The amount of bytes that are to be added to the line start address after a line has been copied, in order to reach the next one
|
||||
#define SV_BLITTER_SRC1_OFFSET ((volatile long *)0x80010068)
|
||||
#define SV_BLITTER_SRC2_OFFSET ((volatile long *)0x8001006C)
|
||||
#define SV_BLITTER_DST_OFFSET ((volatile long *)0x80010070)
|
||||
// bits 11:0 - The amount of horizontal lines to do
|
||||
#define SV_BLITTER_MASK_AND_LINES ((volatile long *)0x80010074)
|
||||
// bit 0 - busy / start
|
||||
// bits 4:1 - blit mode
|
||||
#define SV_BLITTER_CONTROL ((volatile long *)0x80010078)
|
||||
// bits 9:0
|
||||
#define SV_VERSION ((volatile long *)0x8001007C)
|
||||
// bit 0 - empty (read only)
|
||||
// bit 1 - full (read only)
|
||||
// bits 31:0 - data (write only)
|
||||
#define SV_BLITTER_FIFO ((volatile long *)0x80010080)
|
||||
|
||||
#ifdef USE_SV_BLITTER
|
||||
extern int g_superVidelFwVersion;
|
||||
extern const byte *g_blitMask;
|
||||
|
||||
void SyncSuperBlitter();
|
||||
#endif // USE_SV_BLITTER
|
||||
|
||||
void LockSuperBlitter();
|
||||
void UnlockSuperBlitter();
|
||||
|
||||
#else
|
||||
|
||||
static inline void LockSuperBlitter() {}
|
||||
static inline void UnlockSuperBlitter() {}
|
||||
|
||||
#endif // USE_SUPERVIDEL
|
||||
|
||||
extern bool g_hasSuperVidel;
|
||||
|
||||
#endif // BACKENDS_GRAPHICS_ATARI_SUPERVIDEL_H
|
||||
346
backends/graphics/atari/atari-surface.cpp
Normal file
346
backends/graphics/atari/atari-surface.cpp
Normal file
@@ -0,0 +1,346 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "atari-surface.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include <mint/cookie.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/trap14.h>
|
||||
#define ct60_vm(mode, value) (long)trap_14_wwl((short)0xc60e, (short)(mode), (long)(value))
|
||||
#define ct60_vmalloc(value) ct60_vm(0, value)
|
||||
#define ct60_vmfree(value) ct60_vm(1, value)
|
||||
|
||||
#include "backends/graphics/atari/atari-c2p-asm.h"
|
||||
#include "backends/graphics/atari/atari-graphics-asm.h"
|
||||
#include "backends/graphics/atari/atari-supervidel.h"
|
||||
#include "backends/platform/atari/atari-debug.h"
|
||||
#include "backends/platform/atari/dlmalloc.h"
|
||||
#include "common/textconsole.h" // error()
|
||||
|
||||
static struct MemoryPool {
|
||||
void create() {
|
||||
if (base)
|
||||
_mspace = create_mspace_with_base((void *)base, size, 0);
|
||||
|
||||
if (_mspace)
|
||||
atari_debug("Allocated mspace at 0x%08lx (%ld bytes)", base, size);
|
||||
else
|
||||
error("mspace allocation failed at 0x%08lx (%ld bytes)", base, size);
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
if (_mspace) {
|
||||
destroy_mspace(_mspace);
|
||||
_mspace = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void *malloc(size_t bytes) {
|
||||
assert(_mspace);
|
||||
return mspace_malloc(_mspace, bytes);
|
||||
}
|
||||
|
||||
void *calloc(size_t n_elements, size_t elem_size) {
|
||||
assert(_mspace);
|
||||
return mspace_calloc(_mspace, n_elements, elem_size);
|
||||
}
|
||||
|
||||
void free(void *mem) {
|
||||
assert(_mspace);
|
||||
mspace_free(_mspace, mem);
|
||||
}
|
||||
|
||||
long base;
|
||||
long size;
|
||||
|
||||
private:
|
||||
mspace _mspace;
|
||||
} s_videoRamPool, s_blitterPool;
|
||||
|
||||
static MemoryPool *s_currentPool;
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
void Surface::create(int16 width, int16 height, const PixelFormat &f) {
|
||||
assert(width >= 0 && height >= 0);
|
||||
free();
|
||||
|
||||
w = width;
|
||||
h = height;
|
||||
format = f;
|
||||
pitch = w * format.bytesPerPixel;
|
||||
|
||||
if (width && height) {
|
||||
if (s_currentPool) {
|
||||
pixels = s_currentPool->calloc(height * pitch, format.bytesPerPixel);
|
||||
if (!pixels)
|
||||
error("Not enough VRAM to allocate a surface");
|
||||
|
||||
if (s_currentPool == &s_blitterPool) {
|
||||
assert(pixels >= (void *)0xA1000000);
|
||||
} else if (s_currentPool == &s_videoRamPool) {
|
||||
#ifdef USE_SUPERVIDEL
|
||||
if (g_hasSuperVidel)
|
||||
assert(pixels >= (void *)0xA0000000 && pixels < (void *)0xA1000000);
|
||||
else
|
||||
#endif
|
||||
assert(pixels < (void *)0x01000000);
|
||||
}
|
||||
} else {
|
||||
pixels = ::calloc(height * pitch, format.bytesPerPixel);
|
||||
if (!pixels)
|
||||
error("Not enough RAM to allocate a surface");
|
||||
}
|
||||
|
||||
assert(((uintptr)pixels & (MALLOC_ALIGNMENT - 1)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::free() {
|
||||
if (pixels) {
|
||||
if (s_currentPool)
|
||||
s_currentPool->free(pixels);
|
||||
else
|
||||
::free(pixels);
|
||||
|
||||
pixels = nullptr;
|
||||
}
|
||||
|
||||
w = h = pitch = 0;
|
||||
format = PixelFormat();
|
||||
}
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AtariSurface::AtariSurface(int16 width, int16 height, const Graphics::PixelFormat &pixelFormat) {
|
||||
create(width, height, pixelFormat);
|
||||
}
|
||||
|
||||
AtariSurface::~AtariSurface() {
|
||||
free();
|
||||
}
|
||||
|
||||
void AtariSurface::create(int16 width, int16 height, const Graphics::PixelFormat &pixelFormat) {
|
||||
MemoryPool *oldPool = s_currentPool;
|
||||
s_currentPool = &s_videoRamPool;
|
||||
|
||||
Graphics::ManagedSurface::create(width * (format == PIXELFORMAT_RGB121 ? 4 : 8) / 8, height, pixelFormat);
|
||||
w = width;
|
||||
|
||||
s_currentPool = oldPool;
|
||||
}
|
||||
|
||||
void AtariSurface::free() {
|
||||
MemoryPool *oldPool = s_currentPool;
|
||||
s_currentPool = &s_videoRamPool;
|
||||
|
||||
Graphics::ManagedSurface::free();
|
||||
|
||||
s_currentPool = oldPool;
|
||||
}
|
||||
|
||||
void AtariSurface::copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) {
|
||||
assert(width % 16 == 0);
|
||||
assert(destX % 16 == 0);
|
||||
assert(format.bytesPerPixel == 1);
|
||||
|
||||
const byte *pChunky = (const byte *)buffer;
|
||||
const byte *pChunkyEnd = pChunky + (height - 1) * srcPitch + width;
|
||||
|
||||
byte *pScreen = (byte *)getBasePtr(0, destY) + destX * getBitsPerPixel()/8;
|
||||
|
||||
if (getBitsPerPixel() == 8) {
|
||||
if (srcPitch == width) {
|
||||
if (srcPitch == pitch) {
|
||||
asm_c2p1x1_8(pChunky, pChunkyEnd, pScreen);
|
||||
return;
|
||||
} else if (srcPitch == pitch/2) {
|
||||
asm_c2p1x1_8_tt(pChunky, pChunkyEnd, pScreen, pitch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
asm_c2p1x1_8_rect(
|
||||
pChunky, pChunkyEnd,
|
||||
width,
|
||||
srcPitch,
|
||||
pScreen,
|
||||
pitch);
|
||||
} else {
|
||||
if (srcPitch == width && srcPitch/2 == pitch) {
|
||||
asm_c2p1x1_4(pChunky, pChunkyEnd, pScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
asm_c2p1x1_4_rect(
|
||||
pChunky, pChunkyEnd,
|
||||
width,
|
||||
srcPitch,
|
||||
pScreen,
|
||||
pitch);
|
||||
}
|
||||
}
|
||||
|
||||
void AtariSurface::drawMaskedSprite(
|
||||
const Graphics::Surface &srcSurface, const Graphics::Surface &srcMask,
|
||||
const Graphics::Surface &boundingSurface,
|
||||
int destX, int destY,
|
||||
const Common::Rect &subRect) {
|
||||
assert(srcSurface.w == srcMask.w);
|
||||
assert(srcSurface.h == srcMask.h);
|
||||
|
||||
bool skipFirstPix16 = false;
|
||||
bool skipLastPix16 = false;
|
||||
|
||||
int srcSurfaceLeft = 0;
|
||||
int srcSurfaceWidth = srcSurface.w;
|
||||
int dstSurfaceLeft = 0;
|
||||
|
||||
if (subRect.left > 0) {
|
||||
skipFirstPix16 = true;
|
||||
|
||||
const int offset = subRect.left & (-16);
|
||||
srcSurfaceLeft += offset;
|
||||
srcSurfaceWidth -= offset;
|
||||
|
||||
destX = 16 - (subRect.left & (16-1));
|
||||
dstSurfaceLeft -= 16;
|
||||
}
|
||||
|
||||
if (destX + srcSurfaceWidth > boundingSurface.w) {
|
||||
skipLastPix16 = true;
|
||||
|
||||
const int offset = (destX + srcSurfaceWidth - boundingSurface.w) & (-16);
|
||||
srcSurfaceWidth -= offset;
|
||||
}
|
||||
|
||||
assert(srcSurfaceLeft % 16 == 0);
|
||||
assert(srcSurfaceWidth % 16 == 0);
|
||||
|
||||
destX += (this->w - boundingSurface.w) / 2;
|
||||
|
||||
if (getBitsPerPixel() == 8) {
|
||||
asm_draw_8bpl_sprite(
|
||||
(uint16 *)getBasePtr(dstSurfaceLeft, 0),
|
||||
(const uint16 *)srcSurface.getBasePtr(srcSurfaceLeft, subRect.top),
|
||||
(const uint16 *)srcMask.getBasePtr(srcSurfaceLeft / 8, subRect.top),
|
||||
destX, destY,
|
||||
pitch, srcSurface.w, srcSurfaceWidth, subRect.height(),
|
||||
skipFirstPix16, skipLastPix16);
|
||||
} else {
|
||||
asm_draw_4bpl_sprite(
|
||||
(uint16 *)getBasePtr(dstSurfaceLeft / 2, 0),
|
||||
(const uint16 *)srcSurface.getBasePtr(srcSurfaceLeft / 2, subRect.top),
|
||||
(const uint16 *)srcMask.getBasePtr(srcSurfaceLeft / 8, subRect.top),
|
||||
destX, destY,
|
||||
pitch, srcSurface.w / 2, srcSurfaceWidth, subRect.height(),
|
||||
skipFirstPix16, skipLastPix16);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef USE_SUPERVIDEL
|
||||
static long hasSvRamBoosted() {
|
||||
register long ret __asm__ ("d0") = 0;
|
||||
|
||||
__asm__ volatile(
|
||||
"\tmovec %%itt0,%%d1\n"
|
||||
"\tcmp.l #0xA007E060,%%d1\n"
|
||||
"\tbne.s 1f\n"
|
||||
|
||||
"\tmovec %%dtt0,%%d1\n"
|
||||
"\tcmp.l #0xA007E060,%%d1\n"
|
||||
"\tbne.s 1f\n"
|
||||
|
||||
"\tmoveq #1,%%d0\n"
|
||||
|
||||
"1:\n"
|
||||
: "=g"(ret) /* outputs */
|
||||
: /* inputs */
|
||||
: __CLOBBER_RETURN("d0") "d1", "cc"
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif // USE_SUPERVIDEL
|
||||
|
||||
void AtariSurfaceInit() {
|
||||
#ifdef USE_SUPERVIDEL
|
||||
g_hasSuperVidel = Getcookie(C_SupV, NULL) == C_FOUND && VgetMonitor() == MON_VGA;
|
||||
|
||||
if (g_hasSuperVidel) {
|
||||
#ifdef USE_SV_BLITTER
|
||||
g_superVidelFwVersion = *SV_VERSION & 0x01ff;
|
||||
|
||||
atari_debug("SuperVidel FW Revision: %d, using %s", g_superVidelFwVersion,
|
||||
g_superVidelFwVersion >= 9 ? "fast async FIFO" : "slower sync blitting");
|
||||
#else
|
||||
atari_debug("SuperVidel FW Revision: %d, SuperBlitter not used", *SV_VERSION & 0x01ff);
|
||||
#endif
|
||||
if (Supexec(hasSvRamBoosted))
|
||||
atari_debug("SV_XBIOS has the pmmu boost enabled");
|
||||
else
|
||||
atari_warning("SV_XBIOS has the pmmu boost disabled, set 'pmmu_boost = true' in C:\\SV.INF");
|
||||
|
||||
#ifdef USE_SV_BLITTER
|
||||
s_blitterPool.size = ct60_vmalloc(-1) - (16 * 1024 * 1024); // SV XBIOS seems to forget the initial 16 MB ST RAM mirror
|
||||
s_blitterPool.base = s_blitterPool.size > 0 ? ct60_vmalloc(s_blitterPool.size) : 0;
|
||||
s_blitterPool.create();
|
||||
// default pool is either null or blitter
|
||||
s_currentPool = &s_blitterPool;
|
||||
#endif
|
||||
}
|
||||
#endif // USE_SUPERVIDEL
|
||||
|
||||
s_videoRamPool.size = 2 * 1024 * 1024; // allocate 2 MiB, leave the rest for SDMA / Blitter usage
|
||||
s_videoRamPool.base = s_videoRamPool.size > 0 ? Mxalloc(s_videoRamPool.size, MX_STRAM) : 0;
|
||||
#ifdef USE_SUPERVIDEL
|
||||
if (g_hasSuperVidel && s_videoRamPool.base)
|
||||
s_videoRamPool.base |= 0xA0000000;
|
||||
#endif
|
||||
s_videoRamPool.create();
|
||||
}
|
||||
|
||||
void AtariSurfaceDeinit() {
|
||||
s_videoRamPool.destroy();
|
||||
if (s_videoRamPool.base) {
|
||||
#ifdef USE_SUPERVIDEL
|
||||
if (g_hasSuperVidel)
|
||||
s_videoRamPool.base &= 0x00FFFFFF;
|
||||
#endif
|
||||
Mfree(s_videoRamPool.base);
|
||||
s_videoRamPool.base = 0;
|
||||
s_videoRamPool.size = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_SV_BLITTER
|
||||
s_blitterPool.destroy();
|
||||
if (s_blitterPool.base) {
|
||||
ct60_vmfree(s_blitterPool.base);
|
||||
s_blitterPool.base = 0;
|
||||
s_blitterPool.size = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
114
backends/graphics/atari/atari-surface.h
Normal file
114
backends/graphics/atari/atari-surface.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_GRAPHICS_ATARI_SURFACE_H
|
||||
#define BACKENDS_GRAPHICS_ATARI_SURFACE_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
#include "backends/graphics/atari/atari-supervidel.h"
|
||||
|
||||
constexpr Graphics::PixelFormat PIXELFORMAT_CLUT8 = Graphics::PixelFormat::createFormatCLUT8();
|
||||
constexpr Graphics::PixelFormat PIXELFORMAT_RGB332 = Graphics::PixelFormat(1, 3, 3, 2, 0, 5, 2, 0, 0);
|
||||
constexpr Graphics::PixelFormat PIXELFORMAT_RGB121 = Graphics::PixelFormat(1, 1, 2, 1, 0, 3, 1, 0, 0);
|
||||
|
||||
class AtariSurface : public Graphics::ManagedSurface {
|
||||
public:
|
||||
AtariSurface() = default;
|
||||
AtariSurface(int16 width, int16 height, const Graphics::PixelFormat &pixelFormat);
|
||||
~AtariSurface() override;
|
||||
|
||||
using Graphics::ManagedSurface::create;
|
||||
void create(int16 width, int16 height, const Graphics::PixelFormat &pixelFormat) final override;
|
||||
void free() final override;
|
||||
|
||||
void addDirtyRect(const Common::Rect &r) final override {};
|
||||
|
||||
// no override as ManagedSurface::copyRectToSurface is not a virtual function!
|
||||
virtual void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height);
|
||||
virtual void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect &subRect) {
|
||||
assert(subRect.left % 16 == 0);
|
||||
assert(srcSurface.format == format);
|
||||
|
||||
copyRectToSurface(
|
||||
srcSurface.getBasePtr(subRect.left, subRect.top), srcSurface.pitch,
|
||||
destX, destY,
|
||||
subRect.width(), subRect.height());
|
||||
}
|
||||
|
||||
virtual void drawMaskedSprite(const Graphics::Surface &srcSurface, const Graphics::Surface &srcMask,
|
||||
const Graphics::Surface &boundingSurface,
|
||||
int destX, int destY,
|
||||
const Common::Rect &subRect);
|
||||
|
||||
int getBitsPerPixel() const {
|
||||
return format == PIXELFORMAT_RGB121 ? 4 : 8;
|
||||
}
|
||||
|
||||
static Common::Rect alignRect(int x1, int y1, int x2, int y2) {
|
||||
// make non-virtual for performance reasons
|
||||
return g_hasSuperVidel
|
||||
? Common::Rect(x1, y1, x2, y2)
|
||||
: Common::Rect(x1 & (-16), y1, (x2 + 15) & (-16), y2);
|
||||
}
|
||||
static Common::Rect alignRect(const Common::Rect &rect) {
|
||||
// make non-virtual for performance reasons
|
||||
return g_hasSuperVidel
|
||||
? rect
|
||||
: Common::Rect(rect.left & (-16), rect.top, (rect.right + 15) & (-16), rect.bottom);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef USE_SUPERVIDEL
|
||||
class SuperVidelSurface final : public AtariSurface {
|
||||
public:
|
||||
SuperVidelSurface() = default;
|
||||
SuperVidelSurface(int16 width, int16 height, const Graphics::PixelFormat &pixelFormat)
|
||||
: AtariSurface(width, height, pixelFormat) {
|
||||
}
|
||||
|
||||
//using Graphics::ManagedSurface::copyRectToSurface;
|
||||
void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) override {
|
||||
Graphics::ManagedSurface::copyRectToSurface(buffer, srcPitch, destX, destY, width, height);
|
||||
}
|
||||
void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect &subRect) override {
|
||||
Graphics::ManagedSurface::copyRectToSurface(srcSurface, destX, destY, subRect);
|
||||
}
|
||||
|
||||
void drawMaskedSprite(const Graphics::Surface &srcSurface, const Graphics::Surface &srcMask,
|
||||
const Graphics::Surface &boundingSurface,
|
||||
int destX, int destY,
|
||||
const Common::Rect &subRect) override {
|
||||
#ifdef USE_SV_BLITTER
|
||||
g_blitMask = (const byte *)srcMask.getBasePtr(subRect.left, subRect.top);
|
||||
#endif
|
||||
copyRectToSurfaceWithKey(srcSurface, destX, destY, subRect, 0);
|
||||
#ifdef USE_SV_BLITTER
|
||||
g_blitMask = nullptr;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void AtariSurfaceInit();
|
||||
void AtariSurfaceDeinit();
|
||||
|
||||
#endif // BACKENDS_GRAPHICS_ATARI_SURFACE_H
|
||||
Reference in New Issue
Block a user