module "/pliant/language/context.pli"
module "/pliant/math/functions.pli"
module "/pliant/SDL/SDL.pli"


type MODE7_PARAMS
  field Float space_z
  field Int horizon
  field Float scale_x scale_y

function mode7 image texture angle cx cy params
 arg Pointer:SDL_Surface image texture
 arg Float angle cx cy
 arg MODE7_PARAMS params

 var Address image_p texture_p
 var Int screen_x screen_y
 var Float distance horizontal_scale
 var Int mask_x := texture:w - 1
 var Int mask_y := texture:h - 1
 var Int mx my offset
 var Float line_dx line_dy
 var Float space_x space_y

 image_p := image:pixels
 texture_p := texture:pixels

 for screen_y 0 (image:h-1) step 2

  distance := (params:space_z * params:scale_y) / (screen_y + params:horizon)
  horizontal_scale := distance / params:scale_x

  line_dx := -1 * (sin angle)* horizontal_scale
  line_dy := (cos angle) * horizontal_scale

  space_x := cx + (distance * (cos angle)) - ((image:w / 2) * line_dx)
  space_y := cy + (distance * (sin angle)) - ((image:h / 2) * line_dy)


  for screen_x 0 (image:w-1)
   mx := ((cast space_x Int)) .and. mask_x
   my := ((cast space_y Int)) .and. mask_y
   offset := my * texture:pitch + mx

   (image_p map uInt8) := (texture_p map uInt8 offset)
   image_p := (image_p translate uInt8 1)

   space_x += line_dx
   space_y += line_dy
  image_p := (image_p translate uInt8 image:pitch)
function main

 var Pointer:SDL_Surface screen texture
 var MODE7_PARAMS sp
 var Float angle offset_x offset_y
 var SDL_Event event
 var Int keydown := 0
 var Float turn := 0.0
 var Float altitude := 0.0

 sp:space_z := 512.0
 sp:horizon := 10
 sp:scale_x := 512.0
 sp:scale_y := 512.0

 if (SDL_Init SDL_INIT_VIDEO) < 0
  console "could not init video!" eol
  SDL_QUIT
  return

 screen :> SDL_SetVideoMode 640 480 8 0

 if not (exists screen)
  console "Could not open display." eol
  SDL_Quit
  return

 texture :> SDL_LoadBMP "astro_bright.bmp"

 if not (exists texture)
  console "Could not load astro.bmp" eol
  SDL_Quit
  return

 SDL_SetColors screen texture:format:palette:colors 0 texture:format:palette:ncolors

 angle := 0.0

 var CBool done := false

 while not done
  while (SDL_PollEvent:event > 0)
   if event:type = SDL_QUIT
    done := true
   eif event:type = SDL_KEYDOWN
    keydown := event:key:keysym:sym
   eif event:type = SDL_KEYUP
    keydown := 0

  if keydown = SDLK_LEFT
   turn += 0.05
  eif keydown = SDLK_RIGHT
   turn -= 0.05
  eif keydown = SDLK_UP and altitude < 400.0
   altitude += 4.0
   sp:horizon += 1
  eif keydown = SDLK_DOWN and altitude > 0.0
   altitude -= 4.0
   sp:horizon -= 1
  eif keydown = SDLK_ESCAPE
   done := true

  sp:space_z := 50 + altitude
  SDL_LockSurface screen
  (mode7 screen texture turn 50*angle (sin angle/4)*50.0 sp)
  SDL_UnlockSurface screen
  SDL_UpdateRect screen 0 0 0 0
  angle += 0.1
 SDL_FreeSurface texture
 SDL_Quit
 return

main