//-----------------------------------------------------------
// Shift Operations Demo
// Practical examples of << and >> operators
// Shows real-world uses for bit manipulation
//-----------------------------------------------------------

#INCLUDE <c64start.c65>
#INCLUDE <c64defs.c65>
#PRAGMA _P_REMOVE_UNUSED 1
#INCLUDE <cbmiolib.c65>

#PRAGMA _P_USE_CBM_STRINGS 1

GOTO start

// Variables for demos
BYTE demo_value
BYTE demo_result
BYTE demo_shift
WORD demo_word
WORD demo_word_result

//-----------------------------------------------------------
// Wait for key press
//-----------------------------------------------------------
FUNC wait_key
  BYTE key
  
  // Wait for no key
  WHILE 1
    key = PEEK $c5
    IF key = 64
      BREAK
    ENDIF
  WEND
  
  // Wait for key press
  WHILE 1
    key = PEEK $c5
    IF key != 64
      BREAK
    ENDIF
  WEND
  
  // Reset key buffer
  POKE $c6 WITH 0
  
FEND

//-----------------------------------------------------------
// Clear screen
//-----------------------------------------------------------
FUNC clear_screen
  lib_cbmio_cls()
  lib_cbmio_home()
FEND

//-----------------------------------------------------------
// Print binary representation of byte
//-----------------------------------------------------------
FUNC print_binary({BYTE val})
  BYTE i = 7
  BYTE mask
  BYTE bit
  
  lib_cbmio_print(" %")
  
  WHILE i < 8  // Will break when i wraps around to 255
    mask = 1 << i
    bit = val & mask
    IF bit != 0
      lib_cbmio_print("1")
    ELSE
      lib_cbmio_print("0")
    ENDIF
    
    // Add space every 4 bits for readability
    IF i = 4
      lib_cbmio_print(" ")
    ENDIF
    
    // Decrement i, break if we go below 0
    IF i = 0
      BREAK
    ENDIF
    i = i - 1
  WEND
FEND

//-----------------------------------------------------------
// Demo 1: Basic shift operations
//-----------------------------------------------------------
FUNC demo_basic_shifts
  lib_cbmio_printlf("basic shift operations")
  lib_cbmio_printlf("======================")
  lib_cbmio_printlf("")
  
  // Constant left shift
  demo_value = $03  // Binary: 00000011
  demo_result = demo_value << 2
  lib_cbmio_print("$03 << 2 = $")
  lib_cbmio_hexoutb(demo_result)
  print_binary(demo_result)
  lib_cbmio_printlf(" (3 * 4 = 12)")
  lib_cbmio_printlf("")
  
  // Constant right shift  
  demo_value = $30  // Binary: 00110000
  demo_result = demo_value >> 3
  lib_cbmio_print("$30 >> 3 = $")
  lib_cbmio_hexoutb(demo_result)
  print_binary(demo_result)
  lib_cbmio_printlf(" (48 / 8 = 6)")
  lib_cbmio_printlf("")
  
  // Variable shift amount
  demo_value = $80  // Binary: 10000000
  demo_shift = 3
  demo_result = demo_value >> demo_shift
  lib_cbmio_print("$80 >> ")
  lib_cbmio_hexoutb(demo_shift)
  lib_cbmio_print(" = $")
  lib_cbmio_hexoutb(demo_result)
  print_binary(demo_result)
  lib_cbmio_printlf("")
  lib_cbmio_printlf("")
  
  wait_key()
FEND

