#pragma once

#ifndef _VECTREX_H_
#define _VECTREX_H_ 1
#include <stdint.h>

extern void set_scale(uint8_t scale);

#ifdef _VECTREX_C_
// If this header file is included in vectrex.c then actually create the space for the variables:
#define vDECLARE
#else
// otherwise just create an external reference to the declarations in vectrex.c ...
#define vDECLARE extern
#endif

// We're not going as far as actual 6809 emulation, but some global variables should be
// simulated just to make coding for both systems a little easier.
vDECLARE int8_t Vec_Joy_1_X, Vec_Joy_1_Y, Vec_Joy_2_X, Vec_Joy_2_Y;
vDECLARE int8_t Vec_Joy_Mux_1_X, Vec_Joy_Mux_1_Y, Vec_Joy_Mux_2_X, Vec_Joy_Mux_2_Y;
vDECLARE uint8_t VIA_t1_cnt_lo;
vDECLARE uint8_t Vec_Btn_State, Vec_Buttons;
vDECLARE char Vec_Music_1[]
#ifdef _VECTREX_C_
  = {0}
#endif
;

// All of these procedures will need SDL versions that behave as similarly as possible,
// but we can add them as needed.  They don't all have to be written in advance.
extern void Wait_Recal(void);
extern void Set_Refresh(void); 
extern void Recalibrate(void); 
extern void Reset0Ref_D0(void); 
extern void Check0Ref(void); 
extern void Reset0Ref(void);
extern void Reset_Pen(void); 
extern void Reset0Int(void); 
extern void Dec_3_Counters(void); 
extern void Dec_6_Counters(void); 
extern void Dec_Counters(const uint8_t b, void *const x); 
extern void DP_to_D0(void); 
extern void DP_to_C8(void); 
extern void Delay_3(void); 
extern void Delay_2(void); 
extern void Delay_1(void); 
extern void Delay_0(void); 
extern void Delay_b(const uint8_t b); 
extern void Delay_RTS(void); 
extern void Dot_ix_b(const uint8_t b, void *const x); 
extern void Dot_ix(void *const x); 
extern void Dot_d(const int8_t a, const int8_t b); 
extern void Dot_dd(const int16_t d); 
extern void Dot_here(void); 
extern void Dot_List(void *const x); 
extern void Dot_List_Reset(void *const x); 
extern void Print_Str_hwyx(void *const u); 
extern void Print_Str_yx(volatile const void *const u); 
extern void Print_Str_d(const int8_t a, const int8_t b, void *const u); 
extern void Print_Str_dd(const int16_t d, void *const u); 
extern void Print_List_hw(void *const u); 
extern void Print_List(void *const u); 
extern void Print_List_chk(void *const u); 
extern void Print_Ships_x(const uint8_t a, const uint8_t b, void *const x); 
extern void Print_Ships(const uint8_t a, const uint8_t b, const uint16_t x); 
extern void Print_Str(void *const u); 
extern void Print_MRast(void); 
extern void Draw_Pat_VL_a(const uint8_t a, void *const x); 
extern void Draw_Pat_VL_aa(const uint8_t a, void *const x); 
extern void Draw_Pat_VL(void *const x); 
extern void Draw_Pat_VL_d(const uint16_t d, void *const x);

// I'm pretty sure that when I've used Draw_Line_d() it took 2 parameters,
// as in:  extern void Draw_Line_d(int8_t dy, int8_t dx);
// but the Draw_Line_d below came directly from a header file in Vide, so I
// need to look into why it doesn't match my recollection. I've temporarily
// changed my demo.c code to match, until I understand what's going on.
extern void Draw_Line_dab(const int8_t a, const int8_t b); 
extern void Draw_Line_d16(const int16_t d); 
#define Draw_Line_d(d) Draw_Line_d16(d)

