use cpclib_asm::assemble;
#[test]
pub fn assemble_ld_ix_bc() {
let code = "
ld ix, bc
";
let binary = assemble(code).unwrap();
assert_eq!(&binary, &[0xDD, 0x69, 0xDD, 0x60]);
}
#[test]
pub fn test_binary_or_operation() {
let code = "
db 0b00010000 | 0b10000000
";
let binary = assemble(code).unwrap();
assert_eq!(&binary, &[0b00010000 | 0b10000000]);
}
#[test]
pub fn assemble_vsync_test() {
let code = "
org 0x4000
ld b, 0xf5
loop
in a, (c)
rra
jr nc, loop
finish
assert finish == 0x4000 + (3+1+1+2)
jr $
";
let binary = assemble(code).unwrap();
assert_eq!(
&binary,
&[0x06, 0xF5, 0xED, 0x78, 0x1F, 0x30, 0xFB, 0x18, 0xFE]
);
}
#[test]
pub fn macro_local_labels() {
let code = "
MACRO CRC32XOR x1,x2,x3,x4
rr b
jr nc,@nextBit
ld a,e
xor {x1}
ld e,a
ld a,d
xor {x2}
ld d,a
ld a,l
xor {x3}
ld l,a
ld a,h
xor {x4}
ld h,a
@nextBit
MEND
CRC32XOR &2C,&61,&0E,&EE
CRC32XOR &19,&C4,&6D,&07
";
let binary = assemble(code).unwrap();
assert!(!binary.is_empty());
}
#[test]
pub fn test_inner_struct2() {
let code = "
struct point
xx db 4
yy db 5
zz db 6
endstruct
struct triangle
p1 point 1, 2 , 3
p2 point ,,8
p3 point 9
endstruct
my_triangle1: triangle [2, 3, 4], [10, 20, 30], [100, 200, 255]
";
let binary = assemble(code).unwrap();
assert_eq!(binary.len(), 3 * 3);
assert_eq!(&binary, &[2, 3, 4, 10, 20, 30, 100, 200, 255])
}
#[test]
pub fn test_inner_struct3() {
let code = "
struct point
xx db 4
yy db 5
zz db 6
endstruct
struct triangle
p1 point 1, 2 , 3
p2 point ,,8
p3 point 9
endstruct
my_triangle1: triangle [11, 12, 13],, [1, 2, 3]
";
let binary = assemble(code).unwrap();
assert_eq!(binary.len(), 3 * 3);
assert_eq!(&binary, &[11, 12, 13, 4, 5, 8, 1, 2, 3,])
}
#[test]
#[ignore = "Need to better handle default case"]
pub fn test_inner_struct_deeper() {
let code = "
org 0x0000
struct point
xx db 4
yy db 5
zz db 6
endstruct
struct triangle
p1 point 1, 2 , 3
p2 point ,,8
p3 point 9
endstruct
struct shape
tr1 triangle
tr2 triangle
endstruct
my_shape: shape
";
let binary = assemble(code).unwrap();
assert_eq!(
&binary,
&[1, 2, 3, 4, 5, 8, 9, 5, 6, 1, 2, 3, 4, 5, 8, 9, 5, 6,]
)
}
#[test]
#[ignore = "Need to better handle default case"]
pub fn test_inner_struct_deeper2() {
let code = "
struct point
xx db 4
yy db 5
zz db 6
endstruct
struct triangle
p1 point 1, 2 , 3
p2 point ,,8
p3 point 9
endstruct
struct shape
tr1 triangle
tr2 triangle
endstruct
my_shape: shape , [ [1,2,3], [1,2,3], [1,2,3] ]
";
let binary = assemble(code).unwrap();
assert_eq!(binary.len(), 3 * 3 * 2);
assert_eq!(
&binary,
&[1, 2, 3, 4, 5, 8, 9, 5, 6, 1, 2, 3, 1, 2, 3, 1, 2, 3,]
)
}
#[test]
fn regression_crunched_section_sokoban() {
let code = "
ENTITY_EMPTY = 1
ENTITY_FLOOR = 0
ENTITY_DESTINATION = 2
DEST_BIT = 1
ENTITY_BLOC = 4 ; ALWAYS in addition of floor or destination
BLOC_BIT = 2
ENTITY_VOID = 3
ENTITY_WALL = 8
WALL_BIT = 3
ENTITY_PLAYER = 16
macro MAP_CHECK_BLOC bloc
assert {bloc} == ENTITY_EMPTY || {bloc} == ENTITY_BLOC || {bloc} == ENTITY_DESTINATION || {bloc} == ENTITY_FLOOR || {bloc} == ENTITY_WALL || {bloc} == ENTITY_PLAYER || {bloc} == BD || {bloc} == ENTITY_VOID
mend
;;
; Safely produce the data for a line of the map
macro MAP_LINE9 a, b, c, d, e, f, g, h, i
MAP_CHECK_BLOC {a}
MAP_CHECK_BLOC {b}
MAP_CHECK_BLOC {c}
MAP_CHECK_BLOC {d}
MAP_CHECK_BLOC {e}
MAP_CHECK_BLOC {f}
MAP_CHECK_BLOC {g}
MAP_CHECK_BLOC {h}
MAP_CHECK_BLOC {i}
db E_
db E_
db {a}
db {b}
db {c}
db {d}
db {e}
db {f}
db {g}
db {h}
db {i}
db E_
mend
macro MAP_LINE12 a, b, c, d, e, f, g, h, i,j,k,l
MAP_CHECK_BLOC {a}
MAP_CHECK_BLOC {b}
MAP_CHECK_BLOC {c}
MAP_CHECK_BLOC {d}
MAP_CHECK_BLOC {e}
MAP_CHECK_BLOC {f}
MAP_CHECK_BLOC {g}
MAP_CHECK_BLOC {h}
MAP_CHECK_BLOC {i}
db {a}
db {b}
db {c}
db {d}
db {e}
db {f}
db {g}
db {h}
db {i}
db {j}
db {k}
db {l}
mend
W_ = ENTITY_WALL
F_ = ENTITY_FLOOR
B_ = ENTITY_BLOC
D_ = ENTITY_DESTINATION
E_ = ENTITY_EMPTY
P_ = ENTITY_PLAYER
V_ = ENTITY_VOID
BD = B_ + D_
macro MAP_EMPTY_LINE
MAP_LINE9 E_,E_,E_,E_,E_,E_,E_,E_,E_
mend
LZAPU
.player_y db 5
.player_x db 6
MAP_LINE12 E_,E_,E_,E_,W_,W_,W_,W_,W_,E_,E_,E_
MAP_LINE12 E_,E_,W_,W_,W_,F_,F_,F_,W_,E_,E_,E_
MAP_LINE12 E_,E_,W_,F_,F_,BD,W_,F_,W_,W_,E_,E_
MAP_LINE12 E_,E_,W_,F_,W_,F_,F_,BD,F_,W_,E_,E_
MAP_LINE12 E_,E_,W_,F_,BD,F_,F_,W_,F_,W_,E_,E_
MAP_LINE12 E_,E_,W_,W_,F_,W_,D_,F_,F_,W_,E_,E_
MAP_LINE12 E_,E_,E_,W_,F_,F_,F_,B_,W_,W_,E_,E_
MAP_LINE12 E_,E_,E_,W_,W_,W_,F_,F_,W_,E_,E_,E_
MAP_LINE12 E_,E_,E_,E_,E_,W_,W_,W_,W_,E_,E_,E_
LZCLOSE
";
let bin = dbg!(assemble(code));
assert!(bin.is_ok());
}
#[test]
fn label_colon_equ() {
let code = "PLY_AKY_OPCODE_OR_A: equ #b7";
assert!(dbg!(assemble(code)).is_ok());
}
#[test]
fn lzclose() {
let code = "LZX0
INNER_START
defs 100
INNER_STOP
LZCLOSE";
assert!(dbg!(assemble(code)).is_ok());
}