//-----------------------------------------------------------
// Demo 2: Bit manipulation
//-----------------------------------------------------------
FUNC demo_bit_manipulation
  lib_cbmio_printlf("bit manipulation")
  lib_cbmio_printlf("================")
  lib_cbmio_printlf("")
  
  // Extract color components from C64 color byte
  // C64 color: bits 7-4 = background, bits 3-0 = foreground
  BYTE color = $3E  // Background: 3, Foreground: E
  BYTE background
  BYTE foreground
  
  background = color >> 4
  foreground = color & $0F
  
  lib_cbmio_print("color byte: $")
  lib_cbmio_hexoutb(color)
  print_binary(color)
  lib_cbmio_printlf("")
  lib_cbmio_print("background: $")
  lib_cbmio_hexoutb(background)
  lib_cbmio_printlf(" (>> 4)")
  lib_cbmio_print("foreground: $")
  lib_cbmio_hexoutb(foreground)
  lib_cbmio_printlf(" (& $0f)")
  lib_cbmio_printlf("")
  
  // Create bit masks
  lib_cbmio_printlf("bit masks:")
  BYTE mask
  
  mask = 1 << 0
  lib_cbmio_print("1 << 0 = $")
  lib_cbmio_hexoutb(mask)
  lib_cbmio_print(" (bit 0)")
  lib_cbmio_printlf("")
  
  mask = 1 << 7
  lib_cbmio_print("1 << 7 = $")
  lib_cbmio_hexoutb(mask)
  lib_cbmio_print(" (bit 7)")
  lib_cbmio_printlf("")
  
  mask = 1 | 2  // Bits 0 and 1
  lib_cbmio_print("bits 0+1 = $")
  lib_cbmio_hexoutb(mask)
  print_binary(mask)
  lib_cbmio_printlf("")
  lib_cbmio_printlf("")
  
  wait_key()
FEND

//-----------------------------------------------------------
// Demo 3: Multiplication and division
//-----------------------------------------------------------
FUNC demo_multiply_divide
  lib_cbmio_printlf("fast multiply/divide")
  lib_cbmio_printlf("====================")
  lib_cbmio_printlf("")
  
  // Multiplication by powers of 2
  BYTE value = 7
  
  lib_cbmio_print("7 * 2 = ")
  demo_result = value << 1
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_printlf(" (7 << 1)")
  
  lib_cbmio_print("7 * 4 = ")
  demo_result = value << 2
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_printlf(" (7 << 2)")
  
  lib_cbmio_print("7 * 8 = ")
  demo_result = value << 3
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_printlf(" (7 << 3)")
  lib_cbmio_printlf("")
  
  // Division by powers of 2
  value = 100
  
  lib_cbmio_print("100 / 2 = ")
  demo_result = value >> 1
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_printlf(" (100 >> 1)")
  
  lib_cbmio_print("100 / 4 = ")
  demo_result = value >> 2
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_printlf(" (100 >> 2)")
  
  lib_cbmio_print("100 / 8 = ")
  demo_result = value >> 3
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_printlf(" (100 >> 3)")
  lib_cbmio_printlf("")
  
  // Variable shift for scaling
  value = 5
  demo_shift = 3  // Multiply by 8
  
  lib_cbmio_print("5 * 8 = ")
  demo_result = value << demo_shift
  lib_cbmio_hexoutb(demo_result)
  lib_cbmio_print(" (5 << ")
  lib_cbmio_hexoutb(demo_shift)
  lib_cbmio_printlf(")")
  lib_cbmio_printlf("")
  
  wait_key()
FEND

//-----------------------------------------------------------
// Demo 4: Word operations
//-----------------------------------------------------------
FUNC demo_word_operations
  lib_cbmio_printlf("16-bit word operations")
  lib_cbmio_printlf("======================")
  lib_cbmio_printlf("")
  
  // Word left shift (multiply by 2)
  demo_word = $1234
  demo_word_result = demo_word << 1
  
  lib_cbmio_print("$1234 << 1 = $")
  lib_cbmio_hexoutw(demo_word_result)
  lib_cbmio_printlf(" ($1234 * 2 = $2468)")
  lib_cbmio_printlf("")
  
  // Word right shift (divide by 2)
  demo_word = $ABCD
  demo_word_result = demo_word >> 1
  
  lib_cbmio_print("$abcd >> 1 = $")
  lib_cbmio_hexoutw(demo_word_result)
  lib_cbmio_printlf(" ($abcd / 2 = $55e6)")
  lib_cbmio_printlf("")
  
  // Shift between bytes
  demo_word = $00FF
  demo_word_result = demo_word << 8
  
  lib_cbmio_print("$00ff << 8 = $")
  lib_cbmio_hexoutw(demo_word_result)
  lib_cbmio_printlf(" (low->high byte)")
  
  demo_word = $FF00
  demo_word_result = demo_word >> 8
  
  lib_cbmio_print("$ff00 >> 8 = $")
  lib_cbmio_hexoutw(demo_word_result)
  lib_cbmio_printlf(" (high->low byte)")
  lib_cbmio_printlf("")
  
  // Byte to word conversion with shift
  BYTE small = $81
  WORD large
  
  large = small << 2  // Zero-extends byte to word, then shifts
  
  lib_cbmio_print("byte $81 << 2 = word $")
  lib_cbmio_hexoutw(large)
  lib_cbmio_printlf(" (zero-extended)")
  lib_cbmio_printlf("")
  
  wait_key()