extern void Draw_VLc(void *const x); 
extern void Draw_VL_ab(const uint8_t a, const uint8_t b, void *const x); 
extern void Draw_VL(void *const x); 
extern void Draw_VLcs(void *const x); 
extern void Draw_VL_b(const uint8_t b, void *const x); 
extern void Draw_VL_a(const uint8_t a, void *const x); 
extern void Mov_Draw_VLc_a(void *const x); 
extern void Mov_Draw_VL_b(const uint8_t b, void *const x); 
extern void Mov_Draw_VLcs(void *const x); 
extern void Mov_Draw_VL_ab(const uint8_t a, const uint8_t b, void *const x); 
extern void Mov_Draw_VL_a(const uint8_t a, void *const x); 
extern void Mov_Draw_VL(void *const x); 
extern void Mov_Draw_VL_d(const int8_t a, const int8_t b); 
extern void Draw_VL_mode(void *const x); 
extern void Draw_VLp_7F(void *const x); 
extern void Draw_VLp_FF(void *const x); 
extern void Draw_VLp_b(const uint8_t b, void *const x); 
//extern void Draw_VLp(void *const x);
extern void Draw_VLp_scale(void *const x); 
extern void Rot_VL_Mode(const uint8_t a, void *const x, volatile void *volatile const u); 
extern void Rot_VL_Pack(void *const x, void *const u); 
extern void Rot_VL_M_dft(void *const x, void *const u); 
extern void Draw_Grid_VL(void *const x, void *const y); // unofficial
extern uint8_t Random_3(void); 
extern uint8_t Random(void); // should this be signed or unsigned?
extern uint8_t Bitmask_a(const uint8_t a); 
extern uint16_t Abs_a_b(const int8_t a, const int8_t b); 
extern int8_t Abs_b(const int8_t b); 
extern uint16_t Rise_Run_Angle(const int8_t a, const int8_t b); 
extern uint16_t Get_Rise_Idx(const int8_t a); 
extern int8_t Xform_Sin(const int8_t a); 
extern uint16_t Get_Rise_Run(void); 
extern uint16_t Xform_Run_a(const int8_t a); 
extern uint16_t Xform_Run(void); 
extern uint16_t Xform_Rise_a(const int8_t a); 
extern uint16_t Xform_Rise(void); 
extern void Clear_x_b(const uint8_t b, void *const x); 
extern void Clear_C8_RAM(void); 
extern void Clear_x_256(void *const x); 
extern void Clear_x_d(const uint16_t d, void *const x); 
extern void Move_Mem_a_1(const uint8_t a, void *const x, void *const u); 
extern void Move_Mem_a(const uint8_t a, void *const x, void *const u); 
extern void Clear_x_b_80(const int8_t b, void *const x); 
extern void Clear_x_b_a(const uint8_t a, const uint8_t b, void *const x); 
extern void Read_Btns_Mask(const uint8_t a); 
extern void Read_Btns(void); 
extern void Joy_Analog(void);
extern void Joy_Digital(void); 
extern void Select_Game(const uint8_t a, const uint8_t b); 
extern void Display_Option(const uint8_t a, const void *const y); 
extern void Reset(void); 
extern void Init_VIA(void); 
extern void Init_OS_RAM(void); 
extern void Init_OS(void); 
extern void Init_Music_Buf(void); 
extern void Clear_Score(void *const x);
extern void Add_Score_a(const uint8_t a, void *const x); 
extern void Add_Score_d(const uint16_t d, void *const x); 
extern void Strip_Zeros(const uint8_t b, void *const x); 
extern uint8_t Compare_Score(void *const x, void *const u); 
extern void New_High_Score(void *const x, void *const u);
extern void Sound_Byte(const uint8_t a, const uint8_t b); 
extern void Sound_Byte_x(const uint8_t a, const uint8_t b, void *const x); 
extern void Clear_Sound(void); 
extern void Sound_Bytes(void *const u); 
extern void Sound_Bytes_x(void *const x, void *const u); 
extern void Do_Sound(void); 
extern void Do_Sound_x(void *const x); 
extern void Init_Music_chk(const void *const u); 
extern void Init_Music(void *const u); 
extern void Init_Music_a(void *const x, void *const u); 
extern void Init_Music_x(void *const u); 
extern void Stop_Sound(void); 
extern void Explosion_Snd(const void *const u); 
extern void Set_Amp(const uint8_t b); 
extern void Moveto_x_7F(void *const x); 
extern void Moveto_d_7F(const int8_t a, const int8_t b); 
extern void Moveto_dd_7F(const int16_t d); 
extern void Moveto_ix_FF(void *const x); 
extern void Moveto_ix_7F(void *const x); 
extern void Moveto_ix_b(const uint8_t b, void *const x); 
extern void Moveto_ix(void *const x); 
extern void Moveto_d(const int8_t dy, const int8_t dx);
extern void Moveto_dd(const int16_t d); 
extern void Intensity_1F(void); 
extern void Intensity_3F(void); 
extern void Intensity_5F(void); 
extern void Intensity_7F(void); 
extern void Intensity_a(const uint8_t a); 
extern uint8_t Obj_Will_Hit_u(const int8_t a, const int8_t b, const int16_t x, const int16_t y, const int16_t u); 
extern uint8_t Obj_Will_Hit(const int8_t a, const int8_t b, const int16_t x, const int16_t y, const int16_t *u); 
extern uint8_t Obj_Hit(const int8_t a, const int8_t b, const int16_t x, const int16_t y); 
extern uint16_t Rise_Run_X(const int8_t a, const int8_t b); 
extern uint16_t Rise_Run_Y(const int8_t a, const int8_t b); 
extern uint16_t Rise_Run_Len(const int8_t a); 
extern void Rot_VL_ab(const uint8_t a, const uint8_t b, void *const x, void *const u); 
extern void Rot_VL_Diff(const uint8_t b, void *const x, void *const u); 
extern void Rot_VL(void *const x, void *const u); 
extern void Dot_y(const int16_t y); 
extern void Dot_py(void *const y); 
extern void Draw_Pack(const uint8_t b, void *const x, const int16_t y); 
extern void Draw_Pack_py(const uint8_t b, void *const x, void *const y); 
extern void Print_Msg(void *const y, void *const u); 
extern uint8_t Rnd_Cone(void); 
extern uint16_t Displ8_xy(const uint8_t a, const uint8_t b); 
extern uint16_t Displ16_xy(const uint8_t a, const uint8_t b); 
extern uint16_t Ranpos(void); 
extern void Draw_Scores(void); 
extern void Draw_Score(void); 
extern void Wait_Bound(void); 

