џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ `џџ ЎŒіЏlІŒєЇšЇ•ЎŒцЏ\ІŒу /† Ї НЉ((cT H E P E E P E R V2.0чCOPYRIGHT 1983ѓARTHUR J. FLEXSERм'SPECTROSYSTEMSШGMIAMI, FLІџa'HL'J—–­ЃPRINTER CONNECTED? (Y/N) НЁБ„п­Ÿ N'Y'ŽМŸˆ шЦџч— †ЇŒ mџ'€5 2ўїм'ƒў'ƒ?ў&\\ФрZ„ƒП,S0…ŸA0 ŸC08ŸGНЌ žEŸŸ%0Ÿ#Ÿ'Ÿt0‰џ8Ÿ!о!4 žEn‰5ЎŸˆІ€'­Ÿ  іn„Ь 0јНЙІmћ&фЖџ„ўЗџЦŽ•3НЅš0 ДDЇрО ЏбьЯ'!џ&liЬЖџэБЬ;эЌЬџў GэЈ I†~Ї™Œ‰L&މRЦ (ŒЉГ&ŽЉИ_ ŒзМ&ŽзС ŒиЏ&_ŽиДЦ†ЇOЏ_уiэemc'†Ћ@Ї<1UьЄ'ЃIэЁ єoC0ЁП †~З0нП1†9ЗgЇ„ь'C&ЖџŠЗџ9 *ACTIVE* ISџџ ЖjЇОkЏ—0eПk†~Зj9ЎџиП oџбŒЉГ'†~ЗgЎqПkІiЗj0ўЌŸ%Ь0~ЙІ *DISENGAGED* Жџ+Жџ;IOЖџЇ‹1mе'oЯ3˜†?ЎФ'Ї„3C іџЖџ„&!o^ЇЛбmZ&9O‹m|&9Р?&o9 m3&Љl+O‹ђї&m{& цЫч cl\бя&mZ& цђРчьBjх;m@&UЈ§@&oЯ%šП&ЦчПџ"_oЦ9}ћ@&ўЦ”qя&3lЏ#ІЉ &oЁOџH0ть†Ћ‘Зџ"УЖџ"„Ї‚98§&cи,ї&ch3щUl‘ў@&І 'рlЋ5І€ЗџЖџЄ€n„oџэ&lo…гm‚'ѕoyЎ†ŸЇ;3/4@Ќс&1Ц 3о;3ј5†ЏЇ ьlсЏпm"&jя&ІъЇх*o 1!† Cl4@Ќс&1"9џcћ&i— † !I†Їџі1W3’0bŸЌ u3Ÿm'Ъ3•ђ†9ЇьЦZtІ€RА†ІЇйІ`Ї[ёўѓя&2c"3Јкд„0щvŸ`0ˆ^Џ9+†mЇФ9†k љўК§&c3p'†R †AЇФœ– џў™П&/cж3FУm&Н)lџћmЫ' †`ЇУЬэМ9ўcћ&_чŒT0ŒІ…Ї ЩZXCVBNMўDў&Ц оў9ї&Ц гў.П&Ц Шў#ћ&Ц НўП&Ц Вў п&Ц Їўў&*‚ U  \цў!' &ІќЇ c§I§бя&@'! 3І№Ёћё9ІчЇŒ&ІїЇ§f ЦІЇЯ)І Їл§=9§Šў&ІћЕ'ьcћ­ў№§rп&џ}§eп&Я Ъ'Ц~ч#ЦŽчI §№3mћrўtЦ9чч-9~ЂП† љ ІР'&†` щ ю9m &@,‹@Ї 9Ž•3HЦ4ЎФь„ЏэС5Z&я9ŽR3 уŽЦ оџџџџџџџџџ^Жџ"ˆЗџ"9ѕŽч э˜4DDDD5„ #‹‹0џo ‰ЦџoІ€мџbZ&ѓ9Цџ_4ьЦџP5Z&я9 цŸŽџЦ†V%Ї 0Ї€J&ђ9ќY9m—'>Žtь&m/& c)§Л %o Ў„'њгj&њЫ†Ї І„ˆ Ї„њМmR'&0<ц60…mC& 4œ5&0Ў„Жџ SSІЗџ2a5~2v~""0&ќ9†IG?‡7GУCS9&TІCC=A=B=DP=X=Y=U=PC=S=STACK ŽџР†џћv@Ї9№раРА €]'*4"1јІ 'Ё' іmџЮ&І 'A-Z0†НЃ 5" !ўўYO‹3alў §шoќЎj0Џj1P_ЌЄ' 1#mЄ'!\ ѓІ"ЇД†`3ы]'ZЁР&ќ і3_я/†ЇФўo§Чћs†џЇџ 3yћѕќв§В; BREAK AT Џ^F`90ёЦN& І„`&\R ю &І`'ф]'сZ м &'† †`Ї€9. Х5@ьС0…Ї‚Z&ћnФю4@Ќс94& я&M 0O9†`Ї„9F"0%A%4_І‚\`' їС5.Ї€99"ћ‹@ уŽ†џЗ­Ÿ & 1?&іІ„ˆ€Ї„ х4†`Ї„5‚ƒ0,џ~ lћT0аІ€'`&і05ІиўЇР0 щ0Ї њMІ€&†`Їњ@[-€@ќ] шІ`&O0  HHHH4ЋрЇР9І€`&O9€p #‹990џЉю'І€ЇФ і9ћeЧ†ўЗWџ:& ŽћJќп & ч/&CК' 3k0ќЗŠь^1яќP†/ћкTІLќFKI0рЏўЊ†ЇўгЇ6  ^&2ю'3Aя! Н &  ю3_ ьў}&ў‡џuў†џoћmџј& )8'†Ї„0„ўђ3џр0y+ўџЇџб љ)oџЫ0YЏў-†ЇўV§ТЎў4 Ќс9І€`&њІў?C0†9^_[\]FREEZEm``TRACEmR``SLOWmZ``PRINTmMEM`EXAMINEz````````````````````BREAKPOINTSz````````````````````џ6  ^&2ю'3Aя! Н &  ю3_ ьў}&ў‡џuў†џoћmџј& )8'†Ї„0„ўђ3џр0y+ўџЇџб љ)oџЫ0YЏў-†ЇўV§ТЎў4 Ќс9І€`&њІў?C0†9^џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџэ/§џоНЉ(0‡ВНЁБY&xžrŸќ0СŸrОhŸўŽЂППh N&м[0ŒeNнє0ŒgGні0ŒfyЮј†>?НЃ%xчР ј я ј'гžєœі"лжјЮІРЁ€&ёZ&ї4ај$J4НЙЌ5 м7НЃA9~Ђ‚PRINTER? START: END: BYTES: нRŽЉŸ Žй4І€'Ч ј5‚Н‹рŸІŽњo„oŸНˆ!мњ9žќŸržўПhnŸќџ/§0] 01230џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџј& € XГ&HE00 Ѕ &HE16&2 H$:’ X,џ‰("&H"ЋH$):‹&PЂ &HE00 :ƒNOW IN 64K MODE&š(† 1A,50,8E,80,0,B7,FF,DE,EC,84,B7,FF,DF,ED,81,8C,DF,FF,25,F1,1C,AF,39&б2гM"PEEPER",&HD000:’&HE000,0:’&HE005,18:’&HE001,255&ї<ž:‡Є4);"64K PEEPER READY TO EXEC"4K PEџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ*4"1јІ 'Ё' іmџЮ&І 'A-Z0†НЃ 5" !ўўYO‹3alў §шoќЎj0Џj1P_ЌЄ' 1#mЄ'!\ ѓІ"ЇД†`3ы]'ZЁР&ќ і3_я/†ЇФўo§Чћs†џЇџ 3yћѕќв§В; BREAK AT Џ^F`90ёЦN& І„`&\R ю &І`'ф]'сZ м &'† †`Ї€9. Х5@ьС0…Ї‚Z&ћnФю4@Ќс94& я&M 0O9†`Ї„9F"0%A%4_І‚\`' їС5.Ї€99"ћ‹@ уŽ†џЗ­Ÿ & 1?&іІ„ˆ€Ї„ х4†`Ї„5‚ƒ0,џ~ lћT0аІ€'`&і05ІиўЇР0 щ0Ї њMІ€&†`Їњ@[-€@ќ] шІ`&O0  HHHH4ЋрЇР9І€`&O9€p #‹990џЉю'І€ЇФ і9ћeЧ†ўЗWџ:& ŽћJќп & ч/&CК' 3k0ќЗŠь^1яќP†/ћкTІLќFKI0рЏўЊ†ЇўгЇ6  ^&2ю'3Aя! Н &  ю3_ ьў}&ў‡џuў†џoћmџј& )8'†Ї„0„ўђ3џр0y+ўџЇџб љ)oџЫ0YЏў-†ЇўV§ТЎў4 Ќс9І€`&њІў?C0†9^_[\]FREEZEm``TRACEmR``SLOWmZ``PRINTmMEM`EXAMINEz````````````````````BREAKPOINTSz````````````````````џ6  ^&2ю'3Aя! Н &  ю3_ ьў}&ў‡џuў†џoћmџј& )8'†Ї„0„ўђ3џр0y+ўџЇџб љ)oџЫ0YЏў-†ЇўV§ТЎў4 Ќс9І€`&њІў?C0†9^џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЫ<†6Зџ#НЉ(Ћ‰R O M P E E P%˜GCOPYRIGHT 1983%„gARTHUR J. FLEXSER%n‡SPECTROSYSTEMS%[ЇMIAMI, FL%ŽНЁС^&0‰ , &0‰ў "_&0‰ [&0‰№ \&Ž ]&94ЮьэСƒ&і5 Д5ЎŸˆІ€%'НЂ‚ ѕn„џ<ѓ<‡#Ќ2," CLOADM EXEC"&ќF‡#Ќ2'џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџke $mmnn, the address of the program's IRQ routine, into the second and third bytes of Peeper ($1001-2, or offset-adjusted equivalent). The dots that appear between some byte values indicate that the bytes need not be consecutive (although they usually are), but may be separated by an instruction or two. If you are using Peeper in 64K mode, also beware of CLR $FFDE instructions (7F, FF, DE), which disable 64K operation. These should be replaced by 3 NOPs ($12). ^cPeeper and the Color Computer 3^d Peeper requires some minor adjustments to its timing constants in order to be able to single-step properly on the CoCo 3 (i.e., without skipping any instructions). A copy of Peeper that has been modified in this fashion has been placed on the Peeper disk under the name PEEPER3.BIN. ^kN1 ents to its timing constants in order to be able to single-step properly on the CoCo 3 (i.e., without skipping any instructions). A copy of Peeper that has been modified in this fashion has been placed on the Pџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ `џџ ЎŒіЏlІŒєЇšЇ•ЎŒцЏ\ІŒу /† Ї НЉ((cT H E P E E P E R V2.0чCOPYRIGHT 1983ѓARTHUR J. FLEXSERм'SPECTROSYSTEMSШGMIAMI, FLІџa'HL'J—–­ЃPRINTER CONNECTED? (Y/N) НЁБ„п­Ÿ N'Y'ŽМŸˆ шЦџч— †ЇŒ mџ'€5 2ўїм'ƒў'ƒ?ў&\\ФрZ„ƒП,S0…ŸA0 ŸC08ŸGНЌ žEŸŸ%0Ÿ#Ÿ'Ÿt0‰џ8Ÿ!о!4 žEn‰5ЎŸˆІ€'­Ÿ  іn„Ь 0јНЙІmћ&фЖџ„ўЗџЦŽ•3НЅš0 ДDЇрО ЏбьЯ'!џ&liЬЖџэБЬ;эЌЬџў GэЈ I†~Ї™Œ‰L&މRЦ (ŒЉГ&ŽЉИ_ ŒзМ&ŽзС ŒиЏ&_ŽиДЦ†ЇOЏ_уiэemc'†Ћ@Ї<1UьЄ'ЃIэЁ єoC0ЁП †~З0нП1†9ЗgЇ„ь'C&ЖџŠЗџ9 *ACTIVE* ISџџ ЖjЇОkЏ—0eПk†~Зj9ЎџиП oџбŒЉГ'†~ЗgЎqПkІiЗj0ўЌŸ%Ь0~ЙІ *DISENGAGED* Жџ+Жџ;IOЖџЇ‹1mе'oЯ3˜†?ЎФ'Ї„3C іџЖџ„&!o^ЇЛбmZ&9O‹m|&9Р?&o9 m3&Љl+O‹ђї&m{& цЫч cl\бя&mZ& цђРчьBjх;m@&UЈ§@&oЯ%šП&ЦчПџ"_oЦ9}ћ@&ўЦ”qя&3lЏ#ІЉ &oЁOџH0ть†Ћ‘Зџ"УЖџ"„Ї‚98§&cи,ї&ch3щUl‘ў@&І 'рlЋ5І€ЗџЖџЄ€n„oџэ&lo…гm‚'ѕoyЎ†ŸЇ;3/4@Ќс&1Ц 3о;3ј5†ЏЇ ьlсЏпm"&jя&ІъЇх*o 1!† Cl4@Ќс&1"9џcћ&i— † !I†Їџі1W3’0bŸЌ u3Ÿm'Ъ3•ђ†9ЇьЦZtІ€RА†ІЇйІ`Ї[ёўѓя&2c"3Јкд„0щvŸ`0ˆ^Џ9+†mЇФ9†k љўК§&c3p'†R †AЇФœ– џў™П&/cж3FУm&Н)lџћmЫ' †`ЇУЬэМ9ўcћ&_чŒT0ŒІ…Ї ЩZXCVBNMўDў&Ц оў9ї&Ц гў.П&Ц Шў#ћ&Ц НўП&Ц Вў п&Ц Їўў&*‚ U  \цў!' &ІќЇ c§I§бя&@'! 3І№Ёћё9ІчЇŒ&ІїЇ§f ЦІЇЯ)І Їл§=9§Šў&ІћЕ'ьcћ­ў№§rп&џ}§eп&Я Ъ'Ц~ч#ЦŽчI §№3mћrўtЦ9чч-9~ЂП† љ ІР'&†` щ ю9m &@,‹@Ї 9Ž•3HЦ4ЎФь„ЏэС5Z&я9ŽR3 уŽЦ оџџџџџџџџџ^Жџ"ˆЗџ"9ѕŽч э˜4DDDD5„ #‹‹0џo ‰ЦџoІ€мџbZ&ѓ9Цџ_4ьЦџP5Z&я9 цŸŽџЦ†V%Ї 0Ї€J&ђ9ќY9m—'>Žtь&m/& c)§Л %o Ў„'њгj&њЫ†Ї І„ˆ Ї„њМmR'&0<ц60…mC& 4œ5&0Ў„Жџ SSІЗџ2a5~2v~""0&ќ9†B@8€0@УCS9&TІCC=A=B=DP=X=Y=U=PC=S=STACK ŽџР†џћv@Ї9№раРА €]'ept that no return to Basic on RTS is provided for. ^cDisengagement^d The shift-break command is used to disengage Peeper. EXEC will re-engage the program, provided that the default EXEC address has not been redefined by loading in a machine-language program since disengagement. ^cAdding a Command to Peeper^d Provision has been made in Peeper to allow for the addition of a user-provided machine-language subroutine to be invoked whenever the shift-U command is given. At address $16EC are three NOP instructions that may be replaced with an LBSR or JSR to a user-supplied subroutine. Various utilities, such as a disassembler or a graphics screen print program, could be interfaced with Peeper by this method. A strategy that was employed in the design of Peeper, to maximize compatibility with other programs, was to have Peeper preserve the contents of all memory locations except for the contiguous block of locations taken up by Peeper itself. You may or may not wish to require the same criteria for a user-supplied routine, depending on the compatibility requirements of the programs to be monitored. The subroutine SWAPAL, located at address $165E, may be useful in this regard: if called at the beginning and end of a user routine, it will record and later restore the contents of all RAM addresses affected by the ROM keyboard scan and printer output routines. ^kQ PEEP2B/DOC ocated at address $165E, may be useful in this regard: if called at the beginning and end of a user routine, it will reџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ^kT 05 ^kT set x=18,j=1,w=39,N=1 on fmt menu ^kU2 B4 M0 ^kT elite print, margin=11 ^kD1 27 66 02 27 77 11 ^kT underlining and emphasis on, off ^kD2 27 45 1 27 69 ^kD3 27 45 0 27 70 ^kT emlarged emphasized mode on, off ^kD4 27 66 1 14 27 69 ^kD5 20 27 70 ^kT italics ^kD6 27 52 ^kD7 27 53 ^kT initialize prtr ^b ^kC78 ^k* ^cAddendum--Using the Find program^d Now included with Peeper is a machine-language utility program called Find that can be used to facilitate the removal of interrupt-disabling instructions from ML programs in order to achieve compatibility with Peeper. Find will locate all instances of a specified sequence of bytes within a given range of memory. It is relocatable, and requires Extended Basic. After executing Find and answering the printer inquiry with a Y or N response, you will be prompted for the start and end addresses of the region of memory to be searched. Input should be in hexadecimal. When you receive the "Bytes:" prompt, enter the sequence you wish to search for, in hex, one byte per line. After entering the last byte and receiving the subsequent ">" prompt, press the break key to perform the search. After the addresses where the sequence occurs, if any, are printed out, the program will again give a "Bytes:" prompt and you may search the same range of memory for other byte sequences without having to reenter the start and end addresses. If you wish to change the search range, pressing break without entering any byte values will cause the program to prompt for new start and end addresses. To exit Find, use the reset button. ^cInterrupt-Disabling Byte Sequences^d ^k; ^cInstruction^d ^cEquivalent Byte Sequence (hex)^d ORCC #$50 1A, 50 (replace with 12, 12) ORCC #$10 1A, 10 (replace with 12, 12) LDA #$34,...,STA $FF03 86, 34,...,B7, FF, 03 (replace 34 with 35) LDB #$34,...,STB $FF03 C6, 34,...,F7, FF, 03 (replace 34 with 35) LDX #$mmnn,...,STX $10D 8E, mm, nn,...,BF, 01, 0D LDD #$mmnn,...,STD $10D CC, mm, nn,...,FD, 01, 0D LDU #$mmnn,...,STU $10D CE, mm, nn,...,FF, 01, 0D LDY #$mmnn,...,STY $10D 10, 8E, mm, nn,...,10, BF, 01, 0D ^k; (In all 4 cases, replace the bytes after the dots with NOPs ($12) and poand there are no noticeable consequences. But while in Peeper's single-step mode, where an interrupt occurs on ^cevery^d instruction, any read from $FF02 will coincide with an interrupt, and the result will be a sixtieth of a second of normal-speed processing. In such a situation, a block of instructions will be omitted from the trace output. In most cases, instructions that read from $FF02 will be encountered only in connection with Basic's keyboard scan routine (POLCAT), where instances occur at locations $A1D6, $A1EB, and $A23D (for Color Basic 1.1 or 1.2). The effects of this problem can be minimized by placing breakpoints at instructions that follow calls to the POLCAT routine. Such a breakpoint can be placed even after POLCAT has been entered, if the critical instruction at $A1D6 has not yet been reached. In such cases, the appropriate breakpoint address can often be identified by inspection of the stack contents. ^cExamine Mode^d Examine mode, which is accessed by the shift-E command, provides the capability of inspecting and changing the contents of an address that is entered from the keyboard in hexadecimal. When shift-E is typed, the display window is moved to the status page and a blinking cursor appears in the MEM EXAMINE field. Normal processing is suspended until examine mode is exited by pressing the break key. To inspect the contents of an address, enter the address followed by a slash. The contents will be displayed after the slash, with the blinking cursor appearing to the right of them. At this point, the contents may be changed if desired by typing the new contents followed either by Enter (to remain in examine mode) or by the break key (to exit examine mode). If you do not wish to change the contents, possible commands at this point are up or down arrow (to inspect the next higher or lower address), Enter (to clear the MEM EXAMINE field and prepare for entry of a new address), or Break (to exit). Peeper remembers which address was last examined, and will allow this address and its contents to be re-displayed later simply by typing a slash in a blank MEM EXAMINE field. Examine mode may also be used for changing the contents of the registers. More precisely, what can be changed is the stored set of values that will be re-inserted in the registers when interrupt servicing is complete. If you enter Freeze mode and issue a shift-R command, these register values will be displayed on the status page. After doing this, issue a shift-E command and examine the contents of the location that corresponds to the value given for S in the register display. The contents of this location should agree with the first stack byte shown at the bottom of the status display. Repeated up-arrow commands should display the subsequent stack bytes. (This provides a method for inspecting the stack contents to a depth greater than 9, incidentally.) Go back to the first stack byte (using down arrow), and press the down arrow key once more. The byte now displayed corresponds to the second two hex digits (least significant byte) of the PC register value, as you can verify from the register display. Another down arrow will give the first two digits (most significant byte) of PC. If you repeatedly press the down-arrow key, you will see that the successive bytes displayed correspond to the contents of the various registers, which are stored in memory in the same order in which they appear on your screen. Thus, to change the contents of a register (except S), just use the examine mode to change the contents of the memory address where that register's contents are stored. After exiting examine mode, the change may be verified by issuing a second shift-R command. It is strongly recommended that such changes be done only with Freeze on, and that they be verified with shift-R before unfreezing. It is sometimes useful to change the contents of the PC register, although caution should be observed here, as an ill-advised change may cause a crash. Changing the value of PC to a particular address is equivalent to executing a machine-language jump to that address. Such a jump to $AC73, the address of Basic's idle loop, will usually enable a return to Basic from a machine-language program, assuming that no critical Basic addresses have been overwritten and that the DP register is set to zero. A jump to the execution address of a machine-language program provides a way of tracing execution flow from the start of the program that may be used as an alternative to the breakpoint method discussed earlier, excasic.) Note that you could also, as an alternative to setting a breakpoint at the execution address, type EXEC followed by shift-enter to achieve a much more imprecise synchronization of the onset of slow motion with the start of a machine-language program. ^cProgram Tracing Features^d Peeper has the ability to provide a continuous trace readout on the status page. Trace output is also sent to the printer, if printing is enabled. Tracing is toggled on or off by the shift-T command; a plus or minus in the TRACE field on the status page shows whether or not tracing is currently enabled. The shift-T command does not move the display window; if you wish to observe the status page, you will need to use a shift-L command in addition. Two different trace modes, referred to as address tracing and register tracing, are provided. In address trace mode, the address of the current machine-language instruction is displayed on the status page. Previous values remain in view until the display capacity of 18 addresses is filled, after which new addresses overwrite the oldest displayed addresses. A blue cursor precedes the most recent addition to the display. If the trace is engaged while Basic is idling, the output will contain a high proportion of instances of addresses $A7D3 and $A7D5. These addresses correspond to a delay loop that Basic uses for various purposes such as deciding when to change the color of the cursor. In register trace mode, the contents of all registers and of the hardware stack are displayed. The stack contents, displayed to a depth of 9 bytes, provide valuable information for determining where a subroutine was called from, since the first few bytes of the stack will generally contain the address to which control will revert when a return from the subroutine occurs. Knowledge of the stack contents can be particularly helpful when several subroutines are called in nested fashion. Unfortunately, there is no foolproof method for distinguishing stack bytes that represent subroutine return addresses from bytes that represent registers whose contents have been pushed onto the stack. In the shift-Z slow motion mode, the trace display is updated with each machine-language instruction, providing continuous single-stepping. If you turn the Freeze option on, while remaining in shift-Z slow motion mode, one machine-language instruction will be executed with each press of the space bar (discontinuous single-stepping). Faster slow-motion modes will cause a coarser trace; that is, the faster the slow motion, the more instructions will be executed between successive updates of the trace display. The shift-A command switches to the alternate trace mode (address trace/register trace). The currently selected trace mode is indicated by an A or R following the plus or minus in the TRACE field. If occasional single instances of either type of trace output are desired, rather than continuous updating, the shift-space and shift-R commands (used with trace off) will provide respectively an individual update of the address trace or of the register trace. The trace facility, needless to say, is highly useful for debugging machine-language programs. An advantageous technique is to use the speed functions to slow down more and more as you approach a critical point you wish to observe, engaging printing just before this point. Frequently, watching the register display on the status page will be helpful in deciding when to turn on printing. For example, if you know that the X-register must count down to zero before something interesting happens, you can increase speed to "fast forward" until X is close to zero before engaging printing and going into shift-Z speed mode. Peeper's trace facility is particularly useful in developing modifications to commercial machine-language software for which no source listing is available. The trace enables you to find out which routines are active as particular things happen on your screen. This enables many modifications to be accomplished without disassembling more than a small fraction of the program. There is an unfortunate flaw in the design of the 6809 processor that interferes with the proper functioning of the single-step feature in some situations. In normal operation, without Peeper, servicing of an interrupt may occasionally be erroneously omitted. This omission occurs whenever an interrupt happens to coincide with an instruction that reads from location $FF02. Normally, this represents a relatively unlikely coincidence hronized with the end of each "frame" on the TV screen, when the scanning beam has reached the bottom of the screen. When this type of interrupt occurs, provided that interrupts are enabled both in the 6809 processor and in the PIA (peripheral interface adapter) chip that detects the signal, processing jumps to whatever address is contained in locations $10D-$10E. (These locations are defined in ROM as containing a pointer to the IRQ service routine.) Normally, these locations contain the address of Basic's interrupt service routine, which differs according to what version of Basic (Color, Extended, or Disk) you have. In Basic, interrupt servicing times the duration of the SOUND and PLAY commands, updates the value returned by the Extended Basic TIMER function, and times the interval during which the disk motor remains on following a disk operation. Peeper changes the contents of locations $10D-E to substitute its own service routine for Basic's. Peeper's routine checks the keyboard for the commands that Peeper recognizes and performs the functions appropriate to each. It then exits to Basic's service routine so that Basic's servicing functions, as well as Peeper's, are performed. To achieve slow motion, Peeper inserts a delay loop into the service routine. For the slowest speed (the shift-Z mode), the duration of the delay loop has been selected to make the service routine last barely under a thirtieth of a second. This ensures that a new interrupt will occur practically immediately after the servicing of the previous interrupt is completed, so that only a single machine-language instruction has a chance to be executed between interrupts. Less severe degrees of slowing are achieved by reducing the duration of the delay loop to permit more processing between interrupts. ^cPrinter Output^d The commands discussed in the following three sections, which are concerned with various machine-language monitoring functions, all produce output both on Peeper's status page (reached by the shift-L command) and on the printer, if printing is currently enabled. Printer output may be toggled off or on by using the shift-P command; a plus or minus in the PRINT field on the status page indicates whether or not printing is currently enabled. Printing is initially on if a Yes answer was given to the "Printer Connected" question. If a No answer was given, printing is permanently disabled and future shift-P commands will have no effect. ^cBreakpoints^d The shift-H command enables the setting of up to three breakpoints, and removes any previously set breakpoints (H stands for halt). This command moves the display window to the status page, where a blinking cursor will be seen in the BREAKPOINTS field. Breakpoint addresses are entered in hexadecimal notation, separated by spaces; type Enter after the final address. Shift-H followed immediately by Enter may be used to remove previous breakpoints without setting new ones. While the cursor is blinking in the BREAKPOINTS field, normal processing is suspended. After breakpoints have been entered, the shift-L command may be used to return to the previous display page and display mode if desired. When a breakpoint that you have set is encountered during program execution, the display window moves to the status page, where a blinking blue indicator will be seen in the BREAKPOINTS field immediately preceding the address where execution has been halted. Peeper goes into Freeze mode to accomplish this halt; thus, shift-F is used to resume execution by turning off the freeze. Breakpoints remain set until cleared by a shift-H command. Since the functioning of the breakpoint feature requires that Peeper be able to insert an SWI instruction at the specified address, breakpoints will not be recognized if ROM addresses have been specified. It is possible to breakpoint addresses within the Basic interpreter, but only if you have 64K and have transferred Basic to RAM. One use of the breakpoint feature is to provide an opportunity to turn on slow motion and/or program tracing (described below) at a desired point. Thus, you may find it useful to set a breakpoint at the execution address of a machine language program prior to typing EXEC, if you wish to trace execution starting at the beginning. (The execution address of a machine language program may be found by examining locations $9D-$9E after loading in the program. The "examine" feature described later provides a convenient way to do this, or you can type PRINT HEX$(256*PEEK(&H9D) + PEEK(&H9E)) from Bard by the equivalent of $200 bytes as the up or down arrow keys are pressed. The memory address corresponding to the upper left corner of the screen may be determined by counting by $1000s or $200s as discussed previously. Peeper disables a feature of Extended Basic that automatically induces a change to text-display mode whenever any printing is sent to the screen. This disabling allows you to stay in your selected display mode regardless of whether screen printing is taking place. This aspect of Peeper creates an exception to the general rule that Basic programs run normally under Peeper if no Peeper commands are given. The command SCREEN\0 may be inserted at appropriate places in an Extended Basic program if you wish to be snapped back to text mode whenever screen printing occurs. In any case, shift-right arrow will always display the contents of Basic's text screen. ^cSpeed Commands^d To enter or leave Peeper's "slow motion" mode, type shift-S. There are a number of possible degrees of slowing available, which are controlled by the seven keys on the lower left of the keyboard: Z,\X,\C,\V,\B,\N, and M. Pressing one of these with the shift key down will select the degree of slowing that is in effect while in slow-motion mode, with shift-Z producing the slowest and shift-M the fastest motion. These speed modes allow degrees of slowing ranging from about half normal speed in the shift-M mode to several thousand times slower than normal in the shift-Z mode. Shift-Z mode is the default that remains in effect until some other speed is selected. Peeper will respond to a speed-select command whether or not it is currently in slow-motion mode, although the command will affect only slow-motion operation. While slow motion is in effect, if the space bar is held down, the speed will increase to that of the next faster speed mode, and will revert to the former speed when the space bar is released. This feature is useful as a "fast forward" mechanism for rapidly approaching a particular event that you wish to observe at the slower speed. A special command, shift-enter, has been provided for entering a Basic command or other input line and turning on slow motion almost simultaneously. Used instead of the Enter key alone to terminate a line of keyboard input, the shift-enter command causes slow-motion mode to be entered after a sixtieth of a second delay, with this pause being provided to allow Basic time to process the Enter key. (This is necessary because, in the slower speed modes, keyboard input, except for Peeper commands, is effectively disabled.) Occasionally, the sixtieth of a second provided will be insufficient for Basic to recognize the Enter key, and the cursor will remain at the end of the line. In such cases, use shift-S to release the slow motion and try shift-enter again. (Note: the sixtieth of a second will always be insufficient if the register trace feature, described later, is engaged.) The ultimate in slow motion is a complete freeze, which Peeper also permits. Shift-F turns the "Freeze" mode on or off. If slow-motion was in effect when shift-F was pressed, it will resume when freezing is turned off by a second shift-F command. If you use the shift-L command to go to Peeper's status page, you will see that the display includes the words FREEZE and SLOW. A plus or minus indicates the On or Off status of these options; the letter after the plus or minus in the SLOW field indicates the selected slow motion speed. ^cA Note About How Peeper Operates^d Before proceeding to the remaining commands, it may be useful to have some understanding of the mechanisms by which Peeper operates. Peeper's ability to function while another program is running depends on the 6809 processor's ability to handle signals known as interrupts. Whenever an interrupt occurs, the processor stops whatever it is doing, records the current contents of all of its registers (so that it can restore them later), and jumps to an instruction representing the start of an "interrupt service routine". This service routine performs whatever functions have been specified until a "return from interrupt" instruction is encountered, which causes the contents of the registers to be restored to their entry values, and causes execution to resume at the point where it left off when the interrupt occurred. The type of interrupt used by Peeper is the "field sync IRQ", which occurs once every sixtieth of a second. This interrupt is generated by the VDG (video display generator) chip and is sync used, locations $106-$108 (the SWI vector) must be preserved as well. In most cases in which a program overwrites locations $10C-$10E, it does so in order to insert its own IRQ service routine. In such cases, a special provision has been made in Peeper to make it possible to patch in Peeper's IRQ routine ahead of the target program's routine. Doing so involves finding and removing the instruction that stores the address of the target program's routine into locations $10D-$10E, usually a STX $10D or STD $10D instruction. Then, the address of the target program's IRQ routine is inserted at locations $1001-2 at the beginning of Peeper (or $E001-2 in 64K mode). This procedure will cause Peeper's service routine to be patched in as required when Peeper is executed. In addition, if it is desired that the slow motion speeds be properly calibrated and that single-stepping function properly, an adjustment must be made to the slow-motion delay constants, using Peeper addresses $1003-4 (or $E003-4). These procedures will be described in additional detail in the following section, which discusses using Peeper with arcade-style game programs. ^kQ PEEP3/DOC nt must be made to the slow-motion delay constants, using Peeper addresses $1003-4 (or $E003-4). These procedџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ^kT 05 21 ^kD1 27 66 02 ^kT underlining and emphasis on, off ^kD2 27 45 1 27 69 ^kD3 27 45 0 27 70 ^kT emlarged emphasized mode on, off ^kD4 14 27 69 ^kD5 20 27 70 ^kT italics ^kD6 27 52 ^kD7 27 53 ^kC78 ^kT mult. sign ^kDP8 190 ^k^b Note that a character's screen code is not the same as its Ascii value; the two are equivalent for uppercase letters, but are not equivalent in general. ^cDisplay Mode Commands^d The shift-D command allows you to change the display mode in which you are viewing a section of memory. If you type shift-D 13 times in a row, you will view all of the available modes in Color Set 0, one of the two color sets that is available for each display mode. If you now type shift-Q, which causes a change to the alternate color set, Color Set 1 will be in effect and you can again cycle through the 13 modes by repeatedly pressing shift-D. These 26 display options (13 modes ^i 2 color sets) represent the entire set of the CoCo's documented display possibilities, although undocumented modes also exist. Pressing shift-right arrow at any time will return you to text mode and Color Set 0, and will reset the display mode counter to the beginning of its cycle of 13 modes. (Recall that this command also moves the display window to page 2, Basic's text page.) The 13 display modes, in order, are as follows: 1. Text mode (Alphanumeric Internal; Semigraphics-4) (Set-Reset graphics, 64 ^i 32) 2. Graphics-6R (PMODE 4; 256 ^i 192) 3. Graphics-6C (PMODE 3; 128 ^i 192) 4. Graphics-3R (PMODE 2; 128 ^i 192) 5. Graphics-3C (PMODE 1; 128 ^i 96) 6. Graphics-2R (PMODE 0; 128 ^i 96) 7. Graphics-2C (128 ^i 64) 8. Graphics-1R (128 ^i 64) 9. Graphics-1C (64 ^i 64) 10. Semigraphics-24 (64 ^i 192) 11. Semigraphics-12 (64 ^i 96) 12. Semigraphics-8 (64 ^i 64) 13. Semigraphics-6 (64 ^i 48) Since most of these modes display considerably more than $200 bytes on the screen at a time, pressing the up or down arrow keys will not cause a complete replacement of the screen's contents as it does in text mode. Rather, most of the screen's contents will remain the same but will be shifted up or downwy survive a reset, although interrupts will need to be re-enabled by typing EXEC if you do not have Extended Basic.) B. Other Modifiable Locations Discussion of the "substitute IRQ" feature that employs addresses $1001-2 and $1003-4 will be deferred until the sections on Peeper's compatibility requirements and use with arcade-style games. For now, it is merely noted that this advanced feature allows Peeper to be used with programs that employ their own interrupt-service routines. Poking an appropriate constant into location $1005 allows you to save a copy of Peeper that omits the printer inquiry (convenient if you have no printer), or a copy that embodies any desired baud rate constant. ^kN ^k* ^cRompeep^d Peeper does not allow you to display the contents of the Basic ROMs or of Rompack cartridges. For this purpose, a short companion program, Rompeep, has been included with Peeper. Rompeep, unlike Peeper, does not employ interrupts, and consequently cannot run along with another program as Peeper can. The commands that Rompeep recognizes are a subset of those used by Peeper: the up and down arrows (shifted and unshifted) and shift-clear perform the same functions as in Peeper, while the shift-right arrow command exits the program and returns to Basic. Rompeep's method of displaying a memory page is somewhat different than Peeper's. Rather than moving the display window around in memory as Peeper does, (which is accomplished by changing the setting of the display offset register in the SAM, or synchronous address multiplexer), Rompeep copies the desired page of memory to Basic's text page. This copying is done many times per second, so that the view of memory is a dynamic one, similar to what Peeper displays. The advantage of this method over the one used by Peeper is that ROM may be displayed. To look at the memory contained in a Rompack, it is necessary to defeat the Rompack autostart feature. This may be done by taping over two of the pins that protrude from the cartridge. If you look carefully at the pins, you will see that one pin on the upper surface is shorter than the others. The pins to tape are the ones immediately to the left of this pin, one on the upper and one on the lower surface (viewed with the pins pointing towards you). If there are any pins to the left of these, it probably will not interfere with operation to tape over them as well; in fact, leaving these latter pins taped over would be a wise precaution since the voltages to these pins can cause extensive (and expensive) damage to the computer if a Rompack is accidentally inserted with power on. Rompacks should be inserted only with power off; although the autostart can be disabled with a poke as well as with tape, the former method provides no protection from blowing out chips if the Rompack is slightly misaligned when inserted. When the taped-up Rompack has been inserted, power may be turned on and Rompeep may be loaded and executed. ^cCompatibility Requirements for Using Peeper with Machine-Language Programs^d While Peeper was written to maximize compatibility with other programs, various types of incompatibilities may nevertheless be encountered. The most common type of incompatibility results when a program disables the interrupts, which Peeper requires in order to function. Most programs that disable interrupts will also be capable of running with interrupts enabled, so establishing compatibility will involve finding and removing (replacing with NOPs) the instructions that do the disabling. Interrupts can be disabled either in the processor (usually with an ORCC #$50 or ORCC #$10 instruction), or in the PIA (by storing an even number, usually $34, into location $FF03). Removing an interrupt-disabling instruction can occasionally have undesirable side effects, since there are a few locations in low memory used in Basic's interrupt servicing that the program being monitored may use for conflicting purposes. In such cases, an $FF poked into location $1001 (or $E001 if Peeper starts at $E000 in 64K mode) can be used to cause Basic's interrupt servicing to be bypassed. You will need to use POKE &HFF40,0 (or its examine mode equivalent) to shut off the disk drive motor if you have disabled Basic's interrupt servicing. The program to be monitored, which will be referred to as the target program, must also not write to the IRQ vector locations $10C-$10E; these addresses must contain a JMP instruction to Peeper's IRQ service routine. If Peeper's breakpoint function is to be^kT 05 21 ^kD1 27 66 02 ^kT underlining and emphasis on, off ^kD2 27 45 1 27 69 ^kD3 27 45 0 27 70 ^kT emlarged emphasized mode on, off ^kD4 14 27 69 ^kD5 20 27 70 ^kT italics ^kD6 27 52 ^kD7 27 53 ^kC78 ^kT mult. sign ^kDP8 190 ^k^b ^cUser-Modifiable Locations^d Several locations at the beginning of Peeper have been assigned values that you may wish to change in order to "customize" the program for certain applications, as outlined below. Using the start, end, and exec addresses given on the tape label (cassette version), you can save one or more custom versions, embodying any changes you wish to make. Please note that the program is distributed in unprotected (copyable) form for your convenience in making backup or customized copies for your personal use only. ^cLocation^d ^cFunction^d $1000 A zero poked here disables Peeper's relocation feature $1001-2 Substitute IRQ address; $FF in $1001 suppresses Basic's IRQ servicing $1003-4 Slow motion adjustment constant if substitute IRQ is used $1005 A zero poked here will bypass the "Printer Connected" question; Peeper will assume no printer is in use. Any value other than 0 or 255 will be used as a printer baud rate constant. $1006 Contains the number of addresses put on one print line by the address trace (normally 15) $1007 Contains the number of stack bytes (0-9) to be printed out in register trace mode (normally 9) A. Relocation Feature and 64K Operation When Peeper is executed, it copies itself to the top of available memory (excluding unneeded initialization routines) and does the machine language equivalent of Basic's command "CLEAR 200, xxxx", where "xxxx" represents the start address of the relocated Peeper. This procedure protects Peeper from being overwritten by Basic and maximizes the amount of memory available to Basic, regardless of the RAM size of your machine. If you wish to reserve memory above a certain address for machine-language use, enter a CLEAR statement to protect this area of memory prior to executing Peeper. When Peeper is then executed, it will relocate itself immediately below the protected area. For some applications, it may be desirable to disable the relocation feature and have Peeper execute directly in the address range into which it has been loaded. Peeper is relocatable, and may be loaded into whatever address range you wish to place it by using an appropriate offset with the LOADM or CLOADM command. (The supplied copy loads at a start address of $1000, which was chosen to make it easy to calculate offsets.) One application in which it is desirable to offset-load Peeper and disable relocation is if you wish Peeper to execute in high memory in a 64K machine. Locating Peeper above Basic enables the monitoring of programs that take up a full 32K, which otherwise would be impossible since there would be no place to put Peeper. In order to disable relocation, poke a zero into the first byte of the program. This address is listed as $1000 in the preceding address table, to which must be added any offset that is used in loading the program. Thus, to have Peeper load in at $E000 in a 64K machine, enter (C)LOADM "PEEPER", &HD000, then POKE &HE000,0 to disable relocation, and then type EXEC. (This assumes that you have first run a program to enable the 64K mode of operation. One such routine is given in lines 10-40 of the Basic program shown below.) Prior to executing Peeper, you may wish to save a copy that loads in directly at $E000 for future use with 64K. Alternately, if you have a disk system, the following Basic program may be used to put you into 64K mode, load in Peeper at $E000, and disable relocation. Line 60 may be replaced with EXEC if desired. ^k; 10 FOR X=&HE00 TO &HE16 20 READ H$:POKE X,VAL("&H"+H$):NEXT 30 EXEC &HE00 '64K MODE NOW ENABLED 40 DATA 1A,50,8E,80,0,B7,FF,DE,EC,84,B7,FF,DF,ED,81,8C,DF,FF,25,F1,1C,AF,39 50 LOADM"PEEPER",&HD000:POKE&HE000,0 60 CLS:PRINTTAB(4);"64K PEEPER READY TO EXEC" ^k; One caution should be observed when running Peeper in high memory when in 64K mode: do not press reset. If you do, you will no longer be in 64K mode; Basic will try to jump to an IRQ service routine that is no longer in memory that it knows about, and a crash will result. (In non-64K operation, Peeper will normall^kT 05 ^kT set x=18,j=1,w=39,N=1 on fmt menu ^kU2 B4 M0 ^kT elite print, margin=11 ^kD1 27 66 02 27 77 11 ^kT underlining and emphasis on, off ^kD2 27 45 1 27 69 ^kD3 27 45 0 27 70 ^kT emlarged emphasized mode on, off ^kD4 27 66 1 14 27 69 ^kD5 20 27 70 ^kT italics ^kD6 27 52 ^kD7 27 53 ^kT initialize prtr ^kD8 27 64 ^i ^kD8 27 71 ^kD9 27 72 ^kC66 ^k; ^e ************************* ^e * * ^e * T h e P E E P E R * ^e * * ^e ************************* ^k; ^k* ^gA Unique Interrupt-Based Program-Tracer^f ^kC78 ^k*^b^i^g For the Radio Shack Color Computer, 16K min., Extended Basic not required^j ^k* Copyable to disk, compatible with Disk Basic 1.0 and 1.1 ^k*(c) 1984, Arthur J. Flexser ^k*SpectroSystems, Miami, Florida^h The Peeper is a machine-language utility program designed to let you inspect any desired portion of the Color Computer's memory, even while Basic or machine language programs are running. With the Peeper, you can display any part of memory, using any of the CoCo's 26 documented display modes (text, graphics, or semigraphics). You can freeze the action at any time, or slow it down by practically any desired amount. Machine-language programmers are likely to find Peeper to be an invaluable debugging tool, in that it provides the capability of monitoring the slow-motion execution of a machine-language program. The Peeper is capable of providing a running trace of the 6809's registers and stack, and supports single-stepping, breakpoints, and other useful program-monitoring functions. Basic programmers will find Peeper very useful as a means of extending their knowledge beyond the level explained in the manuals. Peeper's ability to let you look "behind the scenes" at what Basic is doing will clarify the uses of many PEEK and POKE commands. The section entitled ^cA Guided Tour Through the CoCo's Memory^d is included to help you explore the functioning of Basic. You are invited to watch what happens in memory as various Basic commands are executed, and an explanation of what you are seeing is provided, at a level that does not presuppose knowledge of machine language. For the pure fun of it (ML experience not required), it is fascinating to use Peeper with arcade-style games. You can use the slow-motion feature to see the fine details of how the animation effects are achieved. See what is happening on "hidden screens" that never normally come into view. Or, see how the game looks and plays in a graphics mode other than the normal one--you will be dazzled at the variety of effects you can achieve with 26 display modes available. (This demonstration is a definite attention-grabber at any gathering of CoCo enthusiasts.) Also included with Peeper are two short companion programs. The first, Rompeep, supplements Peeper in that it allows you to inspect the contents of the Basic ROMs and of Rompack cartridges. The second program, Find, is a utility to aid in locating interrupt-disabling instructions that must be removed from some machine-language programs in order to achieve Peeper compatibility. ^k* ^cUsing the Peeper^d A command reference sheet is included with the program. It is suggested that you have this sheet in front of you for reference as the various commands are discussed. If you have not already done so, load in and execute the program. Peeper should now be asking you whether you have a printer connected; type Y or N as appropriate. Either response will produce Basic's "OK" message and flashing cursor, and your printer, if any, should type a carriage return. (Note: if you use a printer baud rate other than 600 baud, you must poke the appropriate constant into location 150 before executing Peeper, or with Peeper disengaged, or the poke will have no effect. You can also save a "customized" copy of Peeper with your required baud rate constant embedded, as explained later.) ^cDisplay Window Commands^d Now, let's try out some of the commands, starting with those that affect which portion of memory is being displayed. Hexadecimal notation (indicated by a dollar sign) will be used principally in what follows. If you are unfamiliar with hexadecimal, it is recommended that you consult one of the many available sources that explains this notation. As you will see, it is not difficult to keep track of what portion of memory Peeper is displaying when hexadecimal counting is used, whereas this task would be much more involved using the correspџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ ФССФСФ ЦХ!"#$%&Ш()*+,-./У123456789:ТџџџџџџџџџPEEP1 DOCџ +31-Dec-90 14:59PEEP2A DOCџˆ31-Dec-90 15:05PEEP2B DOCџ’31-Dec-90 15:01PEEP3 DOCџ'Ц31-Dec-90 15:02PEEP4 DOCџ0™31-Dec-90 15:06PEEPSUP DOCџ-31-Dec-90 15:10PEEPER BINjROMPEEP BIN еFIND BIN ї 8-Mar-89 15:22PEEP64K BAS ћPEEPER3 BINjџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџonding decimal values. First, press shift-clear. You should now be looking at memory page zero, which contains addresses $0 to $1FF. Each display page contains 512 bytes, equivalent to hexadecimal $200, or 1/2 K. The Color Computer is capable of using addresses from $0 to $FFFF, or 64K of memory. Thus, there are 128 display pages of 1/2 K each, which will be designated as pages 0-127. (These pages are not the same thing as what Radio Shack refers to as a graphics page. A graphics page contains $600 bytes, or three display pages worth.) The section entitled ^cA Guided Tour Through the CoCo's Memory^d, presented later, will describe what it is you are looking at on the various pages of memory; for now, let us concentrate on getting you oriented so that you will be able to locate any desired page of memory or any particular individual byte. In order to keep track easily of where you are in memory, it is necessary to acquire the ability to count by twos in hex: $0,\2,\4,\6,\8,\A,\C,\E,\10,\ 12,\14,\16,\18,\1A,\1C,\1E,\20, etc. Why by twos? Because each screen row contains $20 bytes, and each display page contains $200 bytes; if you can count by twos, you can also count by $20s or $200s. Now, try out the up and down arrow keys. The former moves the display window up $200 (1 page) in memory, while the latter moves you down an equal amount. If you hold the shift key down while pressing up or down arrow, you will move up or down $1000 (8 pages, or 4K) at a time. Use shift-clear to go back to page zero and count 2,\4,\6,\8,\A,\C,\E,\ one thousand,\2,\4,\6,\8,\A,\C,\E,\two thousand, pressing the up-arrow key with each count. You should now be looking at the display page containing addresses $2000-$21FF. Of course, we could have gotten to $2000 faster by pressing shift-up arrow twice. As a check, type two shifted down arrows, which should bring you back to page zero. Suppose we want to locate a particular byte of memory, say $2D56. This address will be on the page containing $2C00-$2DFF. From page zero, type two shifted up arrows, to get to $2000. Now count 2,\4,\6,\8,\A,\C\as you press unshifted up arrow with each count. You should now have the correct page, starting with $2C00, on your screen. Each screen row contains $20 bytes; the row that contains $2D56 will include addresses $2D40-$2D5F, and will be located somewhere in the bottom half of the screen. As you point to the start of each successive row, starting at the top, count 0,\2,\4,\6,\8,\A,\C,\E,\one hundred (=$2D00), 2,\4. This is the row we want, the one starting with $2D40. Starting at the left, count 40, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 50, 1, 2, 3, 4, 5, 6. You should now be pointing at $2D56. (With some practice, you may find it easier to locate $2D5F at the right edge of the screen and count leftwards back to $2D56.) To check that you are really looking at $2D56, try poking something into this location. Press the enter key to start a new line, and then type (blindly) POKE &H2D56,\&H41. If all is well, the letter A should appear at the location you identified as $2D56. ($41 is the screen code for the uppercase form of the letter A; refer to the table of screen codes on page 4 for determining the code corresponding to any desired letter or symbol.) If an A did not appear where expected, you either were looking at the wrong memory location, or you mistyped the command. To find out what went wrong in this case, type shift-right arrow to display Basic's text screen (locations $400-$5FF). Your POKE command should be visible, so that you can verify it. If it is correct and was acknowledged by Basic, try again to locate $2D56; there should be an A displayed there. Otherwise, type the command again and check $2D56. With a little practice, you should be able to find any location reliably. (While practicing, avoid poking locations on page zero, which could cause a crash. Also steer clear of memory locations that contain Peeper itself, for similar reasons. Incidentally, the active copy of Peeper is the one at the top of your available memory; Peeper relocates itself when executed to maximize the memory available to Basic.) In using the commands that move the display window, you should be aware that memory is treated as circular: the page below page zero is page 127, and the page above page 127 is page zero. The final display window command is shift-L (L stands for look), which causes a display of Peeper's "status page". This page contains information concerning the current status of various selectable options, as well as displays used in conjunction with the memory examine, breakpoint, and trace features to be discussed later. A second shift-L command will in most cases restore the display page and display mode that were in effect previously. In some cases, however, it will be necessary to use additional Peeper commands to restore the correct page and mode, since Peeper cannot be aware of changes in page and mode that have been induced by other programs. If the program you are monitoring induces a change in display mode while you are inspecting the status page, rendering the status display unreadable, two successive shift-L commands will have the effect of returning you to the status page in text-display mode. ^cA Note Concerning the Effect of Memory Size^d If you have a 16K machine, containing RAM addresses $0-$3FFF, you will find that the display for pages 32-63, corresponding to addresses $4000-$7FFF, is unstable. This instability is of no consequence, since these addresses are beyond the end of your 16K of RAM in any case. If you have a nonstandard 32K upgraded machine containing two banks of piggybacked 16K chips, the display may also be unstable in this memory range, depending on the exact upgrade method used. This constitutes a much more serious problem, since Peeper will be unable to display half of your available RAM, and since the status page (discussed later) will usually be located in this upper part of RAM. Some minor hardware modifications can correct this difficulty, however; SpectroSystems will supply instructions if the request is accompanied by a stamped, self-addressed envelope. In either the 16K CoCo or the 32K piggyback version, pages 64-127 will be a repeat of pages 0-63. If your CoCo is a standard 32K model, containing 64K chips, your 32K of RAM (addresses $0 to $7FFF) will be displayed on pages 0-63. However, pages 64-127 will ^cnot^d be a repeat of pages 0-63 as would be true in a machine with 16K chips. A Color Computer memory map shows that locations $8000 and up contain the Basic ROMs, so one might reasonably expect the start of Extended Basic to come into view as one flips from page 63 to page 64. If so, one would be wrong. What is actually seen on pages 64-127 is the second 32K bank of RAM that is contained in the 64K chips. This will be true whether or not your CoCo has had the benefit of the 64K modification to enable use of this second bank of RAM. (Newer CoCos have this modification already built in, whether sold as 32K or 64K.) Thus, many of you will be able to see into 32K of RAM that your CoCo is unable to use without modification. Fortunately, the hardware remedy for this somewhat frustrating situation is simple, inexpensive, and has been widely published. ^kT 05 12 19 25 39 46 52 66 73 79 93 100 106 ^kT underline on & off ^kD1 27 45 1 ^kD2 27 45 0 ^kT condensed font on, off (elite) ^kD3 27 66 3 ^kC78 ^kD4 27 66 2 ^kT up arrow, left arrow ^kDP5 164 ^kDP6 166 ^e^bScreen Codes^c A. Non-graphics characters The following table shows the hex bytes corresponding to the inverse (lowercase) and regular (uppercase) forms of the various characters. ^kC132 ^d ^k; Inv Char Reg Inv Char Reg Inv Char Reg Inv Char Reg $00 @ $40 $10 P $50 $20 space $60 $30 0 $70 01 A 41 11 Q 51 21 ! 61 31 1 71 02 B 42 12 R 52 22 " 62 32 2 72 03 C 43 13 S 53 23 # 63 33 3 73 04 D 44 14 T 54 24 $ 64 34 4 74 05 E 45 15 U 55 25 % 65 35 5 75 06 F 46 16 V 56 26 & 66 36 6 76 07 G 47 17 W 57 27 ' 67 37 7 77 08 H 48 18 X 58 28 ( 68 38 8 78 09 I 49 19 Y 59 29 ) 69 39 9 79 0A J 4A 1A Z 5A 2A * 6A 3A : 7A 0B K 4B 1B [ 5B 2B + 6B 3B ; 7B 0C L 4C 1C \ 5C 2C , 6C 3C < 7C 0D M 4D 1D ] 5D 2D - 6D 3D = 7D 0E N 4E 1E ^f 5E 2E . 6E 3E > 7E 0F O 4F 1F ^g 5F 2F / 6F 3F ? 7F ^k; ^kC78 ^e B. Graphics characters The graphics screen codes ($80-$FF) consist of a color code, represented by the first hex digit, and a pattern code, represented by the second digit. The color codes are as follows: $8 green 9 yellow A blue B red C buff D green-blue ("cyan") E blue-purple ("magenta") F orange (Adding 7 to the numbers used by Basic to represent the colors will produce these values.) ^kN The pattern codes ($0-F) that correspond to the second digit of the graphics characters' screen codes are found using the following diagram: ^kDP1 240 ^kDP2 242 ^kDP3 246 ^kDP4 247 ^kDP5 241 ^kDP6 245 ^kDP7 243 ^kDP8 248 ^b^f^f^f^h^f^f^f^c ^kDP1 244 ^kDP2 250 ^kDP7 249 ^g 8 ^g 4 ^g ^b^f^f^f^c^f^f^f^h ^g 2 ^g 1 ^g ^d^f^f^f^i^f^f^f^e To obtain the pattern code for a desired configuration, simply add up the values of the quadrants that are "lit up", that is, non-black. Thus, the screen code value of a graphics character that is red in the upper left and lower left quadrants would be $BA, since $B = red and $A = 8 + 2. ^kQ PEEP2A/DOC tion, simply add up the values of the quadrants that are "lit up", that is, non-black. Thus, the screen code value of a graphics character that is red in the upper left and lower left quadrants would be $BA, sincџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ^kT 05 41 50 57 67 ^kD1 27 66 02 ^kT underlining and emphasis on, off ^kD2 27 45 1 27 69 ^kD3 27 45 0 27 70 ^kC78 ^k* ^cUsing the Peeper with Arcade-style Games^d Many high quality machine-language game programs are now available for the Color Computer and can be used with the Peeper in interesting ways. The slow motion modes permit a detailed examination of how the animation effects are achieved. Frequently, interesting things are happening on "hidden screens" that never come into view ordinarily and which you can view with Peeper. (A number of games do all of their object updating on a duplicate "hidden" screen). In addition, it can be an enjoyable experience to play your favorite game in a different graphics mode than the one originally written into the program, or in slow motion. Unfortunately, incompatibility problems such as those discussed in the preceding section are not infrequently found with arcade programs. Accordingly, in this section, specific instructions are presented for using Peeper with many of the most popular Color Computer games. In addition, the general techniques presented here can be used with programs other than those listed. When possible, descriptions of these techniques will be presented in such a fashion as not to require knowledge of machine language, although such knowledge, and access to a disassembler utility, will be helpful. Using Peeper with a 16K game program will usually require 32K of RAM, since arcade games commonly make full use of the memory available, either for the program itself or for the graphics display. Similarly, 32K games will generally require 64K of RAM in order to find an unused portion of memory that Peeper can occupy. It will be assumed in such cases that you have loaded in Peeper at $E000 and have disabled relocation by storing a zero in location $E000. Probably the most severe problem in using the Peeper with arcade games is that a great many games employ an autostart as a copy-protection device. If modification is required to make a game compatible with Peeper, the autostart feature must first be disabled. In accomplishing this, you are on your own. Some of the games mentioned in what follows are sold with copy protection, while the directions given below apply to deprotected copies. It is sincerely hoped that such deprotected versions have been acquired through legitimate means (that is, by deprotecting your own legally purchased copy), and that these directions will not encourage anyone to obtain copyrighted software illegally. A further consideration is that multiple versions of many games exist, so that specific instructions given below pertaining to particular games cannot be guaranteed to work with the version you may have available. The general techniques outlined, however, should be workable with the great majority of games. It is also recognized that the games discussed below represent only a moderate-sized sample of those available for the CoCo; no attempt has been made to comprehensively survey the wealth of available game software. ^cGames Not Requiring Modification^d The following games have been found to be compatible with Peeper without any modifications, provided that you have sufficient RAM available (32K for 16K games, 64K for 32K games). ^k; Bird Attack (Tom Mix Software, 16K) Cu*Ber (Tom Mix Software, 32K) Food War (Arcade Animation, 32K) * The Frog (Tom Mix Software, 16K) * Grabber (Tom Mix Software, 32K) Ice Master (Arcade Animation, 32K) Kron (Oregon Color Computer Systems, 32K) Planet Invasion (Spectral Associates, 16K) Protector II (Synapse Software, 32K; use Exec address $1DB9) Protectors (Tom Mix Software, 32K) Shark Treasure (Computerware, 16K) * Return of the Jet-I (ThunderVision Software, 32K; use Exec address $7802) Time Patrol (Computerware, 32K) Tube Frenzy (Aardvark Action Software, 16K) ^k; In the case of 16K games, Peeper should be loaded and executed prior to loading the game program, so that Peeper can relocate itself safely at the top of memory and not be overwritten when the game is loaded. For "The Frog" and other games that use the up and down arrow keys, it may be convenient to modify Peeper to avoid conflicting uses of these keys. The following pokes, done prior to executing Peeper, will cause the I and K keys to assume the display window functions ordinarily associated with the up and down arrow keys: ^k* POKE &H135B,&HFD:POKE &H135C,2:POKE &H137C,&HF7:POKE &H137D,2 An asterisk to the left of the name of a game means that you must disable Basic's interrupt servicing by poking an $FF (decimal 255) into location $1001 (or $E001, if using 64K) prior to executing Peeper, as discussed in the preceding section. This disabling is frequently necessary with disk systems; a possible symptom of failure to do this when it is required is an erratically flickering small area within a graphics screen, often followed by a crash, or slow motion in which the shift-Z mode is not the slowest. ^cGames Requiring Removal of an ORCC #$50 or ORCC #$10 Instruction^d Many games disable interrupts, usually at a very early stage of execution, to enhance sound quality and to gain a slight bit of extra speed. This is usually done by means of an instruction denoted in assembly language as ORCC #$50 and represented by the consecutive hex bytes $1A, $50. Less frequently, the instruction ORCC #$10 ($1A, $10) is used instead of ORCC #$50. In either case, all that is usually necessary to achieve compatibility with Peeper is to replace the values $1A and $50 (or $10) with two bytes containing $12 (decimal 18), thus eliminating the ORCC #$50 or ORCC #$10 instruction by replacing it with two NOP (no operation) instructions. The two offending bytes will frequently be found within a few bytes of the execution address of the game program. The machine-language utility program Find that is included with Peeper may be used to locate these and other interrupt-disabling instructions. (See Addendum for instructions on the use of Find.) If more than one or two ORCC #$50 (or ORCC #$10) instructions are found, there is a good possibility that the game uses its own interrupt service routine. In this case, leave the ORCC instructions in and follow the directions given in a later section for this type of game. You should also be aware of the possibility that consecutive bytes of $1A, $50 (or $1A, $10) may occur in a data table and may not necessarily represent an ORCC instruction in all cases. Thus, it is safer, if you have some ML experience, to use a disassembler to inspect a program before changing any bytes. An alternate technique that is useful for removing incompatibilities with Peeper involves using Peeper's trace facility. If you turn on the trace and single-step Peeper up to the point where it stops operating, the last instruction executed will locate the point at which interrupts were disabled. The following game programs become compatible with Peeper when ORCC #$50 or ORCC #$10 instructions at the specified addresses are replaced by NOPs: ^k; Astro Blast (Mark Data Products, 16K tape, 32K disk) $604-5 (tape) $4104-5 (disk) Buzzard's Bait (Tom Mix Software, 32K) $4F7F-80 Colorpede (Intracolor Communications, 16K tape) $607-8 Crash (Tom Mix Software, 32K) $3219-A * Devil Assault (Tom Mix Software, 16K) $1EB1-2; $390F-10 * Fire Copter (Adventure International, 16K) $2007-8 Katerpillar Attack (Tom Mix Software, 16K) $3085-6; $30A2-3 * The King (Tom Mix Software, 32K) $3208-9 (also known as Donkey King) Monkey Kong (Med Systems, 16K) $2A75-6; $2DD6-7 * Storm Arrows (Spectral Associates, 16K) $2000-1; $2C0F-10 ^k; "The King" becomes incompatible with Peeper after the first "barrels" screen has been completed, since the program at that point overwrites the interrupt vector at $10D-E. ^cGames that Store $34 into Location $FF03^d Some games disable interrupts in the PIA by storing a $34 into location $FF03. In this case, the solution is to change the $34 to a $35. The most common instruction sequences to search for in this case are LDA #$34, STA $FF03 ($86,$34,$B7,$FF,$03) and LDB #$34, STB $FF03 ($C6,$34,$F7,$FF,$03), changing the $34 to a $35 in both cases. Games in this category, with the address of the $34, are as follows. The asterisks denote that Basic IRQ servicing should be bypassed: ^k; * Bloc Head (Computerware, 16K) $2617 * Cashman (Computer Shack, 32K) $7128; also put NOPs in $63AC-D * Starblaster (Micro Works, 32K) $4B8C Storm (Computerware, 16K) $261B; also put NOPs in $2820-1; change $2930 from $2A to $21 ^k; ^cGames that Employ Their Own Interrupt Service Routines^d Many recent game programs, especially 32K games, employ their own interrupt service routines, which creates a different kind of incompatibility problem. As discussed in the previous section on incompatibilities, it is possible in such cases to patch Peeper's interrupt service routine in ahead of the game's. First, you must find and remove (by replacing with NOPs) the instruction that overwrites locations $10D-$10E. The most common instruction sequences are either LDX #$mmnn, STX $10D ($8E,$mm,$nn,$BF,$01,$0D), or LDD #$mmnn, STD $10D ($CC,$mm,$nn,$FD,$01,$0D), where $mmnn denotes the hexadecimal address of the game's interrupt service routine. In either case, the last 3 bytes of the sequence should be replaced with 3 NOPs ($12). In addition, prior to executing Peeper, poke the address of the game's service routine ($mmnn) into locations $1001-2 (or $E001-2); that is, store $mm into $1001 ($E001) and $nn into $1002 ($E002). There is one final step that must also be performed if you wish the slow motion speed to work as usual. If it makes little difference to you whether shift-Z is the slowest speed rather than, say, shift-V, and if you do not wish to single-step the program, you can omit this step. As stated previously, slow motion is achieved by a delay loop that causes interrupt servicing to last barely under a thirtieth of a second in the shift-Z mode. The number of iterations of this delay loop must be reduced to compensate for the presence of the game's service routine in order for slow motion to work properly. This is done by poking a subtractive adjustment constant into locations $1003-4 (or $E003-4). In the examples given below, all such constants are less than 256 ($100), so no changes to the contents of $1003 ($E003) will be necessary. The longer the game's service routine is, the larger the adjustment that will be required. The table below gives the relevant information for various games that use their own interrupt service routines. The steps for using the table with a program of this sort are as follows: 1. Load in Peeper (at $1000, or at $E000 in 64K mode with relocation disabled), and poke the address of the game's interrupt service routine (Column 2) into locations $1001-2 ($E001-2). 2. Poke the adjustment constant given in Column 3 (in decimal) into location $1004 ($E004). 3. Execute Peeper. Peeper will not respond to commands until the game activates its interrupt service routine by enabling interrupts. 4. Load in the game. Poke NOPs ($12) into the 3 consecutive bytes that start with the address (or addresses) given in Column 4, to remove the STX $10D instruction(s). (If you have disk, it will be necessary to type POKE &HFF40,0 to shut off the drive motor after loading the game.) Perform any additional pokes as noted in the final column. 5. Execute the game. Peeper will become active when the game enables interrupts. The additional miscellaneous pokes given in the final column are required to maintain 64K compatibility. Some games contain CLR $FFDE instructions that turn off the 64K mode. In another case, a CLR $FFD7 instruction puts the processor in a high-speed mode that is incompatible with 64K operation. In a few cases, the IRQ address given in Column 2 has been adjusted to skip over a test of bit 7 of $FF03 (used to distinguish between two types of IRQ interrupts). A symptom that this adjustment is required is that the game operates when slow motion is on, but freezes otherwise. ^k; IRQ Adj. STX Game Serv. Const. $10D Additional Addr. (dec.) Addr. Reqts. Catalyst (Computer Shack, 32K) $69E3 6 $4B46; $52C1; $6910 Chopper Strike (Computer Shack, 32K) $2C0E 9 $2384 NOP $23A2-3-4 Cubix (Spectral Associates, 32K) $67EB 10 $55F1 Demon Seed (Computer Shack, 32K) $5781 34 $59B3 Dunkey Munkey (Intellectronics, 32K) $55E8 8 $4DE1 Froggie (Spectral Associates, 32K) $6415 23 $4349 Fury (Computer Shack, 32K) $393B 13 $35A6 Ghost Gobbler (Spectral Associates, 16K) $2FC1 7 $22CE Galax Attax (Spectral Associates, 16K) $1E9F 4 $1E91 Intercept-4 (Computer Shack, 32K) $7BF5 8 $4230; $4617; $7DD7 Lancer (Spectral Associates, 32K tape) $4E11 16 $3512 Lunar Rover (Spectral Associates, 32K) $404F 5 $2629 ^kN IRQ Adj. STX Game Serv. Const. $10D Additional Addr. (dec.) Addr. Reqts. Miss Gobbler (Spectral Associates, 32K) $624D 8 $5206 Moon Shuttle (Datasoft, 32K) $3E39 33 $2C9C NOP 3 bytes each at $321F, $3646, $3694, and $3D5E Mudpies (Computer Shack, 32K) $52C8 35 $6DBE Pooyan (Datasoft, 32K) $7C8D 36 $4D3A NOP $4CFC-D-E Sea Dragon (Adventure Internat'l, 32K) $5EB4 6 $3808 Space War (Spectral Associates, 16K) $2C83 6 $1B7A Trapfall (Tom Mix Software, 16K) $2CC3 4 $2C5D Whirlybird Run (Spectral Assoc., 16K) $254B 3 $2084 Exec at $1E10 Zaxxon (Datasoft, 32K) $7BD3 34 $6279 NOP $6235-6-7 ^k; Note that since Peeper does not become active immediately, the setting of a breakpoint at the execution address to trace a program from the beginning is not possible without another step. You can enable interrupts before executing the game by typing POKE &HFF03,&H35, which will activate Peeper, allowing a breakpoint to be set in the normal fashion. However, there is no guarantee, if you try this, that the game's interrupt service routine (which is activated along with Peeper's) will be compatible with Basic, although experience suggests that most such routines cause no problems. A final topic is that of how to find the right value for the adjustment constant for a game or other program not included in the preceding table. Peeper itself allows a method for doing this with some degree of efficiency. Assume, for simplicity of discussion, that we have Peeper at $E000 with relocation disabled, and have not put any adjustment value into $E004. Using examine mode, with the game or other target program running, inspect the contents of addresses $E881-2. These addresses should contain $742, the unadjusted delay constant for the shift-Z slow motion mode. By trying out various values for this constant, and observing the effect on the speed of shift-Z slow motion, we can determine the optimal adjusted value for the delay constant. The difference between this value and the original value of $742 is the adjustment constant that should be used with this program. The adjusted value should be less than $742; the adjustment constant values in the preceding table will give you an idea of how much reduction is typical. A shortcut is possible if one of the other slow motion modes than shift-Z produces either very slow motion or freezing. Freezing while in slow motion (with freeze mode off) results from having a delay constant that is slightly larger than the optimal one. The optimal value is one less than the smallest value for which freezing occurs. The delay constants for the various speed modes, contained in locations $E881 and above, are as follows: Z: $742; X: $740; C: $738; V: $718; B: $680; N: $430; M: $40. Suppose that the shift-V mode produces freezing. In this case, we know that the constant for shift-V, $718, is just a bit larger than the number that we want for the adjusted shift-Z constant. Similarly, if one slow motion mode is very slow, we know that the optimal delay constant is at or slightly larger than the value corresponding to this speed mode. In some cases, there exists no completely satisfactory adjustment constant, because the duration of the game's service routine varies from one interrupt to another, according to the outcome of some conditional instructions embedded in it. This will place a limit on the amount of slowing that is possible, and will make single-stepping unachievable. It may also mean that an adjustment constant that allows single stepping during one phase of a program will need adjustment to work properly during a later phase of execution. If single-stepping is achievable and is seen as necessary, there is also a "fine adjustment" capability that allows a fractional adjustment if the best constant found by the above method is found to skip some instructions. The byte at location $E864 is a zero; changing it to 1 or 2 is equivalent to fractionally reducing the delay constants by 1/3 or 2/3. Do not use any value other than 0, 1, or 2 in this byte or Peeper may crash. It should be emphasized that these somewhat complicated instructions for finding the optimal adjustment constant for a program with its own interrupt service routine are included for the sake of completeness. For any purpose other than an instruction-by-instruction trace, a rough guess at an appropriate constant will most likely yield satisfactory results. ^kQ PEEP4/DOCgram with its own interrupt service routine are included fџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ^kT 05 21 ^kD1 27 66 02 ^kT underlining and emphasis on, off ^kD2 27 45 1 27 69 ^kD3 27 45 0 27 70 ^kT emlarged emphasized mode on, off ^kD4 14 27 69 ^kD5 20 27 70 ^kT italics ^kD6 27 52 ^kD7 27 53 ^kC39 ^kT mult. sign ^kDP8 190 ^k^b ^k* ^c^eA Guided Tour Through The CoCo's Memory^f^d ^kC78 This section is included to help you explore some of the workings of the Basic interpreter using Peeper. Let's begin by taking a look at a few of the more interesting locations on the very busy-looking page zero, after which we will gradually work our way upward through memory. Location $94 seems to be doing something very rapidly. If you enter one of the less severe slow-motion modes, you can observe that this location is being repeatedly decremented from eleven (inverse-K) to one (inverse-A). This location contains the counter Basic uses to determine when to change the cursor color. If you flip between page zero and the text page, you will see that the cursor color changes each time the counter completes its cycle. Another rapidly changing location, provided you have Extended Basic, is $113. Locations $112 and $113 are used to store the value returned by the TIMER command. As mentioned previously, the incrementing of this value is one of the functions performed by Basic's IRQ service routine every sixtieth of a second. Peeper's slow motion commands have no effect on the rate at which the values in locations $112-113 change, since IRQ servicing is still performed every sixtieth of a second regardless of whether slow motion mode is in effect. A prominent feature of page zero is the wide orange strip corresponding to locations $152-159. This is the keyboard memory buffer, also called the keyboard rollover table. If no key is being held down, all eight locations contain $FF. Pressing a key causes one of these locations to assume a different value, with the particular location and value depending on which key is pressed. Internally, the CoCo's keyboard is represented as an array of 8 columns by 7 rows. (If you have the Color Computer Technical Manual, the array is shown in the schematic diagrams.) The column number determines which location from $152 to $159 is affected by a particular keypress, while the row number determines which bit in this location is changed to a zero from its initial value of one. These locations do not interface directly with the keyboard; rather, the values are set by the Basic interpreter's keyboard scan routine (POLCAT), using information that is read from one of the PIAs that does connect directly to the keyboard. The keyboard rollover table locations can be used to provide a handy means of checking from Basic whether a particular key is being held down. (The INKEY$ function is inadquate for this purpose, since it registers only a new keypress.) If you have joysticks, you can also see that these locations are affected by the joystick buttons, which share common PIA connections with two of the keyboard rows. Incidentally, the operation of the PIAs themselves can be viewed using Rompeep. One PIA is mapped into locations $FF00 to $FF03, the other into $FF20-FF23. Each set of four PIA locations will appear to be replicated eight consecutive times in memory due to incomplete address decoding. Watch what happens to these locations when you move a joystick or press the joystick buttons. If you type something while looking at page zero, you will see that locations $88-89 increment with each character. These locations hold the address of the current cursor position, and will stop incrementing when the cursor reaches the bottom of the screen. Try running the following one-line program: ^k* 10 X = JOYSTK(0): GOTO 10 Now, if you move the joysticks, you will see that locations $15A-15D, immediately to the right of the keyboard memory buffer, are used for recording the four joystick coordinates: right horizontal, right vertical, left horizontal, and left vertical. Each coordinate can take on the values zero (inverse-@) to $3F (decimal 63; inverse-?). These values are computed by the Basic interpreter's JOYIN routine, using a software analog-to-digital converter technique to converge upon the appropriate values by successive approximations. (The CoCo cannot read the joystick voltages directly; however, its hardware does allow it to determine whether each of a series of trial matching voltages that it generates is too big or too small.) When a Basic program is being executed, quite a few locations on page zero change rapidly. The most important of these are locations $A6-A7, which contain the address of the next program byte to be interpreted, and locations $68-69, which contain the line number of the current program line, or $FFFF if no program is being executed. Also, before we leave page zero, type shift-zero a few time and notice the toggling of the uppercase-lowercase flag at location $11A ($FF=upper, 0=lower). Now, let's have a look at page one. Starting at $2DD is a 256-byte line input buffer that holds the Ascii character values of whatever you type in from the keyboard. Uppercase but not lowercase letters will appear normally in Peeper's display of this buffer; this is because screen codes are the same as Ascii values for uppercase but not lowercase letters. Thus, for example, a lowercase ^cA^d, which has an Ascii value of $61, will display as the character for which the screen code is $61--an exclamation point. For the same reason, numbers, symbols, and spaces will appear in inverse form. The buffer at $2DD is also used in the inputting of Ascii-format tape files. You can watch a cassette file read in while using Peeper. However, you will be unable to switch pages or use other Peeper commands while the data is being read since interrupts are disabled during data reading, rendering Peeper inactive. You can switch pages during the gaps in gapped tape files, however. Interrupts are disabled for much briefer intervals during the reading of disk files; disk users will be able to use Peeper's functions while loading data. Also on page one is a 256-byte buffer used in the loading of non-Ascii tape files. This buffer actually starts near the end of page zero, at $1DA, and continues onto page 1. Locations $1D2-1D9 contain the name of the file that is being searched for, while locations $1DA-1E1 contain the filename of any file encountered on the tape. Now, load in any Basic program that you may have handy. The address at which Basic stores the program will depend on which version of Basic you have. In Color Basic, the program will be stored starting at $601, just above Basic's text page. If you have Extended Basic, and have not issued any PCLEAR commands, the program will start at $1E01, while in Disk Basic, the corresponding address is $2601. In Extended Basic, the memory between the end of the text page ($600) and the start of the program is reserved for graphics use. PCLEAR 4 is assumed in the absence of any explicit PCLEAR command, which allows four graphics pages of 1.5K ($600) each, equalling 12 of the Peeper's 1/2 K display pages. The memory Basic reserves for graphics use can also be used for storing machine-language programs if your Basic program does not make use of any graphics commands. In Disk Basic, programs must start $800 bytes higher than in Extended Basic, due to the fact that the 2K of memory between $600 and $DFF is reserved for various disk-related functions. Let's look at the effect of PCLEAR, assuming you have Extended or Disk Basic. Find the start of your program at $1E01 or $2601 and move the display window down nine pages from there, which equals three graphics pages. This is where the program would have loaded in had you typed PCLEAR 1 prior to loading. Now try typing PCLEAR 1. You should observe that the program suddenly appears in the new starting location. (Try this in slow motion if you like.) It is still there in the old location as well (unless the program is so long that the copies overlap), and you can create additional RAM copies by using the PCLEAR command with other argument values. If you look at page zero while giving various PCLEAR commands, you will notice that the values in four consecutive pairs of locations, starting with $19-1A, change as you change the value of the PCLEAR argument. Locations $19-1A are used to store the address of the start of your Basic program. If you, for example, type POKE &H19,&H22: POKE &H1A,&H33 and then load a Basic program in from tape or disk, you will find that the program has loaded in starting at address $2233. However, if you type RUN, you will probably get a syntax error message. This is because the RUN command requires that there be a zero in the byte preceding the program start. Type POKE &H2232,0 and you will find that Basic will now accept the RUN command. This explanation should enable you to understand the principle underlying the well-known method of simulating the illegal PCLEAR 0 command, which is done by POKE &H19,6:NEW in Extended Basic and by POKE &H19,&HE:POKE &HE00,0:NEW in Disk Basic. These commands move the program buffer to $601 in Extended Basic and to $E01 in Disk Basic. (It is unnecessary to poke a zero into location $600 because this is done as part of Basic's cold start initialization. It is also unnecessary to poke a one into location $1A, since this value will also already be there. The NEW command resets some necessary pointers, as detailed below.) What about the other three pairs of locations affected by the PCLEAR command? Addresses $1B-1C contain a pointer to the end of the program, which is also the start of the area of memory reserved for variable storage. Locations $1D-1E point to the start of array storage (which is also the end of variable storage), while locations $1F-20 point to the end of array storage. These pointers can be used to merge two Basic programs as follows: First, load in the first program, making note of its start address ($19-1A) and end address ($1B-1C). Then poke into location $19-1A an address equal to the contents of $1B-1C, minus two. When you now load in the second program, the new value in $19-1A will cause it to load in immediately following the first program. (The "minus two" was to eliminate two bytes containing zeroes at the end of the first program that Basic uses as a program terminator.) You can renumber the second program at this point to resolve line number conflicts between it and the first program if necessary. Finally, put back the original contents of $19-1A and you will find that the two programs have been merged. Basic programs are stored in memory in "tokenized" form. (This is also true of program storage on tape or disk, unless Ascii format has been specified.) Each Basic keyword is abbreviated as a one-byte token, with the exception of functions, which are represented as $FF followed by a second byte. Characters that are not part of tokenized keywords are stored as Ascii values. At the beginning of each line is a two-byte pointer to the address where the next line starts, followed by two bytes containing the hex equivalent of the line number. Each line is terminated by a zero byte. The end of the program is marked by two extra zero bytes that follow the last line's zero terminator. Try typing the NEW command while looking at the beginning of your Basic program in memory. Not much happened, did it? The only effect was to replace the first and second bytes of the program with two zeroes that constitute Basic's program terminator. If you look at page zero while typing NEW after a program has been loaded into memory, you will see that another effect of this command is to set each of the pointers at $1B-1C, $1D-1E, and $1F-20 to a value two greater than the start address contained in $19-1A, thus freeing up the memory formerly reserved for program, variable, and array storage. It is, incidentally, not difficult to reverse both of these effects of the NEW command in order to recover a program that has been accidentally NEWed out of memory. Another way a program can be recovered is to set the "start" pointer at $19-1A to the start of an inactive copy of the program left over from a previous use of the PCLEAR command. (You should also set the "end" pointer at $1B-1C to somewhere at or beyond the actual end of the program, to avoid the possibility of your program being overwritten by newly created variable table entries. The other two pointers will adjust themselves when you type RUN.) It is also possible to have two or more Basic programs in different parts of memory and switch between them by moving the "start" and "end" pointers. You may find it of interest to take a slow motion look at various program editing operations such as line insertion and deletion. A particularly interesting command to look at is RENUM. You will see that the program first expands and then contracts as renumbering proceeds. Using the slow motion option, you can verify that renumbering involves successively expanding each line that contains a line number reference in order to make room for the possibility that the replacement line number will be five digits long. (Although a line's own number is represented by a two-byte hex equivalent, line number references within a line are stored as Ascii codes for individual digits.) Each time a line is expanded, the entire part of the program following that line is pushed upwards to make room for the extra bytes. When all necessary lines have been expanded, the replacement line numbers are inserted. Finally, the lines are contracted one by one to squeeze out unnecessary space previously inserted if the new line numbers are less than five digits in length. As with expansion, each time a line is contracted, the entire part of the program following that line is moved correspondingly. Is it any wonder that renumbering can take quite a few seconds when the program is a long one containing lots of embedded line number references? Now, lets look at numerical variable and array storage. Turn the computer off and back on to clear memory, and then reload and execute Peeper. Type in the following one-line program: ^k* 10 XX = 3: YY = 5 Locate this program in memory and type (blindly) RUN. A variable table containing entries for XX and YY will appear following the program. Following each variable name is the variable's current value, expressed as a five-byte floating-point quantity consisting of a one-byte exponent followed by a four-byte mantissa. Typing XX = 5 will change the bytes following XX to agree with those following YY. If you type in some random letters and a carriage return, notice that the result is not simply a syntax error message, but also the creation of a variable whose name consists of the first two letters that you have typed. Each variable created takes up seven bytes of available memory: two for the name and five for the value. Extended Basic's VARPTR function can be used to locate a particular variable in the variable table: PRINT HEX$(VARPTR(XX)) will display the hexadecimal address of the first of the five bytes used to store the current value of variable XX. Whenever RUN is typed, Basic reinitializes the existing variable and array areas by setting the pointers at $1D-1E and $1F-20 equal to the $1B-1C "end" pointer value, thus freeing the area previously reserved for variables and arrays. (You can resurrect your old variable values following such an initialization by moving the $1D-1E pointer up to or beyond its former location.) Reinitialization also occurs if any program changes are made or if a CLEAR or PCLEAR statement is executed. It is a useful fact that variable and array reinitialization can be avoided (provided no program changes have been made) if a program is re-executed by means of a GOTO statement entered from direct mode, rather than by a RUN staement. This capability provides a method for recovering from many types of errors encountered during execution without having to restart your program from the beginning. It is also possible to test a particular portion of a program by setting various variables to trial values in direct mode and then executing a direct-mode GOTO to enter the program at the desired point. To see how numerical arrays are stored, type DIM ZZ(2,1) to create an entry in the array storage area that follows the area for ordinary variable storage. This DIM statement creates a six-element array, since subscripts can take on the value of zero. The array area should now contain an array descriptor block, to be described, followed by six 5-byte values that are initialized to zero. Array elements are ordered with the first subscript varying fastest: (0,0), (1,0), (2,0), (0,1), (1,1), (2,1). If an array element is referenced without having been previously declared in a DIM statement, the effect is the same as if the array had been dimensioned with a value of 10 for each subscript. The array descriptor block that is created by the statement DIM ZZ(2,1) begins with two bytes containing Ascii values corresponding to the variable name ZZ, after which are the following seven bytes: 0, $27, 2, 0, 2, 0, 3. The first two of these bytes represent the total number of bytes taken up by the array: $0027, or 39 bytes. The length of 39 bytes is arrived at by adding the nine bytes that make up the descriptor block for a two-dimensional array to the 30 bytes taken up by six five-byte array elements. The byte following the length specifier gives the number of dimensions in the array (two, in this case). This "number of dimensions" byte is followed by two double bytes ($0002 and $0003) that are derived from the subscript values in the DIM statement by adding one to each (on account of the zero subscript) and reversing the order of the values. Now let's consider string variables. Type AB$ = "HELLO". A new entry should appear in the variable table. As with numeric variables, this entry consists of two bytes for the varible name plus an additional five bytes. The "B" in the name "AB" will appear as a graphics character because Basic adds $80 to the second byte of the name to signify that the variable type is string rather than numeric. The first byte of the five-byte string descriptor that follows the variable name contains the length of the string; since only one byte is allotted for this purpose, strings cannot exceed 255 characters in length. The third and fourth bytes contain a pointer to the first character of the string. If you use the screen code table presented on page 4 to read this pointer (or do so by using examine mode), you will find that it references an address near the top of available RAM, where you will find the string "HELLO". Bytes 2 and 5 of the five-byte string descriptor appear to be unused by Basic. String arrays are represented in the same way as numeric arrays, except that each five-byte array element is a string descriptor instead of a numeric value. Finally, let us take a look at what is happening near the top of RAM. For this purpose, it may be desirable to again turn the machine off and on to clear memory and reload Peeper. However, before typing EXEC this time, poke a zero into location $1000 to disable Peeper's relocation feature. This will cause the top of RAM to be left in its "natural" state instead of being used to accommodate Peeper. In the absence of an explicit CLEAR statement, Basic reserves the top 200 bytes of RAM for the storage of strings. Look at the page containing addresses $3E00-3FFF if you have a 16K machine, or $7E00-7FFF in a 32K machine. It is easy to see where the reserved string area starts, because it is right above a rather busy 30 or 40 bytes that constitute the "stack", which is used for various kinds of temporary storage by machine-language routines. (For example, whenever a machine-language subroutine is called, the address to which control will return when the subroutine is exited is "pushed" onto the stack, causing it to grow downward by two bytes. When the subroutine is exited by the execution of a machine-language "return" instruction, these two bytes are "pulled" off of the stack, which recedes upward.) If you type CLEAR 300, you will cause the string storage area to expand to 300 bytes; Basic moves the stack down 100 bytes to make room for the additional string storage. Conversely, typing CLEAR 100 will cause the stack to move upward to within 100 bytes of the end of available RAM. Now type CLEAR 50, &H3000. You will now find the stack and 50 bytes of string storage area residing immediately below address $3000. Addresses above $3000 are protected from Basic by this statement, allowing machine language programs in this region of memory to coexist safely with Basic programs that use a lower portion of memory. Looking at the string storage area, for which we have reserved 50 bytes, enter the statement A$ = "THIS IS A STRING". The string is placed at the top of the string storage area, in addition to an entry for A$ being created in the variable table as discussed previously. Now type B$ = "HERE IS ANOTHER STRING". This second string is placed immediately below the first, and we have almost exhausted our 50 allocated bytes. Enter C$ = "A THIRD STRING", and an OS error ("out of string space") results. Now type A$ = "X", replacing the previous longer value of A$ with a shorter one to make more room in the string buffer. Notice that the new value of A$ has been added to the string area, but that the old value is still there as well. Now try again to enter C$ = "A THIRD STRING". This time, C$ is successfully incorporated into the string buffer area, and the "obsolete" value of A$ is gone. This example illustrates the operation of a process colorfully known as "garbage collection". Whenever a new string cannot immediately be accommodated within the string storage area, Basic "housecleans" this buffer by packing at the top of the string area only those strings currently assigned to variables (that is, strings referenced by pointers in the variable and array storage areas). Any string storage bytes released by this process can be used to accommodate new strings. Not all strings, incidentally, are stored in the string storage area at the top of RAM. String constants appearing in Basic program lines, such as in assignment statements or in data statements, exist only in the program memory area and are referenced there by the pointers that are set up in the variable and array tables. ^k; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ^k; Copies of the assembly language source listing for the Peeper, in Edtasm+ format, are available to previous purchasers of the program at a cost of $4.00, including postage and handling. SpectroSystems 11111 N. Kendall Drive, Suite A108 Miami, Florida 33176 (305) 274-3899 CompuServe 72355,407 ^k; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ^k; ^kN ^kQ PEEPSUP/DOC Suite A108 Miami, Florida 33176 (305) 274-3899 џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџ