WOLFETTE - VBXE FX blitter demo with raycasting (Atari 8-bit + VBXE FX 1.27, llvm-mos)

FILES
  wolfette.xex    program (160 rays, full resolution 160x144)
  wolfette.c, tables.h, wolfette.ld, walls_asm.s, math_asm.s, gen_walls.py  - sources

CONTROLS
  Autopilot by default (the camera walks through waypoints and shoots at targets).
  Joystick 1: up/down - move, left/right - turn, FIRE - shoot.
  After 400 jiffies without input the autopilot returns. ESC - exit.
  The bottom line of the HUD shows "JOYSTICK: MOVE / TURN, FIRE = SHOOT".

WHAT IT SHOWS
  A 3D maze drawn by raycasting with textured walls, floor and ceiling, sprites (barrels,
  balls), a map and a crosshair.
  - Wall textures 64x64, made at start: most of them drawn by the blitter; the golden
    quilted panel (a grid of diamonds with grooves and bevels lit from the upper left,
    rivets in the centers, 2D grain) is computed by the CPU.
  - Framed wolf pictures hang in 8 places on the outer (brick) wall: a stylized wolf face
    from the front with fangs (wall type 5, texture $1A000: copy of the bricks + frame by
    the blitter + head of triangles drawn by the CPU).
  - A hit lights the whole 3D scene red (floor, ceiling, walls, sprites, map): one MODE 7
    BCB over the whole view through the AUX=3 table, strength 3-2-1 in consecutive frames;
    the lock state (LOCKED) is kept in the red frames.
  - HUD: "BLITTER LOAD 0.0%" - blitter working time / elapsed time, refreshed about every
    1.2 s. The end of the BCB list raises the Blitter-Done interrupt, the time is measured
    with the frame counter + VCOUNT (resolution 2 lines). The HUD labels are prerendered
    once to VRAM ($08000); a label change = 1 BCB copy.

BLITTER FUNCTIONS
  Raycasting (container %01: X/Y accumulators 8.8, 1 BCB = 1 wall column),
  64x64 textures drawn by the blitter (lines, bands, grain with MODE 2 + NOISE),
  MODE 7 (fog/shading through table TBL2, red flash TBL3),
  MODE 1 (transparency: sprites, map, crosshair), MODE 2 (add/saturate),
  ZOOM scaling, negative Y step (logo reflection), triple XDL buffering,
  BCB chains with jump (abs/rel), collisions (the crosshair locks on the balls),
  palette 1 through PSEL/CSEL, LR 160x144 + SR 320x48 Overlay (HUD),
  Blitter-Done interrupt (blitter load measurement).

REQUIREMENTS / MEMORY
  VBXE FX rev >= $27 (otherwise message and exit), MEMAC-A 4 KB window at $A000,
  code+data $2800-$9FFF. The font is taken from ROM $E000. Initialization takes a few seconds.
  ANTIC DMA is completely off (DMACTL = 0, changed only in VBLANK) from the start of the
  program until exit; at exit it is turned on again in VBLANK.
  The VBXE IRQ line must be connected for the BLITTER LOAD measurement to work;
  without it (or with a foreign IRQ) the HUD shows "--.-%", the demo works normally.
  After initialization the OS is off (ROM and interrupts); the program uses its own
  vectors, and RESET restores the OS.

BUILD
  python3 gen_walls.py > walls_asm.s
  mos-atari8-dos-clang -Oz -mlto-zp=48 -T wolfette.ld -o wolfette.xex wolfette.c walls_asm.s math_asm.s