//extern void Intensity_a(uint8_t a);
//extern void Moveto_d(int8_t dy, int8_t dx);
////extern void Draw_VLp(int8_t *ra);
//extern void Read_Btns(void);
//extern uint8_t Random(void);
//extern void Wait_Recal(void);
//extern void Reset0Ref(void);
//extern void Intensity_7F(void);
//extern void Print_Str_d (const int8_t y, const int8_t x, void *const s /* const char *s */);

// These should really be in "controller.h" but I'm being lazy at the moment.  Will fix later.
extern void Joy_Digital(void);
extern void enable_controller_1_x(void);
extern void enable_controller_1_y(void);
extern void enable_controller_2_x(void);
extern void enable_controller_2_y(void);
extern void disable_controller_1_x(void);
extern void disable_controller_1_y(void);
extern void disable_controller_2_x(void);
extern void disable_controller_2_y(void);
extern void check_buttons(void);
extern uint8_t buttons_pressed(void);
extern uint8_t buttons_held(void);
extern uint8_t button_1_1_pressed(void);
extern uint8_t button_1_2_pressed(void);
extern uint8_t button_1_3_pressed(void);
extern uint8_t button_1_4_pressed(void);
extern uint8_t button_2_1_pressed(void);
extern uint8_t button_2_2_pressed(void);
extern uint8_t button_2_3_pressed(void);
extern uint8_t button_2_4_pressed(void);
extern uint8_t button_1_1_held(void);
extern uint8_t button_1_2_held(void);
extern uint8_t button_1_3_held(void);
extern uint8_t button_1_4_held(void);
extern uint8_t button_2_1_held(void);
extern uint8_t button_2_2_held(void);
extern uint8_t button_2_3_held(void);
extern uint8_t button_2_4_held(void);
extern void check_joysticks(void);
extern int8_t joystick_1_x(void);
extern int8_t joystick_1_y(void);
extern int8_t joystick_2_x(void);
extern int8_t joystick_2_y(void);
extern int8_t joystick_1_left(void);
extern int8_t joystick_1_right(void);
extern int8_t joystick_1_down(void);
extern int8_t joystick_1_up(void);
extern int8_t joystick_2_left(void);
extern int8_t joystick_2_right(void);
extern int8_t joystick_2_down(void);
extern int8_t joystick_2_up(void);


#ifndef _VECTREX_C_
// Do not execute the following if vectrex.h was included in vectrex.c:

#define main vectrex_main

// crude approximation to gcc6809's brain-dead and standard-breaking 8-bit int default
// (ISO/IEC 9899:1999 (E) section 5.2.4.2 - INT_MIN must be at least -32767 and INT_MAX
//  at least +32767, with UINT_MAX at least 65535U)

// No linux headers allowed after this point or this will seriously break them!

#define long short
#define short int8_t  // note that int8_t is not quite the same as 'signed char'
#define int int8_t

#endif // !_VECTREX_C_

#endif // _VECTREX_H_