FEND

//-----------------------------------------------------------
// Demo 5: Practical C64 example
//-----------------------------------------------------------
FUNC demo_c64_example
  lib_cbmio_printlf("c64 practical example")
  lib_cbmio_printlf("=====================")
  lib_cbmio_printlf("")
  
  // Simulate reading joystick port 2
  // Bits: 0=up, 1=down, 2=left, 3=right, 4=fire
  BYTE joystick = $17  // Binary: 00010111 (up, down, right, fire)
  
  lib_cbmio_print("joystick port: $")
  lib_cbmio_hexoutb(joystick)
  print_binary(joystick)
  lib_cbmio_printlf("")
  lib_cbmio_printlf("")
  
  // Check individual buttons using shifts
  lib_cbmio_printlf("checking buttons:")
  lib_cbmio_printlf("")
  
  // Fire button (bit 4)
  BYTE fire_mask
  BYTE fire_check
  fire_mask = 1 << 4
  fire_check = joystick & fire_mask
  IF fire_check = 0
    lib_cbmio_printlf("fire: pressed")
  ELSE
    lib_cbmio_printlf("fire: not pressed")
  ENDIF
  
  // Up button (bit 0)
  BYTE up_mask
  BYTE up_check
  up_mask = 1 << 0
  up_check = joystick & up_mask
  IF up_check = 0
    lib_cbmio_printlf("up: pressed")
  ELSE
    lib_cbmio_printlf("up: not pressed")
  ENDIF
  
  // Right button (bit 3)
  BYTE right_mask
  BYTE right_check
  right_mask = 1 << 3
  right_check = joystick & right_mask
  IF right_check = 0
    lib_cbmio_printlf("right: pressed")
  ELSE
    lib_cbmio_printlf("right: not pressed")
  ENDIF
  lib_cbmio_printlf("")
  
  // Extract direction bits to nibble
  BYTE direction
  direction = joystick & $0F  // Mask off fire button
  
  lib_cbmio_print("direction bits: $")
  lib_cbmio_hexoutb(direction)
  print_binary(direction)
  lib_cbmio_printlf("")
  lib_cbmio_printlf("")
  
  wait_key()
FEND

//-----------------------------------------------------------
// Main program
//-----------------------------------------------------------
LABEL start
clear_screen()

lib_cbmio_printlf("shift operators demo")
lib_cbmio_printlf("====================")
lib_cbmio_printlf("")
lib_cbmio_printlf("press any key...")
lib_cbmio_printlf("")
wait_key()

demo_basic_shifts()
clear_screen()

demo_bit_manipulation()
clear_screen()

demo_multiply_divide()
clear_screen()

demo_word_operations()
clear_screen()

demo_c64_example()
clear_screen()

lib_cbmio_printlf("demo complete!")
lib_cbmio_printlf("")
lib_cbmio_printlf("shift operators:")
lib_cbmio_printlf("  <<  left shift (multiply)")
lib_cbmio_printlf("  >> right shift (divide)")
lib_cbmio_printlf("")
lib_cbmio_printlf("works with bytes and words")
lib_cbmio_printlf("")

// Infinite loop
LABEL loop
GOTO loop