From 1b0d5ac319c20c18b9da7d46572379fe361217b4 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Mon, 9 Sep 2024 22:05:12 -0400 Subject: [PATCH 01/20] Start unification of QuakeGX --- source/cl_input.c | 101 ++++++++++++++++++++++++++++++++++++++------ source/cl_main.c | 29 ++++++++++--- source/cl_slist.c | 6 +++ source/cl_tent.c | 5 +-- source/ctr/client.h | 1 - 5 files changed, 118 insertions(+), 24 deletions(-) diff --git a/source/cl_input.c b/source/cl_input.c index 9acc78e..5a6c12f 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -45,7 +45,10 @@ state bit 2 is edge triggered on the down to up transition =============================================================================== */ - +#ifdef __WII__ +kbutton_t in_vlock; +extern float scr_usetime_off; +#endif kbutton_t in_klook;//Heffo - mlook cvar kbutton_t in_left, in_right, in_forward, in_back; kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; @@ -119,14 +122,16 @@ qboolean croshhairmoving = false; void IN_KLookDown (void) {KeyDown(&in_klook);} void IN_KLookUp (void) {KeyUp(&in_klook);} - +#ifdef __WII__ +void IN_VLockDown (void) {KeyDown(&in_vlock);} +void IN_VLockUp (void) {KeyUp(&in_vlock);} +#endif /*void IN_MLookDown (void) {KeyDown(&in_mlook);} void IN_MLookUp (void){ KeyUp(&in_mlook); if ( !(in_mlook.state&1) && lookspring.value) V_StartPitchDrift(); } Heffo - mlook cvar*/ - void IN_UpDown(void) {KeyDown(&in_up);} void IN_UpUp(void) {KeyUp(&in_up);} void IN_DownDown(void) {KeyDown(&in_down);} @@ -160,8 +165,34 @@ void IN_StrafeUp(void) {KeyUp(&in_strafe);} void IN_AttackDown(void) {KeyDown(&in_attack);} void IN_AttackUp(void) {KeyUp(&in_attack);} -void IN_UseDown (void) {KeyDown(&in_use);} -void IN_UseUp (void) {KeyUp(&in_use);} +void IN_UseDown (void) { + KeyDown(&in_use); + +#ifdef __WII__ + // + // sB this is all hacked in for now. + // the real concern is that there are now + // 3 binds all hardcoded to '+ use' + // this is not ideal for a number of reasons :/ + // + if (scr_usetime_off <= 0) { + KeyDown(&in_vlock); + } + // if moving HACK + if (croshhairmoving == 1) { + if (cl.stats[STAT_ZOOM] != 1 && cl.stats[STAT_ZOOM] != 2) { + KeyUp(&in_vlock); + Cbuf_AddText("impulse 23\n"); // sprinting impulse - "impulse 23" + } + } +#endif +} +void IN_UseUp (void) { + KeyUp(&in_use); +#ifdef __WII__ + KeyUp(&in_vlock); +#endif +} void IN_JumpDown (void) {KeyDown(&in_jump);} void IN_JumpUp (void) {KeyUp(&in_jump);} void IN_GrenadeDown (void) {KeyDown(&in_grenade);} @@ -251,6 +282,10 @@ cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5"}; cvar_t in_mlook = {"in_mlook", "1", true}; //Heffo - mlook cvar cvar_t in_aimassist = {"in_aimassist", "1", true}; +#ifdef __WII__ +cvar_t ads_center = {"ads_center", "0", true}; +cvar_t sniper_center = {"sniper_center", "0", true}; +#endif //Shpuld - Porting over lower sens for lower fov extern cvar_t scr_fov; @@ -298,10 +333,13 @@ void CL_AdjustAngles (void) #ifdef __PSP__ cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right) * in_sensitivity.value; cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left) * in_sensitivity.value; -#else +#elif _3DS cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right) * sensitivity.value; cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left) * sensitivity.value; -#endif // __PSP__ +#else + cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right); + cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left); +#endif cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); } if (in_klook.state & 1) @@ -314,9 +352,12 @@ void CL_AdjustAngles (void) #ifdef __PSP__ up = CL_KeyState (&in_lookup) * in_sensitivity.value; down = CL_KeyState(&in_lookdown) * in_sensitivity.value; -#else +#elif _3DS up = CL_KeyState (&in_lookup) * sensitivity.value; down = CL_KeyState(&in_lookdown) * sensitivity.value; +#else + up = CL_KeyState (&in_lookup); + down = CL_KeyState(&in_lookdown); #endif // __PSP__ cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up; @@ -454,6 +495,9 @@ int EN_Find(int num,char *string) return 0; } +#ifdef __WII__ +qboolean aimsnap = false; +#endif void CL_Aim_Snap(void) { edict_t *z,*bz,*player; @@ -524,8 +568,13 @@ void CL_Aim_Snap(void) if(distVec[0] < -70 || distVec[0] > 80) return; - +#ifdef __WII__ + aimsnap = true; +#endif VectorCopy(distVec,cl.viewangles); +#ifdef __WII__ + aimsnap = false; +#endif } } @@ -538,9 +587,11 @@ CL_SendMove int zoom_snap; float angledelta(float a); float deltaPitch,deltaYaw; +#ifdef __WII__ +extern cvar_t cl_crossx, cl_crossy; +#endif void CL_SendMove (usercmd_t *cmd) { - int i; long int bits; sizebuf_t buf; byte data[128]; @@ -561,8 +612,12 @@ void CL_SendMove (usercmd_t *cmd) zoom_snap = 1; } } - else + else { zoom_snap = 0; +#ifdef __WII__ + aimsnap = false; +#endif + } //==== Sniper Scope Swaying ==== if(cl.stats[STAT_ZOOM] == 2 && !(cl.perks & 64)) @@ -599,8 +654,26 @@ void CL_SendMove (usercmd_t *cmd) MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times VectorAdd(cl.gun_kick, cl.viewangles, tempv); +#ifdef __WII__ + float xcrossnormal, ycrossnormal; + xcrossnormal = (cl_crossx.value / (vid.width/2)) * IR_YAWRANGE; + ycrossnormal = (cl_crossy.value / (vid.height/2)) * IR_PITCHRANGE; + + // sB lock crosshair in the center of screen + if(aimsnap == true || (cl.stats[STAT_ZOOM] == 1 && ads_center.value) || sniper_center.value) { + MSG_WriteAngle (&buf, tempv[PITCH]/* + (cl_crossy.value/vid.height) * IR_PITCHRANGE*/); + MSG_WriteAngle (&buf, tempv[YAW]/* - (cl_crossx.value/vid.width - 1) * IR_YAWRANGE*/); + MSG_WriteAngle (&buf, tempv[ROLL]); + } else { + //sBTODO figure out how to make this way more accurate than it is + MSG_WriteAngle (&buf, tempv[PITCH] + ycrossnormal); + MSG_WriteAngle (&buf, tempv[YAW] - xcrossnormal); + MSG_WriteAngle (&buf, tempv[ROLL]); + } +#else for (i=0 ; i<3 ; i++) MSG_WriteFloat (&buf, tempv[i]); +#endif MSG_WriteShort (&buf, cmd->forwardmove); MSG_WriteShort (&buf, cmd->sidemove); @@ -718,8 +791,10 @@ void CL_InitInput (void) Cmd_AddCommand ("impulse", IN_Impulse); Cmd_AddCommand ("+klook", IN_KLookDown); Cmd_AddCommand ("-klook", IN_KLookUp); - - +#ifdef __WII__ + Cmd_AddCommand ("+vlock", IN_VLockDown); + Cmd_AddCommand ("-vlock", IN_VLockUp); +#endif } diff --git a/source/cl_main.c b/source/cl_main.c index 4d565b2..062170e 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -38,8 +38,10 @@ cvar_t lookspring = {"lookspring","0", true}; cvar_t lookstrafe = {"lookstrafe","0", true}; #ifdef __PSP__ cvar_t in_sensitivity = {"sensitivity","3", true}; -#else +#elif _3DS cvar_t sensitivity = {"sensitivity","8", true}; +#else +cvar_t sensitivity = {"sensitivity","3", true}; #endif // __PSP__ cvar_t in_tolerance = {"tolerance","0.25", true}; cvar_t in_acceleration = {"acceleration","1.0", true}; @@ -750,13 +752,13 @@ void CL_RelinkEntities (void) AngleVectors (tempangles, v_forward, v_right, v_up); VectorCopy (cl_entities[cl.viewentity].origin, smokeorg); - smokeorg[2] += 32; + smokeorg[2] += cl.viewheight; // account for beta maps VectorCopy(smokeorg,start); right_offset = sv_player->v.Flash_Offset[0]; up_offset = sv_player->v.Flash_Offset[1]; forward_offset = sv_player->v.Flash_Offset[2]; - + right_offset = right_offset/1000; up_offset = up_offset/1000; forward_offset = forward_offset/1000; @@ -765,7 +767,6 @@ void CL_RelinkEntities (void) VectorMA (smokeorg, up_offset, v_up ,smokeorg); VectorMA (smokeorg, right_offset, v_right ,smokeorg); VectorAdd(smokeorg,CWeaponOffset,smokeorg); - QMB_MuzzleFlash (smokeorg); } @@ -872,7 +873,11 @@ void CL_RelinkEntities (void) if (ent->effects & EF_RAYGREEN) { +#ifdef __WII__ + QMB_RocketTrail(oldorg, ent->origin, RAYGREEN_TRAIL); +#else R_RocketTrail (oldorg, ent->origin, 12); +#endif dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = 25; @@ -880,12 +885,17 @@ void CL_RelinkEntities (void) dl->color[0] = 0; dl->color[1] = 255; dl->color[2] = 0; - dl->type = SetDlightColor (2, lt_rocket, true); + //DLight color 4 is green + dl->type = SetDlightColor (4, lt_rocket, true); } if (ent->effects & EF_RAYRED) { +#ifdef __WII__ + QMB_RocketTrail(oldorg, ent->origin, RAYRED_TRAIL); +#else R_RocketTrail (oldorg, ent->origin, 13); +#endif dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = 25; @@ -893,7 +903,8 @@ void CL_RelinkEntities (void) dl->color[0] = 255; dl->color[1] = 0; dl->color[2] = 0; - dl->type = SetDlightColor (2, lt_rocket, true); + //DLight color 1 is red + dl->type = SetDlightColor (1, lt_rocket, true); } if (!strcmp(ent->model->name, "progs/flame2.mdl")) @@ -1116,7 +1127,11 @@ void CL_Init (void) Cvar_RegisterVariable (&in_analog_strafe); Cvar_RegisterVariable (&in_x_axis_adjust); Cvar_RegisterVariable (&in_y_axis_adjust); - + +#ifdef __WII__ + Cvar_RegisterVariable (&ads_center); + Cvar_RegisterVariable (&sniper_center); +#endif Cvar_RegisterVariable (&m_pitch); Cvar_RegisterVariable (&m_yaw); diff --git a/source/cl_slist.c b/source/cl_slist.c index ccbfa3b..b140401 100644 --- a/source/cl_slist.c +++ b/source/cl_slist.c @@ -124,9 +124,15 @@ void SList_Switch (int a, int b) if (b >= MAX_SERVER_LIST || b < 0) Sys_Error ("SList_Switch: Bad index %d", b); +#ifdef __PSP__ memcpy_vfpu(&temp, &slist[a], sizeof(temp)); memcpy_vfpu(&slist[a], &slist[b], sizeof(temp)); memcpy_vfpu(&slist[b], &temp, sizeof(temp)); +#else + memcpy(&temp, &slist[a], sizeof(temp)); + memcpy(&slist[a], &slist[b], sizeof(temp)); + memcpy(&slist[b], &temp, sizeof(temp)); +#endif } int SList_Length (void) diff --git a/source/cl_tent.c b/source/cl_tent.c index 266bb5e..1daddd6 100644 --- a/source/cl_tent.c +++ b/source/cl_tent.c @@ -409,12 +409,11 @@ void CL_UpdateTEnts (void) if (!b->model || b->endtime < cl.time) continue; -#ifdef __PSP__ // if coming from the player, update the start position if (b->entity == cl.viewentity) { VectorCopy (cl_entities[cl.viewentity].origin, b->start); - +#ifdef __PSP__ b->start[2] += cl.crouch + bound(-7, scr_ofsy.value, 4); b->start[2] += bound(0, cl_lightning_zadjust.value, 20);//progs.dat aims from 20 for traceline @@ -458,9 +457,9 @@ void CL_UpdateTEnts (void) if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, org, b->end, &trace)) VectorCopy(trace.endpos, b->end); } - } #endif // __PSP__ + } // calculate pitch and yaw VectorSubtract (b->end, b->start, dist); diff --git a/source/ctr/client.h b/source/ctr/client.h index da9875a..7b74af3 100644 --- a/source/ctr/client.h +++ b/source/ctr/client.h @@ -254,7 +254,6 @@ typedef struct // cvars // extern cvar_t cl_name; -extern cvar_t cl_color; extern cvar_t cl_upspeed; extern float cl_forwardspeed; From 84922d57cd950aa86bde03fe6a85d9d39e3f7090 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Mon, 9 Sep 2024 22:18:03 -0400 Subject: [PATCH 02/20] silence warning --- source/cl_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/cl_parse.c b/source/cl_parse.c index 0a533e4..8c7da2e 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -274,7 +274,7 @@ int has_perk_deadshot; int has_perk_mulekick; void CL_ParseServerInfo (void) { - char *str, tempname[MAX_QPATH];; + char *str; int i; int nummodels, numsounds; char model_precache[MAX_MODELS][MAX_QPATH]; From 8974ed4f8a5228f7b94c05ec1ccbf274c0195ea5 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Tue, 10 Sep 2024 21:45:56 -0400 Subject: [PATCH 03/20] Unify draw header --- source/draw.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/draw.h b/source/draw.h index 9a0d562..fa7b0bd 100644 --- a/source/draw.h +++ b/source/draw.h @@ -40,7 +40,10 @@ void Draw_ConsoleBackground (int lines); void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha); void Draw_Fill (int x, int y, int w, int h, int c); void Draw_LoadingFill(void); -#endif // __PSP__ +#elif __WII__ +void Draw_TileClear (int x, int y, int w, int h); +void Draw_Fill (int x, int y, int w, int h, float r, float g, float b, float a); +#endif void Draw_FillByColor (int x, int y, int w, int h, int r, int g, int b, int a); void Draw_FadeScreen (void); void Draw_String (int x, int y, char *str); @@ -61,4 +64,6 @@ extern int font_kerningamount[96]; qpic_t *Draw_CachePic (char *path); #ifdef __PSP__ qpic_t *Draw_CacheImg (char *path); -#endif // __PSP__ \ No newline at end of file +#elif __WII__ +qpic_t *Draw_LMP (char *path); +#endif \ No newline at end of file From a93bd161d818ccc77b55ad9605efd172132d5cf2 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Wed, 11 Sep 2024 22:01:44 -0400 Subject: [PATCH 04/20] Add mathlib and pr_cmds to unified list --- source/mathlib.h | 5 +++++ source/pr_cmds.c | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/source/mathlib.h b/source/mathlib.h index bf4c621..b360847 100644 --- a/source/mathlib.h +++ b/source/mathlib.h @@ -39,6 +39,11 @@ typedef int fixed16_t; #define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h #endif +#ifdef __WII__ +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + #define RAD2DEG( x ) ((float)(x) * (float)(180.f / M_PI)) #define DEG2RAD( x ) ((float)(x) * (float)(M_PI / 180.f)) diff --git a/source/pr_cmds.c b/source/pr_cmds.c index 738ed68..f2a1b6a 100644 --- a/source/pr_cmds.c +++ b/source/pr_cmds.c @@ -22,7 +22,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef _3DS extern bool new3ds_flag; -#endif // _3DS +#elif __WII__ +#include +#include +#include +extern double time_wpad_off; +extern int rumble_on; +extern cvar_t rumble; +#endif // _3DS, __WII__ #define PR_MAX_TEMPSTRING 2048 // 2001-10-25 Enhanced temp string handling by Maddes #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) @@ -1475,9 +1482,11 @@ This is where the magic happens #ifdef __PSP__ #define MaxZombies 12 -#else +#elif _3DS #define MaxZombies 18 -#endif +#elif __WII__ +#define MaxZombies 24 +#endif //__PSP__, _3DS, __WII__ #define WAYPOINT_SET_NONE 0 @@ -3479,6 +3488,7 @@ nzp_rumble() */ void PF_Rumble(void) { +#ifndef __WII__ client_t *client; int entnum; int low_frequency; @@ -3498,6 +3508,23 @@ void PF_Rumble(void) MSG_WriteShort (&client->message, low_frequency); MSG_WriteShort (&client->message, high_frequency); MSG_WriteShort (&client->message, duration); +#else + client_t *client; + int entnum; + + entnum = G_EDICTNUM(OFS_PARM0); + if (entnum < 1 || entnum > svs.maxclients) + return; + + if (!rumble.value) return; + double rumble_time; + rumble_time = G_FLOAT(OFS_PARM3) / 1000.0; + + //it switches rumble on for rumble_time milliseconds + WPAD_Rumble(0, true); + rumble_on=1; + time_wpad_off = Sys_FloatTime() + rumble_time; +#endif } /* @@ -3566,14 +3593,14 @@ nzp_maxai() */ void PF_MaxZombies(void) { -#ifdef __PSP__ - G_FLOAT(OFS_RETURN) = MaxZombies; -#else +#ifdef _3DS if (new3ds_flag) G_FLOAT(OFS_RETURN) = MaxZombies; else G_FLOAT(OFS_RETURN) = 12; -#endif // __PSP__ +#else + G_FLOAT(OFS_RETURN) = MaxZombies; +#endif } /* From ecbafc7d9d69470bfe29c78301f8ed998fc75eb1 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sat, 14 Sep 2024 18:49:59 -0400 Subject: [PATCH 05/20] add view and wad to unified files --- source/view.c | 188 +++++++++++++++++++++----------------------------- source/wad.c | 6 +- 2 files changed, 82 insertions(+), 112 deletions(-) diff --git a/source/view.c b/source/view.c index 2b4604c..c945477 100644 --- a/source/view.c +++ b/source/view.c @@ -56,6 +56,11 @@ cvar_t cl_bobside = {"cl_bobside","0.02"}; cvar_t cl_bobsidecycle = {"cl_bobsidecycle","0.9"}; cvar_t cl_bobsideup = {"cl_bobsideup","0.5"}; +#ifdef __WII__ +cvar_t cl_crossx = {"cl_crossx", "0", false}; +cvar_t cl_crossy = {"cl_crossy", "0", false}; +#endif + cvar_t v_kicktime = {"v_kicktime", "0.5", false}; cvar_t v_kickroll = {"v_kickroll", "0.6", false}; cvar_t v_kickpitch = {"v_kickpitch", "0.6", false}; @@ -721,6 +726,12 @@ CalcGunAngle static float OldYawTheta; static float OldPitchTheta; +#ifdef __WII__ +int lock_viewmodel; +extern float centerdrift_offset_yaw; +extern float centerdrift_offset_pitch; +extern qboolean aimsnap; +#endif static vec3_t cADSOfs; @@ -781,6 +792,7 @@ void CalcGunAngle (void) side = V_CalcRoll (cl_entities[cl.viewentity].angles, cl.velocity); cl.viewent.angles[ROLL] = angledelta(cl.viewent.angles[ROLL] - ((cl.viewent.angles[ROLL] - (side * 5)) * 0.5)); +#ifndef __WII__ //^^^ Model swaying if(cl.stats[STAT_ZOOM] == 1) { @@ -794,6 +806,66 @@ void CalcGunAngle (void) cl.viewent.angles[PITCH] = -1 * ((r_refdef.viewangles[PITCH] + pitch) - (angledelta((r_refdef.viewangles[PITCH] + pitch) + OldPitchTheta ) * 0.2)); //cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); +#else + float xcrossnormal; + float ycrossnormal; + + xcrossnormal = (cl_crossx.value / (vid.width/2) * IR_YAWRANGE); + ycrossnormal = (cl_crossy.value / (vid.height/2) * IR_PITCHRANGE); + + //Con_Printf ("x: %f", xcrossnormal); + //Con_Printf (" y: %f", ycrossnormal); + + float roll_og_pos; + float inroll_smooth; + float last_roll = 0.0f; + static float smooth_amt = 0.001f; + + if (aimsnap == false && !(cl.stats[STAT_ZOOM] == 1 && ads_center.value) && lock_viewmodel != 1 && !(cl.stats[STAT_ZOOM] == 2 && sniper_center.value)) + { + cl.viewent.angles[YAW] = (r_refdef.viewangles[YAW]/* + yaw*/) - (xcrossnormal); + + //cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw - ((cl_crossx.value/scr_vrect.width * IR_YAWRANGE) * (centerdrift_offset_yaw) - OldYawTheta); + + //cl.viewent.angles[PITCH] = - r_refdef.viewangles[PITCH] + pitch + ((cl_crossy.value/scr_vrect.height * IR_PITCHRANGE) * (centerdrift_offset_pitch*-1)); + cl.viewent.angles[PITCH] = -(r_refdef.viewangles[PITCH]/* + pitch*/) + (ycrossnormal)*-1; + //guMtxTrans(temp, viewmod->origin[0] - (r_refdef.viewangles[PITCH]/* + pitch*/) + (ycrossnormal * scr_vrect.width)*-1, viewmod->origin[1], viewmod->origin[2]); + + //Con_Printf("YAW:%f PITCH%f\n", cl.viewent.angles[YAW], -cl.viewent.angles[PITCH]); + //Con_Printf ("viewent origin: %f %f %f\n", cl.viewent.origin[0], cl.viewent.origin[1], cl.viewent.origin[2]); + + if (cl_weapon_inrollangle.value) { + if (cl.stats[STAT_ZOOM] == 0) { + + roll_og_pos = in_rollangle; + + inroll_smooth = /*lin_lerp (in_rollangle, last_roll, smooth_amt)*/roll_og_pos; + + if(inroll_smooth > 24.5f) + inroll_smooth = 24.5f; + else if(inroll_smooth < -24.5f) + inroll_smooth = -24.5f; + + //Con_Printf("roll: %f\n", inroll_smooth); + cl.viewent.angles[ROLL] = inroll_smooth; + last_roll = roll_og_pos; + } + } + } + else + { + // ELUTODO: Maybe there are other cases besides demo playback + if (lock_viewmodel != 1) { + cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw; + cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); + //Con_Printf ("viewent origin: %f %f %f\n", cl.viewent.origin[0], cl.viewent.origin[1], cl.viewent.origin[2]); + } else { + cl.viewent.angles[YAW] = r_refdef.viewangles[YAW]; + cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH]); + //Con_Printf ("viewent origin: %f %f %f\n", cl.viewent.origin[0], cl.viewent.origin[1], cl.viewent.origin[2]); + } + } +#endif //BLUBS STOPS HERE OldYawTheta = cl.viewent.angles[YAW]; @@ -907,116 +979,6 @@ void V_CalcIntermissionRefdef (void) v_idlescale.value = old; } -float ApproxEqual(float A, float B) -{ - if((A-B) < -0.001) - return 0; - if(A-B > 0.001) - return 0; - - //Con_Printf ("%f",sinf(M_PI)); - - return 1; -}; - -/* -================== -Weapon ADS Declarations -================== -*/ -void GetWeaponADSOfs(vec2_t out) -{ - switch(cl.stats[STAT_ACTIVEWEAPON]) - { - case W_COLT: - { - //out[0] = -15.281; - //out[1] = 5.0677; - out[0] = -5.4792; - out[1] = 1.6500; - return; - } - case W_KAR: - { - //out[0] = -15.4472; - //out[1] = 8.75790; - out[0] = -5.4959; - out[1] = 3.1869; - return; - } - case W_KAR_SCOPE: - { - //out[0] = -15.4472; - //out[1] = 1.8985; - out[0] = -5.2860; - out[1] = 0.7061; - return; - } - case W_THOMPSON: - { - //out[0] = -14.0936; - //out[1] = 6.7265; - out[0] = -6.0693; - out[1] = 3.0076; - return; - } - case W_TRENCH: - { - //out[0] = -20.5952; - //out[1] = 10.1903; - out[0] = -5.5271; - out[1] = 2.8803; - return; - } - case W_357: - { - //out[0] = -15.3425; - //out[1] = 3.7888; - out[0] = -8.3065; - out[1] = 0.8792; - return; - } - case W_MG: - { - out[0] = -6.6437; - out[1] = 3.5092; - return; - } - case W_DB: - { - out[0] = -5.8017; - out[1] = 2.9121; - return; - } - case W_SAWNOFF: - { - out[0] = -5.8017; - out[1] = 2.9121; - return; - } - case W_M1A1: - { - out[0] = -5.3878; - out[1] = 3.6719; - return; - } - case W_BAR: - { - out[0] = -3.8833; - //out[1] = 2.3745; - out[1] = 2.6745; - return; - } - default: - { - //Large values > 20ish cause weapon to flicker, scale model down if we encounter! - //Scale better be 4.3, or else viewbobbing is going to be inaccurate. - out[0] = -5.4792; - out[1] = 1.6500; - return; - } - } -}; /* ================== V_CalcRefdef @@ -1752,6 +1714,12 @@ void V_Init (void) Cvar_RegisterVariable (&cl_bobside); Cvar_RegisterVariable (&cl_bobsidecycle); Cvar_RegisterVariable (&cl_bobsideup); + +#ifdef __WII__ + Cvar_RegisterVariable (&cl_crossx); + Cvar_RegisterVariable (&cl_crossy); + Cvar_RegisterVariable (&cl_weapon_inrollangle); +#endif Cvar_RegisterVariable (&v_kicktime); Cvar_RegisterVariable (&v_kickroll); diff --git a/source/wad.c b/source/wad.c index c21cad7..54166f4 100644 --- a/source/wad.c +++ b/source/wad.c @@ -93,8 +93,10 @@ void W_LoadWadFile (char *filename) lump_p->filepos = LittleLong(lump_p->filepos); lump_p->size = LittleLong(lump_p->size); W_CleanupName (lump_p->name, lump_p->name); +#ifndef __WII__ if (lump_p->type == TYP_QPIC) SwapPic ( (qpic_t *)(wad_base + lump_p->filepos)); +#endif } } @@ -162,7 +164,7 @@ void SwapPic (qpic_t *pic) WAD3 Texture Loading for BSP 3.0 Support From Baker --Diabolickal HLBSP ============================================================================= */ -#ifdef _3DS +#ifndef __PSP__ #define TEXWAD_MAXIMAGES 16384 @@ -316,4 +318,4 @@ byte *WAD3_LoadTexture(miptex_t *mt) { } return NULL; } -#endif // _3DS \ No newline at end of file +#endif // _3DS, WII \ No newline at end of file From 28ad20ab153bc27e2b16f52d3d424f51dd260f05 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sat, 14 Sep 2024 18:52:33 -0400 Subject: [PATCH 06/20] Fix rumble not being multiplayer safe on Wii --- source/cl_parse.c | 4 ++++ source/input.h | 6 +++++- source/pr_cmds.c | 21 --------------------- source/view.h | 4 ++++ 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/source/cl_parse.c b/source/cl_parse.c index 8c7da2e..46e2ddc 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -1214,9 +1214,13 @@ void CL_ParseServerMessage (void) case svc_rumble: // This platform doesn't use this. +#ifdef __WII__ + Wiimote_Rumble ((int)MSG_ReadShort(), (int)MSG_ReadShort(), (int)MSG_ReadShort()); +#else MSG_ReadShort(); MSG_ReadShort(); MSG_ReadShort(); +#endif break; case svc_screenflash: diff --git a/source/input.h b/source/input.h index 42f0510..067bbf8 100644 --- a/source/input.h +++ b/source/input.h @@ -34,4 +34,8 @@ void IN_ClearStates (void); #ifdef _3DS void IN_SwitchKeyboard (void); -#endif // _3DS \ No newline at end of file +#endif // _3DS + +#ifdef __WII__ +void Wiimote_Rumble (int low_frequency, int high_frequency, int duration); +#endif // __WII__ \ No newline at end of file diff --git a/source/pr_cmds.c b/source/pr_cmds.c index f2a1b6a..514c316 100644 --- a/source/pr_cmds.c +++ b/source/pr_cmds.c @@ -26,9 +26,6 @@ extern bool new3ds_flag; #include #include #include -extern double time_wpad_off; -extern int rumble_on; -extern cvar_t rumble; #endif // _3DS, __WII__ #define PR_MAX_TEMPSTRING 2048 // 2001-10-25 Enhanced temp string handling by Maddes @@ -3488,7 +3485,6 @@ nzp_rumble() */ void PF_Rumble(void) { -#ifndef __WII__ client_t *client; int entnum; int low_frequency; @@ -3508,23 +3504,6 @@ void PF_Rumble(void) MSG_WriteShort (&client->message, low_frequency); MSG_WriteShort (&client->message, high_frequency); MSG_WriteShort (&client->message, duration); -#else - client_t *client; - int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) - return; - - if (!rumble.value) return; - double rumble_time; - rumble_time = G_FLOAT(OFS_PARM3) / 1000.0; - - //it switches rumble on for rumble_time milliseconds - WPAD_Rumble(0, true); - rumble_on=1; - time_wpad_off = Sys_FloatTime() + rumble_time; -#endif } /* diff --git a/source/view.h b/source/view.h index e7c30b1..aa22348 100644 --- a/source/view.h +++ b/source/view.h @@ -27,6 +27,10 @@ extern float v_blend[4]; extern cvar_t lcd_x; +#ifdef __WII__ +#define IR_YAWRANGE 30.0f +#define IR_PITCHRANGE 20.0f +#endif extern vec3_t CWeaponOffset;//blubs declared this extern vec3_t CWeaponRot; From 4f6b56c662d1a80823db2e37e52dde997542dfc0 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sat, 14 Sep 2024 19:04:48 -0400 Subject: [PATCH 07/20] host.c unified --- source/host.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/source/host.c b/source/host.c index ba08ee4..1cb1e53 100644 --- a/source/host.c +++ b/source/host.c @@ -72,7 +72,9 @@ cvar_t teamplay = {"teamplay","0",false,true}; cvar_t samelevel = {"samelevel","0"}; cvar_t show_fps = {"show_fps","0", true}; // set for running times - muff +#ifndef __WII__ cvar_t cl_maxfps = {"cl_maxfps", "30", true}; // dr_mabuse1981: maxfps setting +#endif #ifdef __PSP__ cvar_t show_bat = {"show_bat","0"}; // test @@ -238,7 +240,9 @@ void Host_InitLocal (void) #endif // __PSP__ Cvar_RegisterVariable (&show_fps); // muff +#ifndef __WII__ Cvar_RegisterVariable (&cl_maxfps); // dr_mabuse1981: maxfps setting +#endif Cvar_RegisterVariable (&fraglimit); Cvar_RegisterVariable (&timelimit); Cvar_RegisterVariable (&teamplay); @@ -272,7 +276,7 @@ void Host_WriteConfiguration (void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars - if (host_initialized & !isDedicated) + if (host_initialized && !isDedicated) { f = fopen (va("%s/config.cfg",com_gamedir), "w"); if (!f) @@ -282,7 +286,9 @@ void Host_WriteConfiguration (void) } Key_WriteBindings (f); +#ifndef __WII__ Key_WriteDTBindings (f); +#endif Cvar_WriteVariables (f); fclose (f); @@ -507,6 +513,10 @@ extern float crosshair_offset_step; void Host_ClearMemory (void) { Con_DPrintf ("Clearing memory\n"); + +#ifdef __WII__ + GL_ClearTextureCache(); +#endif Mod_ClearAll (); @@ -547,10 +557,14 @@ Returns false if the time is too short to run a frame qboolean Host_FilterTime (float time) { realtime += time; - +#ifndef __WII__ if (cl_maxfps.value < 1) Cvar_SetValue("cl_maxfps", 30); if (!cls.timedemo && realtime - oldrealtime < 1.0/cl_maxfps.value) return false; // framerate is too high +#else + if (!cls.timedemo && realtime - oldrealtime < 1.0f/72.0f) + return false; // framerate is too high +#endif host_frametime = realtime - oldrealtime; oldrealtime = realtime; @@ -911,6 +925,8 @@ void Host_Init (quakeparms_t *parms) Con_Printf ("3DS Model: NEW Nintendo 3DS\n"); else Con_Printf ("3DS Model: Nintendo 3DS\n"); +#elif __WII__ + Con_Printf ("WII NZP v%4.1f (DOL: "__TIME__" "__DATE__")\n", (float)(VERSION)); #endif // __PSP__, _3DS Con_Printf ("%4.1f megabyte Quake hunk \n",parms->memsize/ (1024*1024.0)); @@ -942,7 +958,9 @@ void Host_Init (quakeparms_t *parms) SCR_Init (); R_Init (); S_Init (); +#ifndef __WII__ CDAudio_Init (); +#endif HUD_Init (); CL_Init (); } @@ -953,6 +971,9 @@ void Host_Init (quakeparms_t *parms) host_hunklevel = Hunk_LowMark (); host_initialized = true; +#ifdef __WII__ + VIDEO_SetBlack(false); +#endif M_Start_Menu_f(); Sys_Printf ("========Nazi Zombies Portable Initialized=========\n"); } From 234699d58f1c16a4b6d163c88eb82fa347a15c24 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sat, 14 Sep 2024 19:13:55 -0400 Subject: [PATCH 08/20] various merge cleanups --- source/cdaudio.h | 4 ++++ source/cl_input.c | 13 ++++++------- source/crc.c | 3 +++ source/sv_main.c | 18 ++++++++++++++++++ source/sv_phys.c | 5 ++++- source/view.c | 1 + 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/source/cdaudio.h b/source/cdaudio.h index 7c5dc99..d7cf9f1 100644 --- a/source/cdaudio.h +++ b/source/cdaudio.h @@ -19,7 +19,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ int CDAudio_Init(void); +#ifndef __WII__ void CDAudio_Play(byte track, qboolean looping); +#else +void CDAudio_Play(char* filename, qboolean looping) +#endif #ifdef __PSP__ void CDAudio_PlayFromString(char* track_name, qboolean looping); #endif // __PSP__ diff --git a/source/cl_input.c b/source/cl_input.c index 5a6c12f..ddfd59a 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -167,7 +167,6 @@ void IN_AttackUp(void) {KeyUp(&in_attack);} void IN_UseDown (void) { KeyDown(&in_use); - #ifdef __WII__ // // sB this is all hacked in for now. @@ -661,14 +660,14 @@ void CL_SendMove (usercmd_t *cmd) // sB lock crosshair in the center of screen if(aimsnap == true || (cl.stats[STAT_ZOOM] == 1 && ads_center.value) || sniper_center.value) { - MSG_WriteAngle (&buf, tempv[PITCH]/* + (cl_crossy.value/vid.height) * IR_PITCHRANGE*/); - MSG_WriteAngle (&buf, tempv[YAW]/* - (cl_crossx.value/vid.width - 1) * IR_YAWRANGE*/); - MSG_WriteAngle (&buf, tempv[ROLL]); + MSG_WriteFloat (&buf, tempv[PITCH]/* + (cl_crossy.value/vid.height) * IR_PITCHRANGE*/); + MSG_WriteFloat (&buf, tempv[YAW]/* - (cl_crossx.value/vid.width - 1) * IR_YAWRANGE*/); + MSG_WriteFloat (&buf, tempv[ROLL]); } else { //sBTODO figure out how to make this way more accurate than it is - MSG_WriteAngle (&buf, tempv[PITCH] + ycrossnormal); - MSG_WriteAngle (&buf, tempv[YAW] - xcrossnormal); - MSG_WriteAngle (&buf, tempv[ROLL]); + MSG_WriteFloat (&buf, tempv[PITCH] + ycrossnormal); + MSG_WriteFloat (&buf, tempv[YAW] - xcrossnormal); + MSG_WriteFloat (&buf, tempv[ROLL]); } #else for (i=0 ; i<3 ; i++) diff --git a/source/crc.c b/source/crc.c index f76844c..352cf92 100644 --- a/source/crc.c +++ b/source/crc.c @@ -21,6 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "crc.h" +#ifdef __WII__ +#include +#endif // this is a 16 bit, non-reflected CRC using the polynomial 0x1021 // and the initial and final xor values shown below... in other words, the diff --git a/source/sv_main.c b/source/sv_main.c index 5451540..462cbfb 100644 --- a/source/sv_main.c +++ b/source/sv_main.c @@ -20,6 +20,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // sv_main.c -- server main program #include "quakedef.h" +#ifdef __WII__ +#include +void SV_SendNop (client_t *client); +#endif server_t sv; server_static_t svs; @@ -1296,7 +1300,14 @@ int W_fopen (void) int h = 0; Sys_FileOpenRead (va("%s/maps/%s.way",com_gamedir, sv.name), &h); +#ifdef __WII__ + if (h > 0) + return h; + else + return -1; +#else return h; +#endif } int W_fopenbeta(void) @@ -1304,7 +1315,14 @@ int W_fopenbeta(void) int h = 0; Sys_FileOpenRead (va("%s/data/%s",com_gamedir, sv.name), &h); +#ifdef __WII__ + if (h > 0) + return h; + else + return -1; +#else return h; +#endif } void W_fclose (int h) diff --git a/source/sv_phys.c b/source/sv_phys.c index 3d5902e..438eb43 100644 --- a/source/sv_phys.c +++ b/source/sv_phys.c @@ -1775,8 +1775,11 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore) save_frametime = host_frametime; host_frametime = 0.05; - +#ifdef __PSP__ memcpy_vfpu(&tempent, ent, sizeof(edict_t)); +#else + memcpy(&tempent, ent, sizeof(edict_t)); +#endif tent = &tempent; while (1) diff --git a/source/view.c b/source/view.c index c945477..1b9956e 100644 --- a/source/view.c +++ b/source/view.c @@ -59,6 +59,7 @@ cvar_t cl_bobsideup = {"cl_bobsideup","0.5"}; #ifdef __WII__ cvar_t cl_crossx = {"cl_crossx", "0", false}; cvar_t cl_crossy = {"cl_crossy", "0", false}; +cvar_t cl_weapon_inrollangle = {"cl_weapon_inrollangle", "0", true}; #endif cvar_t v_kicktime = {"v_kicktime", "0.5", false}; From a1b646e83c11ff813423eff2ee3e17c820985d6c Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sat, 14 Sep 2024 21:36:15 -0400 Subject: [PATCH 09/20] Remove unnecessary ifdefs --- source/cdaudio.h | 8 ++------ source/cl_input.c | 34 +++++++++++++--------------------- source/cl_main.c | 8 -------- source/cl_parse.c | 2 +- source/crc.c | 2 -- source/host.c | 2 -- source/mathlib.h | 5 ----- 7 files changed, 16 insertions(+), 45 deletions(-) diff --git a/source/cdaudio.h b/source/cdaudio.h index d7cf9f1..d3e494d 100644 --- a/source/cdaudio.h +++ b/source/cdaudio.h @@ -19,14 +19,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ int CDAudio_Init(void); -#ifndef __WII__ void CDAudio_Play(byte track, qboolean looping); -#else -void CDAudio_Play(char* filename, qboolean looping) -#endif -#ifdef __PSP__ +#ifndef _3DS void CDAudio_PlayFromString(char* track_name, qboolean looping); -#endif // __PSP__ +#endif // _3DS void CDAudio_Stop(void); void CDAudio_Pause(void); void CDAudio_Resume(void); diff --git a/source/cl_input.c b/source/cl_input.c index ddfd59a..b5cbe21 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -303,6 +303,7 @@ void CL_AdjustAngles (void) { float speed; float up, down; + float cl_sensitivity; if (in_speed.state & 1) speed = host_frametime * cl_anglespeedkey.value; @@ -325,20 +326,19 @@ void CL_AdjustAngles (void) speed *= 0.5; else if (cl.stats[STAT_ZOOM] == 2) speed *= 0.25; - - - if (!(in_strafe.state & 1)) - { + #ifdef __PSP__ - cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right) * in_sensitivity.value; - cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left) * in_sensitivity.value; + cl_sensitivity = in_sensitivity.value #elif _3DS - cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right) * sensitivity.value; - cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left) * sensitivity.value; -#else - cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right); - cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left); + cl_sensitivity = sensitivity.value +#else + cl_sensitivity = 1.0f; #endif + + if (!(in_strafe.state & 1)) + { + cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right) * cl_sensitivity; + cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left) * cl_sensitivity; cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]); } if (in_klook.state & 1) @@ -348,16 +348,8 @@ void CL_AdjustAngles (void) cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back); } -#ifdef __PSP__ - up = CL_KeyState (&in_lookup) * in_sensitivity.value; - down = CL_KeyState(&in_lookdown) * in_sensitivity.value; -#elif _3DS - up = CL_KeyState (&in_lookup) * sensitivity.value; - down = CL_KeyState(&in_lookdown) * sensitivity.value; -#else - up = CL_KeyState (&in_lookup); - down = CL_KeyState(&in_lookdown); -#endif // __PSP__ + up = CL_KeyState (&in_lookup) * cl_sensitivity; + down = CL_KeyState(&in_lookdown) * cl_sensitivity; cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up; cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down; diff --git a/source/cl_main.c b/source/cl_main.c index 062170e..85528a9 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -873,11 +873,7 @@ void CL_RelinkEntities (void) if (ent->effects & EF_RAYGREEN) { -#ifdef __WII__ - QMB_RocketTrail(oldorg, ent->origin, RAYGREEN_TRAIL); -#else R_RocketTrail (oldorg, ent->origin, 12); -#endif dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = 25; @@ -891,11 +887,7 @@ void CL_RelinkEntities (void) if (ent->effects & EF_RAYRED) { -#ifdef __WII__ - QMB_RocketTrail(oldorg, ent->origin, RAYRED_TRAIL); -#else R_RocketTrail (oldorg, ent->origin, 13); -#endif dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->radius = 25; diff --git a/source/cl_parse.c b/source/cl_parse.c index 46e2ddc..7a1fad0 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -1213,10 +1213,10 @@ void CL_ParseServerMessage (void) break; case svc_rumble: - // This platform doesn't use this. #ifdef __WII__ Wiimote_Rumble ((int)MSG_ReadShort(), (int)MSG_ReadShort(), (int)MSG_ReadShort()); #else + // These platforms don't use this. MSG_ReadShort(); MSG_ReadShort(); MSG_ReadShort(); diff --git a/source/crc.c b/source/crc.c index 352cf92..3896f28 100644 --- a/source/crc.c +++ b/source/crc.c @@ -21,9 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "crc.h" -#ifdef __WII__ #include -#endif // this is a 16 bit, non-reflected CRC using the polynomial 0x1021 // and the initial and final xor values shown below... in other words, the diff --git a/source/host.c b/source/host.c index 1cb1e53..1b59da8 100644 --- a/source/host.c +++ b/source/host.c @@ -958,9 +958,7 @@ void Host_Init (quakeparms_t *parms) SCR_Init (); R_Init (); S_Init (); -#ifndef __WII__ CDAudio_Init (); -#endif HUD_Init (); CL_Init (); } diff --git a/source/mathlib.h b/source/mathlib.h index b360847..bf4c621 100644 --- a/source/mathlib.h +++ b/source/mathlib.h @@ -39,11 +39,6 @@ typedef int fixed16_t; #define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h #endif -#ifdef __WII__ -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - #define RAD2DEG( x ) ((float)(x) * (float)(180.f / M_PI)) #define DEG2RAD( x ) ((float)(x) * (float)(M_PI / 180.f)) From 65c19fd34ba27eb7ca71d65a0c3b57e1c20babb4 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sat, 14 Sep 2024 21:52:47 -0400 Subject: [PATCH 10/20] properly document ifdef --- source/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/host.c b/source/host.c index 1b59da8..efbdcde 100644 --- a/source/host.c +++ b/source/host.c @@ -74,7 +74,7 @@ cvar_t samelevel = {"samelevel","0"}; cvar_t show_fps = {"show_fps","0", true}; // set for running times - muff #ifndef __WII__ cvar_t cl_maxfps = {"cl_maxfps", "30", true}; // dr_mabuse1981: maxfps setting -#endif +#endif // __WII__ creates a timing issue within Dolphin emu - and vsync is always on anyhow #ifdef __PSP__ cvar_t show_bat = {"show_bat","0"}; // test From 8ac13fec62f9c73f630a3993f9f858732cb3025c Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 15 Sep 2024 10:18:02 -0400 Subject: [PATCH 11/20] console.c unified --- source/console.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/console.c b/source/console.c index 92406db..a2e44ab 100644 --- a/source/console.c +++ b/source/console.c @@ -67,12 +67,12 @@ extern void M_Menu_Main_f (void); #define MAXGAMEDIRLEN 1000 char debuglogfile[MAXGAMEDIRLEN + 1]; -#ifdef __PSP__ +#ifndef _3DS void M_OSK_Draw (void); void Con_OSK_f (char *input, char *output, int outlen); void Con_OSK_Key(int key); void Con_DrawOSK(void); -#endif // __PSP__ +#endif // __PSP__, __WII__ extern qboolean console_enabled; /* @@ -625,12 +625,12 @@ void Con_DrawConsole (int lines, qboolean drawinput) if (drawinput) Con_DrawInput (); -#ifdef __PSP__ +#ifndef _3DS Con_DrawOSK(); #endif // __PSP__ } -#ifdef __PSP__ +#ifndef _3DS static qboolean scr_osk_active = false; @@ -676,6 +676,9 @@ void Con_NotifyBox (char *text) t1 = Sys_FloatTime (); SCR_UpdateScreen (); Sys_SendKeyEvents (); +#ifdef __WII__ + IN_Commands (); +#endif t2 = Sys_FloatTime (); realtime += t2-t1; // make the cursor blink } while (key_count < 0); From d41af489dba00ec6fe2438ac9b08586e24ad692e Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 15 Sep 2024 10:36:56 -0400 Subject: [PATCH 12/20] update paths and folder structure for wii --- source/quakedef.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/source/quakedef.h b/source/quakedef.h index 28ee181..aa8f212 100644 --- a/source/quakedef.h +++ b/source/quakedef.h @@ -42,6 +42,8 @@ extern int psp_system_model; #define WINQUAKE_VERSION 0.996 #define LINUX_VERSION 1.30 #define X11_VERSION 1.10 +#define WIIGX_VERSION 0.09 +#define QUAKE_WII_BASEDIR "/apps/nzportable" #define GAMENAME "nzp" @@ -214,7 +216,13 @@ extern int psp_system_model; #include "psp/common.h" #include "psp/vid.h" #include "psp/sys.h" -#endif // _3DS +#elif __WII__ +#include +#include "wii/common.h" +#include "wii/vid.h" +#include "wii/sys.h" +extern u32 MALLOC_MEM2; +#endif // _3DS, __PSP__, __WII__ #include "zone.h" #include "mathlib.h" #include "bspfile.h" @@ -245,11 +253,16 @@ typedef struct #elif __PSP__ #include "psp/screen.h" #include "psp/net.h" +#elif __WII__ //sBTODO change paths in quakedef.h +#include "wii/screen.h" +#include "wii/net.h" #endif // _3DS #include "protocol.h" #include "cmd.h" #ifdef _3DS #include "ctr/sbar.h" +#elif __WII__ +#include "wii/sbar.h" #endif // _3DS #include "cl_hud.h" #include "sound.h" @@ -259,17 +272,24 @@ typedef struct #elif __PSP__ #include "psp/render.h" #include "psp/client.h" +#elif __WII__ +#include "wii/render.h" +#include "wii/client.h" #endif // _3DS #include "progs.h" #ifdef _3DS #include "ctr/server.h" #elif __PSP__ #include "psp/server.h" +#elif __WII__ +#include "wii/server.h" #endif // _3DS #ifdef _3DS #include "ctr/gl/gl_model.h" #include "ctr/gl/gl_decal.h" +#elif __WII__ +#include "wii/gx/gx_model.h" #else #include "psp/gu/gu_model.h" #endif @@ -280,6 +300,8 @@ typedef struct #include "ctr/keys.h" #elif __PSP__ #include "psp/keys.h" +#elif __WII__ +#include "wii/keys.h" #endif #include "console.h" #include "view.h" @@ -287,12 +309,16 @@ typedef struct #include "ctr/menu.h" #elif __PSP__ #include "psp/menu.h" +#elif __WII__ +#include "wii/menu.h" #endif #include "crc.h" #include "cdaudio.h" #ifdef _3DS #include "ctr/glquake.h" +#elif __WII__ +#include "wii/gx/gxquake.h" #else #include "psp/gu/gu_psp.h" #endif From 3e35e419962799755c5e3f3a2d4368856230a0cc Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 15 Sep 2024 10:40:41 -0400 Subject: [PATCH 13/20] protection against some crashes on wii --- source/pr_cmds.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/pr_cmds.c b/source/pr_cmds.c index 514c316..41e98e7 100644 --- a/source/pr_cmds.c +++ b/source/pr_cmds.c @@ -2467,6 +2467,11 @@ void PF_fopen (void) { case 0: // read Sys_FileOpenRead (va("%s/%s",com_gamedir, p), &h); + // protection against crash on Wii + if(h <= 0) { + G_FLOAT(OFS_RETURN) = -1; + return; + } G_FLOAT(OFS_RETURN) = (float) h; return; case 1: // append -- this is nasty @@ -2504,7 +2509,9 @@ void fclose (float) void PF_fclose (void) { int h = (int)G_FLOAT(OFS_PARM0); - Sys_FileClose(h); + if (h > 0) { // stop crashing on Wii HW + Sys_FileClose(h); + } } /* @@ -2525,6 +2532,7 @@ void PF_fgets (void) h = (int)G_FLOAT(OFS_PARM0); count = Sys_FileRead(h, &buffer, 1); + if (count && buffer == '\r') // carriage return { count = Sys_FileRead(h, &buffer, 1); // skip From fb9766bbae9ebfc1e8d8ebf3d5ba3f72b474144c Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 15 Sep 2024 11:02:42 -0400 Subject: [PATCH 14/20] Change scale to accept floats --- source/ctr/gl/gl_draw.c | 20 ++++++++++---------- source/draw.h | 9 +++------ source/psp/gu/gu_draw.cpp | 22 +++++++++++----------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/source/ctr/gl/gl_draw.c b/source/ctr/gl/gl_draw.c index 0a9484e..7e4b6d7 100644 --- a/source/ctr/gl/gl_draw.c +++ b/source/ctr/gl/gl_draw.c @@ -519,43 +519,43 @@ void Draw_String (int x, int y, char *str) Draw_ColoredString(x, y, str, 255, 255, 255, 255, 1); } -void Draw_ColoredString(int x, int y, char *str, float r, float g, float b, float a, int scale) +void Draw_ColoredString(int x, int y, char *str, float r, float g, float b, float a, float scale) { while (*str) { - Draw_CharacterRGBA (x, y, *str, r, g, b, a, scale); + Draw_CharacterRGBA (x, y, *str, r, g, b, a, (int)scale); // Hooray for variable-spacing! if (*str == ' ') - x += 4 * scale; + x += 4 * (int)scale; else if ((int)*str < 33 || (int)*str > 126) - x += 8 * scale; + x += 8 * (int)scale; else - x += (font_kerningamount[(int)(*str - 33)] + 1) * scale; + x += (font_kerningamount[(int)(*str - 33)] + 1) * (int)scale; str++; } } -int getTextWidth(char *str, int scale) +int getTextWidth(char *str, float scale) { int width = 0; for (int i = 0; i < strlen(str); i++) { // Hooray for variable-spacing! if (str[i] == ' ') - width += 4 * scale; + width += 4 * (int)scale; else if ((int)str[i] < 33 || (int)str[i] > 126) - width += 8 * scale; + width += 8 * (int)scale; else - width += (font_kerningamount[(int)(str[i] - 33)] + 1) * scale; + width += (font_kerningamount[(int)(str[i] - 33)] + 1) * (int)scale; } return width; } -void Draw_ColoredStringCentered(int y, char *str, float r, float g, float b, float a, int scale) +void Draw_ColoredStringCentered(int y, char *str, float r, float g, float b, float a, float scale) { Draw_ColoredString((vid.width - getTextWidth(str, scale))/2, y, str, r, g, b, a, scale); } diff --git a/source/draw.h b/source/draw.h index fa7b0bd..91afdeb 100644 --- a/source/draw.h +++ b/source/draw.h @@ -31,8 +31,8 @@ void Draw_PicIndex (int x, int y, int width, int height, int texture_index); void Draw_StretchPic (int x, int y, qpic_t *pic, int x_value, int y_value); void Draw_ColorPic (int x, int y, qpic_t *pic, float r, float g , float b, float a); void Draw_ColoredStretchPic (int x, int y, qpic_t *pic, int x_value, int y_value, int r, int g, int b, int a); -void Draw_ColoredString (int x, int y, char *text, float r, float g, float b, float a, int scale); -void Draw_ColoredStringCentered(int y, char *text, float r, float g, float b, float a, int scale); +void Draw_ColoredString (int x, int y, char *text, float r, float g, float b, float a, float scale); +void Draw_ColoredStringCentered(int y, char *text, float r, float g, float b, float a, float scale); void Draw_TransPic (int x, int y, qpic_t *pic); void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation); void Draw_ConsoleBackground (int lines); @@ -40,14 +40,11 @@ void Draw_ConsoleBackground (int lines); void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha); void Draw_Fill (int x, int y, int w, int h, int c); void Draw_LoadingFill(void); -#elif __WII__ -void Draw_TileClear (int x, int y, int w, int h); -void Draw_Fill (int x, int y, int w, int h, float r, float g, float b, float a); #endif void Draw_FillByColor (int x, int y, int w, int h, int r, int g, int b, int a); void Draw_FadeScreen (void); void Draw_String (int x, int y, char *str); -int getTextWidth(char *str, int scale); +int getTextWidth(char *str, float scale); //other void Clear_LoadingFill (void); diff --git a/source/psp/gu/gu_draw.cpp b/source/psp/gu/gu_draw.cpp index 1116819..253ef97 100644 --- a/source/psp/gu/gu_draw.cpp +++ b/source/psp/gu/gu_draw.cpp @@ -1562,7 +1562,7 @@ static int HexToInt(char c) } // Creds to UP Team for scale code - cypress -void Draw_ColoredString(int x, int y, char *text, float r, float g, float b, float a, int scale) +void Draw_ColoredString(int x, int y, char *text, float r, float g, float b, float a, float scale) { int num; qboolean white = qtrue; @@ -1611,8 +1611,8 @@ void Draw_ColoredString(int x, int y, char *text, float r, float g, float b, flo vertices[1].u = (fcol + 1) * 8; vertices[1].v = (frow + 1) * 8; - vertices[1].x = x + (8*scale); - vertices[1].y = y + (8*scale); + vertices[1].x = x + (8*(int)scale); + vertices[1].y = y + (8*(int)scale); vertices[1].z = 0; sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices); @@ -1620,11 +1620,11 @@ void Draw_ColoredString(int x, int y, char *text, float r, float g, float b, flo // Hooray for variable-spacing! if (*text == ' ') - x += 4 * scale; + x += 4 * (int)scale; else if ((int)*text < 33 || (int)*text > 126) - x += 8 * scale; + x += 8 * (int)scale; else - x += (font_kerningamount[(int)(*text - 33)] + 1) * scale; + x += (font_kerningamount[(int)(*text - 33)] + 1) * (int)scale; } if (!white) @@ -1634,25 +1634,25 @@ void Draw_ColoredString(int x, int y, char *text, float r, float g, float b, flo sceGuTexFunc(GU_TFX_REPLACE , GU_TCC_RGBA); } -int getTextWidth(char *str, int scale) +int getTextWidth(char *str, float scale) { int width = 0; for (int i = 0; i < strlen(str); i++) { // Hooray for variable-spacing! if (str[i] == ' ') - width += 4 * scale; + width += 4 * (int)scale; else if ((int)str[i] < 33 || (int)str[i] > 126) - width += 8 * scale; + width += 8 * (int)scale; else - width += (font_kerningamount[(int)(str[i] - 33)] + 1) * scale; + width += (font_kerningamount[(int)(str[i] - 33)] + 1) * (int)scale; } return width; } -void Draw_ColoredStringCentered(int y, char *str, float r, float g, float b, float a, int scale) +void Draw_ColoredStringCentered(int y, char *str, float r, float g, float b, float a, float scale) { Draw_ColoredString((vid.width - getTextWidth(str, scale))/2, y, str, r, g, b, a, scale); } From 7ce51c86215b09a84d5a66e321f2ad88e49b5198 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Mon, 7 Oct 2024 12:22:33 -0400 Subject: [PATCH 15/20] merge cl_hud.c --- source/cl_hud.c | 482 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 341 insertions(+), 141 deletions(-) diff --git a/source/cl_hud.c b/source/cl_hud.c index 7d9488e..4332fb2 100644 --- a/source/cl_hud.c +++ b/source/cl_hud.c @@ -53,7 +53,17 @@ qpic_t *b_abutton; qpic_t *b_bbutton; qpic_t *b_xbutton; qpic_t *b_ybutton; -#endif // __PSP__ +#elif __WII__ +qpic_t *b_abutton; +qpic_t *b_bbutton; +qpic_t *b_cbutton; +qpic_t *b_zbutton; +qpic_t *b_minus; +qpic_t *b_plus; +qpic_t *b_one; +qpic_t *b_two; +qpic_t *b_home; +#endif // __PSP__, _3DS, __WII__ qpic_t *b_left; qpic_t *b_right; @@ -85,6 +95,11 @@ int x_value, y_value; void M_DrawPic (int x, int y, qpic_t *pic); +#ifdef __WII__ +void HUD_Scoreboard_Down (void); +void HUD_Scoreboard_Up (void); +#endif // __WII__ + double HUD_Change_time;//hide hud when not chagned double bettyprompt_time; double nameprint_time; @@ -122,6 +137,31 @@ typedef struct point_change_t point_change[10]; +int hud_scale_factor; +float text_scale_factor; + +/* +=============== +HUD_DictateScaleFactor +=============== +*/ +void HUD_DictateScaleFactor(void) +{ + // General HUD position scale factor. + hud_scale_factor = vid.height / 240; + + // Platform-dictated text scale. +#ifdef __WII__ + text_scale_factor = 1.5f; +#elif __PSP__ + text_scale_factor = 1.0f; +#elif _3DS + text_scale_factor = 1.0f; +#else + text_scale_factor = (float)hud_scale_factor; +#endif // __WII__, __PSP__, _3DS +} + /* =============== HUD_Init @@ -188,18 +228,34 @@ void HUD_Init (void) b_zrt = Draw_CachePic ("gfx/butticons/shldr_zr"); b_start = Draw_CachePic ("gfx/butticons/func_sta"); b_select = Draw_CachePic ("gfx/butticons/func_sel"); -#endif // __PSP__, _3DS - +#elif __WII__ + b_abutton = Draw_CachePic ("gfx/butticons/abutton"); + b_bbutton = Draw_CachePic ("gfx/butticons/bbutton"); + b_cbutton = Draw_CachePic ("gfx/butticons/cbutton"); + b_zbutton = Draw_CachePic ("gfx/butticons/zbutton"); + b_left = Draw_CachePic ("gfx/butticons/Dleftbutton"); + b_right = Draw_CachePic ("gfx/butticons/Drightbutton"); + b_up = Draw_CachePic ("gfx/butticons/Dupbutton"); + b_down = Draw_CachePic ("gfx/butticons/Ddownbutton"); + b_minus = Draw_CachePic ("gfx/butticons/-button"); + b_plus = Draw_CachePic ("gfx/butticons/+button"); + b_home = Draw_CachePic ("gfx/butticons/homebutton"); + b_one = Draw_CachePic ("gfx/butticons/1button"); + b_two = Draw_CachePic ("gfx/butticons/2button"); +#endif // __PSP__, _3DS, __WII__ fx_blood_lu = Draw_CachePic ("gfx/hud/blood"); - /*fx_blood_lu = Draw_CachePic ("gfx/hud/blood_tl"); - /fx_blood_ru = Draw_CachePic ("gfx/hud/blood_tr"); - fx_blood_ld = Draw_CachePic ("gfx/hud/blood_bl"); - fx_blood_rd = Draw_CachePic ("gfx/hud/blood_br");*/ + +#ifdef __WII__ + Cmd_AddCommand ("+showscores", HUD_Scoreboard_Down); + Cmd_AddCommand ("-showscores", HUD_Scoreboard_Up); +#endif // __WII__ #ifdef __PSP__ Achievement_Init(); #endif // __PSP__ + + HUD_DictateScaleFactor(); } /* @@ -230,6 +286,9 @@ void HUD_NewMap (void) round_center_x = (vid.width - sb_round[0]->width) /2; round_center_y = (vid.height - sb_round[0]->height) /2; + + bettyprompt_time = 0; + nameprint_time = 0; } @@ -309,6 +368,20 @@ void HUD_Sortpoints (void) } } +#ifdef __WII__ +qboolean showscoreboard = false; +void HUD_Scoreboard_Down (void) +{ + if (key_dest == key_game) + showscoreboard = true; +} + +void HUD_Scoreboard_Up (void) +{ + showscoreboard = false; +} +#endif // __WII__ + /* =============== HUD_EndScreen @@ -325,6 +398,8 @@ void HUD_EndScreen (void) l = scoreboardlines; +#ifndef __WII__ + Draw_ColoredStringCentered(40, "GAME OVER", 255, 0, 0, 255, 1); sprintf (str,"You survived %3i rounds", cl.stats[STAT_ROUNDS]); @@ -352,6 +427,61 @@ void HUD_EndScreen (void) y += 10; } +#else + + if (!showscoreboard) { + Draw_ColoredStringCentered(65, "GAME OVER", 255, 0, 0, 255, text_scale_factor); + + sprintf (str,"You survived %3i rounds", cl.stats[STAT_ROUNDS]); + Draw_String ((vid.width - strlen (str)*8)/2, 85, str); + + sprintf (str,"Name Kills Points"); + x = (vid.width - strlen (str)*8)/2; + + Draw_String (x, 105, str); + y = 0; + for (i=0; iname[0]) + continue; + + Draw_String (x, 125 + y, s->name); + + d = strlen (va("%i",s->kills)); + Draw_String (x + (20 - d)*8, 125 + y, va("%i",s->kills)); + + d = strlen (va("%i",s->points)); + Draw_String (x + (31 - d)*8, 125 + y, va("%i",s->points)); + y += 20; + } + } else { + sprintf (str,"Name Kills Points"); + x = (vid.width - strlen (str)*8)/2; + + Draw_String (x, 105, str); + y = 0; + for (i=0; iname[0]) + continue; + + Draw_String (x, 125 + y, s->name); + + d = strlen (va("%i",s->kills)); + Draw_String (x + (20 - d)*8, 125 + y, va("%i",s->kills)); + + d = strlen (va("%i",s->points)); + Draw_String (x + (31 - d)*8, 125 + y, va("%i",s->points)); + y += 20; + } + } + +#endif // __WII__ + } @@ -384,10 +514,10 @@ void HUD_Parse_Point_Change (int points, int negative, int x_start, int y_start) point_change[i].negative = negative; f = HUD_itoa (points, str); - point_change[i].x = x_start + 10.0 + 8.0*f; + point_change[i].x = x_start + (10.0 + 8.0*f * text_scale_factor); point_change[i].y = y_start; - point_change[i].move_x = 1.0; - point_change[i].move_y = ((rand ()&0x7fff) / ((float)0x7fff)) - 0.5; + point_change[i].move_x = (1.0 * text_scale_factor); + point_change[i].move_y = ((rand ()&0x7fff) / ((float)0x7fff)) - (0.5 * text_scale_factor); point_change[i].alive_time = Sys_FloatTime() + 0.4; } @@ -406,8 +536,8 @@ void HUD_Points (void) l = scoreboardlines; - x = 6; - y = vid.height - 72; + x = 6 * text_scale_factor; + y = vid.height - (72 * text_scale_factor); for (i=0 ; iwidth * text_scale_factor, sb_moneyback->height * text_scale_factor); + xplus = getTextWidth(va("%i", current_points), text_scale_factor); + Draw_ColoredString((((64 * text_scale_factor) - xplus)/2) + (5 * text_scale_factor), y + (3 * text_scale_factor), va("%i", current_points), 255, 255, 255, 255, text_scale_factor); if (old_points != f) { if (f > old_points) - HUD_Parse_Point_Change(f - old_points, 0, ((64 - xplus)/2)+5, y + 3); + HUD_Parse_Point_Change(f - old_points, 0, (((64 * text_scale_factor) - xplus)/2) + (5 * text_scale_factor), y + (3 * text_scale_factor)); else - HUD_Parse_Point_Change(old_points - f, 1, ((64 - xplus)/2)+5, y + 3); + HUD_Parse_Point_Change(old_points - f, 1, (((64 * text_scale_factor) - xplus)/2) + (5 * text_scale_factor), y + (3 * text_scale_factor)); old_points = f; } @@ -484,9 +614,9 @@ void HUD_Point_Change (void) if (point_change[i].points) { if (point_change[i].negative) - Draw_ColoredString (point_change[i].x, point_change[i].y, va ("-%i", point_change[i].points), 255, 0, 0, 255, 1); + Draw_ColoredString (point_change[i].x, point_change[i].y, va ("-%i", point_change[i].points), 255, 0, 0, 255, text_scale_factor); else - Draw_ColoredString (point_change[i].x, point_change[i].y, va ("+%i", point_change[i].points), 255, 255, 0, 255, 1); + Draw_ColoredString (point_change[i].x, point_change[i].y, va ("+%i", point_change[i].points), 255, 255, 0, 255, text_scale_factor); point_change[i].y = point_change[i].y + point_change[i].move_y; point_change[i].x = point_change[i].x + point_change[i].move_x; if (point_change[i].alive_time && point_change[i].alive_time < Sys_FloatTime()) @@ -588,19 +718,19 @@ void HUD_WorldText(int alpha) if (!strcmp("chaptertitle", key)) // search for chaptertitle key { has_chaptertitle = true; - Draw_ColoredString(6, vid.height/2 + 10, value, 255, 255, 255, alpha, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); } if (!strcmp("location", key)) // search for location key { - Draw_ColoredString(6, vid.height/2 + 20, value, 255, 255, 255, alpha, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (20 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); } if (!strcmp("date", key)) // search for date key { - Draw_ColoredString(6, vid.height/2 + 30, value, 255, 255, 255, alpha, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (30 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); } if (!strcmp("person", key)) // search for person key { - Draw_ColoredString(6, vid.height/2 + 40, value, 255, 255, 255, alpha, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (40 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); } } } @@ -617,8 +747,8 @@ void HUD_MaxAmmo(void) { char* maxammo_string = "Max Ammo!"; - int start_y = 55; - int end_y = 45; + int start_y = 55 * text_scale_factor; + int end_y = 45 * text_scale_factor; int diff_y = end_y - start_y; float text_alpha = 1.0f; @@ -646,7 +776,7 @@ void HUD_MaxAmmo(void) text_alpha = 1 - percent_time; } - Draw_ColoredStringCentered(pos_y, maxammo_string, 255, 255, 255, (int)(255 * text_alpha), 1); + Draw_ColoredStringCentered(pos_y, maxammo_string, 255, 255, 255, (int)(255 * text_alpha), text_scale_factor); } /* @@ -684,7 +814,7 @@ void HUD_Rounds (void) if (!value) value = 255; - Draw_ColoredStringCentered(80, "Round", 255, value, value, 255, 2); + Draw_ColoredStringCentered(80 * text_scale_factor, "Round", 255, value, value, 255, text_scale_factor * 2); value -= cl.time * 0.4; @@ -698,12 +828,12 @@ void HUD_Rounds (void) // Now, fade out, and start fading worldtext in // ~3s for fade out, else if (textstate == 1) { - Draw_ColoredStringCentered(80, "Round", 255, 0, 0, value, 2); + Draw_ColoredStringCentered(80 * text_scale_factor, "Round", 255, 0, 0, value, text_scale_factor * 2); HUD_WorldText(value2); if (has_chaptertitle == false) - Draw_ColoredString(6, vid.height/2 + 10, "'Nazi Zombies'", 255, 255, 255, value2, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), "'Nazi Zombies'", 255, 255, 255, value2, text_scale_factor); value -= cl.time * 0.4; value2 += cl.time * 0.4; @@ -719,7 +849,7 @@ void HUD_Rounds (void) HUD_WorldText(255); if (has_chaptertitle == false) - Draw_ColoredString(4, vid.height/2 + 10, "'Nazi Zombies'", 255, 255, 255, 255, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), "'Nazi Zombies'", 255, 255, 255, 255, text_scale_factor); value2 += cl.time * 0.4; @@ -733,7 +863,7 @@ void HUD_Rounds (void) HUD_WorldText(value2); if (has_chaptertitle == false) - Draw_ColoredString(4, vid.height/2 + 10, "'Nazi Zombies'", 255, 255, 255, value2, 1); + Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), "'Nazi Zombies'", 255, 255, 255, value2, text_scale_factor); value2 -= cl.time * 0.4; @@ -753,7 +883,9 @@ void HUD_Rounds (void) textstate = 0; } - Draw_ColorPic ((vid.width - sb_round[0]->width) /2, (vid.height - sb_round[0]->height) /2, sb_round[0], 107, 1, 0, alphabling); + Draw_ColoredStretchPic ((vid.width - (sb_round[0]->width * text_scale_factor))/2, + (vid.height - (sb_round[0]->height * text_scale_factor))/2, sb_round[0], + sb_round[0]->width * text_scale_factor, sb_round[0]->height * text_scale_factor, 107, 1, 0, alphabling); alphabling = alphabling + 15; @@ -764,13 +896,14 @@ void HUD_Rounds (void) } else if (cl.stats[STAT_ROUNDCHANGE] == 2)//this is the rounds icon moving from middle { - Draw_ColorPic (round_center_x, round_center_y, sb_round[0], 107, 1, 0, 255); - round_center_x = round_center_x - (229/108) - 0.2; - round_center_y = round_center_y + 1; - if (round_center_x <= 5) - round_center_x = 5; - if (round_center_y >= vid.height - sb_round[0]->height - 2) - round_center_y = vid.height - sb_round[0]->height - 2; + Draw_ColoredStretchPic(round_center_x, round_center_y, sb_round[0], + sb_round[0]->width * text_scale_factor, sb_round[0]->height * text_scale_factor, 107, 1, 0, 255); + round_center_x = round_center_x - (229/108) - (0.2 * text_scale_factor); + round_center_y = round_center_y + (0.95 * text_scale_factor); // don't move y too quickly + if (round_center_x <= 5 * text_scale_factor) + round_center_x = 5 * text_scale_factor; + if (round_center_y >= vid.height - (sb_round[0]->height * text_scale_factor) - 2) + round_center_y = vid.height - (sb_round[0]->height * text_scale_factor) - 2; } else if (cl.stats[STAT_ROUNDCHANGE] == 3)//shift to white { @@ -801,14 +934,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColorPic (5, vid.height - sb_round[4]->height - 4, sb_round[4], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - savex = x_offset + 10; - x_offset = x_offset + 10; + Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, sb_round[4], + sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + savex = x_offset + 10 * text_scale_factor; + x_offset = x_offset + 10 * text_scale_factor; continue; } if (i == 9) { - Draw_ColorPic (5 + savex, vid.height - sb_round[4]->height - 4, sb_round[4], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); continue; } if (i > 4) @@ -816,9 +951,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColorPic (5 + x_offset, vid.height - sb_round[icon_num]->height - 4, sb_round[icon_num], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * text_scale_factor + (x_offset * text_scale_factor), vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round[icon_num]->width + 3; + x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; } } else @@ -826,23 +962,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[2]]->height - 4, sb_round_num[num[2]], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round_num[num[2]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, sb_round_num[num[2]], + sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[1]]->height - 4, sb_round_num[num[1]], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round_num[num[1]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[0]]->height - 4, sb_round_num[num[0]], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round_num[num[0]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; } } else if (cl.stats[STAT_ROUNDCHANGE] == 4)//blink white @@ -863,14 +1002,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColorPic (5, vid.height - sb_round[4]->height - 4, sb_round[4], 255, 255, 255, blinking); - savex = x_offset + 10; - x_offset = x_offset + 10; + Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); + savex = x_offset + 10 * text_scale_factor; + x_offset = x_offset + 10 * text_scale_factor; continue; } if (i == 9) { - Draw_ColorPic (5 + savex, vid.height - sb_round[4]->height - 4, sb_round[4], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); continue; } if (i > 4) @@ -878,9 +1019,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColorPic (5 + x_offset, vid.height - sb_round[icon_num]->height - 4, sb_round[icon_num], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + sb_round[icon_num]->width + 3; + x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; } } else @@ -888,23 +1030,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[2]]->height - 4, sb_round_num[num[2]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[2]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[1]]->height - 4, sb_round_num[num[1]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[1]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[0]]->height - 4, sb_round_num[num[0]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[0]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; } if (endroundchange == 0) { @@ -924,14 +1069,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColorPic (5, vid.height - sb_round[4]->height - 4, sb_round[4], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); savex = x_offset + 10; - x_offset = x_offset + 10; + x_offset = (x_offset * text_scale_factor) + 10; continue; } if (i == 9) { - Draw_ColorPic (5 + savex, vid.height - sb_round[4]->height - 4, sb_round[4], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); continue; } if (i > 4) @@ -939,9 +1086,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColorPic (5 + x_offset, vid.height - sb_round[icon_num]->height - 4, sb_round[icon_num], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + sb_round[icon_num]->width + 3; + x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; } } else @@ -949,23 +1097,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[2]]->height - 4, sb_round_num[num[2]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[2]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[1]]->height - 4, sb_round_num[num[1]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[1]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[0]]->height - 4, sb_round_num[num[0]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[0]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; } } else if (cl.stats[STAT_ROUNDCHANGE] == 6)//blink white while fading back @@ -986,14 +1137,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColorPic (5, vid.height - sb_round[4]->height - 4, sb_round[4], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); savex = x_offset + 10; - x_offset = x_offset + 10; + x_offset = x_offset + 10 * text_scale_factor; continue; } if (i == 9) { - Draw_ColorPic (5 + savex, vid.height - sb_round[4]->height - 4, sb_round[4], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); continue; } if (i > 4) @@ -1001,9 +1154,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColorPic (5 + x_offset, vid.height - sb_round[icon_num]->height - 4, sb_round[icon_num], 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + sb_round[icon_num]->width + 3; + x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; } } else @@ -1011,23 +1165,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[2]]->height - 4, sb_round_num[num[2]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[2]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[1]]->height - 4, sb_round_num[num[1]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[1]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[0]]->height - 4, sb_round_num[num[0]], 255, 255, 255, blinking); - x_offset = x_offset + sb_round_num[num[0]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; } } else if (cl.stats[STAT_ROUNDCHANGE] == 7)//blink white while fading back @@ -1058,14 +1215,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColorPic (5, vid.height - sb_round[4]->height - 4, sb_round[4], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - savex = x_offset + 10; - x_offset = x_offset + 10; + Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + savex = x_offset + 10 * text_scale_factor; + x_offset = x_offset + 10 * text_scale_factor; continue; } if (i == 9) { - Draw_ColorPic (5 + savex, vid.height - sb_round[4]->height - 4, sb_round[4], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); continue; } if (i > 4) @@ -1073,9 +1232,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColorPic (5 + x_offset, vid.height - sb_round[icon_num]->height - 4, sb_round[icon_num], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round[icon_num]->width + 3; + x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; } } else @@ -1083,23 +1243,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[2]]->height - 4, sb_round_num[num[2]], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round_num[num[2]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[1]]->height - 4, sb_round_num[num[1]], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round_num[num[1]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[0]]->height - 4, sb_round_num[num[0]], (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + sb_round_num[num[0]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; } } else @@ -1115,14 +1278,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColorPic (5, vid.height - sb_round[4]->height - 4, sb_round[4], 107, 1, 0, 255); - savex = x_offset + 10; - x_offset = x_offset + 10; + Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 107, 1, 0, 255); + savex = x_offset + 10 * text_scale_factor; + x_offset = x_offset + 10 * text_scale_factor; continue; } if (i == 9) { - Draw_ColorPic (5 + savex, vid.height - sb_round[4]->height - 4, sb_round[4], 107, 1, 0, 255); + Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, + sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 107, 1, 0, 255); continue; } if (i > 4) @@ -1130,9 +1295,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColorPic (5 + x_offset, vid.height - sb_round[icon_num]->height - 4, sb_round[icon_num], 107, 1, 0, 255); + Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 107, 1, 0, 255); - x_offset = x_offset + sb_round[icon_num]->width + 3; + x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; } } else @@ -1140,16 +1306,18 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[2]]->height - 4, sb_round_num[num[2]], 107, 1, 0, 255); - x_offset = x_offset + sb_round_num[num[2]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 107, 1, 0, 255); + x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[1]]->height - 4, sb_round_num[num[1]], 107, 1, 0, 255); - x_offset = x_offset + sb_round_num[num[1]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 107, 1, 0, 255); + x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; } else num[1] = 0; @@ -1159,8 +1327,9 @@ void HUD_Rounds (void) if(cl.stats[STAT_ROUNDS] == 0) return; - Draw_ColorPic (2 + x_offset, vid.height - sb_round_num[num[0]]->height - 4, sb_round_num[num[0]], 107, 1, 0, 255); - x_offset = x_offset + sb_round_num[num[0]]->width - 8; + Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 107, 1, 0, 255); + x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; } } } @@ -1186,9 +1355,9 @@ void HUD_Perks (void) { int x, y, scale; - x = 18; - y = 2; - scale = 22; + x = 18 * text_scale_factor + 6; + y = 2 * text_scale_factor; + scale = 22 * text_scale_factor; // Double-Tap 2.0 specialty icon qpic_t* double_tap_icon; @@ -1213,8 +1382,8 @@ void HUD_Perks (void) y += scale; } - x = 6; - y = 2; + x = 6 * text_scale_factor; + y = 2 * text_scale_factor; // Now the first column. for (int i = 0; i < 4; i++) { @@ -1240,6 +1409,9 @@ HUD_Powerups void HUD_Powerups (void) { int count = 0; + float scale; + + scale = 26 * text_scale_factor; // horrible way to offset check :)))))))))))))))))) :DDDDDDDD XOXO @@ -1251,13 +1423,13 @@ void HUD_Powerups (void) // both are avail draw fixed order if (count == 2) { - Draw_StretchPic((vid.width/2) - 27, vid.height - 29, x2pic, 26, 26); - Draw_StretchPic((vid.width/2) + 3, vid.height - 29, instapic, 26, 26); + Draw_StretchPic((vid.width/2) - (27 * text_scale_factor), vid.height - 29, x2pic, scale, scale); + Draw_StretchPic((vid.width/2) + (3 * text_scale_factor), vid.height - 29, instapic, scale, scale); } else { if (cl.stats[STAT_X2]) - Draw_StretchPic((vid.width/2) - 13, vid.height - 29, x2pic, 26, 26); + Draw_StretchPic((vid.width/2) - (13 * text_scale_factor), vid.height - 29, x2pic, scale, scale); if(cl.stats[STAT_INSTA]) - Draw_StretchPic ((vid.width/2) - 13, vid.height - 29, instapic, 26, 26); + Draw_StretchPic ((vid.width/2) - (13 * text_scale_factor), vid.height - 29, instapic, scale, scale); } } @@ -1299,6 +1471,8 @@ float smallsec; int ach_pic; void HUD_Achievement (void) { +#ifndef __WII__ + if (achievement_unlocked == 1) { smallsec = smallsec + 0.7; @@ -1315,10 +1489,14 @@ void HUD_Achievement (void) { achievement_unlocked = 0; } + +#endif // __WII__ } void HUD_Parse_Achievement (int ach) { +#ifndef __WII__ + if (achievement_list[ach].unlocked) return; @@ -1331,6 +1509,8 @@ void HUD_Parse_Achievement (int ach) #ifdef __PSP__ Save_Achivements(); #endif // __PSP__ + +#endif // __WII__ } /* @@ -1373,16 +1553,16 @@ void HUD_Ammo (void) char* magstring; int reslen; - reslen = getTextWidth(va("/%i", cl.stats[STAT_AMMO]), 1); + reslen = getTextWidth(va("/%i", cl.stats[STAT_AMMO]), text_scale_factor); // // Magazine // magstring = va("%i", cl.stats[STAT_CURRENTMAG]); if (GetLowAmmo(cl.stats[STAT_ACTIVEWEAPON], 1) >= cl.stats[STAT_CURRENTMAG]) { - Draw_ColoredString(((vid.width - 55) - (reslen)) - getTextWidth(magstring, 1), vid.height - 25, magstring, 255, 0, 0, 255, 1); + Draw_ColoredString(((vid.width - (55 * text_scale_factor)) - (reslen)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 0, 0, 255, text_scale_factor); } else { - Draw_ColoredString(((vid.width - 55) - (reslen)) - getTextWidth(magstring, 1), vid.height - 25, magstring, 255, 255, 255, 255, 1); + Draw_ColoredString(((vid.width - (55 * text_scale_factor)) - (reslen)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 255, 255, 255, text_scale_factor); } // @@ -1390,9 +1570,9 @@ void HUD_Ammo (void) // magstring = va("/%i", cl.stats[STAT_AMMO]); if (GetLowAmmo(cl.stats[STAT_ACTIVEWEAPON], 0) >= cl.stats[STAT_AMMO]) { - Draw_ColoredString((vid.width - 55) - getTextWidth(magstring, 1), vid.height - 25, magstring, 255, 0, 0, 255, 1); + Draw_ColoredString((vid.width - (55 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 0, 0, 255, text_scale_factor); } else { - Draw_ColoredString((vid.width - 55) - getTextWidth(magstring, 1), vid.height - 25, magstring, 255, 255, 255, 255, 1); + Draw_ColoredString((vid.width - (55 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 255, 255, 255, text_scale_factor); } // @@ -1401,9 +1581,9 @@ void HUD_Ammo (void) if (IsDualWeapon(cl.stats[STAT_ACTIVEWEAPON])) { magstring = va("%i", cl.stats[STAT_CURRENTMAG2]); if (GetLowAmmo(cl.stats[STAT_ACTIVEWEAPON], 0) >= cl.stats[STAT_CURRENTMAG2]) { - Draw_ColoredString((vid.width - 89) - strlen(magstring)*8, vid.height - 25, magstring, 255, 0, 0, 255, 1); + Draw_ColoredString((vid.width - (89 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 0, 0, 255, text_scale_factor); } else { - Draw_ColoredString((vid.width - 89) - strlen(magstring)*8, vid.height - 25, magstring, 255, 255, 255, 255, 1); + Draw_ColoredString((vid.width - (89 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 255, 255, 255, text_scale_factor); } } } @@ -1421,11 +1601,11 @@ void HUD_AmmoString (void) int x; if (0 < cl.stats[STAT_AMMO] && cl.stats[STAT_CURRENTMAG] >= 0) { - Draw_ColoredStringCentered(vid.height - 100, "Reload", 255, 255, 255, 255, 1); + Draw_ColoredStringCentered(vid.height - (100 * text_scale_factor), "Reload", 255, 255, 255, 255, text_scale_factor); } else if (0 < cl.stats[STAT_CURRENTMAG]) { - Draw_ColoredStringCentered(vid.height - 100, "LOW AMMO", 255, 255, 0, 255, 1); + Draw_ColoredStringCentered(vid.height - (100 * text_scale_factor), "LOW AMMO", 255, 255, 0, 255, text_scale_factor); } else { - Draw_ColoredStringCentered(vid.height - 100, "NO AMMO", 255, 0, 0, 255, 1); + Draw_ColoredStringCentered(vid.height - (100 * text_scale_factor), "NO AMMO", 255, 0, 0, 255, text_scale_factor); } } } @@ -1440,23 +1620,23 @@ HUD_Grenades void HUD_Grenades (void) { - Draw_StretchPic (vid.width - 53, vid.height - 40, fragpic, 22, 22); + Draw_StretchPic (vid.width - (53 * text_scale_factor), vid.height - (40 * text_scale_factor), fragpic, 22 * text_scale_factor, 22 * text_scale_factor); if (cl.stats[STAT_GRENADES] & UI_FRAG) { if (cl.stats[STAT_PRIGRENADES] <= 0) - Draw_ColoredString (vid.width - 40, vid.height - 25, va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 0, 0, 255, 1); + Draw_ColoredString (vid.width - (40 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 0, 0, 255, text_scale_factor); else - Draw_String (vid.width - 40, vid.height - 25, va ("%i",cl.stats[STAT_PRIGRENADES])); + Draw_ColoredString (vid.width - (40 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 255, 255, 255, text_scale_factor); } if (cl.stats[STAT_GRENADES] & UI_BETTY) { - Draw_StretchPic (vid.width - 32, vid.height - 40, bettypic, 22, 22); + Draw_StretchPic (vid.width - (32 * text_scale_factor), vid.height - (40 * text_scale_factor), bettypic, 22 * text_scale_factor, 22 * text_scale_factor); if (cl.stats[STAT_PRIGRENADES] <= 0) - Draw_ColoredString (vid.width - 17, vid.height - 25, va ("%i",cl.stats[STAT_SECGRENADES]), 255, 0, 0, 255, 1); + Draw_ColoredString (vid.width - (17 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_SECGRENADES]), 255, 0, 0, 255, text_scale_factor); else - Draw_String (vid.width - 17, vid.height - 25, va ("%i",cl.stats[STAT_SECGRENADES])); + Draw_ColoredString (vid.width - (17 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_SECGRENADES]), 255, 255, 255, 255, text_scale_factor); } } @@ -1470,16 +1650,16 @@ void HUD_Weapon (void) char str[32]; float l; x_value = vid.width; - y_value = vid.height - 40; + y_value = vid.height - (40 * text_scale_factor); strcpy(str, pr_strings+sv_player->v.Weapon_Name); l = strlen(str); - x_value = (vid.width - 58) - getTextWidth(str, 1); - Draw_String (x_value, y_value, str); + x_value = (vid.width - (55 * text_scale_factor)) - getTextWidth(str, text_scale_factor); + Draw_ColoredString (x_value, y_value, str, 255, 255, 255, 255, text_scale_factor); } -/* +/*a =============== HUD_BettyPrompt =============== @@ -1519,7 +1699,19 @@ void HUD_BettyPrompt (void) Draw_Pic (x + getTextWidth("Tap SWAP then press ", 1) - 4, 56, GetButtonIcon("+grenade")); -#endif // __PSP__, _3DS +#elif __WII__ + + char str[32]; + char str2[32]; + + strcpy(str, "Press to\n"); + strcpy(str2, "place a Bouncing Betty"); + + Draw_ColoredStringCentered((70 * text_scale_factor), str, 255, 255, 255, 255, text_scale_factor); + Draw_ColoredStringCentered((90 * text_scale_factor), str2, 255, 255, 255, 255, text_scale_factor); + Draw_Pic (200 * text_scale_factor + 14, 68 * text_scale_factor, b_minus); + +#endif // __PSP__, _3DS, __WII__ } /* @@ -1534,7 +1726,7 @@ void HUD_PlayerName (void) if (nameprint_time - sv.time < 1) alpha = (int)((nameprint_time - sv.time)*255); - Draw_ColoredString(70, vid.height - 70, player_name, 255, 255, 255, alpha, 1); + Draw_ColoredString(70 * text_scale_factor, vid.height - (70 * text_scale_factor), player_name, 255, 255, 255, alpha, text_scale_factor); } /* @@ -1638,14 +1830,22 @@ void HUD_Draw (void) return; } +#ifdef __WII__ + if (cl.stats[STAT_HEALTH] <= 0 || showscoreboard == true) +#else if (cl.stats[STAT_HEALTH] <= 0) +#endif // __WII__ { HUD_EndScreen (); // Make sure we still draw the screen flash. if (screenflash_duration > sv.time) HUD_Screenflash(); - return; + +#ifdef __WII__ + if (cl.stats[STAT_HEALTH] <= 0) +#endif // __WII__ + return; } if (bettyprompt_time > sv.time) From 5276a116a9ae2895f48a86d3bb1f2e03f170954d Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Mon, 7 Oct 2024 15:08:11 -0400 Subject: [PATCH 16/20] Cleaup cl_hud merger and fix an input bug --- source/cl_hud.c | 411 ++++++++++++++++++++-------------------------- source/cl_input.c | 4 +- source/console.c | 6 +- source/host.c | 6 +- source/view.c | 10 +- 5 files changed, 198 insertions(+), 239 deletions(-) diff --git a/source/cl_hud.c b/source/cl_hud.c index 4332fb2..5422771 100644 --- a/source/cl_hud.c +++ b/source/cl_hud.c @@ -137,8 +137,7 @@ typedef struct point_change_t point_change[10]; -int hud_scale_factor; -float text_scale_factor; +float hud_scale_factor; /* =============== @@ -147,18 +146,15 @@ HUD_DictateScaleFactor */ void HUD_DictateScaleFactor(void) { - // General HUD position scale factor. - hud_scale_factor = vid.height / 240; - // Platform-dictated text scale. #ifdef __WII__ - text_scale_factor = 1.5f; + hud_scale_factor = 1.5f; #elif __PSP__ - text_scale_factor = 1.0f; + hud_scale_factor = 1.0f; #elif _3DS - text_scale_factor = 1.0f; + hud_scale_factor = 1.0f; #else - text_scale_factor = (float)hud_scale_factor; + hud_scale_factor = 1.0f; #endif // __WII__, __PSP__, _3DS } @@ -368,7 +364,6 @@ void HUD_Sortpoints (void) } } -#ifdef __WII__ qboolean showscoreboard = false; void HUD_Scoreboard_Down (void) { @@ -380,7 +375,6 @@ void HUD_Scoreboard_Up (void) { showscoreboard = false; } -#endif // __WII__ /* =============== @@ -398,39 +392,8 @@ void HUD_EndScreen (void) l = scoreboardlines; -#ifndef __WII__ - - Draw_ColoredStringCentered(40, "GAME OVER", 255, 0, 0, 255, 1); - - sprintf (str,"You survived %3i rounds", cl.stats[STAT_ROUNDS]); - Draw_String ((vid.width - strlen (str)*8)/2, 52, str); - - sprintf (str,"Name Kills Points"); - x = (vid.width - strlen (str)*8)/2; - - Draw_String (x, 68, str); - y = 0; - for (i=0; iname[0]) - continue; - - Draw_String (x, 78 + y, s->name); - - d = strlen (va("%i",s->kills)); - Draw_String (x + (20 - d)*8, 78 + y, va("%i",s->kills)); - - d = strlen (va("%i",s->points)); - Draw_String (x + (31 - d)*8, 78 + y, va("%i",s->points)); - y += 10; - } - -#else - if (!showscoreboard) { - Draw_ColoredStringCentered(65, "GAME OVER", 255, 0, 0, 255, text_scale_factor); + Draw_ColoredStringCentered(65, "GAME OVER", 255, 0, 0, 255, hud_scale_factor); sprintf (str,"You survived %3i rounds", cl.stats[STAT_ROUNDS]); Draw_String ((vid.width - strlen (str)*8)/2, 85, str); @@ -479,9 +442,6 @@ void HUD_EndScreen (void) y += 20; } } - -#endif // __WII__ - } @@ -514,10 +474,10 @@ void HUD_Parse_Point_Change (int points, int negative, int x_start, int y_start) point_change[i].negative = negative; f = HUD_itoa (points, str); - point_change[i].x = x_start + (10.0 + 8.0*f * text_scale_factor); + point_change[i].x = x_start + (10.0 + 8.0*f * hud_scale_factor); point_change[i].y = y_start; - point_change[i].move_x = (1.0 * text_scale_factor); - point_change[i].move_y = ((rand ()&0x7fff) / ((float)0x7fff)) - (0.5 * text_scale_factor); + point_change[i].move_x = (1.0 * hud_scale_factor); + point_change[i].move_y = ((rand ()&0x7fff) / ((float)0x7fff)) - (0.5 * hud_scale_factor); point_change[i].alive_time = Sys_FloatTime() + 0.4; } @@ -536,8 +496,8 @@ void HUD_Points (void) l = scoreboardlines; - x = 6 * text_scale_factor; - y = vid.height - (72 * text_scale_factor); + x = 6 * hud_scale_factor; + y = vid.height - (72 * hud_scale_factor); for (i=0 ; iwidth * text_scale_factor, sb_moneyback->height * text_scale_factor); - xplus = getTextWidth(va("%i", current_points), text_scale_factor); - Draw_ColoredString((((64 * text_scale_factor) - xplus)/2) + (5 * text_scale_factor), y + (3 * text_scale_factor), va("%i", current_points), 255, 255, 255, 255, text_scale_factor); + Draw_StretchPic (x, y, sb_moneyback, sb_moneyback->width * hud_scale_factor, sb_moneyback->height * hud_scale_factor); + xplus = getTextWidth(va("%i", current_points), hud_scale_factor); + Draw_ColoredString((((64 * hud_scale_factor) - xplus)/2) + (5 * hud_scale_factor), y + (3 * hud_scale_factor), va("%i", current_points), 255, 255, 255, 255, hud_scale_factor); if (old_points != f) { if (f > old_points) - HUD_Parse_Point_Change(f - old_points, 0, (((64 * text_scale_factor) - xplus)/2) + (5 * text_scale_factor), y + (3 * text_scale_factor)); + HUD_Parse_Point_Change(f - old_points, 0, (((64 * hud_scale_factor) - xplus)/2) + (5 * hud_scale_factor), y + (3 * hud_scale_factor)); else - HUD_Parse_Point_Change(old_points - f, 1, (((64 * text_scale_factor) - xplus)/2) + (5 * text_scale_factor), y + (3 * text_scale_factor)); + HUD_Parse_Point_Change(old_points - f, 1, (((64 * hud_scale_factor) - xplus)/2) + (5 * hud_scale_factor), y + (3 * hud_scale_factor)); old_points = f; } @@ -614,9 +574,9 @@ void HUD_Point_Change (void) if (point_change[i].points) { if (point_change[i].negative) - Draw_ColoredString (point_change[i].x, point_change[i].y, va ("-%i", point_change[i].points), 255, 0, 0, 255, text_scale_factor); + Draw_ColoredString (point_change[i].x, point_change[i].y, va ("-%i", point_change[i].points), 255, 0, 0, 255, hud_scale_factor); else - Draw_ColoredString (point_change[i].x, point_change[i].y, va ("+%i", point_change[i].points), 255, 255, 0, 255, text_scale_factor); + Draw_ColoredString (point_change[i].x, point_change[i].y, va ("+%i", point_change[i].points), 255, 255, 0, 255, hud_scale_factor); point_change[i].y = point_change[i].y + point_change[i].move_y; point_change[i].x = point_change[i].x + point_change[i].move_x; if (point_change[i].alive_time && point_change[i].alive_time < Sys_FloatTime()) @@ -718,19 +678,19 @@ void HUD_WorldText(int alpha) if (!strcmp("chaptertitle", key)) // search for chaptertitle key { has_chaptertitle = true; - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (10 * hud_scale_factor), value, 255, 255, 255, alpha, hud_scale_factor); } if (!strcmp("location", key)) // search for location key { - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (20 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (20 * hud_scale_factor), value, 255, 255, 255, alpha, hud_scale_factor); } if (!strcmp("date", key)) // search for date key { - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (30 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (30 * hud_scale_factor), value, 255, 255, 255, alpha, hud_scale_factor); } if (!strcmp("person", key)) // search for person key { - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (40 * text_scale_factor), value, 255, 255, 255, alpha, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (40 * hud_scale_factor), value, 255, 255, 255, alpha, hud_scale_factor); } } } @@ -747,8 +707,8 @@ void HUD_MaxAmmo(void) { char* maxammo_string = "Max Ammo!"; - int start_y = 55 * text_scale_factor; - int end_y = 45 * text_scale_factor; + int start_y = 55 * hud_scale_factor; + int end_y = 45 * hud_scale_factor; int diff_y = end_y - start_y; float text_alpha = 1.0f; @@ -776,7 +736,7 @@ void HUD_MaxAmmo(void) text_alpha = 1 - percent_time; } - Draw_ColoredStringCentered(pos_y, maxammo_string, 255, 255, 255, (int)(255 * text_alpha), text_scale_factor); + Draw_ColoredStringCentered(pos_y, maxammo_string, 255, 255, 255, (int)(255 * text_alpha), hud_scale_factor); } /* @@ -814,7 +774,7 @@ void HUD_Rounds (void) if (!value) value = 255; - Draw_ColoredStringCentered(80 * text_scale_factor, "Round", 255, value, value, 255, text_scale_factor * 2); + Draw_ColoredStringCentered(80 * hud_scale_factor, "Round", 255, value, value, 255, hud_scale_factor * 2); value -= cl.time * 0.4; @@ -828,12 +788,12 @@ void HUD_Rounds (void) // Now, fade out, and start fading worldtext in // ~3s for fade out, else if (textstate == 1) { - Draw_ColoredStringCentered(80 * text_scale_factor, "Round", 255, 0, 0, value, text_scale_factor * 2); + Draw_ColoredStringCentered(80 * hud_scale_factor, "Round", 255, 0, 0, value, hud_scale_factor * 2); HUD_WorldText(value2); if (has_chaptertitle == false) - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), "'Nazi Zombies'", 255, 255, 255, value2, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (10 * hud_scale_factor), "'Nazi Zombies'", 255, 255, 255, value2, hud_scale_factor); value -= cl.time * 0.4; value2 += cl.time * 0.4; @@ -849,7 +809,7 @@ void HUD_Rounds (void) HUD_WorldText(255); if (has_chaptertitle == false) - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), "'Nazi Zombies'", 255, 255, 255, 255, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (10 * hud_scale_factor), "'Nazi Zombies'", 255, 255, 255, 255, hud_scale_factor); value2 += cl.time * 0.4; @@ -863,7 +823,7 @@ void HUD_Rounds (void) HUD_WorldText(value2); if (has_chaptertitle == false) - Draw_ColoredString(6 * text_scale_factor, vid.height/2 + (10 * text_scale_factor), "'Nazi Zombies'", 255, 255, 255, value2, text_scale_factor); + Draw_ColoredString(6 * hud_scale_factor, vid.height/2 + (10 * hud_scale_factor), "'Nazi Zombies'", 255, 255, 255, value2, hud_scale_factor); value2 -= cl.time * 0.4; @@ -883,9 +843,9 @@ void HUD_Rounds (void) textstate = 0; } - Draw_ColoredStretchPic ((vid.width - (sb_round[0]->width * text_scale_factor))/2, - (vid.height - (sb_round[0]->height * text_scale_factor))/2, sb_round[0], - sb_round[0]->width * text_scale_factor, sb_round[0]->height * text_scale_factor, 107, 1, 0, alphabling); + Draw_ColoredStretchPic ((vid.width - (sb_round[0]->width * hud_scale_factor))/2, + (vid.height - (sb_round[0]->height * hud_scale_factor))/2, sb_round[0], + sb_round[0]->width * hud_scale_factor, sb_round[0]->height * hud_scale_factor, 107, 1, 0, alphabling); alphabling = alphabling + 15; @@ -897,13 +857,13 @@ void HUD_Rounds (void) else if (cl.stats[STAT_ROUNDCHANGE] == 2)//this is the rounds icon moving from middle { Draw_ColoredStretchPic(round_center_x, round_center_y, sb_round[0], - sb_round[0]->width * text_scale_factor, sb_round[0]->height * text_scale_factor, 107, 1, 0, 255); - round_center_x = round_center_x - (229/108) - (0.2 * text_scale_factor); - round_center_y = round_center_y + (0.95 * text_scale_factor); // don't move y too quickly - if (round_center_x <= 5 * text_scale_factor) - round_center_x = 5 * text_scale_factor; - if (round_center_y >= vid.height - (sb_round[0]->height * text_scale_factor) - 2) - round_center_y = vid.height - (sb_round[0]->height * text_scale_factor) - 2; + sb_round[0]->width * hud_scale_factor, sb_round[0]->height * hud_scale_factor, 107, 1, 0, 255); + round_center_x = round_center_x - (229/108) - (0.2 * hud_scale_factor); + round_center_y = round_center_y + (0.95 * hud_scale_factor); // don't move y too quickly + if (round_center_x <= 5 * hud_scale_factor) + round_center_x = 5 * hud_scale_factor; + if (round_center_y >= vid.height - (sb_round[0]->height * hud_scale_factor) - 2) + round_center_y = vid.height - (sb_round[0]->height * hud_scale_factor) - 2; } else if (cl.stats[STAT_ROUNDCHANGE] == 3)//shift to white { @@ -934,16 +894,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, sb_round[4], - sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - savex = x_offset + 10 * text_scale_factor; - x_offset = x_offset + 10 * text_scale_factor; + Draw_ColoredStretchPic (5 * hud_scale_factor, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, sb_round[4], + sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + savex = x_offset + 10 * hud_scale_factor; + x_offset = x_offset + 10 * hud_scale_factor; continue; } if (i == 9) { - Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * hud_scale_factor + savex, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); continue; } if (i > 4) @@ -951,10 +911,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColoredStretchPic (5 * text_scale_factor + (x_offset * text_scale_factor), vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, - sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * hud_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * hud_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * hud_scale_factor, sb_round[icon_num]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; + x_offset = x_offset + (sb_round[icon_num]->width * hud_scale_factor) + 3; } } else @@ -962,26 +922,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, sb_round_num[num[2]], - sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * hud_scale_factor) - 4, sb_round_num[num[2]], + sb_round_num[num[2]]->width * hud_scale_factor, sb_round_num[num[2]]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[2]]->width * hud_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, - sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * hud_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * hud_scale_factor, sb_round_num[num[1]]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[1]]->width * hud_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, - sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * hud_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * hud_scale_factor, sb_round_num[num[0]]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[0]]->width * hud_scale_factor) - 8; } } else if (cl.stats[STAT_ROUNDCHANGE] == 4)//blink white @@ -1002,16 +962,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); - savex = x_offset + 10 * text_scale_factor; - x_offset = x_offset + 10 * text_scale_factor; + Draw_ColoredStretchPic (5 * hud_scale_factor, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 255, 255, 255, blinking); + savex = x_offset + 10 * hud_scale_factor; + x_offset = x_offset + 10 * hud_scale_factor; continue; } if (i == 9) { - Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * hud_scale_factor + savex, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 255, 255, 255, blinking); continue; } if (i > 4) @@ -1019,10 +979,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, - sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * hud_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * hud_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * hud_scale_factor, sb_round[icon_num]->height * hud_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; + x_offset = x_offset + (sb_round[icon_num]->width * hud_scale_factor) + 3; } } else @@ -1030,26 +990,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, - sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * hud_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * hud_scale_factor, sb_round_num[num[2]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[2]]->width * hud_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, - sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * hud_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * hud_scale_factor, sb_round_num[num[1]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[1]]->width * hud_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, - sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * hud_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * hud_scale_factor, sb_round_num[num[0]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[0]]->width * hud_scale_factor) - 8; } if (endroundchange == 0) { @@ -1069,16 +1029,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); - savex = x_offset + 10; - x_offset = (x_offset * text_scale_factor) + 10; + Draw_ColoredStretchPic (5 * hud_scale_factor, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 255, 255, 255, blinking); + savex = x_offset + 10 * hud_scale_factor; + x_offset = (x_offset * hud_scale_factor) + 10; continue; } if (i == 9) { - Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * hud_scale_factor + savex, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 255, 255, 255, blinking); continue; } if (i > 4) @@ -1086,10 +1046,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, - sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * hud_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * hud_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * hud_scale_factor, sb_round[icon_num]->height * hud_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; + x_offset = x_offset + (sb_round[icon_num]->width * hud_scale_factor) + 3; } } else @@ -1097,26 +1057,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, - sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * hud_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * hud_scale_factor, sb_round_num[num[2]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[2]]->width * hud_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, - sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * hud_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * hud_scale_factor, sb_round_num[num[1]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[1]]->width * hud_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, - sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * hud_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * hud_scale_factor, sb_round_num[num[0]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[0]]->width * hud_scale_factor) - 8; } } else if (cl.stats[STAT_ROUNDCHANGE] == 6)//blink white while fading back @@ -1137,16 +1097,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); - savex = x_offset + 10; - x_offset = x_offset + 10 * text_scale_factor; + Draw_ColoredStretchPic (5 * hud_scale_factor, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 255, 255, 255, blinking); + savex = x_offset + 10 * hud_scale_factor; + x_offset = x_offset + 10 * hud_scale_factor; continue; } if (i == 9) { - Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * hud_scale_factor + savex, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 255, 255, 255, blinking); continue; } if (i > 4) @@ -1154,10 +1114,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, - sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 255, 255, 255, blinking); + Draw_ColoredStretchPic (5 * hud_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * hud_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * hud_scale_factor, sb_round[icon_num]->height * hud_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; + x_offset = x_offset + (sb_round[icon_num]->width * hud_scale_factor) + 3; } } else @@ -1165,26 +1125,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, - sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * hud_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * hud_scale_factor, sb_round_num[num[2]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[2]]->width * hud_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, - sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * hud_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * hud_scale_factor, sb_round_num[num[1]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[1]]->width * hud_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, - sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 255, 255, 255, blinking); - x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * hud_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * hud_scale_factor, sb_round_num[num[0]]->height * hud_scale_factor, 255, 255, 255, blinking); + x_offset = x_offset + (sb_round_num[num[0]]->width * hud_scale_factor) - 8; } } else if (cl.stats[STAT_ROUNDCHANGE] == 7)//blink white while fading back @@ -1215,16 +1175,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - savex = x_offset + 10 * text_scale_factor; - x_offset = x_offset + 10 * text_scale_factor; + Draw_ColoredStretchPic (5 * hud_scale_factor, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + savex = x_offset + 10 * hud_scale_factor; + x_offset = x_offset + 10 * hud_scale_factor; continue; } if (i == 9) { - Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * hud_scale_factor + savex, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); continue; } if (i > 4) @@ -1232,10 +1192,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, - sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + Draw_ColoredStretchPic (5 * hud_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * hud_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * hud_scale_factor, sb_round[icon_num]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; + x_offset = x_offset + (sb_round[icon_num]->width * hud_scale_factor) + 3; } } else @@ -1243,26 +1203,26 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, - sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * hud_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * hud_scale_factor, sb_round_num[num[2]]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[2]]->width * hud_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, - sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * hud_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * hud_scale_factor, sb_round_num[num[1]]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[1]]->width * hud_scale_factor) - 8; } else num[1] = 0; num[0] = cl.stats[STAT_ROUNDS] - num[2]*100 - num[1]*10; - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, - sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); - x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * hud_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * hud_scale_factor, sb_round_num[num[0]]->height * hud_scale_factor, (int)color_shift[0], (int)color_shift[1], (int)color_shift[2], 255); + x_offset = x_offset + (sb_round_num[num[0]]->width * hud_scale_factor) - 8; } } else @@ -1278,16 +1238,16 @@ void HUD_Rounds (void) { if (i == 4) { - Draw_ColoredStretchPic (5 * text_scale_factor, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 107, 1, 0, 255); - savex = x_offset + 10 * text_scale_factor; - x_offset = x_offset + 10 * text_scale_factor; + Draw_ColoredStretchPic (5 * hud_scale_factor, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 107, 1, 0, 255); + savex = x_offset + 10 * hud_scale_factor; + x_offset = x_offset + 10 * hud_scale_factor; continue; } if (i == 9) { - Draw_ColoredStretchPic (5 * text_scale_factor + savex, vid.height - (sb_round[4]->height * text_scale_factor) - 4, - sb_round[4], sb_round[4]->width * text_scale_factor, sb_round[4]->height * text_scale_factor, 107, 1, 0, 255); + Draw_ColoredStretchPic (5 * hud_scale_factor + savex, vid.height - (sb_round[4]->height * hud_scale_factor) - 4, + sb_round[4], sb_round[4]->width * hud_scale_factor, sb_round[4]->height * hud_scale_factor, 107, 1, 0, 255); continue; } if (i > 4) @@ -1295,10 +1255,10 @@ void HUD_Rounds (void) else icon_num = i; - Draw_ColoredStretchPic (5 * text_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * text_scale_factor) - 4, - sb_round[icon_num], sb_round[icon_num]->width * text_scale_factor, sb_round[icon_num]->height * text_scale_factor, 107, 1, 0, 255); + Draw_ColoredStretchPic (5 * hud_scale_factor + x_offset, vid.height - (sb_round[icon_num]->height * hud_scale_factor) - 4, + sb_round[icon_num], sb_round[icon_num]->width * hud_scale_factor, sb_round[icon_num]->height * hud_scale_factor, 107, 1, 0, 255); - x_offset = x_offset + (sb_round[icon_num]->width * text_scale_factor) + 3; + x_offset = x_offset + (sb_round[icon_num]->width * hud_scale_factor) + 3; } } else @@ -1306,18 +1266,18 @@ void HUD_Rounds (void) if (cl.stats[STAT_ROUNDS] >= 100) { num[2] = (int)(cl.stats[STAT_ROUNDS]/100); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * text_scale_factor) - 4, - sb_round_num[num[2]], sb_round_num[num[2]]->width * text_scale_factor, sb_round_num[num[2]]->height * text_scale_factor, 107, 1, 0, 255); - x_offset = x_offset + (sb_round_num[num[2]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[2]]->height * hud_scale_factor) - 4, + sb_round_num[num[2]], sb_round_num[num[2]]->width * hud_scale_factor, sb_round_num[num[2]]->height * hud_scale_factor, 107, 1, 0, 255); + x_offset = x_offset + (sb_round_num[num[2]]->width * hud_scale_factor) - 8; } else num[2] = 0; if (cl.stats[STAT_ROUNDS] >= 10) { num[1] = (int)((cl.stats[STAT_ROUNDS] - num[2]*100)/10); - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * text_scale_factor) - 4, - sb_round_num[num[1]], sb_round_num[num[1]]->width * text_scale_factor, sb_round_num[num[1]]->height * text_scale_factor, 107, 1, 0, 255); - x_offset = x_offset + (sb_round_num[num[1]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[1]]->height * hud_scale_factor) - 4, + sb_round_num[num[1]], sb_round_num[num[1]]->width * hud_scale_factor, sb_round_num[num[1]]->height * hud_scale_factor, 107, 1, 0, 255); + x_offset = x_offset + (sb_round_num[num[1]]->width * hud_scale_factor) - 8; } else num[1] = 0; @@ -1327,9 +1287,9 @@ void HUD_Rounds (void) if(cl.stats[STAT_ROUNDS] == 0) return; - Draw_ColoredStretchPic (2 * text_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * text_scale_factor) - 4, - sb_round_num[num[0]], sb_round_num[num[0]]->width * text_scale_factor, sb_round_num[num[0]]->height * text_scale_factor, 107, 1, 0, 255); - x_offset = x_offset + (sb_round_num[num[0]]->width * text_scale_factor) - 8; + Draw_ColoredStretchPic (2 * hud_scale_factor + x_offset, vid.height - (sb_round_num[num[0]]->height * hud_scale_factor) - 4, + sb_round_num[num[0]], sb_round_num[num[0]]->width * hud_scale_factor, sb_round_num[num[0]]->height * hud_scale_factor, 107, 1, 0, 255); + x_offset = x_offset + (sb_round_num[num[0]]->width * hud_scale_factor) - 8; } } } @@ -1355,9 +1315,9 @@ void HUD_Perks (void) { int x, y, scale; - x = 18 * text_scale_factor + 6; - y = 2 * text_scale_factor; - scale = 22 * text_scale_factor; + x = 18 * hud_scale_factor; + y = 2 * hud_scale_factor; + scale = 22 * hud_scale_factor; // Double-Tap 2.0 specialty icon qpic_t* double_tap_icon; @@ -1382,8 +1342,8 @@ void HUD_Perks (void) y += scale; } - x = 6 * text_scale_factor; - y = 2 * text_scale_factor; + x = 6 * hud_scale_factor; + y = 2 * hud_scale_factor; // Now the first column. for (int i = 0; i < 4; i++) { @@ -1411,7 +1371,7 @@ void HUD_Powerups (void) int count = 0; float scale; - scale = 26 * text_scale_factor; + scale = 26 * hud_scale_factor; // horrible way to offset check :)))))))))))))))))) :DDDDDDDD XOXO @@ -1423,13 +1383,13 @@ void HUD_Powerups (void) // both are avail draw fixed order if (count == 2) { - Draw_StretchPic((vid.width/2) - (27 * text_scale_factor), vid.height - 29, x2pic, scale, scale); - Draw_StretchPic((vid.width/2) + (3 * text_scale_factor), vid.height - 29, instapic, scale, scale); + Draw_StretchPic((vid.width/2) - (27 * hud_scale_factor), vid.height - (29 * hud_scale_factor), x2pic, scale, scale); + Draw_StretchPic((vid.width/2) + (3 * hud_scale_factor), vid.height - (29 * hud_scale_factor), instapic, scale, scale); } else { if (cl.stats[STAT_X2]) - Draw_StretchPic((vid.width/2) - (13 * text_scale_factor), vid.height - 29, x2pic, scale, scale); + Draw_StretchPic((vid.width/2) - (13 * hud_scale_factor), vid.height - (29 * hud_scale_factor), x2pic, scale, scale); if(cl.stats[STAT_INSTA]) - Draw_StretchPic ((vid.width/2) - (13 * text_scale_factor), vid.height - 29, instapic, scale, scale); + Draw_StretchPic ((vid.width/2) - (13 * hud_scale_factor), vid.height - (29 * hud_scale_factor), instapic, scale, scale); } } @@ -1553,16 +1513,16 @@ void HUD_Ammo (void) char* magstring; int reslen; - reslen = getTextWidth(va("/%i", cl.stats[STAT_AMMO]), text_scale_factor); + reslen = getTextWidth(va("/%i", cl.stats[STAT_AMMO]), hud_scale_factor); // // Magazine // magstring = va("%i", cl.stats[STAT_CURRENTMAG]); if (GetLowAmmo(cl.stats[STAT_ACTIVEWEAPON], 1) >= cl.stats[STAT_CURRENTMAG]) { - Draw_ColoredString(((vid.width - (55 * text_scale_factor)) - (reslen)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 0, 0, 255, text_scale_factor); + Draw_ColoredString(((vid.width - (55 * hud_scale_factor)) - (reslen)) - getTextWidth(magstring, hud_scale_factor), vid.height - (25 * hud_scale_factor), magstring, 255, 0, 0, 255, hud_scale_factor); } else { - Draw_ColoredString(((vid.width - (55 * text_scale_factor)) - (reslen)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 255, 255, 255, text_scale_factor); + Draw_ColoredString(((vid.width - (55 * hud_scale_factor)) - (reslen)) - getTextWidth(magstring, hud_scale_factor), vid.height - (25 * hud_scale_factor), magstring, 255, 255, 255, 255, hud_scale_factor); } // @@ -1570,9 +1530,9 @@ void HUD_Ammo (void) // magstring = va("/%i", cl.stats[STAT_AMMO]); if (GetLowAmmo(cl.stats[STAT_ACTIVEWEAPON], 0) >= cl.stats[STAT_AMMO]) { - Draw_ColoredString((vid.width - (55 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 0, 0, 255, text_scale_factor); + Draw_ColoredString((vid.width - (55 * hud_scale_factor)) - getTextWidth(magstring, hud_scale_factor), vid.height - (25 * hud_scale_factor), magstring, 255, 0, 0, 255, hud_scale_factor); } else { - Draw_ColoredString((vid.width - (55 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 255, 255, 255, text_scale_factor); + Draw_ColoredString((vid.width - (55 * hud_scale_factor)) - getTextWidth(magstring, hud_scale_factor), vid.height - (25 * hud_scale_factor), magstring, 255, 255, 255, 255, hud_scale_factor); } // @@ -1581,9 +1541,9 @@ void HUD_Ammo (void) if (IsDualWeapon(cl.stats[STAT_ACTIVEWEAPON])) { magstring = va("%i", cl.stats[STAT_CURRENTMAG2]); if (GetLowAmmo(cl.stats[STAT_ACTIVEWEAPON], 0) >= cl.stats[STAT_CURRENTMAG2]) { - Draw_ColoredString((vid.width - (89 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 0, 0, 255, text_scale_factor); + Draw_ColoredString((vid.width - (89 * hud_scale_factor)) - getTextWidth(magstring, hud_scale_factor), vid.height - (25 * hud_scale_factor), magstring, 255, 0, 0, 255, hud_scale_factor); } else { - Draw_ColoredString((vid.width - (89 * text_scale_factor)) - getTextWidth(magstring, text_scale_factor), vid.height - (25 * text_scale_factor), magstring, 255, 255, 255, 255, text_scale_factor); + Draw_ColoredString((vid.width - (89 * hud_scale_factor)) - getTextWidth(magstring, hud_scale_factor), vid.height - (25 * hud_scale_factor), magstring, 255, 255, 255, 255, hud_scale_factor); } } } @@ -1601,11 +1561,11 @@ void HUD_AmmoString (void) int x; if (0 < cl.stats[STAT_AMMO] && cl.stats[STAT_CURRENTMAG] >= 0) { - Draw_ColoredStringCentered(vid.height - (100 * text_scale_factor), "Reload", 255, 255, 255, 255, text_scale_factor); + Draw_ColoredStringCentered(vid.height - (100 * hud_scale_factor), "Reload", 255, 255, 255, 255, hud_scale_factor); } else if (0 < cl.stats[STAT_CURRENTMAG]) { - Draw_ColoredStringCentered(vid.height - (100 * text_scale_factor), "LOW AMMO", 255, 255, 0, 255, text_scale_factor); + Draw_ColoredStringCentered(vid.height - (100 * hud_scale_factor), "LOW AMMO", 255, 255, 0, 255, hud_scale_factor); } else { - Draw_ColoredStringCentered(vid.height - (100 * text_scale_factor), "NO AMMO", 255, 0, 0, 255, text_scale_factor); + Draw_ColoredStringCentered(vid.height - (100 * hud_scale_factor), "NO AMMO", 255, 0, 0, 255, hud_scale_factor); } } } @@ -1620,23 +1580,23 @@ HUD_Grenades void HUD_Grenades (void) { - Draw_StretchPic (vid.width - (53 * text_scale_factor), vid.height - (40 * text_scale_factor), fragpic, 22 * text_scale_factor, 22 * text_scale_factor); + Draw_StretchPic (vid.width - (53 * hud_scale_factor), vid.height - (40 * hud_scale_factor), fragpic, 22 * hud_scale_factor, 22 * hud_scale_factor); if (cl.stats[STAT_GRENADES] & UI_FRAG) { if (cl.stats[STAT_PRIGRENADES] <= 0) - Draw_ColoredString (vid.width - (40 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 0, 0, 255, text_scale_factor); + Draw_ColoredString (vid.width - (40 * hud_scale_factor), vid.height - (25 * hud_scale_factor), va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 0, 0, 255, hud_scale_factor); else - Draw_ColoredString (vid.width - (40 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 255, 255, 255, text_scale_factor); + Draw_ColoredString (vid.width - (40 * hud_scale_factor), vid.height - (25 * hud_scale_factor), va ("%i",cl.stats[STAT_PRIGRENADES]), 255, 255, 255, 255, hud_scale_factor); } if (cl.stats[STAT_GRENADES] & UI_BETTY) { - Draw_StretchPic (vid.width - (32 * text_scale_factor), vid.height - (40 * text_scale_factor), bettypic, 22 * text_scale_factor, 22 * text_scale_factor); + Draw_StretchPic (vid.width - (32 * hud_scale_factor), vid.height - (40 * hud_scale_factor), bettypic, 22 * hud_scale_factor, 22 * hud_scale_factor); if (cl.stats[STAT_PRIGRENADES] <= 0) - Draw_ColoredString (vid.width - (17 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_SECGRENADES]), 255, 0, 0, 255, text_scale_factor); + Draw_ColoredString (vid.width - (17 * hud_scale_factor), vid.height - (25 * hud_scale_factor), va ("%i",cl.stats[STAT_SECGRENADES]), 255, 0, 0, 255, hud_scale_factor); else - Draw_ColoredString (vid.width - (17 * text_scale_factor), vid.height - (25 * text_scale_factor), va ("%i",cl.stats[STAT_SECGRENADES]), 255, 255, 255, 255, text_scale_factor); + Draw_ColoredString (vid.width - (17 * hud_scale_factor), vid.height - (25 * hud_scale_factor), va ("%i",cl.stats[STAT_SECGRENADES]), 255, 255, 255, 255, hud_scale_factor); } } @@ -1650,13 +1610,13 @@ void HUD_Weapon (void) char str[32]; float l; x_value = vid.width; - y_value = vid.height - (40 * text_scale_factor); + y_value = vid.height - (40 * hud_scale_factor); strcpy(str, pr_strings+sv_player->v.Weapon_Name); l = strlen(str); - x_value = (vid.width - (55 * text_scale_factor)) - getTextWidth(str, text_scale_factor); - Draw_ColoredString (x_value, y_value, str, 255, 255, 255, 255, text_scale_factor); + x_value = (vid.width - (55 * hud_scale_factor)) - getTextWidth(str, hud_scale_factor); + Draw_ColoredString (x_value, y_value, str, 255, 255, 255, 255, hud_scale_factor); } /*a @@ -1707,9 +1667,9 @@ void HUD_BettyPrompt (void) strcpy(str, "Press to\n"); strcpy(str2, "place a Bouncing Betty"); - Draw_ColoredStringCentered((70 * text_scale_factor), str, 255, 255, 255, 255, text_scale_factor); - Draw_ColoredStringCentered((90 * text_scale_factor), str2, 255, 255, 255, 255, text_scale_factor); - Draw_Pic (200 * text_scale_factor + 14, 68 * text_scale_factor, b_minus); + Draw_ColoredStringCentered((70 * hud_scale_factor), str, 255, 255, 255, 255, hud_scale_factor); + Draw_ColoredStringCentered((90 * hud_scale_factor), str2, 255, 255, 255, 255, hud_scale_factor); + Draw_Pic (200 * hud_scale_factor + 14, 68 * hud_scale_factor, b_minus); #endif // __PSP__, _3DS, __WII__ } @@ -1726,7 +1686,7 @@ void HUD_PlayerName (void) if (nameprint_time - sv.time < 1) alpha = (int)((nameprint_time - sv.time)*255); - Draw_ColoredString(70 * text_scale_factor, vid.height - (70 * text_scale_factor), player_name, 255, 255, 255, alpha, text_scale_factor); + Draw_ColoredString(70 * hud_scale_factor, vid.height - (70 * hud_scale_factor), player_name, 255, 255, 255, alpha, hud_scale_factor); } /* @@ -1830,11 +1790,7 @@ void HUD_Draw (void) return; } -#ifdef __WII__ if (cl.stats[STAT_HEALTH] <= 0 || showscoreboard == true) -#else - if (cl.stats[STAT_HEALTH] <= 0) -#endif // __WII__ { HUD_EndScreen (); @@ -1842,10 +1798,7 @@ void HUD_Draw (void) if (screenflash_duration > sv.time) HUD_Screenflash(); -#ifdef __WII__ - if (cl.stats[STAT_HEALTH] <= 0) -#endif // __WII__ - return; + return; } if (bettyprompt_time > sv.time) diff --git a/source/cl_input.c b/source/cl_input.c index b5cbe21..186f204 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -487,7 +487,7 @@ int EN_Find(int num,char *string) } #ifdef __WII__ -qboolean aimsnap = false; +extern qboolean aimsnap; #endif void CL_Aim_Snap(void) { @@ -651,7 +651,7 @@ void CL_SendMove (usercmd_t *cmd) ycrossnormal = (cl_crossy.value / (vid.height/2)) * IR_PITCHRANGE; // sB lock crosshair in the center of screen - if(aimsnap == true || (cl.stats[STAT_ZOOM] == 1 && ads_center.value) || sniper_center.value) { + if(aimsnap == true || (cl.stats[STAT_ZOOM] == 1 && ads_center.value) || (cl.stats[STAT_ZOOM] == 2 && sniper_center.value)) { MSG_WriteFloat (&buf, tempv[PITCH]/* + (cl_crossy.value/vid.height) * IR_PITCHRANGE*/); MSG_WriteFloat (&buf, tempv[YAW]/* - (cl_crossx.value/vid.width - 1) * IR_YAWRANGE*/); MSG_WriteFloat (&buf, tempv[ROLL]); diff --git a/source/console.c b/source/console.c index a2e44ab..b3d7944 100644 --- a/source/console.c +++ b/source/console.c @@ -622,12 +622,14 @@ void Con_DrawConsole (int lines, qboolean drawinput) } // draw the input prompt, user text, and cursor if desired +#ifndef __WII__ if (drawinput) Con_DrawInput (); +#endif // __WII__ #ifndef _3DS Con_DrawOSK(); -#endif // __PSP__ +#endif // __PSP__, __WII__ } #ifndef _3DS @@ -649,7 +651,7 @@ void Con_DrawOSK(void) { M_OSK_Draw(); } } -#endif // __PSP__ +#endif // __PSP__, __WII__ /* ================== diff --git a/source/host.c b/source/host.c index efbdcde..50b9af8 100644 --- a/source/host.c +++ b/source/host.c @@ -951,8 +951,9 @@ void Host_Init (quakeparms_t *parms) if (!host_h2pal) Sys_Error ("Couldn't load gfx/h2pal.lmp"); #endif // __PSP__ - +#ifndef __WII__ IN_Init (); +#endif VID_Init (host_basepal); Draw_Init (); SCR_Init (); @@ -961,6 +962,9 @@ void Host_Init (quakeparms_t *parms) CDAudio_Init (); HUD_Init (); CL_Init (); +#ifdef __WII__ + IN_Init (); +#endif //the Wii requires initialization of input AFTER client is initializd } Preload(); Cbuf_InsertText ("exec nzp.rc\n"); diff --git a/source/view.c b/source/view.c index 1b9956e..fabd9fa 100644 --- a/source/view.c +++ b/source/view.c @@ -57,8 +57,8 @@ cvar_t cl_bobsidecycle = {"cl_bobsidecycle","0.9"}; cvar_t cl_bobsideup = {"cl_bobsideup","0.5"}; #ifdef __WII__ -cvar_t cl_crossx = {"cl_crossx", "0", false}; -cvar_t cl_crossy = {"cl_crossy", "0", false}; +cvar_t cl_crossx = {"cl_crossx", "0"}; +cvar_t cl_crossy = {"cl_crossy", "0"}; cvar_t cl_weapon_inrollangle = {"cl_weapon_inrollangle", "0", true}; #endif @@ -819,8 +819,8 @@ void CalcGunAngle (void) float roll_og_pos; float inroll_smooth; - float last_roll = 0.0f; - static float smooth_amt = 0.001f; + //float last_roll = 0.0f; + //static float smooth_amt = 0.001f; if (aimsnap == false && !(cl.stats[STAT_ZOOM] == 1 && ads_center.value) && lock_viewmodel != 1 && !(cl.stats[STAT_ZOOM] == 2 && sniper_center.value)) { @@ -849,7 +849,7 @@ void CalcGunAngle (void) //Con_Printf("roll: %f\n", inroll_smooth); cl.viewent.angles[ROLL] = inroll_smooth; - last_roll = roll_og_pos; + //last_roll = roll_og_pos; } } } From d9bf7bc1990597218ae842e4c48a7a6b695b85ab Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Mon, 7 Oct 2024 16:04:43 -0400 Subject: [PATCH 17/20] Upload GX specific files --- source/wii/cdaudio.c | 106 + source/wii/client.h | 419 + source/wii/common.c | 1836 + source/wii/common.h | 192 + source/wii/gx/128_128_datamap.h | 65555 ++++++++++++++++++++++++++++++ source/wii/gx/anorm_dots.h | 37 + source/wii/gx/gx_decal.c | 658 + source/wii/gx/gx_decal.h | 2 + source/wii/gx/gx_draw.c | 1432 + source/wii/gx/gx_fog.c | 357 + source/wii/gx/gx_mesh.c | 316 + source/wii/gx/gx_model.c | 2202 + source/wii/gx/gx_model.h | 468 + source/wii/gx/gx_qmb.c | 3061 ++ source/wii/gx/gx_refrag.c | 234 + source/wii/gx/gx_rlight.c | 297 + source/wii/gx/gx_rmain.c | 2072 + source/wii/gx/gx_rmisc.c | 423 + source/wii/gx/gx_rpart.c | 858 + source/wii/gx/gx_rsurf.c | 1534 + source/wii/gx/gx_screen.c | 1796 + source/wii/gx/gx_textures.c | 1221 + source/wii/gx/gx_warp.c | 784 + source/wii/gx/gx_warp_sin.h | 51 + source/wii/gx/gxquake.h | 428 + source/wii/gx/video_gx.c | 341 + source/wii/input.c | 842 + source/wii/input_wiimote.h | 26 + source/wii/keys.c | 1023 + source/wii/keys.h | 149 + source/wii/main.c | 264 + source/wii/menu.c | 3597 ++ source/wii/menu.h | 37 + source/wii/modelgen.h | 134 + source/wii/net.h | 317 + source/wii/net_dgrm.c | 1373 + source/wii/net_dgrm.h | 34 + source/wii/net_main.c | 997 + source/wii/net_udp_wii.c | 532 + source/wii/net_udp_wii.h | 39 + source/wii/net_wii.c | 94 + source/wii/render.h | 211 + source/wii/sbar.c | 402 + source/wii/sbar.h | 39 + source/wii/screen.h | 63 + source/wii/server.h | 269 + source/wii/sound.c | 117 + source/wii/sys.h | 74 + source/wii/system.c | 307 + source/wii/vid.h | 77 + 50 files changed, 97697 insertions(+) create mode 100644 source/wii/cdaudio.c create mode 100644 source/wii/client.h create mode 100644 source/wii/common.c create mode 100644 source/wii/common.h create mode 100644 source/wii/gx/128_128_datamap.h create mode 100644 source/wii/gx/anorm_dots.h create mode 100644 source/wii/gx/gx_decal.c create mode 100644 source/wii/gx/gx_decal.h create mode 100644 source/wii/gx/gx_draw.c create mode 100644 source/wii/gx/gx_fog.c create mode 100644 source/wii/gx/gx_mesh.c create mode 100644 source/wii/gx/gx_model.c create mode 100644 source/wii/gx/gx_model.h create mode 100644 source/wii/gx/gx_qmb.c create mode 100644 source/wii/gx/gx_refrag.c create mode 100644 source/wii/gx/gx_rlight.c create mode 100644 source/wii/gx/gx_rmain.c create mode 100644 source/wii/gx/gx_rmisc.c create mode 100644 source/wii/gx/gx_rpart.c create mode 100644 source/wii/gx/gx_rsurf.c create mode 100644 source/wii/gx/gx_screen.c create mode 100644 source/wii/gx/gx_textures.c create mode 100644 source/wii/gx/gx_warp.c create mode 100644 source/wii/gx/gx_warp_sin.h create mode 100644 source/wii/gx/gxquake.h create mode 100644 source/wii/gx/video_gx.c create mode 100644 source/wii/input.c create mode 100644 source/wii/input_wiimote.h create mode 100644 source/wii/keys.c create mode 100644 source/wii/keys.h create mode 100644 source/wii/main.c create mode 100644 source/wii/menu.c create mode 100644 source/wii/menu.h create mode 100644 source/wii/modelgen.h create mode 100644 source/wii/net.h create mode 100644 source/wii/net_dgrm.c create mode 100644 source/wii/net_dgrm.h create mode 100644 source/wii/net_main.c create mode 100644 source/wii/net_udp_wii.c create mode 100644 source/wii/net_udp_wii.h create mode 100644 source/wii/net_wii.c create mode 100644 source/wii/render.h create mode 100644 source/wii/sbar.c create mode 100644 source/wii/sbar.h create mode 100644 source/wii/screen.h create mode 100644 source/wii/server.h create mode 100644 source/wii/sound.c create mode 100644 source/wii/sys.h create mode 100644 source/wii/system.c create mode 100644 source/wii/vid.h diff --git a/source/wii/cdaudio.c b/source/wii/cdaudio.c new file mode 100644 index 0000000..38bb55b --- /dev/null +++ b/source/wii/cdaudio.c @@ -0,0 +1,106 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "../quakedef.h" +#include +#include + +// sB MP3 Playback +// will expand to add OGG support in future? + +byte* mp3_data; +qboolean stopmp3 = false; + +void CDAudio_Play(byte track, qboolean looping) +{ + return; +} + +void CDAudio_PlayFromString(char* track_name, qboolean looping) +{ + stopmp3 = false; + byte *mp3buffer; + + mp3buffer = COM_LoadFile (track_name, 5); + + if (mp3buffer == NULL) { + Con_Printf("NULL MP3: %s\n", track_name); + return; + } + + mp3_data = mp3buffer; + + MP3Player_Volume(255); + + MP3Player_PlayBuffer (mp3buffer, com_filesize, NULL); + + return; +} + +void CDAudio_Stop(void) +{ + stopmp3 = true; +} + + +void CDAudio_Pause(void) +{ +} + + +void CDAudio_Resume(void) +{ + stopmp3 = false; +} + + +void CDAudio_Update(void) +{ + qboolean isplaying; + + isplaying = MP3Player_IsPlaying (); + + if (isplaying == false) { + free (mp3_data); + stopmp3 = true; + } + + if (stopmp3 == true) { + if (mp3_data) { + free (mp3_data); + } + } + +} + + +int CDAudio_Init(void) +{ + /* + ASND_Init(); + MP3Player_Init(); + */ + return 0; +} + + +void CDAudio_Shutdown(void) +{ + stopmp3 = true; +} diff --git a/source/wii/client.h b/source/wii/client.h new file mode 100644 index 0000000..5fc99e2 --- /dev/null +++ b/source/wii/client.h @@ -0,0 +1,419 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// client.h + +typedef struct +{ + vec3_t viewangles; + +// intended velocities + float forwardmove; + float sidemove; + float upmove; +#ifdef QUAKE2 + byte lightlevel; +#endif +} usercmd_t; + +typedef struct +{ + int length; + char map[MAX_STYLESTRING]; + char average; //johnfitz + char peak; //johnfitz +} lightstyle_t; + +typedef struct +{ + char name[MAX_SCOREBOARDNAME]; + float entertime; + int points; + int maxpoints; + int kills; + int headshots; +} scoreboard_t; + +typedef enum +{ + lt_default, lt_muzzleflash, lt_explosion, lt_rocket, + lt_red, lt_blue, lt_redblue, lt_green, NUM_DLIGHTTYPES, + lt_explosion2, lt_explosion3, lt_rayred, lt_raygreen +} dlighttype_t; + +typedef struct +{ + int destcolor[3]; + int percent; // 0-256 +} cshift_t; + +#define CSHIFT_CONTENTS 0 +#define CSHIFT_DAMAGE 1 +#define CSHIFT_BONUS 2 +#define CSHIFT_POWERUP 3 +#define NUM_CSHIFTS 4 + +#define NAME_LENGTH 64 + + +// +// client_state_t should hold all pieces of the client state +// + +#define SIGNONS 4 // signon messages to receive before connected + +#define MAX_DLIGHTS 32 +typedef struct +{ + vec3_t origin; + float radius; + float die; // stop lighting after this time + float decay; // drop this each second + float minlight; // don't add when contributing less + int key; +#ifdef QUAKE2 + qboolean dark; // subtracts light instead of adding +#endif + vec3_t color; //LordHavoc Lit. Support + int type; // color +} dlight_t; + + +#define MAX_BEAMS 24 +typedef struct +{ + int entity; + struct model_s *model; + float endtime; + vec3_t start, end; +} beam_t; + +#define MAX_EFRAGS 640 + +#define MAX_MAPSTRING 2048 +#define MAX_DEMOS 8 +#define MAX_DEMONAME 16 + +typedef enum { +ca_dedicated, // a dedicated server with no ability to start a client +ca_disconnected, // full screen console with no connection +ca_connected // valid netcon, talking to a server +} cactive_t; + +// +// the client_static_t structure is persistant through an arbitrary number +// of server connections +// +typedef struct +{ + cactive_t state; + +// personalization data sent to server + char mapstring[MAX_QPATH]; + char spawnparms[MAX_MAPSTRING]; // to restart a level + +// demo loop control + int demonum; // -1 = don't play demos + char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing + +// demo recording info must be here, because record is started before +// entering a map (and clearing client_state_t) + qboolean demorecording; + qboolean demoplayback; + qboolean timedemo; + int forcetrack; // -1 = use normal cd track + int demofile; + int td_lastframe; // to meter out one message a frame + int td_startframe; // host_framecount at start + float td_starttime; // realtime at second frame of timedemo + + +// connection information + int signon; // 0 to SIGNONS + struct qsocket_s *netcon; + sizebuf_t message; // writing buffer to send to server + +} client_static_t; + +extern client_static_t cls; + +typedef struct +{ + int movemessages; // since connecting to this server + // throw out the first couple, so the player + // doesn't accidentally do something the + // first frame + usercmd_t cmd; // last command sent to the server + +// information for local display + int stats[MAX_CL_STATS]; // health, etc + int perks; // Perk icons. + int progress_bar; // Perk icons. + float item_gettime[32]; // cl.time of aquiring item, for blinking + float faceanimtime; // use anim frame if cl.time < this + + cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups + cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types + +// the client maintains its own idea of view angles, which are +// sent to the server each frame. The server sets punchangle when +// the view is temporarliy offset, and an angle reset commands at the start +// of each level and after teleporting. + vec3_t mviewangles[2]; // during demo playback viewangles is lerped + // between these + vec3_t viewangles; + + vec3_t mvelocity[2]; // update by server, used for lean+bob + // (0 is newest) + vec3_t velocity; // lerped between mvelocity[0] and [1] + + vec3_t punchangle; // temporary offset + vec3_t gun_kick; // temporary kick + +// pitch drifting vars + float idealpitch; + float pitchvel; + qboolean nodrift; + float driftmove; + double laststop; + + float viewheight; + float crouch; // local amount for smoothing stepups + + qboolean paused; // send over by server + qboolean onground; + qboolean inwater; + + int intermission; // don't change view angle, full screen, etc + int completed_time; // latched at intermission start + + double mtime[2]; // the timestamp of last two messages + double time; // clients view of time, should be between + // servertime and oldservertime to generate + // a lerp point for other data + double oldtime; // previous cl.time, time-oldtime is used + // to decay light values and smooth step ups + double ctime; // joe: copy of cl.time, to avoid incidents caused by rewind + + + float last_received_message; // (realtime) for net trouble icon + double laser_point_time; + +// +// information that is static for the entire time connected to a server +// + struct model_s *model_precache[MAX_MODELS]; + struct sfx_s *sound_precache[MAX_SOUNDS]; + + char levelname[40]; // for display on solo scoreboard + int viewentity; // cl_entitites[cl.viewentity] = player + int maxclients; + int gametype; + +// refresh related state + struct model_s *worldmodel; // cl_entitites[0].model + struct efrag_s *free_efrags; + int num_entities; // held in cl_entities array + int num_statics; // held in cl_staticentities array + entity_t viewent; // the gun model + entity_t viewent2; // the second gun model + + int cdtrack, looptrack; // cd audio + +// frag scoreboard + scoreboard_t *scores; // [cl.maxclients] + +#ifdef QUAKE2 +// light level at player's position including dlights +// this is sent back to the server each frame +// architectually ugly but it works + int light_level; +#endif +} client_state_t; + + +// +// cvars +// +extern cvar_t cl_name; + +extern cvar_t cl_upspeed; +extern float cl_forwardspeed; +extern float cl_backspeed; +extern float cl_sidespeed; + +extern cvar_t cl_movespeedkey; +extern cvar_t cl_anglespeedkey; + +extern cvar_t cl_yawspeed; +extern cvar_t cl_pitchspeed; + +extern cvar_t cl_autofire; + +extern cvar_t cl_shownet; +extern cvar_t cl_nolerp; + +extern cvar_t cl_pitchdriftspeed; +extern cvar_t lookspring; +extern cvar_t lookstrafe; +extern cvar_t sensitivity; +extern cvar_t in_aimassist; +extern cvar_t ads_center; +extern cvar_t sniper_center; + +extern cvar_t m_pitch; +extern cvar_t m_yaw; +extern cvar_t m_forward; +extern cvar_t m_side; +extern cvar_t in_mlook; + + +#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc +#define MAX_STATIC_ENTITIES 256 // torches, etc + +extern client_state_t cl; + +// FIXME, allocate dynamically +extern efrag_t cl_efrags[MAX_EFRAGS]; +extern entity_t cl_entities[MAX_EDICTS]; +extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; +extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; +extern dlight_t cl_dlights[MAX_DLIGHTS]; +extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; +extern beam_t cl_beams[MAX_BEAMS]; + +//============================================================================= + +// +// cl_main +// +dlight_t *CL_AllocDlight (int key); +void CL_DecayLights (void); + +void CL_Init (void); + +void CL_EstablishConnection (char *host); +void CL_Signon1 (void); +void CL_Signon2 (void); +void CL_Signon3 (void); +void CL_Signon4 (void); + +void CL_Disconnect (void); +void CL_Disconnect_f (void); +void CL_NextDemo (void); + +#define MAX_VISEDICTS 256 +extern int cl_numvisedicts; +extern entity_t *cl_visedicts[MAX_VISEDICTS]; +extern int cl_numstaticbrushmodels; +extern entity_t *cl_staticbrushmodels[MAX_VISEDICTS]; + +// +// model indexes +typedef enum modelindex_s +{ + mi_player, + mi_eyes, + mi_flame0, + mi_flame1, + mi_flame2, + mi_q3torso, + mi_q3head, +/* + mi_vw_light, + mi_vw_nail1, + mi_vw_nail2, + mi_vw_rock1, + mi_vw_rock2, + mi_vw_shot1, + mi_vw_shot2, + mi_vw_player, +*/ + NUM_MODELINDEX +} modelindex_t; + +extern modelindex_t cl_modelindex[NUM_MODELINDEX]; +extern char *cl_modelnames[NUM_MODELINDEX]; +// cl_input +// +typedef struct +{ + int down[2]; // key nums holding it down + int state; // low bit is down state +} kbutton_t; + +extern kbutton_t in_vlock, in_klook; +extern kbutton_t in_strafe; +extern kbutton_t in_speed; + +void CL_InitInput (void); +void CL_SendCmd (void); +void CL_SendMove (usercmd_t *cmd); + +void CL_ParseTEnt (void); +void CL_UpdateTEnts (void); + +void CL_ClearState (void); + + +int CL_ReadFromServer (void); +void CL_WriteToServer (usercmd_t *cmd); +void CL_BaseMove (usercmd_t *cmd); + + +float CL_KeyState (kbutton_t *key); +char *Key_KeynumToString (int keynum); + +// +// cl_demo.c +// +void CL_StopPlayback (void); +int CL_GetMessage (void); + +void CL_Stop_f (void); +void CL_Record_f (void); +void CL_PlayDemo_f (void); +void CL_TimeDemo_f (void); + +// +// cl_parse.c +// +void CL_ParseServerMessage (void); +void CL_NewTranslation (int slot); + +// +// view +// +void V_StartPitchDrift (void); +void V_StopPitchDrift (void); + +void V_RenderView (void); +void V_UpdatePalette (void); +void V_Register (void); +void V_ParseDamage (void); +void V_SetContentsColor (int contents); + + +// +// cl_tent +// +void CL_InitTEnts (void); +void CL_SignonReply (void); + +qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); \ No newline at end of file diff --git a/source/wii/common.c b/source/wii/common.c new file mode 100644 index 0000000..3e2b3db --- /dev/null +++ b/source/wii/common.c @@ -0,0 +1,1836 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// common.c -- misc functions used in client and server + +#include "../quakedef.h" + +#define NUM_SAFE_ARGVS 7 + +static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1]; +static char *argvdummy = " "; + +static char *safeargvs[NUM_SAFE_ARGVS] = + {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse", "-dibonly"}; + +cvar_t registered = {"registered","1"}; +cvar_t cmdline = {"cmdline","0", false, true}; + +qboolean com_modified; // set true if using non-id files + +qboolean proghack; + +int static_registered = 1; // only for startup check, then set + +qboolean msg_suppress_1 = 0; + +void COM_InitFilesystem (void); + +// if a packfile directory differs from this, it is assumed to be hacked +#define PAK0_COUNT 339 +#define PAK0_CRC 32981 + +char com_token[1024]; +int com_argc; +char **com_argv; + +#define CMDLINE_LENGTH 256 +char com_cmdline[CMDLINE_LENGTH]; + +qboolean standard_quake = true, rogue, hipnotic; + +// this graphic needs to be in the pak file to use registered features +unsigned short pop[] = +{ + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000 +,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000 +,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600 +,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563 +,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564 +,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564 +,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563 +,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500 +,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200 +,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000 +,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000 +,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000 +}; + +/* + + +All of Quake's data access is through a hierchal file system, but the contents of the file system can be transparently merged from several sources. + +The "base directory" is the path to the directory holding the quake.exe and all game directories. The sys_* files pass this to host_init in quakeparms_t->basedir. This can be overridden with the "-basedir" command line parm to allow code debugging in a different directory. The base directory is +only used during filesystem initialization. + +The "game directory" is the first tree on the search path and directory that all generated files (savegames, screenshots, demos, config files) will be saved to. This can be overridden with the "-game" command line parameter. The game directory can never be changed while quake is executing. This is a precacution against having a malicious server instruct clients to write files over areas they shouldn't. + +The "cache directory" is only used during development to save network bandwidth, especially over ISDN / T1 lines. If there is a cache directory +specified, when a file is found by the normal search path, it will be mirrored +into the cache directory, then opened there. + + + +FIXME: +The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line. + +*/ + +//============================================================================ + + +// ClearLink is used for new headnodes +void ClearLink (link_t *l) +{ + l->prev = l->next = l; +} + +void RemoveLink (link_t *l) +{ + l->next->prev = l->prev; + l->prev->next = l->next; +} + +void InsertLinkBefore (link_t *l, link_t *before) +{ + l->next = before; + l->prev = before->prev; + l->prev->next = l; + l->next->prev = l; +} +void InsertLinkAfter (link_t *l, link_t *after) +{ + l->next = after->next; + l->prev = after; + l->prev->next = l; + l->next->prev = l; +} + +/* +============================================================================ + + LIBRARY REPLACEMENT FUNCTIONS + +============================================================================ +*/ + +void Q_memset (void *dest, int fill, int count) +{ + int i; + + if ( (((long)dest | count) & 3) == 0) + { + count >>= 2; + fill = fill | (fill<<8) | (fill<<16) | (fill<<24); + for (i=0 ; i>=2; + for (i=0 ; i= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + if (!c1) + return 0; // strings are equal +// s1++; +// s2++; + } + + return -1; +} + +int Q_strcasecmp (char *s1, char *s2) +{ + return strncasecmp (s1, s2, 99999); +} + +int Q_atoi (char *str) +{ + int val; + int sign; + int c; + + if (*str == '-') + { + sign = -1; + str++; + } + else + sign = 1; + + val = 0; + +// +// check for hex +// + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) + { + str += 2; + while (1) + { + c = *str++; + if (c >= '0' && c <= '9') + val = (val<<4) + c - '0'; + else if (c >= 'a' && c <= 'f') + val = (val<<4) + c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = (val<<4) + c - 'A' + 10; + else + return val*sign; + } + } + +// +// check for character +// + if (str[0] == '\'') + { + return sign * str[1]; + } + +// +// assume decimal +// + while (1) + { + c = *str++; + if (c <'0' || c > '9') + return val*sign; + val = val*10 + c - '0'; + } + + return 0; +} + + +float Q_atof (char *str) +{ + float val; + int sign; + int c; + int decimal, total; + + if (*str == '-') + { + sign = -1; + str++; + } + else + sign = 1; + + val = 0; + +// +// check for hex +// + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) + { + str += 2; + while (1) + { + c = *str++; + if (c >= '0' && c <= '9') + val = (val*16) + c - '0'; + else if (c >= 'a' && c <= 'f') + val = (val*16) + c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + val = (val*16) + c - 'A' + 10; + else + return val*sign; + } + } + +// +// check for character +// + if (str[0] == '\'') + { + return sign * str[1]; + } + +// +// assume decimal +// + decimal = -1; + total = 0; + while (1) + { + c = *str++; + if (c == '.') + { + decimal = total; + continue; + } + if (c <'0' || c > '9') + break; + val = val*10 + c - '0'; + total++; + } + + if (decimal == -1) + return val*sign; + while (total > decimal) + { + val /= 10; + total--; + } + + return val*sign; +} + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +qboolean bigendien; + +short (*BigShort) (short l); +short (*LittleShort) (short l); +int (*BigLong) (int l); +int (*LittleLong) (int l); +float (*BigFloat) (float l); +float (*LittleFloat) (float l); + +short ShortSwap (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) | b2; +} + +short ShortNoSwap (short l) +{ + return l; +} + +int LongSwap (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) | ((int)b2<<16) | ((int)b3<<8) | b4; +} + +int LongNoSwap (int l) +{ + return l; +} + +float FloatSwap (float f) +{ + union + { + float f; + byte b[4]; + } dat1, dat2; + + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; +} + +float FloatNoSwap (float f) +{ + return f; +} + +/* +============================================================================== + + MESSAGE IO FUNCTIONS + +Handles byte ordering and avoids alignment errors +============================================================================== +*/ + +// +// writing functions +// + +void MSG_WriteChar (sizebuf_t *sb, int c) +{ + byte *buf; + +#ifdef PARANOID + if (c < -128 || c > 127) + Sys_Error ("MSG_WriteChar: range error"); +#endif + + buf = SZ_GetSpace (sb, 1); + buf[0] = c; +} + +void MSG_WriteByte (sizebuf_t *sb, int c) +{ + byte *buf; + +#ifdef PARANOID + if (c < 0 || c > 255) + Sys_Error ("MSG_WriteByte: range error"); +#endif + + buf = SZ_GetSpace (sb, 1); + buf[0] = c; +} + +void MSG_WriteShort (sizebuf_t *sb, int c) +{ + byte *buf; + +#ifdef PARANOID + if (c < ((short)0x8000) || c > (short)0x7fff) + Sys_Error ("MSG_WriteShort: range error"); +#endif + + buf = SZ_GetSpace (sb, 2); + buf[0] = c&0xff; + buf[1] = c>>8; +} + +void MSG_WriteLong (sizebuf_t *sb, int c) +{ + byte *buf; + + buf = SZ_GetSpace (sb, 4); + buf[0] = c&0xff; + buf[1] = (c>>8)&0xff; + buf[2] = (c>>16)&0xff; + buf[3] = c>>24; +} + +void MSG_WriteFloat (sizebuf_t *sb, float f) +{ + union + { + float f; + int l; + } dat; + + + dat.f = f; + dat.l = LittleLong (dat.l); + + SZ_Write (sb, &dat.l, 4); +} + +void MSG_WriteString (sizebuf_t *sb, char *s) +{ + if (!s) + SZ_Write (sb, "", 1); + else + SZ_Write (sb, s, strlen(s)+1); +} + +void MSG_WriteCoord (sizebuf_t *sb, float f) +{ + MSG_WriteShort (sb, (int)(f*8)); +} + +void MSG_WriteAngle (sizebuf_t *sb, float f) +{ + MSG_WriteByte (sb, ((int)f*256/360) & 255); +} + +// +// reading functions +// +int msg_readcount; +qboolean msg_badread; + +void MSG_BeginReading (void) +{ + msg_readcount = 0; + msg_badread = false; +} + +// returns -1 and sets msg_badread if no more characters are available +int MSG_ReadChar (void) +{ + int c; + + if (msg_readcount+1 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = (signed char)net_message.data[msg_readcount]; + msg_readcount++; + + return c; +} + +int MSG_ReadByte (void) +{ + int c; + + if (msg_readcount+1 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = (unsigned char)net_message.data[msg_readcount]; + msg_readcount++; + + return c; +} + +int MSG_ReadShort (void) +{ + int c; + + if (msg_readcount+2 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = (short)(net_message.data[msg_readcount] + + (net_message.data[msg_readcount+1]<<8)); + + msg_readcount += 2; + + return c; +} + +int MSG_ReadLong (void) +{ + int c; + + if (msg_readcount+4 > net_message.cursize) + { + msg_badread = true; + return -1; + } + + c = net_message.data[msg_readcount] + + (net_message.data[msg_readcount+1]<<8) + + (net_message.data[msg_readcount+2]<<16) + + (net_message.data[msg_readcount+3]<<24); + + msg_readcount += 4; + + return c; +} + +float MSG_ReadFloat (void) +{ + union + { + byte b[4]; + float f; + int l; + } dat; + + dat.b[0] = net_message.data[msg_readcount]; + dat.b[1] = net_message.data[msg_readcount+1]; + dat.b[2] = net_message.data[msg_readcount+2]; + dat.b[3] = net_message.data[msg_readcount+3]; + msg_readcount += 4; + + dat.l = LittleLong (dat.l); + + return dat.f; +} + +char *MSG_ReadString (void) +{ + static char string[2048]; + int l,c; + + l = 0; + do + { + c = MSG_ReadChar (); + if (c == -1 || c == 0) + break; + string[l] = c; + l++; + } while (l < sizeof(string)-1); + + string[l] = 0; + + return string; +} + +float MSG_ReadCoord (void) +{ + return MSG_ReadShort() * (1.0f/8); +} + +float MSG_ReadAngle (void) +{ + return MSG_ReadChar() * (360.0f/256); +} + + + +//=========================================================================== + +void SZ_Alloc (sizebuf_t *buf, int startsize) +{ + if (startsize < 256) + startsize = 256; + buf->data = Hunk_AllocName (startsize, "sizebuf"); + buf->maxsize = startsize; + buf->cursize = 0; +} + + +void SZ_Free (sizebuf_t *buf) +{ +// Z_Free (buf->data); +// buf->data = NULL; +// buf->maxsize = 0; + buf->cursize = 0; +} + +void SZ_Clear (sizebuf_t *buf) +{ + buf->cursize = 0; +} + +void *SZ_GetSpace (sizebuf_t *buf, int length) +{ + void *data; + + if (buf->cursize + length > buf->maxsize) + { + if (!buf->allowoverflow) + Sys_Error ("SZ_GetSpace: overflow without allowoverflow set"); + + if (length > buf->maxsize) + Sys_Error ("SZ_GetSpace: %i is > full buffer size", length); + + buf->overflowed = true; + Con_Printf ("SZ_GetSpace: overflow"); + SZ_Clear (buf); + } + + data = buf->data + buf->cursize; + buf->cursize += length; + + return data; +} + +void SZ_Write (sizebuf_t *buf, void *data, int length) +{ + memcpy (SZ_GetSpace(buf,length),data,length); +} + +void SZ_Print (sizebuf_t *buf, char *data) +{ + int len; + + len = strlen(data)+1; + +// byte * cast to keep VC++ happy + if (buf->data[buf->cursize-1]) + memcpy ((byte *)SZ_GetSpace(buf, len),data,len); // no trailing 0 + else + memcpy ((byte *)SZ_GetSpace(buf, len-1)-1,data,len); // write over trailing 0 +} + + +//============================================================================ + + +/* +============ +COM_SkipPath +============ +*/ +char *COM_SkipPath (char *pathname) +{ + char *last; + + last = pathname; + while (*pathname) + { + if (*pathname=='/') + last = pathname+1; + pathname++; + } + return last; +} + +/* +============ +COM_StripExtension +============ +*/ +void COM_StripExtension (char *in, char *out) +{ + while (*in && *in != '.') + *out++ = *in++; + *out = 0; +} + +/* +============ +COM_FileExtension +============ +*/ +char *COM_FileExtension (char *in) +{ + static char exten[8]; + int i; + + while (*in && *in != '.') + in++; + if (!*in) + return ""; + in++; + for (i=0 ; i<7 && *in ; i++,in++) + exten[i] = *in; + exten[i] = 0; + return exten; +} + +/* +============ +COM_FileBase +============ +*/ +void COM_FileBase (char *in, char *out) +{ + char *s, *s2; + + s = in + strlen(in) - 1; + + while (s != in && *s != '.') + s--; + + for (s2 = s ; *s2 && *s2 != '/' ; s2--) + ; + + if (s-s2 < 2) + strcpy (out,"?model?"); + else + { + s--; + strncpy (out,s2+1, s-s2); + out[s-s2] = 0; + } +} + + +/* +================== +COM_DefaultExtension +================== +*/ +void COM_DefaultExtension (char *path, char *extension) +{ + char *src; +// +// if path doesn't have a .EXT, append extension +// (extension should include the .) +// + src = path + strlen(path) - 1; + + while (*src != '/' && src != path) + { + if (*src == '.') + return; // it has an extension + src--; + } + + strcat (path, extension); +} + + +/* +============== +COM_Parse + +Parse a token out of a string +============== +*/ +char *COM_Parse (char *data) +{ + int c; + int len; + + len = 0; + com_token[0] = 0; + + if (!data) + return NULL; + +// skip whitespace +skipwhite: + while ( (c = *data) <= ' ') + { + if (c == 0) + return NULL; // end of file; + data++; + } + +// skip // comments + if (c=='/' && data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + + +// handle quoted strings specially + if (c == '\"') + { + data++; + while (1) + { + c = *data++; + if (c=='\"' || !c) + { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } + } + +// parse single characters + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + { + com_token[len] = c; + len++; + com_token[len] = 0; + return data+1; + } + +// parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + break; + } while (c>32); + + com_token[len] = 0; + return data; +} + + +/* +================ +COM_CheckParm + +Returns the position (1 to argc-1) in the program's argument list +where the given parameter apears, or 0 if not present +================ +*/ +int COM_CheckParm (char *parm) +{ + int i; + + for (i=1 ; inext) + { + if (s->pack) + { + Con_Printf ("%s (%i files)\n", s->pack->filename, s->pack->numfiles); + } + else + Con_Printf ("%s\n", s->filename); + } +} + +/* +============ +COM_WriteFile + +The filename will be prefixed by the current game directory +============ +*/ +void COM_WriteFile (char *filename, void *data, int len) +{ + int handle; + char name[MAX_OSPATH]; + + sprintf (name, "%s/%s", com_gamedir, filename); + + handle = Sys_FileOpenWrite (name); + if (handle == -1) + { + Sys_Printf ("COM_WriteFile: failed on %s\n", name); + return; + } + + Sys_Printf ("COM_WriteFile: %s\n", name); + Sys_FileWrite (handle, data, len); + Sys_FileClose (handle); +} + + +/* +============ +COM_CreatePath + +Only used for CopyFile +============ +*/ +void COM_CreatePath (char *path) +{ + char *ofs; + + for (ofs = path+1 ; *ofs ; ofs++) + { + if (*ofs == '/') + { // create the directory + *ofs = 0; + Sys_mkdir (path); + *ofs = '/'; + } + } +} + + +/* +=========== +COM_CopyFile + +Copies a file over from the net to the local cache, creating any directories +needed. This is for the convenience of developers using ISDN from home. +=========== +*/ +void COM_CopyFile (char *netpath, char *cachepath) +{ + int in, out; + int remaining, count; + char buf[4096]; + + remaining = Sys_FileOpenRead (netpath, &in); + COM_CreatePath (cachepath); // create directories up to the cache file + out = Sys_FileOpenWrite (cachepath); + + while (remaining) + { + if (remaining < sizeof(buf)) + count = remaining; + else + count = sizeof(buf); + Sys_FileRead (in, buf, count); + Sys_FileWrite (out, buf, count); + remaining -= count; + } + + Sys_FileClose (in); + Sys_FileClose (out); +} + +/* +=========== +COM_FindFile + +Finds the file in the search path. +Sets com_filesize and one of handle or file +=========== +*/ +int COM_FindFile (char *filename, int *handle, int *file) +{ + searchpath_t *search; + char netpath[MAX_OSPATH]; + char cachepath[MAX_OSPATH]; + pack_t *pak; + int i; + int findtime, cachetime; + + if (file && handle) + Sys_Error ("COM_FindFile: both handle and file set"); + if (!file && !handle) + Sys_Error ("COM_FindFile: neither handle or file set"); + +// +// search through the path, one element at a time +// + search = com_searchpaths; + if (proghack) + { // gross hack to use quake 1 progs with quake 2 maps + if (!strcmp(filename, "progs.dat")) + search = search->next; + } + + for ( ; search ; search = search->next) + { + // is the element a pak file? + if (search->pack) + { + // look through all the pak file elements + pak = search->pack; + for (i=0 ; inumfiles ; i++) + if (!strcmp (pak->files[i].name, filename)) + { // found it! + Sys_Printf ("PackFile: %s : %s\n",pak->filename, filename); + if (handle) + { + *handle = pak->handle; + Sys_FileSeek (pak->handle, pak->files[i].filepos); + } + else + { // open a new file on the pakfile + Sys_FileOpenRead(pak->filename, file); + if ((*file) >= 0) + Sys_FileSeek(*file, pak->files[i].filepos); + } + com_filesize = pak->files[i].filelen; + return com_filesize; + } + } + else + { + // check a file in the directory tree + if (!static_registered) + { // if not a registered version, don't ever go beyond base + if ( strchr (filename, '/') || strchr (filename,'\\')) + continue; + } + + sprintf (netpath, "%s/%s",search->filename, filename); + + findtime = Sys_FileTime (netpath); + if (findtime == -1) + continue; + + // see if the file needs to be updated in the cache + if (!com_cachedir[0]) + strcpy (cachepath, netpath); + else + { + sprintf (cachepath,"%s%s", com_cachedir, netpath); + + cachetime = Sys_FileTime (cachepath); + + if (cachetime < findtime) + COM_CopyFile (netpath, cachepath); + strcpy (netpath, cachepath); + } + + Sys_Printf ("FindFile: %s\n",netpath); + com_filesize = Sys_FileOpenRead (netpath, &i); + if (handle) + *handle = i; + else + { + Sys_FileClose (i); + Sys_FileOpenRead(netpath, file); + } + return com_filesize; + } + + } + + Sys_Printf ("FindFile: can't find %s\n", filename); + + if (handle) + *handle = -1; + else + *file = -1; + com_filesize = -1; + return -1; +} + + +/* +=========== +COM_OpenFile + +filename never has a leading slash, but may contain directory walks +returns a handle and a length +it may actually be inside a pak file +=========== +*/ +int COM_OpenFile (char *filename, int *handle) +{ + return COM_FindFile (filename, handle, NULL); +} + +/* +=========== +COM_FOpenFile + +If the requested file is inside a packfile, a new file will be opened +into the file. +=========== +*/ +int COM_FOpenFile (char *filename, int *file) +{ + return COM_FindFile (filename, NULL, file); +} + +/* +============ +COM_CloseFile + +If it is a pak file handle, don't really close it +============ +*/ +void COM_CloseFile (int h) +{ + searchpath_t *s; + + for (s = com_searchpaths ; s ; s=s->next) + if (s->pack && s->pack->handle == h) + return; + + Sys_FileClose (h); +} + + +/* +============ +COM_LoadFile + +Filename are reletive to the quake directory. +Allways appends a 0 byte. +============ +*/ +cache_user_t *loadcache; +byte *loadbuf; +int loadsize; +byte *COM_LoadFile (char *path, int usehunk) +{ + int h; + byte *buf; + char base[32]; + int len; + + buf = NULL; // quiet compiler warning + +// look for it in the filesystem or pack files + len = COM_OpenFile (path, &h); + if (h == -1) + return NULL; + +// extract the filename base name for hunk tag + COM_FileBase (path, base); + + if (usehunk == 1) + buf = Hunk_AllocName (len+1, base); + else if (usehunk == 2) + buf = Hunk_TempAlloc (len+1); + else if (usehunk == 0) + buf = Z_Malloc (len+1); + else if (usehunk == 3) + buf = Cache_Alloc (loadcache, len+1, base); + else if (usehunk == 4) + { + if (len+1 > loadsize) + buf = Hunk_TempAlloc (len+1); + else + buf = loadbuf; + } + else if (usehunk == 5) + { + buf = malloc(len+1); + } + else + Sys_Error ("COM_LoadFile: bad usehunk"); + + if (!buf) + Sys_Error ("COM_LoadFile: not enough space for %s", path); + + ((byte *)buf)[len] = 0; + + Sys_FileRead (h, buf, len); + COM_CloseFile (h); + + return buf; +} + +byte *COM_LoadHunkFile (char *path) +{ + return COM_LoadFile (path, 1); +} + +byte *COM_LoadTempFile (char *path) +{ + return COM_LoadFile (path, 2); +} + +void COM_LoadCacheFile (char *path, struct cache_user_s *cu) +{ + loadcache = cu; + COM_LoadFile (path, 3); +} + +// uses temp hunk if larger than bufsize +byte *COM_LoadStackFile (char *path, void *buffer, int bufsize) +{ + byte *buf; + + loadbuf = (byte *)buffer; + loadsize = bufsize; + buf = COM_LoadFile (path, 4); + + return buf; +} + +/* +================= +COM_LoadPackFile + +Takes an explicit (not game tree related) path to a pak file. + +Loads the header and directory, adding the files at the beginning +of the list so they override previous pack files. +================= +*/ +pack_t *COM_LoadPackFile (char *packfile) +{ + dpackheader_t header; + int i; + packfile_t *newfiles; + int numpackfiles; + pack_t *pack; + int packhandle; + dpackfile_t info[MAX_FILES_IN_PACK]; + unsigned short crc; + + if (Sys_FileOpenRead (packfile, &packhandle) == -1) + { + //Con_Printf ("Couldn't open %s\n", packfile); + return NULL; + } + Sys_FileRead (packhandle, (void *)&header, sizeof(header)); + if (header.id[0] != 'P' || header.id[1] != 'A' + || header.id[2] != 'C' || header.id[3] != 'K') + Sys_Error ("%s is not a packfile", packfile); + header.dirofs = LittleLong (header.dirofs); + header.dirlen = LittleLong (header.dirlen); + + numpackfiles = header.dirlen / sizeof(dpackfile_t); + + if (numpackfiles > MAX_FILES_IN_PACK) + Sys_Error ("%s has %i files", packfile, numpackfiles); + + if (numpackfiles != PAK0_COUNT) + com_modified = true; // not the original file + + newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "packfile"); + + Sys_FileSeek (packhandle, header.dirofs); + Sys_FileRead (packhandle, (void *)info, header.dirlen); + +// crc the directory to check for modifications + + CRC_Init (&crc); + for (i=0 ; ifilename, packfile); + pack->handle = packhandle; + pack->numfiles = numpackfiles; + pack->files = newfiles; + + Con_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles); + return pack; +} + + +/* +================ +COM_AddGameDirectory + +Sets com_gamedir, adds the directory to the head of the path, +then loads and adds pak1.pak pak2.pak ... +================ +*/ +void COM_AddGameDirectory (char *dir) +{ + //int i; + searchpath_t *search; + //pack_t *pak; + //char pakfile[MAX_OSPATH]; + + strcpy (com_gamedir, dir); + +// +// add the directory to the search path +// + search = Hunk_Alloc (sizeof(searchpath_t)); + strcpy (search->filename, dir); + search->next = com_searchpaths; + com_searchpaths = search; + +// +// add any pak files in the format pak0.pak pak1.pak, ... +// + /* + sprintf (pakfile, "%s/nzp.pak", dir, i); + pak = COM_LoadPackFile (pakfile); + if (pak) + { + search = Hunk_Alloc (sizeof(searchpath_t)); + search->pack = pak; + search->next = com_searchpaths; + com_searchpaths = search; + } + + sprintf (pakfile, "%s/wii.pak", dir); + pak = COM_LoadPackFile (pakfile); + if (pak) + { + search = Hunk_Alloc (sizeof(searchpath_t)); + search->pack = pak; + search->next = com_searchpaths; + com_searchpaths = search; + } + */ +// +// add the contents of the parms.txt file to the end of the command line +// + +} + +/* +================ +COM_InitFilesystem +================ +*/ +void COM_InitFilesystem (void) +{ + int i, j; + char basedir[MAX_OSPATH]; + searchpath_t *search; + +// +// -basedir +// Overrides the system supplied base directory (under GAMENAME) +// + i = COM_CheckParm ("-basedir"); + if (i && i < com_argc-1) + strcpy (basedir, com_argv[i+1]); + else + strcpy (basedir, host_parms.basedir); + + j = strlen (basedir); + + if (j > 0) + { + if ((basedir[j-1] == '\\') || (basedir[j-1] == '/')) + basedir[j-1] = 0; + } + +// +// -cachedir +// Overrides the system supplied cache directory (NULL or /qcache) +// -cachedir - will disable caching. +// + i = COM_CheckParm ("-cachedir"); + if (i && i < com_argc-1) + { + if (com_argv[i+1][0] == '-') + com_cachedir[0] = 0; + else + strcpy (com_cachedir, com_argv[i+1]); + } + else if (host_parms.cachedir) + strcpy (com_cachedir, host_parms.cachedir); + else + com_cachedir[0] = 0; + +// +// start up with GAMENAME by default (nzp) +// + COM_AddGameDirectory (va("%s/"GAMENAME, basedir) ); + + if (COM_CheckParm ("-rogue")) + COM_AddGameDirectory (va("%s/rogue", basedir) ); + if (COM_CheckParm ("-hipnotic")) + COM_AddGameDirectory (va("%s/hipnotic", basedir) ); + +// +// -game +// Adds basedir/gamedir as an override game +// + i = COM_CheckParm ("-game"); + if (i && i < com_argc-1) + { + com_modified = true; + COM_AddGameDirectory (va("%s/%s", basedir, com_argv[i+1])); + } + +// +// -path [] ... +// Fully specifies the exact serach path, overriding the generated one +// + i = COM_CheckParm ("-path"); + if (i) + { + com_modified = true; + com_searchpaths = NULL; + while (++i < com_argc) + { + if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-') + break; + + search = Hunk_Alloc (sizeof(searchpath_t)); + if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") ) + { + search->pack = COM_LoadPackFile (com_argv[i]); + if (!search->pack) + Sys_Error ("Couldn't load packfile: %s", com_argv[i]); + } + else + strcpy (search->filename, com_argv[i]); + search->next = com_searchpaths; + com_searchpaths = search; + } + } + + if (COM_CheckParm ("-proghack")) + proghack = true; +} + +void Q_strncpyz (char *dest, char *src, size_t size) +{ + strncpy (dest, src, size - 1); + dest[size-1] = 0; +} diff --git a/source/wii/common.h b/source/wii/common.h new file mode 100644 index 0000000..6ff9c4d --- /dev/null +++ b/source/wii/common.h @@ -0,0 +1,192 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// comndef.h -- general definitions + +#if !defined BYTE_DEFINED +typedef unsigned char byte; +#define BYTE_DEFINED 1 +#endif + +// libogc +#include +typedef bool qboolean; + + +//============================================================================ + +typedef struct sizebuf_s +{ + qboolean allowoverflow; // if false, do a Sys_Error + qboolean overflowed; // set to true if the buffer size failed + byte *data; + int maxsize; + int cursize; +} sizebuf_t; + +void SZ_Alloc (sizebuf_t *buf, int startsize); +void SZ_Free (sizebuf_t *buf); +void SZ_Clear (sizebuf_t *buf); +void *SZ_GetSpace (sizebuf_t *buf, int length); +void SZ_Write (sizebuf_t *buf, void *data, int length); +void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf + +//============================================================================ + +typedef struct link_s +{ + struct link_s *prev, *next; +} link_t; + + +void ClearLink (link_t *l); +void RemoveLink (link_t *l); +void InsertLinkBefore (link_t *l, link_t *before); +void InsertLinkAfter (link_t *l, link_t *after); + +// (type *)STRUCT_FROM_LINK(link_t *link, type, member) +// ent = STRUCT_FROM_LINK(link,entity_t,order) +// FIXME: remove this mess! +#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) + +//============================================================================ + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define Q_MAXCHAR ((char)0x7f) +#define Q_MAXSHORT ((short)0x7fff) +#define Q_MAXINT ((int)0x7fffffff) +#define Q_MAXLONG ((int)0x7fffffff) +#define Q_MAXFLOAT ((int)0x7fffffff) + +#define Q_MINCHAR ((char)0x80) +#define Q_MINSHORT ((short)0x8000) +#define Q_MININT ((int)0x80000000) +#define Q_MINLONG ((int)0x80000000) +#define Q_MINFLOAT ((int)0x7fffffff) + +#define bound(a, b, c) ((a) >= (c) ? (a) : (b) < (a) ? (a) : (b) > (c) ? (c) : (b)) + +//============================================================================ + +extern qboolean bigendien; + +extern short (*BigShort) (short l); +extern short (*LittleShort) (short l); +extern int (*BigLong) (int l); +extern int (*LittleLong) (int l); +extern float (*BigFloat) (float l); +extern float (*LittleFloat) (float l); + +//============================================================================ + +void MSG_WriteChar (sizebuf_t *sb, int c); +void MSG_WriteByte (sizebuf_t *sb, int c); +void MSG_WriteShort (sizebuf_t *sb, int c); +void MSG_WriteLong (sizebuf_t *sb, int c); +void MSG_WriteFloat (sizebuf_t *sb, float f); +void MSG_WriteString (sizebuf_t *sb, char *s); +void MSG_WriteCoord (sizebuf_t *sb, float f); +void MSG_WriteAngle (sizebuf_t *sb, float f); + +extern int msg_readcount; +extern qboolean msg_badread; // set if a read goes beyond end of message + +void MSG_BeginReading (void); +int MSG_ReadChar (void); +int MSG_ReadByte (void); +int MSG_ReadShort (void); +int MSG_ReadLong (void); +float MSG_ReadFloat (void); +char *MSG_ReadString (void); + +float MSG_ReadCoord (void); +float MSG_ReadAngle (void); + +//============================================================================ + +void Q_memset (void *dest, int fill, int count); +void Q_memcpy (void *dest, void *src, int count); +int Q_memcmp (void *m1, void *m2, int count); +void Q_strcpy (char *dest, char *src); +void Q_strncpy (char *dest, char *src, int count); +int Q_strlen (char *str); +char *Q_strrchr (char *s, char c); +void Q_strcat (char *dest, char *src); +int Q_strcmp (char *s1, char *s2); +int Q_strncmp (char *s1, char *s2, int count); +int Q_strcasecmp (char *s1, char *s2); +int Q_strncasecmp (char *s1, char *s2, int n); +int Q_atoi (char *str); +float Q_atof (char *str); + +//============================================================================ + +extern char com_token[1024]; +extern qboolean com_eof; + +char *COM_Parse (char *data); + + +extern int com_argc; +extern char **com_argv; + +int COM_CheckParm (char *parm); +void COM_Init (char *path); +void COM_InitArgv (int argc, char **argv); + +char *COM_SkipPath (char *pathname); +void COM_StripExtension (char *in, char *out); +void COM_FileBase (char *in, char *out); +void COM_DefaultExtension (char *path, char *extension); + +char *va(char *format, ...); +char *CopyString (char *in); +// does a varargs printf into a temp buffer + + +//============================================================================ + +extern int com_filesize; +struct cache_user_s; + +extern char com_gamedir[MAX_OSPATH]; + +void COM_WriteFile (char *filename, void *data, int len); +byte *COM_LoadFile (char *path, int usehunk); +int COM_OpenFile (char *filename, int *hndl); +int COM_FOpenFile (char *filename, int *file); +void COM_CloseFile (int h); + +byte *COM_LoadStackFile (char *path, void *buffer, int bufsize); +byte *COM_LoadTempFile (char *path); +byte *COM_LoadHunkFile (char *path); +void COM_LoadCacheFile (char *path, struct cache_user_s *cu); + + +extern struct cvar_s registered; + +extern qboolean standard_quake, rogue, hipnotic; +void Q_strncpyz (char *dest, char *src, size_t size); + +short ShortSwap (short l); +int LongSwap (int l); +float FloatSwap (float f); \ No newline at end of file diff --git a/source/wii/gx/128_128_datamap.h b/source/wii/gx/128_128_datamap.h new file mode 100644 index 0000000..986714a --- /dev/null +++ b/source/wii/gx/128_128_datamap.h @@ -0,0 +1,65555 @@ +/* +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +0, +33, +32, +1, +2, +35, +34, +3, +4, +37, +36, +5, +6, +39, +38, +7, +64, +97, +96, +65, +66, +99, +98, +67, +68, +101, +100, +69, +70, +103, +102, +71, +128, +161, +160, +129, +130, +163, +162, +131, +132, +165, +164, +133, +134, +167, +166, +135, +192, +225, +224, +193, +194, +227, +226, +195, +196, +229, +228, +197, +198, +231, +230, +199, +256, +289, +288, +257, +258, +291, +290, +259, +260, +293, +292, +261, +262, +295, +294, +263, +320, +353, +352, +321, +322, +355, +354, +323, +324, +357, +356, +325, +326, +359, +358, +327, +384, +417, +416, +385, +386, +419, +418, +387, +388, +421, +420, +389, +390, +423, +422, +391, +448, +481, +480, +449, +450, +483, +482, +451, +452, +485, +484, +453, +454, +487, +486, +455, +512, +545, +544, +513, +514, +547, +546, +515, +516, +549, +548, +517, +518, +551, +550, +519, +576, +609, +608, +577, +578, +611, +610, +579, +580, +613, +612, +581, +582, +615, +614, +583, +640, +673, +672, +641, +642, +675, +674, +643, +644, +677, +676, +645, +646, +679, +678, +647, +704, +737, +736, +705, +706, +739, +738, +707, +708, +741, +740, +709, +710, +743, +742, +711, +768, +801, +800, +769, +770, +803, +802, +771, +772, +805, +804, +773, +774, +807, +806, +775, +832, +865, +864, +833, +834, +867, +866, +835, +836, +869, +868, +837, +838, +871, +870, +839, +896, +929, +928, +897, +898, +931, +930, +899, +900, +933, +932, +901, +902, +935, +934, +903, +960, +993, +992, +961, +962, +995, +994, +963, +964, +997, +996, +965, +966, +999, +998, +967, +1024, +1057, +1056, +1025, +1026, +1059, +1058, +1027, +1028, +1061, +1060, +1029, +1030, +1063, +1062, +1031, +1088, +1121, +1120, +1089, +1090, +1123, +1122, +1091, +1092, +1125, +1124, +1093, +1094, +1127, +1126, +1095, +1152, +1185, +1184, +1153, +1154, +1187, +1186, +1155, +1156, +1189, +1188, +1157, +1158, +1191, +1190, +1159, +1216, +1249, +1248, +1217, +1218, +1251, +1250, +1219, +1220, +1253, +1252, +1221, +1222, +1255, +1254, +1223, +1280, +1313, +1312, +1281, +1282, +1315, +1314, +1283, +1284, +1317, +1316, +1285, +1286, +1319, +1318, +1287, +1344, +1377, +1376, +1345, +1346, +1379, +1378, +1347, +1348, +1381, +1380, +1349, +1350, +1383, +1382, +1351, +1408, +1441, +1440, +1409, +1410, +1443, +1442, +1411, +1412, +1445, +1444, +1413, +1414, +1447, +1446, +1415, +1472, +1505, +1504, +1473, +1474, +1507, +1506, +1475, +1476, +1509, +1508, +1477, +1478, +1511, +1510, +1479, +1536, +1569, +1568, +1537, +1538, +1571, +1570, +1539, +1540, +1573, +1572, +1541, +1542, +1575, +1574, +1543, +1600, +1633, +1632, +1601, +1602, +1635, +1634, +1603, +1604, +1637, +1636, +1605, +1606, +1639, +1638, +1607, +1664, +1697, +1696, +1665, +1666, +1699, +1698, +1667, +1668, +1701, +1700, +1669, +1670, +1703, +1702, +1671, +1728, +1761, +1760, +1729, +1730, +1763, +1762, +1731, +1732, +1765, +1764, +1733, +1734, +1767, +1766, +1735, +1792, +1825, +1824, +1793, +1794, +1827, +1826, +1795, +1796, +1829, +1828, +1797, +1798, +1831, +1830, +1799, +1856, +1889, +1888, +1857, +1858, +1891, +1890, +1859, +1860, +1893, +1892, +1861, +1862, +1895, +1894, +1863, +1920, +1953, +1952, +1921, +1922, +1955, +1954, +1923, +1924, +1957, +1956, +1925, +1926, +1959, +1958, +1927, +1984, +2017, +2016, +1985, +1986, +2019, +2018, +1987, +1988, +2021, +2020, +1989, +1990, +2023, +2022, +1991, +8, +41, +40, +9, +10, +43, +42, +11, +12, +45, +44, +13, +14, +47, +46, +15, +72, +105, +104, +73, +74, +107, +106, +75, +76, +109, +108, +77, +78, +111, +110, +79, +136, +169, +168, +137, +138, +171, +170, +139, +140, +173, +172, +141, +142, +175, +174, +143, +200, +233, +232, +201, +202, +235, +234, +203, +204, +237, +236, +205, +206, +239, +238, +207, +264, +297, +296, +265, +266, +299, +298, +267, +268, +301, +300, +269, +270, +303, +302, +271, +328, +361, +360, +329, +330, +363, +362, +331, +332, +365, +364, +333, +334, +367, +366, +335, +392, +425, +424, +393, +394, +427, +426, +395, +396, +429, +428, +397, +398, +431, +430, +399, +456, +489, +488, +457, +458, +491, +490, +459, +460, +493, +492, +461, +462, +495, +494, +463, +520, +553, +552, +521, +522, +555, +554, +523, +524, +557, +556, +525, +526, +559, +558, +527, +584, +617, +616, +585, +586, +619, +618, +587, +588, +621, +620, +589, +590, +623, +622, +591, +648, +681, +680, +649, +650, +683, +682, +651, +652, +685, +684, +653, +654, +687, +686, +655, +712, +745, +744, +713, +714, +747, +746, +715, +716, +749, +748, +717, +718, +751, +750, +719, +776, +809, +808, +777, +778, +811, +810, +779, +780, +813, +812, +781, +782, +815, +814, +783, +840, +873, +872, +841, +842, +875, +874, +843, +844, +877, +876, +845, +846, +879, +878, +847, +904, +937, +936, +905, +906, +939, +938, +907, +908, +941, +940, +909, +910, +943, +942, +911, +968, +1001, +1000, +969, +970, +1003, +1002, +971, +972, +1005, +1004, +973, +974, +1007, +1006, +975, +1032, +1065, +1064, +1033, +1034, +1067, +1066, +1035, +1036, +1069, +1068, +1037, +1038, +1071, +1070, +1039, +1096, +1129, +1128, +1097, +1098, +1131, +1130, +1099, +1100, +1133, +1132, +1101, +1102, +1135, +1134, +1103, +1160, +1193, +1192, +1161, +1162, +1195, +1194, +1163, +1164, +1197, +1196, +1165, +1166, +1199, +1198, +1167, +1224, +1257, +1256, +1225, +1226, +1259, +1258, +1227, +1228, +1261, +1260, +1229, +1230, +1263, +1262, +1231, +1288, +1321, +1320, +1289, +1290, +1323, +1322, +1291, +1292, +1325, +1324, +1293, +1294, +1327, +1326, +1295, +1352, +1385, +1384, +1353, +1354, +1387, +1386, +1355, +1356, +1389, +1388, +1357, +1358, +1391, +1390, +1359, +1416, +1449, +1448, +1417, +1418, +1451, +1450, +1419, +1420, +1453, +1452, +1421, +1422, +1455, +1454, +1423, +1480, +1513, +1512, +1481, +1482, +1515, +1514, +1483, +1484, +1517, +1516, +1485, +1486, +1519, +1518, +1487, +1544, +1577, +1576, +1545, +1546, +1579, +1578, +1547, +1548, +1581, +1580, +1549, +1550, +1583, +1582, +1551, +1608, +1641, +1640, +1609, +1610, +1643, +1642, +1611, +1612, +1645, +1644, +1613, +1614, +1647, +1646, +1615, +1672, +1705, +1704, +1673, +1674, +1707, +1706, +1675, +1676, +1709, +1708, +1677, +1678, +1711, +1710, +1679, +1736, +1769, +1768, +1737, +1738, +1771, +1770, +1739, +1740, +1773, +1772, +1741, +1742, +1775, +1774, +1743, +1800, +1833, +1832, +1801, +1802, +1835, +1834, +1803, +1804, +1837, +1836, +1805, +1806, +1839, +1838, +1807, +1864, +1897, +1896, +1865, +1866, +1899, +1898, +1867, +1868, +1901, +1900, +1869, +1870, +1903, +1902, +1871, +1928, +1961, +1960, +1929, +1930, +1963, +1962, +1931, +1932, +1965, +1964, +1933, +1934, +1967, +1966, +1935, +1992, +2025, +2024, +1993, +1994, +2027, +2026, +1995, +1996, +2029, +2028, +1997, +1998, +2031, +2030, +1999, +16, +49, +48, +17, +18, +51, +50, +19, +20, +53, +52, +21, +22, +55, +54, +23, +80, +113, +112, +81, +82, +115, +114, +83, +84, +117, +116, +85, +86, +119, +118, +87, +144, +177, +176, +145, +146, +179, +178, +147, +148, +181, +180, +149, +150, +183, +182, +151, +208, +241, +240, +209, +210, +243, +242, +211, +212, +245, +244, +213, +214, +247, +246, +215, +272, +305, +304, +273, +274, +307, +306, +275, +276, +309, +308, +277, +278, +311, +310, +279, +336, +369, +368, +337, +338, +371, +370, +339, +340, +373, +372, +341, +342, +375, +374, +343, +400, +433, +432, +401, +402, +435, +434, +403, +404, +437, +436, +405, +406, +439, +438, +407, +464, +497, +496, +465, +466, +499, +498, +467, +468, +501, +500, +469, +470, +503, +502, +471, +528, +561, +560, +529, +530, +563, +562, +531, +532, +565, +564, +533, +534, +567, +566, +535, +592, +625, +624, +593, +594, +627, +626, +595, +596, +629, +628, +597, +598, +631, +630, +599, +656, +689, +688, +657, +658, +691, +690, +659, +660, +693, +692, +661, +662, +695, +694, +663, +720, +753, +752, +721, +722, +755, +754, +723, +724, +757, +756, +725, +726, +759, +758, +727, +784, +817, +816, +785, +786, +819, +818, +787, +788, +821, +820, +789, +790, +823, +822, +791, +848, +881, +880, +849, +850, +883, +882, +851, +852, +885, +884, +853, +854, +887, +886, +855, +912, +945, +944, +913, +914, +947, +946, +915, +916, +949, +948, +917, +918, +951, +950, +919, +976, +1009, +1008, +977, +978, +1011, +1010, +979, +980, +1013, +1012, +981, +982, +1015, +1014, +983, +1040, +1073, +1072, +1041, +1042, +1075, +1074, +1043, +1044, +1077, +1076, +1045, +1046, +1079, +1078, +1047, +1104, +1137, +1136, +1105, +1106, +1139, +1138, +1107, +1108, +1141, +1140, +1109, +1110, +1143, +1142, +1111, +1168, +1201, +1200, +1169, +1170, +1203, +1202, +1171, +1172, +1205, +1204, +1173, +1174, +1207, +1206, +1175, +1232, +1265, +1264, +1233, +1234, +1267, +1266, +1235, +1236, +1269, +1268, +1237, +1238, +1271, +1270, +1239, +1296, +1329, +1328, +1297, +1298, +1331, +1330, +1299, +1300, +1333, +1332, +1301, +1302, +1335, +1334, +1303, +1360, +1393, +1392, +1361, +1362, +1395, +1394, +1363, +1364, +1397, +1396, +1365, +1366, +1399, +1398, +1367, +1424, +1457, +1456, +1425, +1426, +1459, +1458, +1427, +1428, +1461, +1460, +1429, +1430, +1463, +1462, +1431, +1488, +1521, +1520, +1489, +1490, +1523, +1522, +1491, +1492, +1525, +1524, +1493, +1494, +1527, +1526, +1495, +1552, +1585, +1584, +1553, +1554, +1587, +1586, +1555, +1556, +1589, +1588, +1557, +1558, +1591, +1590, +1559, +1616, +1649, +1648, +1617, +1618, +1651, +1650, +1619, +1620, +1653, +1652, +1621, +1622, +1655, +1654, +1623, +1680, +1713, +1712, +1681, +1682, +1715, +1714, +1683, +1684, +1717, +1716, +1685, +1686, +1719, +1718, +1687, +1744, +1777, +1776, +1745, +1746, +1779, +1778, +1747, +1748, +1781, +1780, +1749, +1750, +1783, +1782, +1751, +1808, +1841, +1840, +1809, +1810, +1843, +1842, +1811, +1812, +1845, +1844, +1813, +1814, +1847, +1846, +1815, +1872, +1905, +1904, +1873, +1874, +1907, +1906, +1875, +1876, +1909, +1908, +1877, +1878, +1911, +1910, +1879, +1936, +1969, +1968, +1937, +1938, +1971, +1970, +1939, +1940, +1973, +1972, +1941, +1942, +1975, +1974, +1943, +2000, +2033, +2032, +2001, +2002, +2035, +2034, +2003, +2004, +2037, +2036, +2005, +2006, +2039, +2038, +2007, +24, +57, +56, +25, +26, +59, +58, +27, +28, +61, +60, +29, +30, +63, +62, +31, +88, +121, +120, +89, +90, +123, +122, +91, +92, +125, +124, +93, +94, +127, +126, +95, +152, +185, +184, +153, +154, +187, +186, +155, +156, +189, +188, +157, +158, +191, +190, +159, +216, +249, +248, +217, +218, +251, +250, +219, +220, +253, +252, +221, +222, +255, +254, +223, +280, +313, +312, +281, +282, +315, +314, +283, +284, +317, +316, +285, +286, +319, +318, +287, +344, +377, +376, +345, +346, +379, +378, +347, +348, +381, +380, +349, +350, +383, +382, +351, +408, +441, +440, +409, +410, +443, +442, +411, +412, +445, +444, +413, +414, +447, +446, +415, +472, +505, +504, +473, +474, +507, +506, +475, +476, +509, +508, +477, +478, +511, +510, +479, +536, +569, +568, +537, +538, +571, +570, +539, +540, +573, +572, +541, +542, +575, +574, +543, +600, +633, +632, +601, +602, +635, +634, +603, +604, +637, +636, +605, +606, +639, +638, +607, +664, +697, +696, +665, +666, +699, +698, +667, +668, +701, +700, +669, +670, +703, +702, +671, +728, +761, +760, +729, +730, +763, +762, +731, +732, +765, +764, +733, +734, +767, +766, +735, +792, +825, +824, +793, +794, +827, +826, +795, +796, +829, +828, +797, +798, +831, +830, +799, +856, +889, +888, +857, +858, +891, +890, +859, +860, +893, +892, +861, +862, +895, +894, +863, +920, +953, +952, +921, +922, +955, +954, +923, +924, +957, +956, +925, +926, +959, +958, +927, +984, +1017, +1016, +985, +986, +1019, +1018, +987, +988, +1021, +1020, +989, +990, +1023, +1022, +991, +1048, +1081, +1080, +1049, +1050, +1083, +1082, +1051, +1052, +1085, +1084, +1053, +1054, +1087, +1086, +1055, +1112, +1145, +1144, +1113, +1114, +1147, +1146, +1115, +1116, +1149, +1148, +1117, +1118, +1151, +1150, +1119, +1176, +1209, +1208, +1177, +1178, +1211, +1210, +1179, +1180, +1213, +1212, +1181, +1182, +1215, +1214, +1183, +1240, +1273, +1272, +1241, +1242, +1275, +1274, +1243, +1244, +1277, +1276, +1245, +1246, +1279, +1278, +1247, +1304, +1337, +1336, +1305, +1306, +1339, +1338, +1307, +1308, +1341, +1340, +1309, +1310, +1343, +1342, +1311, +1368, +1401, +1400, +1369, +1370, +1403, +1402, +1371, +1372, +1405, +1404, +1373, +1374, +1407, +1406, +1375, +1432, +1465, +1464, +1433, +1434, +1467, +1466, +1435, +1436, +1469, +1468, +1437, +1438, +1471, +1470, +1439, +1496, +1529, +1528, +1497, +1498, +1531, +1530, +1499, +1500, +1533, +1532, +1501, +1502, +1535, +1534, +1503, +1560, +1593, +1592, +1561, +1562, +1595, +1594, +1563, +1564, +1597, +1596, +1565, +1566, +1599, +1598, +1567, +1624, +1657, +1656, +1625, +1626, +1659, +1658, +1627, +1628, +1661, +1660, +1629, +1630, +1663, +1662, +1631, +1688, +1721, +1720, +1689, +1690, +1723, +1722, +1691, +1692, +1725, +1724, +1693, +1694, +1727, +1726, +1695, +1752, +1785, +1784, +1753, +1754, +1787, +1786, +1755, +1756, +1789, +1788, +1757, +1758, +1791, +1790, +1759, +1816, +1849, +1848, +1817, +1818, +1851, +1850, +1819, +1820, +1853, +1852, +1821, +1822, +1855, +1854, +1823, +1880, +1913, +1912, +1881, +1882, +1915, +1914, +1883, +1884, +1917, +1916, +1885, +1886, +1919, +1918, +1887, +1944, +1977, +1976, +1945, +1946, +1979, +1978, +1947, +1948, +1981, +1980, +1949, +1950, +1983, +1982, +1951, +2008, +2041, +2040, +2009, +2010, +2043, +2042, +2011, +2012, +2045, +2044, +2013, +2014, +2047, +2046, +2015, +2048, +2081, +2080, +2049, +2050, +2083, +2082, +2051, +2052, +2085, +2084, +2053, +2054, +2087, +2086, +2055, +2112, +2145, +2144, +2113, +2114, +2147, +2146, +2115, +2116, +2149, +2148, +2117, +2118, +2151, +2150, +2119, +2176, +2209, +2208, +2177, +2178, +2211, +2210, +2179, +2180, +2213, +2212, +2181, +2182, +2215, +2214, +2183, +2240, +2273, +2272, +2241, +2242, +2275, +2274, +2243, +2244, +2277, +2276, +2245, +2246, +2279, +2278, +2247, +2304, +2337, +2336, +2305, +2306, +2339, +2338, +2307, +2308, +2341, +2340, +2309, +2310, +2343, +2342, +2311, +2368, +2401, +2400, +2369, +2370, +2403, +2402, +2371, +2372, +2405, +2404, +2373, +2374, +2407, +2406, +2375, +2432, +2465, +2464, +2433, +2434, +2467, +2466, +2435, +2436, +2469, +2468, +2437, +2438, +2471, +2470, +2439, +2496, +2529, +2528, +2497, +2498, +2531, +2530, +2499, +2500, +2533, +2532, +2501, +2502, +2535, +2534, +2503, +2560, +2593, +2592, +2561, +2562, +2595, +2594, +2563, +2564, +2597, +2596, +2565, +2566, +2599, +2598, +2567, +2624, +2657, +2656, +2625, +2626, +2659, +2658, +2627, +2628, +2661, +2660, +2629, +2630, +2663, +2662, +2631, +2688, +2721, +2720, +2689, +2690, +2723, +2722, +2691, +2692, +2725, +2724, +2693, +2694, +2727, +2726, +2695, +2752, +2785, +2784, +2753, +2754, +2787, +2786, +2755, +2756, +2789, +2788, +2757, +2758, +2791, +2790, +2759, +2816, +2849, +2848, +2817, +2818, +2851, +2850, +2819, +2820, +2853, +2852, +2821, +2822, +2855, +2854, +2823, +2880, +2913, +2912, +2881, +2882, +2915, +2914, +2883, +2884, +2917, +2916, +2885, +2886, +2919, +2918, +2887, +2944, +2977, +2976, +2945, +2946, +2979, +2978, +2947, +2948, +2981, +2980, +2949, +2950, +2983, +2982, +2951, +3008, +3041, +3040, +3009, +3010, +3043, +3042, +3011, +3012, +3045, +3044, +3013, +3014, +3047, +3046, +3015, +3072, +3105, +3104, +3073, +3074, +3107, +3106, +3075, +3076, +3109, +3108, +3077, +3078, +3111, +3110, +3079, +3136, +3169, +3168, +3137, +3138, +3171, +3170, +3139, +3140, +3173, +3172, +3141, +3142, +3175, +3174, +3143, +3200, +3233, +3232, +3201, +3202, +3235, +3234, +3203, +3204, +3237, +3236, +3205, +3206, +3239, +3238, +3207, +3264, +3297, +3296, +3265, +3266, +3299, +3298, +3267, +3268, +3301, +3300, +3269, +3270, +3303, +3302, +3271, +3328, +3361, +3360, +3329, +3330, +3363, +3362, +3331, +3332, +3365, +3364, +3333, +3334, +3367, +3366, +3335, +3392, +3425, +3424, +3393, +3394, +3427, +3426, +3395, +3396, +3429, +3428, +3397, +3398, +3431, +3430, +3399, +3456, +3489, +3488, +3457, +3458, +3491, +3490, +3459, +3460, +3493, +3492, +3461, +3462, +3495, +3494, +3463, +3520, +3553, +3552, +3521, +3522, +3555, +3554, +3523, +3524, +3557, +3556, +3525, +3526, +3559, +3558, +3527, +3584, +3617, +3616, +3585, +3586, +3619, +3618, +3587, +3588, +3621, +3620, +3589, +3590, +3623, +3622, +3591, +3648, +3681, +3680, +3649, +3650, +3683, +3682, +3651, +3652, +3685, +3684, +3653, +3654, +3687, +3686, +3655, +3712, +3745, +3744, +3713, +3714, +3747, +3746, +3715, +3716, +3749, +3748, +3717, +3718, +3751, +3750, +3719, +3776, +3809, +3808, +3777, +3778, +3811, +3810, +3779, +3780, +3813, +3812, +3781, +3782, +3815, +3814, +3783, +3840, +3873, +3872, +3841, +3842, +3875, +3874, +3843, +3844, +3877, +3876, +3845, +3846, +3879, +3878, +3847, +3904, +3937, +3936, +3905, +3906, +3939, +3938, +3907, +3908, +3941, +3940, +3909, +3910, +3943, +3942, +3911, +3968, +4001, +4000, +3969, +3970, +4003, +4002, +3971, +3972, +4005, +4004, +3973, +3974, +4007, +4006, +3975, +4032, +4065, +4064, +4033, +4034, +4067, +4066, +4035, +4036, +4069, +4068, +4037, +4038, +4071, +4070, +4039, +2056, +2089, +2088, +2057, +2058, +2091, +2090, +2059, +2060, +2093, +2092, +2061, +2062, +2095, +2094, +2063, +2120, +2153, +2152, +2121, +2122, +2155, +2154, +2123, +2124, +2157, +2156, +2125, +2126, +2159, +2158, +2127, +2184, +2217, +2216, +2185, +2186, +2219, +2218, +2187, +2188, +2221, +2220, +2189, +2190, +2223, +2222, +2191, +2248, +2281, +2280, +2249, +2250, +2283, +2282, +2251, +2252, +2285, +2284, +2253, +2254, +2287, +2286, +2255, +2312, +2345, +2344, +2313, +2314, +2347, +2346, +2315, +2316, +2349, +2348, +2317, +2318, +2351, +2350, +2319, +2376, +2409, +2408, +2377, +2378, +2411, +2410, +2379, +2380, +2413, +2412, +2381, +2382, +2415, +2414, +2383, +2440, +2473, +2472, +2441, +2442, +2475, +2474, +2443, +2444, +2477, +2476, +2445, +2446, +2479, +2478, +2447, +2504, +2537, +2536, +2505, +2506, +2539, +2538, +2507, +2508, +2541, +2540, +2509, +2510, +2543, +2542, +2511, +2568, +2601, +2600, +2569, +2570, +2603, +2602, +2571, +2572, +2605, +2604, +2573, +2574, +2607, +2606, +2575, +2632, +2665, +2664, +2633, +2634, +2667, +2666, +2635, +2636, +2669, +2668, +2637, +2638, +2671, +2670, +2639, +2696, +2729, +2728, +2697, +2698, +2731, +2730, +2699, +2700, +2733, +2732, +2701, +2702, +2735, +2734, +2703, +2760, +2793, +2792, +2761, +2762, +2795, +2794, +2763, +2764, +2797, +2796, +2765, +2766, +2799, +2798, +2767, +2824, +2857, +2856, +2825, +2826, +2859, +2858, +2827, +2828, +2861, +2860, +2829, +2830, +2863, +2862, +2831, +2888, +2921, +2920, +2889, +2890, +2923, +2922, +2891, +2892, +2925, +2924, +2893, +2894, +2927, +2926, +2895, +2952, +2985, +2984, +2953, +2954, +2987, +2986, +2955, +2956, +2989, +2988, +2957, +2958, +2991, +2990, +2959, +3016, +3049, +3048, +3017, +3018, +3051, +3050, +3019, +3020, +3053, +3052, +3021, +3022, +3055, +3054, +3023, +3080, +3113, +3112, +3081, +3082, +3115, +3114, +3083, +3084, +3117, +3116, +3085, +3086, +3119, +3118, +3087, +3144, +3177, +3176, +3145, +3146, +3179, +3178, +3147, +3148, +3181, +3180, +3149, +3150, +3183, +3182, +3151, +3208, +3241, +3240, +3209, +3210, +3243, +3242, +3211, +3212, +3245, +3244, +3213, +3214, +3247, +3246, +3215, +3272, +3305, +3304, +3273, +3274, +3307, +3306, +3275, +3276, +3309, +3308, +3277, +3278, +3311, +3310, +3279, +3336, +3369, +3368, +3337, +3338, +3371, +3370, +3339, +3340, +3373, +3372, +3341, +3342, +3375, +3374, +3343, +3400, +3433, +3432, +3401, +3402, +3435, +3434, +3403, +3404, +3437, +3436, +3405, +3406, +3439, +3438, +3407, +3464, +3497, +3496, +3465, +3466, +3499, +3498, +3467, +3468, +3501, +3500, +3469, +3470, +3503, +3502, +3471, +3528, +3561, +3560, +3529, +3530, +3563, +3562, +3531, +3532, +3565, +3564, +3533, +3534, +3567, +3566, +3535, +3592, +3625, +3624, +3593, +3594, +3627, +3626, +3595, +3596, +3629, +3628, +3597, +3598, +3631, +3630, +3599, +3656, +3689, +3688, +3657, +3658, +3691, +3690, +3659, +3660, +3693, +3692, +3661, +3662, +3695, +3694, +3663, +3720, +3753, +3752, +3721, +3722, +3755, +3754, +3723, +3724, +3757, +3756, +3725, +3726, +3759, +3758, +3727, +3784, +3817, +3816, +3785, +3786, +3819, +3818, +3787, +3788, +3821, +3820, +3789, +3790, +3823, +3822, +3791, +3848, +3881, +3880, +3849, +3850, +3883, +3882, +3851, +3852, +3885, +3884, +3853, +3854, +3887, +3886, +3855, +3912, +3945, +3944, +3913, +3914, +3947, +3946, +3915, +3916, +3949, +3948, +3917, +3918, +3951, +3950, +3919, +3976, +4009, +4008, +3977, +3978, +4011, +4010, +3979, +3980, +4013, +4012, +3981, +3982, +4015, +4014, +3983, +4040, +4073, +4072, +4041, +4042, +4075, +4074, +4043, +4044, +4077, +4076, +4045, +4046, +4079, +4078, +4047, +2064, +2097, +2096, +2065, +2066, +2099, +2098, +2067, +2068, +2101, +2100, +2069, +2070, +2103, +2102, +2071, +2128, +2161, +2160, +2129, +2130, +2163, +2162, +2131, +2132, +2165, +2164, +2133, +2134, +2167, +2166, +2135, +2192, +2225, +2224, +2193, +2194, +2227, +2226, +2195, +2196, +2229, +2228, +2197, +2198, +2231, +2230, +2199, +2256, +2289, +2288, +2257, +2258, +2291, +2290, +2259, +2260, +2293, +2292, +2261, +2262, +2295, +2294, +2263, +2320, +2353, +2352, +2321, +2322, +2355, +2354, +2323, +2324, +2357, +2356, +2325, +2326, +2359, +2358, +2327, +2384, +2417, +2416, +2385, +2386, +2419, +2418, +2387, +2388, +2421, +2420, +2389, +2390, +2423, +2422, +2391, +2448, +2481, +2480, +2449, +2450, +2483, +2482, +2451, +2452, +2485, +2484, +2453, +2454, +2487, +2486, +2455, +2512, +2545, +2544, +2513, +2514, +2547, +2546, +2515, +2516, +2549, +2548, +2517, +2518, +2551, +2550, +2519, +2576, +2609, +2608, +2577, +2578, +2611, +2610, +2579, +2580, +2613, +2612, +2581, +2582, +2615, +2614, +2583, +2640, +2673, +2672, +2641, +2642, +2675, +2674, +2643, +2644, +2677, +2676, +2645, +2646, +2679, +2678, +2647, +2704, +2737, +2736, +2705, +2706, +2739, +2738, +2707, +2708, +2741, +2740, +2709, +2710, +2743, +2742, +2711, +2768, +2801, +2800, +2769, +2770, +2803, +2802, +2771, +2772, +2805, +2804, +2773, +2774, +2807, +2806, +2775, +2832, +2865, +2864, +2833, +2834, +2867, +2866, +2835, +2836, +2869, +2868, +2837, +2838, +2871, +2870, +2839, +2896, +2929, +2928, +2897, +2898, +2931, +2930, +2899, +2900, +2933, +2932, +2901, +2902, +2935, +2934, +2903, +2960, +2993, +2992, +2961, +2962, +2995, +2994, +2963, +2964, +2997, +2996, +2965, +2966, +2999, +2998, +2967, +3024, +3057, +3056, +3025, +3026, +3059, +3058, +3027, +3028, +3061, +3060, +3029, +3030, +3063, +3062, +3031, +3088, +3121, +3120, +3089, +3090, +3123, +3122, +3091, +3092, +3125, +3124, +3093, +3094, +3127, +3126, +3095, +3152, +3185, +3184, +3153, +3154, +3187, +3186, +3155, +3156, +3189, +3188, +3157, +3158, +3191, +3190, +3159, +3216, +3249, +3248, +3217, +3218, +3251, +3250, +3219, +3220, +3253, +3252, +3221, +3222, +3255, +3254, +3223, +3280, +3313, +3312, +3281, +3282, +3315, +3314, +3283, +3284, +3317, +3316, +3285, +3286, +3319, +3318, +3287, +3344, +3377, +3376, +3345, +3346, +3379, +3378, +3347, +3348, +3381, +3380, +3349, +3350, +3383, +3382, +3351, +3408, +3441, +3440, +3409, +3410, +3443, +3442, +3411, +3412, +3445, +3444, +3413, +3414, +3447, +3446, +3415, +3472, +3505, +3504, +3473, +3474, +3507, +3506, +3475, +3476, +3509, +3508, +3477, +3478, +3511, +3510, +3479, +3536, +3569, +3568, +3537, +3538, +3571, +3570, +3539, +3540, +3573, +3572, +3541, +3542, +3575, +3574, +3543, +3600, +3633, +3632, +3601, +3602, +3635, +3634, +3603, +3604, +3637, +3636, +3605, +3606, +3639, +3638, +3607, +3664, +3697, +3696, +3665, +3666, +3699, +3698, +3667, +3668, +3701, +3700, +3669, +3670, +3703, +3702, +3671, +3728, +3761, +3760, +3729, +3730, +3763, +3762, +3731, +3732, +3765, +3764, +3733, +3734, +3767, +3766, +3735, +3792, +3825, +3824, +3793, +3794, +3827, +3826, +3795, +3796, +3829, +3828, +3797, +3798, +3831, +3830, +3799, +3856, +3889, +3888, +3857, +3858, +3891, +3890, +3859, +3860, +3893, +3892, +3861, +3862, +3895, +3894, +3863, +3920, +3953, +3952, +3921, +3922, +3955, +3954, +3923, +3924, +3957, +3956, +3925, +3926, +3959, +3958, +3927, +3984, +4017, +4016, +3985, +3986, +4019, +4018, +3987, +3988, +4021, +4020, +3989, +3990, +4023, +4022, +3991, +4048, +4081, +4080, +4049, +4050, +4083, +4082, +4051, +4052, +4085, +4084, +4053, +4054, +4087, +4086, +4055, +2072, +2105, +2104, +2073, +2074, +2107, +2106, +2075, +2076, +2109, +2108, +2077, +2078, +2111, +2110, +2079, +2136, +2169, +2168, +2137, +2138, +2171, +2170, +2139, +2140, +2173, +2172, +2141, +2142, +2175, +2174, +2143, +2200, +2233, +2232, +2201, +2202, +2235, +2234, +2203, +2204, +2237, +2236, +2205, +2206, +2239, +2238, +2207, +2264, +2297, +2296, +2265, +2266, +2299, +2298, +2267, +2268, +2301, +2300, +2269, +2270, +2303, +2302, +2271, +2328, +2361, +2360, +2329, +2330, +2363, +2362, +2331, +2332, +2365, +2364, +2333, +2334, +2367, +2366, +2335, +2392, +2425, +2424, +2393, +2394, +2427, +2426, +2395, +2396, +2429, +2428, +2397, +2398, +2431, +2430, +2399, +2456, +2489, +2488, +2457, +2458, +2491, +2490, +2459, +2460, +2493, +2492, +2461, +2462, +2495, +2494, +2463, +2520, +2553, +2552, +2521, +2522, +2555, +2554, +2523, +2524, +2557, +2556, +2525, +2526, +2559, +2558, +2527, +2584, +2617, +2616, +2585, +2586, +2619, +2618, +2587, +2588, +2621, +2620, +2589, +2590, +2623, +2622, +2591, +2648, +2681, +2680, +2649, +2650, +2683, +2682, +2651, +2652, +2685, +2684, +2653, +2654, +2687, +2686, +2655, +2712, +2745, +2744, +2713, +2714, +2747, +2746, +2715, +2716, +2749, +2748, +2717, +2718, +2751, +2750, +2719, +2776, +2809, +2808, +2777, +2778, +2811, +2810, +2779, +2780, +2813, +2812, +2781, +2782, +2815, +2814, +2783, +2840, +2873, +2872, +2841, +2842, +2875, +2874, +2843, +2844, +2877, +2876, +2845, +2846, +2879, +2878, +2847, +2904, +2937, +2936, +2905, +2906, +2939, +2938, +2907, +2908, +2941, +2940, +2909, +2910, +2943, +2942, +2911, +2968, +3001, +3000, +2969, +2970, +3003, +3002, +2971, +2972, +3005, +3004, +2973, +2974, +3007, +3006, +2975, +3032, +3065, +3064, +3033, +3034, +3067, +3066, +3035, +3036, +3069, +3068, +3037, +3038, +3071, +3070, +3039, +3096, +3129, +3128, +3097, +3098, +3131, +3130, +3099, +3100, +3133, +3132, +3101, +3102, +3135, +3134, +3103, +3160, +3193, +3192, +3161, +3162, +3195, +3194, +3163, +3164, +3197, +3196, +3165, +3166, +3199, +3198, +3167, +3224, +3257, +3256, +3225, +3226, +3259, +3258, +3227, +3228, +3261, +3260, +3229, +3230, +3263, +3262, +3231, +3288, +3321, +3320, +3289, +3290, +3323, +3322, +3291, +3292, +3325, +3324, +3293, +3294, +3327, +3326, +3295, +3352, +3385, +3384, +3353, +3354, +3387, +3386, +3355, +3356, +3389, +3388, +3357, +3358, +3391, +3390, +3359, +3416, +3449, +3448, +3417, +3418, +3451, +3450, +3419, +3420, +3453, +3452, +3421, +3422, +3455, +3454, +3423, +3480, +3513, +3512, +3481, +3482, +3515, +3514, +3483, +3484, +3517, +3516, +3485, +3486, +3519, +3518, +3487, +3544, +3577, +3576, +3545, +3546, +3579, +3578, +3547, +3548, +3581, +3580, +3549, +3550, +3583, +3582, +3551, +3608, +3641, +3640, +3609, +3610, +3643, +3642, +3611, +3612, +3645, +3644, +3613, +3614, +3647, +3646, +3615, +3672, +3705, +3704, +3673, +3674, +3707, +3706, +3675, +3676, +3709, +3708, +3677, +3678, +3711, +3710, +3679, +3736, +3769, +3768, +3737, +3738, +3771, +3770, +3739, +3740, +3773, +3772, +3741, +3742, +3775, +3774, +3743, +3800, +3833, +3832, +3801, +3802, +3835, +3834, +3803, +3804, +3837, +3836, +3805, +3806, +3839, +3838, +3807, +3864, +3897, +3896, +3865, +3866, +3899, +3898, +3867, +3868, +3901, +3900, +3869, +3870, +3903, +3902, +3871, +3928, +3961, +3960, +3929, +3930, +3963, +3962, +3931, +3932, +3965, +3964, +3933, +3934, +3967, +3966, +3935, +3992, +4025, +4024, +3993, +3994, +4027, +4026, +3995, +3996, +4029, +4028, +3997, +3998, +4031, +4030, +3999, +4056, +4089, +4088, +4057, +4058, +4091, +4090, +4059, +4060, +4093, +4092, +4061, +4062, +4095, +4094, +4063, +4096, +4129, +4128, +4097, +4098, +4131, +4130, +4099, +4100, +4133, +4132, +4101, +4102, +4135, +4134, +4103, +4160, +4193, +4192, +4161, +4162, +4195, +4194, +4163, +4164, +4197, +4196, +4165, +4166, +4199, +4198, +4167, +4224, +4257, +4256, +4225, +4226, +4259, +4258, +4227, +4228, +4261, +4260, +4229, +4230, +4263, +4262, +4231, +4288, +4321, +4320, +4289, +4290, +4323, +4322, +4291, +4292, +4325, +4324, +4293, +4294, +4327, +4326, +4295, +4352, +4385, +4384, +4353, +4354, +4387, +4386, +4355, +4356, +4389, +4388, +4357, +4358, +4391, +4390, +4359, +4416, +4449, +4448, +4417, +4418, +4451, +4450, +4419, +4420, +4453, +4452, +4421, +4422, +4455, +4454, +4423, +4480, +4513, +4512, +4481, +4482, +4515, +4514, +4483, +4484, +4517, +4516, +4485, +4486, +4519, +4518, +4487, +4544, +4577, +4576, +4545, +4546, +4579, +4578, +4547, +4548, +4581, +4580, +4549, +4550, +4583, +4582, +4551, +4608, +4641, +4640, +4609, +4610, +4643, +4642, +4611, +4612, +4645, +4644, +4613, +4614, +4647, +4646, +4615, +4672, +4705, +4704, +4673, +4674, +4707, +4706, +4675, +4676, +4709, +4708, +4677, +4678, +4711, +4710, +4679, +4736, +4769, +4768, +4737, +4738, +4771, +4770, +4739, +4740, +4773, +4772, +4741, +4742, +4775, +4774, +4743, +4800, +4833, +4832, +4801, +4802, +4835, +4834, +4803, +4804, +4837, +4836, +4805, +4806, +4839, +4838, +4807, +4864, +4897, +4896, +4865, +4866, +4899, +4898, +4867, +4868, +4901, +4900, +4869, +4870, +4903, +4902, +4871, +4928, +4961, +4960, +4929, +4930, +4963, +4962, +4931, +4932, +4965, +4964, +4933, +4934, +4967, +4966, +4935, +4992, +5025, +5024, +4993, +4994, +5027, +5026, +4995, +4996, +5029, +5028, +4997, +4998, +5031, +5030, +4999, +5056, +5089, +5088, +5057, +5058, +5091, +5090, +5059, +5060, +5093, +5092, +5061, +5062, +5095, +5094, +5063, +5120, +5153, +5152, +5121, +5122, +5155, +5154, +5123, +5124, +5157, +5156, +5125, +5126, +5159, +5158, +5127, +5184, +5217, +5216, +5185, +5186, +5219, +5218, +5187, +5188, +5221, +5220, +5189, +5190, +5223, +5222, +5191, +5248, +5281, +5280, +5249, +5250, +5283, +5282, +5251, +5252, +5285, +5284, +5253, +5254, +5287, +5286, +5255, +5312, +5345, +5344, +5313, +5314, +5347, +5346, +5315, +5316, +5349, +5348, +5317, +5318, +5351, +5350, +5319, +5376, +5409, +5408, +5377, +5378, +5411, +5410, +5379, +5380, +5413, +5412, +5381, +5382, +5415, +5414, +5383, +5440, +5473, +5472, +5441, +5442, +5475, +5474, +5443, +5444, +5477, +5476, +5445, +5446, +5479, +5478, +5447, +5504, +5537, +5536, +5505, +5506, +5539, +5538, +5507, +5508, +5541, +5540, +5509, +5510, +5543, +5542, +5511, +5568, +5601, +5600, +5569, +5570, +5603, +5602, +5571, +5572, +5605, +5604, +5573, +5574, +5607, +5606, +5575, +5632, +5665, +5664, +5633, +5634, +5667, +5666, +5635, +5636, +5669, +5668, +5637, +5638, +5671, +5670, +5639, +5696, +5729, +5728, +5697, +5698, +5731, +5730, +5699, +5700, +5733, +5732, +5701, +5702, +5735, +5734, +5703, +5760, +5793, +5792, +5761, +5762, +5795, +5794, +5763, +5764, +5797, +5796, +5765, +5766, +5799, +5798, +5767, +5824, +5857, +5856, +5825, +5826, +5859, +5858, +5827, +5828, +5861, +5860, +5829, +5830, +5863, +5862, +5831, +5888, +5921, +5920, +5889, +5890, +5923, +5922, +5891, +5892, +5925, +5924, +5893, +5894, +5927, +5926, +5895, +5952, +5985, +5984, +5953, +5954, +5987, +5986, +5955, +5956, +5989, +5988, +5957, +5958, +5991, +5990, +5959, +6016, +6049, +6048, +6017, +6018, +6051, +6050, +6019, +6020, +6053, +6052, +6021, +6022, +6055, +6054, +6023, +6080, +6113, +6112, +6081, +6082, +6115, +6114, +6083, +6084, +6117, +6116, +6085, +6086, +6119, +6118, +6087, +4104, +4137, +4136, +4105, +4106, +4139, +4138, +4107, +4108, +4141, +4140, +4109, +4110, +4143, +4142, +4111, +4168, +4201, +4200, +4169, +4170, +4203, +4202, +4171, +4172, +4205, +4204, +4173, +4174, +4207, +4206, +4175, +4232, +4265, +4264, +4233, +4234, +4267, +4266, +4235, +4236, +4269, +4268, +4237, +4238, +4271, +4270, +4239, +4296, +4329, +4328, +4297, +4298, +4331, +4330, +4299, +4300, +4333, +4332, +4301, +4302, +4335, +4334, +4303, +4360, +4393, +4392, +4361, +4362, +4395, +4394, +4363, +4364, +4397, +4396, +4365, +4366, +4399, +4398, +4367, +4424, +4457, +4456, +4425, +4426, +4459, +4458, +4427, +4428, +4461, +4460, +4429, +4430, +4463, +4462, +4431, +4488, +4521, +4520, +4489, +4490, +4523, +4522, +4491, +4492, +4525, +4524, +4493, +4494, +4527, +4526, +4495, +4552, +4585, +4584, +4553, +4554, +4587, +4586, +4555, +4556, +4589, +4588, +4557, +4558, +4591, +4590, +4559, +4616, +4649, +4648, +4617, +4618, +4651, +4650, +4619, +4620, +4653, +4652, +4621, +4622, +4655, +4654, +4623, +4680, +4713, +4712, +4681, +4682, +4715, +4714, +4683, +4684, +4717, +4716, +4685, +4686, +4719, +4718, +4687, +4744, +4777, +4776, +4745, +4746, +4779, +4778, +4747, +4748, +4781, +4780, +4749, +4750, +4783, +4782, +4751, +4808, +4841, +4840, +4809, +4810, +4843, +4842, +4811, +4812, +4845, +4844, +4813, +4814, +4847, +4846, +4815, +4872, +4905, +4904, +4873, +4874, +4907, +4906, +4875, +4876, +4909, +4908, +4877, +4878, +4911, +4910, +4879, +4936, +4969, +4968, +4937, +4938, +4971, +4970, +4939, +4940, +4973, +4972, +4941, +4942, +4975, +4974, +4943, +5000, +5033, +5032, +5001, +5002, +5035, +5034, +5003, +5004, +5037, +5036, +5005, +5006, +5039, +5038, +5007, +5064, +5097, +5096, +5065, +5066, +5099, +5098, +5067, +5068, +5101, +5100, +5069, +5070, +5103, +5102, +5071, +5128, +5161, +5160, +5129, +5130, +5163, +5162, +5131, +5132, +5165, +5164, +5133, +5134, +5167, +5166, +5135, +5192, +5225, +5224, +5193, +5194, +5227, +5226, +5195, +5196, +5229, +5228, +5197, +5198, +5231, +5230, +5199, +5256, +5289, +5288, +5257, +5258, +5291, +5290, +5259, +5260, +5293, +5292, +5261, +5262, +5295, +5294, +5263, +5320, +5353, +5352, +5321, +5322, +5355, +5354, +5323, +5324, +5357, +5356, +5325, +5326, +5359, +5358, +5327, +5384, +5417, +5416, +5385, +5386, +5419, +5418, +5387, +5388, +5421, +5420, +5389, +5390, +5423, +5422, +5391, +5448, +5481, +5480, +5449, +5450, +5483, +5482, +5451, +5452, +5485, +5484, +5453, +5454, +5487, +5486, +5455, +5512, +5545, +5544, +5513, +5514, +5547, +5546, +5515, +5516, +5549, +5548, +5517, +5518, +5551, +5550, +5519, +5576, +5609, +5608, +5577, +5578, +5611, +5610, +5579, +5580, +5613, +5612, +5581, +5582, +5615, +5614, +5583, +5640, +5673, +5672, +5641, +5642, +5675, +5674, +5643, +5644, +5677, +5676, +5645, +5646, +5679, +5678, +5647, +5704, +5737, +5736, +5705, +5706, +5739, +5738, +5707, +5708, +5741, +5740, +5709, +5710, +5743, +5742, +5711, +5768, +5801, +5800, +5769, +5770, +5803, +5802, +5771, +5772, +5805, +5804, +5773, +5774, +5807, +5806, +5775, +5832, +5865, +5864, +5833, +5834, +5867, +5866, +5835, +5836, +5869, +5868, +5837, +5838, +5871, +5870, +5839, +5896, +5929, +5928, +5897, +5898, +5931, +5930, +5899, +5900, +5933, +5932, +5901, +5902, +5935, +5934, +5903, +5960, +5993, +5992, +5961, +5962, +5995, +5994, +5963, +5964, +5997, +5996, +5965, +5966, +5999, +5998, +5967, +6024, +6057, +6056, +6025, +6026, +6059, +6058, +6027, +6028, +6061, +6060, +6029, +6030, +6063, +6062, +6031, +6088, +6121, +6120, +6089, +6090, +6123, +6122, +6091, +6092, +6125, +6124, +6093, +6094, +6127, +6126, +6095, +4112, +4145, +4144, +4113, +4114, +4147, +4146, +4115, +4116, +4149, +4148, +4117, +4118, +4151, +4150, +4119, +4176, +4209, +4208, +4177, +4178, +4211, +4210, +4179, +4180, +4213, +4212, +4181, +4182, +4215, +4214, +4183, +4240, +4273, +4272, +4241, +4242, +4275, +4274, +4243, +4244, +4277, +4276, +4245, +4246, +4279, +4278, +4247, +4304, +4337, +4336, +4305, +4306, +4339, +4338, +4307, +4308, +4341, +4340, +4309, +4310, +4343, +4342, +4311, +4368, +4401, +4400, +4369, +4370, +4403, +4402, +4371, +4372, +4405, +4404, +4373, +4374, +4407, +4406, +4375, +4432, +4465, +4464, +4433, +4434, +4467, +4466, +4435, +4436, +4469, +4468, +4437, +4438, +4471, +4470, +4439, +4496, +4529, +4528, +4497, +4498, +4531, +4530, +4499, +4500, +4533, +4532, +4501, +4502, +4535, +4534, +4503, +4560, +4593, +4592, +4561, +4562, +4595, +4594, +4563, +4564, +4597, +4596, +4565, +4566, +4599, +4598, +4567, +4624, +4657, +4656, +4625, +4626, +4659, +4658, +4627, +4628, +4661, +4660, +4629, +4630, +4663, +4662, +4631, +4688, +4721, +4720, +4689, +4690, +4723, +4722, +4691, +4692, +4725, +4724, +4693, +4694, +4727, +4726, +4695, +4752, +4785, +4784, +4753, +4754, +4787, +4786, +4755, +4756, +4789, +4788, +4757, +4758, +4791, +4790, +4759, +4816, +4849, +4848, +4817, +4818, +4851, +4850, +4819, +4820, +4853, +4852, +4821, +4822, +4855, +4854, +4823, +4880, +4913, +4912, +4881, +4882, +4915, +4914, +4883, +4884, +4917, +4916, +4885, +4886, +4919, +4918, +4887, +4944, +4977, +4976, +4945, +4946, +4979, +4978, +4947, +4948, +4981, +4980, +4949, +4950, +4983, +4982, +4951, +5008, +5041, +5040, +5009, +5010, +5043, +5042, +5011, +5012, +5045, +5044, +5013, +5014, +5047, +5046, +5015, +5072, +5105, +5104, +5073, +5074, +5107, +5106, +5075, +5076, +5109, +5108, +5077, +5078, +5111, +5110, +5079, +5136, +5169, +5168, +5137, +5138, +5171, +5170, +5139, +5140, +5173, +5172, +5141, +5142, +5175, +5174, +5143, +5200, +5233, +5232, +5201, +5202, +5235, +5234, +5203, +5204, +5237, +5236, +5205, +5206, +5239, +5238, +5207, +5264, +5297, +5296, +5265, +5266, +5299, +5298, +5267, +5268, +5301, +5300, +5269, +5270, +5303, +5302, +5271, +5328, +5361, +5360, +5329, +5330, +5363, +5362, +5331, +5332, +5365, +5364, +5333, +5334, +5367, +5366, +5335, +5392, +5425, +5424, +5393, +5394, +5427, +5426, +5395, +5396, +5429, +5428, +5397, +5398, +5431, +5430, +5399, +5456, +5489, +5488, +5457, +5458, +5491, +5490, +5459, +5460, +5493, +5492, +5461, +5462, +5495, +5494, +5463, +5520, +5553, +5552, +5521, +5522, +5555, +5554, +5523, +5524, +5557, +5556, +5525, +5526, +5559, +5558, +5527, +5584, +5617, +5616, +5585, +5586, +5619, +5618, +5587, +5588, +5621, +5620, +5589, +5590, +5623, +5622, +5591, +5648, +5681, +5680, +5649, +5650, +5683, +5682, +5651, +5652, +5685, +5684, +5653, +5654, +5687, +5686, +5655, +5712, +5745, +5744, +5713, +5714, +5747, +5746, +5715, +5716, +5749, +5748, +5717, +5718, +5751, +5750, +5719, +5776, +5809, +5808, +5777, +5778, +5811, +5810, +5779, +5780, +5813, +5812, +5781, +5782, +5815, +5814, +5783, +5840, +5873, +5872, +5841, +5842, +5875, +5874, +5843, +5844, +5877, +5876, +5845, +5846, +5879, +5878, +5847, +5904, +5937, +5936, +5905, +5906, +5939, +5938, +5907, +5908, +5941, +5940, +5909, +5910, +5943, +5942, +5911, +5968, +6001, +6000, +5969, +5970, +6003, +6002, +5971, +5972, +6005, +6004, +5973, +5974, +6007, +6006, +5975, +6032, +6065, +6064, +6033, +6034, +6067, +6066, +6035, +6036, +6069, +6068, +6037, +6038, +6071, +6070, +6039, +6096, +6129, +6128, +6097, +6098, +6131, +6130, +6099, +6100, +6133, +6132, +6101, +6102, +6135, +6134, +6103, +4120, +4153, +4152, +4121, +4122, +4155, +4154, +4123, +4124, +4157, +4156, +4125, +4126, +4159, +4158, +4127, +4184, +4217, +4216, +4185, +4186, +4219, +4218, +4187, +4188, +4221, +4220, +4189, +4190, +4223, +4222, +4191, +4248, +4281, +4280, +4249, +4250, +4283, +4282, +4251, +4252, +4285, +4284, +4253, +4254, +4287, +4286, +4255, +4312, +4345, +4344, +4313, +4314, +4347, +4346, +4315, +4316, +4349, +4348, +4317, +4318, +4351, +4350, +4319, +4376, +4409, +4408, +4377, +4378, +4411, +4410, +4379, +4380, +4413, +4412, +4381, +4382, +4415, +4414, +4383, +4440, +4473, +4472, +4441, +4442, +4475, +4474, +4443, +4444, +4477, +4476, +4445, +4446, +4479, +4478, +4447, +4504, +4537, +4536, +4505, +4506, +4539, +4538, +4507, +4508, +4541, +4540, +4509, +4510, +4543, +4542, +4511, +4568, +4601, +4600, +4569, +4570, +4603, +4602, +4571, +4572, +4605, +4604, +4573, +4574, +4607, +4606, +4575, +4632, +4665, +4664, +4633, +4634, +4667, +4666, +4635, +4636, +4669, +4668, +4637, +4638, +4671, +4670, +4639, +4696, +4729, +4728, +4697, +4698, +4731, +4730, +4699, +4700, +4733, +4732, +4701, +4702, +4735, +4734, +4703, +4760, +4793, +4792, +4761, +4762, +4795, +4794, +4763, +4764, +4797, +4796, +4765, +4766, +4799, +4798, +4767, +4824, +4857, +4856, +4825, +4826, +4859, +4858, +4827, +4828, +4861, +4860, +4829, +4830, +4863, +4862, +4831, +4888, +4921, +4920, +4889, +4890, +4923, +4922, +4891, +4892, +4925, +4924, +4893, +4894, +4927, +4926, +4895, +4952, +4985, +4984, +4953, +4954, +4987, +4986, +4955, +4956, +4989, +4988, +4957, +4958, +4991, +4990, +4959, +5016, +5049, +5048, +5017, +5018, +5051, +5050, +5019, +5020, +5053, +5052, +5021, +5022, +5055, +5054, +5023, +5080, +5113, +5112, +5081, +5082, +5115, +5114, +5083, +5084, +5117, +5116, +5085, +5086, +5119, +5118, +5087, +5144, +5177, +5176, +5145, +5146, +5179, +5178, +5147, +5148, +5181, +5180, +5149, +5150, +5183, +5182, +5151, +5208, +5241, +5240, +5209, +5210, +5243, +5242, +5211, +5212, +5245, +5244, +5213, +5214, +5247, +5246, +5215, +5272, +5305, +5304, +5273, +5274, +5307, +5306, +5275, +5276, +5309, +5308, +5277, +5278, +5311, +5310, +5279, +5336, +5369, +5368, +5337, +5338, +5371, +5370, +5339, +5340, +5373, +5372, +5341, +5342, +5375, +5374, +5343, +5400, +5433, +5432, +5401, +5402, +5435, +5434, +5403, +5404, +5437, +5436, +5405, +5406, +5439, +5438, +5407, +5464, +5497, +5496, +5465, +5466, +5499, +5498, +5467, +5468, +5501, +5500, +5469, +5470, +5503, +5502, +5471, +5528, +5561, +5560, +5529, +5530, +5563, +5562, +5531, +5532, +5565, +5564, +5533, +5534, +5567, +5566, +5535, +5592, +5625, +5624, +5593, +5594, +5627, +5626, +5595, +5596, +5629, +5628, +5597, +5598, +5631, +5630, +5599, +5656, +5689, +5688, +5657, +5658, +5691, +5690, +5659, +5660, +5693, +5692, +5661, +5662, +5695, +5694, +5663, +5720, +5753, +5752, +5721, +5722, +5755, +5754, +5723, +5724, +5757, +5756, +5725, +5726, +5759, +5758, +5727, +5784, +5817, +5816, +5785, +5786, +5819, +5818, +5787, +5788, +5821, +5820, +5789, +5790, +5823, +5822, +5791, +5848, +5881, +5880, +5849, +5850, +5883, +5882, +5851, +5852, +5885, +5884, +5853, +5854, +5887, +5886, +5855, +5912, +5945, +5944, +5913, +5914, +5947, +5946, +5915, +5916, +5949, +5948, +5917, +5918, +5951, +5950, +5919, +5976, +6009, +6008, +5977, +5978, +6011, +6010, +5979, +5980, +6013, +6012, +5981, +5982, +6015, +6014, +5983, +6040, +6073, +6072, +6041, +6042, +6075, +6074, +6043, +6044, +6077, +6076, +6045, +6046, +6079, +6078, +6047, +6104, +6137, +6136, +6105, +6106, +6139, +6138, +6107, +6108, +6141, +6140, +6109, +6110, +6143, +6142, +6111, +6144, +6177, +6176, +6145, +6146, +6179, +6178, +6147, +6148, +6181, +6180, +6149, +6150, +6183, +6182, +6151, +6208, +6241, +6240, +6209, +6210, +6243, +6242, +6211, +6212, +6245, +6244, +6213, +6214, +6247, +6246, +6215, +6272, +6305, +6304, +6273, +6274, +6307, +6306, +6275, +6276, +6309, +6308, +6277, +6278, +6311, +6310, +6279, +6336, +6369, +6368, +6337, +6338, +6371, +6370, +6339, +6340, +6373, +6372, +6341, +6342, +6375, +6374, +6343, +6400, +6433, +6432, +6401, +6402, +6435, +6434, +6403, +6404, +6437, +6436, +6405, +6406, +6439, +6438, +6407, +6464, +6497, +6496, +6465, +6466, +6499, +6498, +6467, +6468, +6501, +6500, +6469, +6470, +6503, +6502, +6471, +6528, +6561, +6560, +6529, +6530, +6563, +6562, +6531, +6532, +6565, +6564, +6533, +6534, +6567, +6566, +6535, +6592, +6625, +6624, +6593, +6594, +6627, +6626, +6595, +6596, +6629, +6628, +6597, +6598, +6631, +6630, +6599, +6656, +6689, +6688, +6657, +6658, +6691, +6690, +6659, +6660, +6693, +6692, +6661, +6662, +6695, +6694, +6663, +6720, +6753, +6752, +6721, +6722, +6755, +6754, +6723, +6724, +6757, +6756, +6725, +6726, +6759, +6758, +6727, +6784, +6817, +6816, +6785, +6786, +6819, +6818, +6787, +6788, +6821, +6820, +6789, +6790, +6823, +6822, +6791, +6848, +6881, +6880, +6849, +6850, +6883, +6882, +6851, +6852, +6885, +6884, +6853, +6854, +6887, +6886, +6855, +6912, +6945, +6944, +6913, +6914, +6947, +6946, +6915, +6916, +6949, +6948, +6917, +6918, +6951, +6950, +6919, +6976, +7009, +7008, +6977, +6978, +7011, +7010, +6979, +6980, +7013, +7012, +6981, +6982, +7015, +7014, +6983, +7040, +7073, +7072, +7041, +7042, +7075, +7074, +7043, +7044, +7077, +7076, +7045, +7046, +7079, +7078, +7047, +7104, +7137, +7136, +7105, +7106, +7139, +7138, +7107, +7108, +7141, +7140, +7109, +7110, +7143, +7142, +7111, +7168, +7201, +7200, +7169, +7170, +7203, +7202, +7171, +7172, +7205, +7204, +7173, +7174, +7207, +7206, +7175, +7232, +7265, +7264, +7233, +7234, +7267, +7266, +7235, +7236, +7269, +7268, +7237, +7238, +7271, +7270, +7239, +7296, +7329, +7328, +7297, +7298, +7331, +7330, +7299, +7300, +7333, +7332, +7301, +7302, +7335, +7334, +7303, +7360, +7393, +7392, +7361, +7362, +7395, +7394, +7363, +7364, +7397, +7396, +7365, +7366, +7399, +7398, +7367, +7424, +7457, +7456, +7425, +7426, +7459, +7458, +7427, +7428, +7461, +7460, +7429, +7430, +7463, +7462, +7431, +7488, +7521, +7520, +7489, +7490, +7523, +7522, +7491, +7492, +7525, +7524, +7493, +7494, +7527, +7526, +7495, +7552, +7585, +7584, +7553, +7554, +7587, +7586, +7555, +7556, +7589, +7588, +7557, +7558, +7591, +7590, +7559, +7616, +7649, +7648, +7617, +7618, +7651, +7650, +7619, +7620, +7653, +7652, +7621, +7622, +7655, +7654, +7623, +7680, +7713, +7712, +7681, +7682, +7715, +7714, +7683, +7684, +7717, +7716, +7685, +7686, +7719, +7718, +7687, +7744, +7777, +7776, +7745, +7746, +7779, +7778, +7747, +7748, +7781, +7780, +7749, +7750, +7783, +7782, +7751, +7808, +7841, +7840, +7809, +7810, +7843, +7842, +7811, +7812, +7845, +7844, +7813, +7814, +7847, +7846, +7815, +7872, +7905, +7904, +7873, +7874, +7907, +7906, +7875, +7876, +7909, +7908, +7877, +7878, +7911, +7910, +7879, +7936, +7969, +7968, +7937, +7938, +7971, +7970, +7939, +7940, +7973, +7972, +7941, +7942, +7975, +7974, +7943, +8000, +8033, +8032, +8001, +8002, +8035, +8034, +8003, +8004, +8037, +8036, +8005, +8006, +8039, +8038, +8007, +8064, +8097, +8096, +8065, +8066, +8099, +8098, +8067, +8068, +8101, +8100, +8069, +8070, +8103, +8102, +8071, +8128, +8161, +8160, +8129, +8130, +8163, +8162, +8131, +8132, +8165, +8164, +8133, +8134, +8167, +8166, +8135, +6152, +6185, +6184, +6153, +6154, +6187, +6186, +6155, +6156, +6189, +6188, +6157, +6158, +6191, +6190, +6159, +6216, +6249, +6248, +6217, +6218, +6251, +6250, +6219, +6220, +6253, +6252, +6221, +6222, +6255, +6254, +6223, +6280, +6313, +6312, +6281, +6282, +6315, +6314, +6283, +6284, +6317, +6316, +6285, +6286, +6319, +6318, +6287, +6344, +6377, +6376, +6345, +6346, +6379, +6378, +6347, +6348, +6381, +6380, +6349, +6350, +6383, +6382, +6351, +6408, +6441, +6440, +6409, +6410, +6443, +6442, +6411, +6412, +6445, +6444, +6413, +6414, +6447, +6446, +6415, +6472, +6505, +6504, +6473, +6474, +6507, +6506, +6475, +6476, +6509, +6508, +6477, +6478, +6511, +6510, +6479, +6536, +6569, +6568, +6537, +6538, +6571, +6570, +6539, +6540, +6573, +6572, +6541, +6542, +6575, +6574, +6543, +6600, +6633, +6632, +6601, +6602, +6635, +6634, +6603, +6604, +6637, +6636, +6605, +6606, +6639, +6638, +6607, +6664, +6697, +6696, +6665, +6666, +6699, +6698, +6667, +6668, +6701, +6700, +6669, +6670, +6703, +6702, +6671, +6728, +6761, +6760, +6729, +6730, +6763, +6762, +6731, +6732, +6765, +6764, +6733, +6734, +6767, +6766, +6735, +6792, +6825, +6824, +6793, +6794, +6827, +6826, +6795, +6796, +6829, +6828, +6797, +6798, +6831, +6830, +6799, +6856, +6889, +6888, +6857, +6858, +6891, +6890, +6859, +6860, +6893, +6892, +6861, +6862, +6895, +6894, +6863, +6920, +6953, +6952, +6921, +6922, +6955, +6954, +6923, +6924, +6957, +6956, +6925, +6926, +6959, +6958, +6927, +6984, +7017, +7016, +6985, +6986, +7019, +7018, +6987, +6988, +7021, +7020, +6989, +6990, +7023, +7022, +6991, +7048, +7081, +7080, +7049, +7050, +7083, +7082, +7051, +7052, +7085, +7084, +7053, +7054, +7087, +7086, +7055, +7112, +7145, +7144, +7113, +7114, +7147, +7146, +7115, +7116, +7149, +7148, +7117, +7118, +7151, +7150, +7119, +7176, +7209, +7208, +7177, +7178, +7211, +7210, +7179, +7180, +7213, +7212, +7181, +7182, +7215, +7214, +7183, +7240, +7273, +7272, +7241, +7242, +7275, +7274, +7243, +7244, +7277, +7276, +7245, +7246, +7279, +7278, +7247, +7304, +7337, +7336, +7305, +7306, +7339, +7338, +7307, +7308, +7341, +7340, +7309, +7310, +7343, +7342, +7311, +7368, +7401, +7400, +7369, +7370, +7403, +7402, +7371, +7372, +7405, +7404, +7373, +7374, +7407, +7406, +7375, +7432, +7465, +7464, +7433, +7434, +7467, +7466, +7435, +7436, +7469, +7468, +7437, +7438, +7471, +7470, +7439, +7496, +7529, +7528, +7497, +7498, +7531, +7530, +7499, +7500, +7533, +7532, +7501, +7502, +7535, +7534, +7503, +7560, +7593, +7592, +7561, +7562, +7595, +7594, +7563, +7564, +7597, +7596, +7565, +7566, +7599, +7598, +7567, +7624, +7657, +7656, +7625, +7626, +7659, +7658, +7627, +7628, +7661, +7660, +7629, +7630, +7663, +7662, +7631, +7688, +7721, +7720, +7689, +7690, +7723, +7722, +7691, +7692, +7725, +7724, +7693, +7694, +7727, +7726, +7695, +7752, +7785, +7784, +7753, +7754, +7787, +7786, +7755, +7756, +7789, +7788, +7757, +7758, +7791, +7790, +7759, +7816, +7849, +7848, +7817, +7818, +7851, +7850, +7819, +7820, +7853, +7852, +7821, +7822, +7855, +7854, +7823, +7880, +7913, +7912, +7881, +7882, +7915, +7914, +7883, +7884, +7917, +7916, +7885, +7886, +7919, +7918, +7887, +7944, +7977, +7976, +7945, +7946, +7979, +7978, +7947, +7948, +7981, +7980, +7949, +7950, +7983, +7982, +7951, +8008, +8041, +8040, +8009, +8010, +8043, +8042, +8011, +8012, +8045, +8044, +8013, +8014, +8047, +8046, +8015, +8072, +8105, +8104, +8073, +8074, +8107, +8106, +8075, +8076, +8109, +8108, +8077, +8078, +8111, +8110, +8079, +8136, +8169, +8168, +8137, +8138, +8171, +8170, +8139, +8140, +8173, +8172, +8141, +8142, +8175, +8174, +8143, +6160, +6193, +6192, +6161, +6162, +6195, +6194, +6163, +6164, +6197, +6196, +6165, +6166, +6199, +6198, +6167, +6224, +6257, +6256, +6225, +6226, +6259, +6258, +6227, +6228, +6261, +6260, +6229, +6230, +6263, +6262, +6231, +6288, +6321, +6320, +6289, +6290, +6323, +6322, +6291, +6292, +6325, +6324, +6293, +6294, +6327, +6326, +6295, +6352, +6385, +6384, +6353, +6354, +6387, +6386, +6355, +6356, +6389, +6388, +6357, +6358, +6391, +6390, +6359, +6416, +6449, +6448, +6417, +6418, +6451, +6450, +6419, +6420, +6453, +6452, +6421, +6422, +6455, +6454, +6423, +6480, +6513, +6512, +6481, +6482, +6515, +6514, +6483, +6484, +6517, +6516, +6485, +6486, +6519, +6518, +6487, +6544, +6577, +6576, +6545, +6546, +6579, +6578, +6547, +6548, +6581, +6580, +6549, +6550, +6583, +6582, +6551, +6608, +6641, +6640, +6609, +6610, +6643, +6642, +6611, +6612, +6645, +6644, +6613, +6614, +6647, +6646, +6615, +6672, +6705, +6704, +6673, +6674, +6707, +6706, +6675, +6676, +6709, +6708, +6677, +6678, +6711, +6710, +6679, +6736, +6769, +6768, +6737, +6738, +6771, +6770, +6739, +6740, +6773, +6772, +6741, +6742, +6775, +6774, +6743, +6800, +6833, +6832, +6801, +6802, +6835, +6834, +6803, +6804, +6837, +6836, +6805, +6806, +6839, +6838, +6807, +6864, +6897, +6896, +6865, +6866, +6899, +6898, +6867, +6868, +6901, +6900, +6869, +6870, +6903, +6902, +6871, +6928, +6961, +6960, +6929, +6930, +6963, +6962, +6931, +6932, +6965, +6964, +6933, +6934, +6967, +6966, +6935, +6992, +7025, +7024, +6993, +6994, +7027, +7026, +6995, +6996, +7029, +7028, +6997, +6998, +7031, +7030, +6999, +7056, +7089, +7088, +7057, +7058, +7091, +7090, +7059, +7060, +7093, +7092, +7061, +7062, +7095, +7094, +7063, +7120, +7153, +7152, +7121, +7122, +7155, +7154, +7123, +7124, +7157, +7156, +7125, +7126, +7159, +7158, +7127, +7184, +7217, +7216, +7185, +7186, +7219, +7218, +7187, +7188, +7221, +7220, +7189, +7190, +7223, +7222, +7191, +7248, +7281, +7280, +7249, +7250, +7283, +7282, +7251, +7252, +7285, +7284, +7253, +7254, +7287, +7286, +7255, +7312, +7345, +7344, +7313, +7314, +7347, +7346, +7315, +7316, +7349, +7348, +7317, +7318, +7351, +7350, +7319, +7376, +7409, +7408, +7377, +7378, +7411, +7410, +7379, +7380, +7413, +7412, +7381, +7382, +7415, +7414, +7383, +7440, +7473, +7472, +7441, +7442, +7475, +7474, +7443, +7444, +7477, +7476, +7445, +7446, +7479, +7478, +7447, +7504, +7537, +7536, +7505, +7506, +7539, +7538, +7507, +7508, +7541, +7540, +7509, +7510, +7543, +7542, +7511, +7568, +7601, +7600, +7569, +7570, +7603, +7602, +7571, +7572, +7605, +7604, +7573, +7574, +7607, +7606, +7575, +7632, +7665, +7664, +7633, +7634, +7667, +7666, +7635, +7636, +7669, +7668, +7637, +7638, +7671, +7670, +7639, +7696, +7729, +7728, +7697, +7698, +7731, +7730, +7699, +7700, +7733, +7732, +7701, +7702, +7735, +7734, +7703, +7760, +7793, +7792, +7761, +7762, +7795, +7794, +7763, +7764, +7797, +7796, +7765, +7766, +7799, +7798, +7767, +7824, +7857, +7856, +7825, +7826, +7859, +7858, +7827, +7828, +7861, +7860, +7829, +7830, +7863, +7862, +7831, +7888, +7921, +7920, +7889, +7890, +7923, +7922, +7891, +7892, +7925, +7924, +7893, +7894, +7927, +7926, +7895, +7952, +7985, +7984, +7953, +7954, +7987, +7986, +7955, +7956, +7989, +7988, +7957, +7958, +7991, +7990, +7959, +8016, +8049, +8048, +8017, +8018, +8051, +8050, +8019, +8020, +8053, +8052, +8021, +8022, +8055, +8054, +8023, +8080, +8113, +8112, +8081, +8082, +8115, +8114, +8083, +8084, +8117, +8116, +8085, +8086, +8119, +8118, +8087, +8144, +8177, +8176, +8145, +8146, +8179, +8178, +8147, +8148, +8181, +8180, +8149, +8150, +8183, +8182, +8151, +6168, +6201, +6200, +6169, +6170, +6203, +6202, +6171, +6172, +6205, +6204, +6173, +6174, +6207, +6206, +6175, +6232, +6265, +6264, +6233, +6234, +6267, +6266, +6235, +6236, +6269, +6268, +6237, +6238, +6271, +6270, +6239, +6296, +6329, +6328, +6297, +6298, +6331, +6330, +6299, +6300, +6333, +6332, +6301, +6302, +6335, +6334, +6303, +6360, +6393, +6392, +6361, +6362, +6395, +6394, +6363, +6364, +6397, +6396, +6365, +6366, +6399, +6398, +6367, +6424, +6457, +6456, +6425, +6426, +6459, +6458, +6427, +6428, +6461, +6460, +6429, +6430, +6463, +6462, +6431, +6488, +6521, +6520, +6489, +6490, +6523, +6522, +6491, +6492, +6525, +6524, +6493, +6494, +6527, +6526, +6495, +6552, +6585, +6584, +6553, +6554, +6587, +6586, +6555, +6556, +6589, +6588, +6557, +6558, +6591, +6590, +6559, +6616, +6649, +6648, +6617, +6618, +6651, +6650, +6619, +6620, +6653, +6652, +6621, +6622, +6655, +6654, +6623, +6680, +6713, +6712, +6681, +6682, +6715, +6714, +6683, +6684, +6717, +6716, +6685, +6686, +6719, +6718, +6687, +6744, +6777, +6776, +6745, +6746, +6779, +6778, +6747, +6748, +6781, +6780, +6749, +6750, +6783, +6782, +6751, +6808, +6841, +6840, +6809, +6810, +6843, +6842, +6811, +6812, +6845, +6844, +6813, +6814, +6847, +6846, +6815, +6872, +6905, +6904, +6873, +6874, +6907, +6906, +6875, +6876, +6909, +6908, +6877, +6878, +6911, +6910, +6879, +6936, +6969, +6968, +6937, +6938, +6971, +6970, +6939, +6940, +6973, +6972, +6941, +6942, +6975, +6974, +6943, +7000, +7033, +7032, +7001, +7002, +7035, +7034, +7003, +7004, +7037, +7036, +7005, +7006, +7039, +7038, +7007, +7064, +7097, +7096, +7065, +7066, +7099, +7098, +7067, +7068, +7101, +7100, +7069, +7070, +7103, +7102, +7071, +7128, +7161, +7160, +7129, +7130, +7163, +7162, +7131, +7132, +7165, +7164, +7133, +7134, +7167, +7166, +7135, +7192, +7225, +7224, +7193, +7194, +7227, +7226, +7195, +7196, +7229, +7228, +7197, +7198, +7231, +7230, +7199, +7256, +7289, +7288, +7257, +7258, +7291, +7290, +7259, +7260, +7293, +7292, +7261, +7262, +7295, +7294, +7263, +7320, +7353, +7352, +7321, +7322, +7355, +7354, +7323, +7324, +7357, +7356, +7325, +7326, +7359, +7358, +7327, +7384, +7417, +7416, +7385, +7386, +7419, +7418, +7387, +7388, +7421, +7420, +7389, +7390, +7423, +7422, +7391, +7448, +7481, +7480, +7449, +7450, +7483, +7482, +7451, +7452, +7485, +7484, +7453, +7454, +7487, +7486, +7455, +7512, +7545, +7544, +7513, +7514, +7547, +7546, +7515, +7516, +7549, +7548, +7517, +7518, +7551, +7550, +7519, +7576, +7609, +7608, +7577, +7578, +7611, +7610, +7579, +7580, +7613, +7612, +7581, +7582, +7615, +7614, +7583, +7640, +7673, +7672, +7641, +7642, +7675, +7674, +7643, +7644, +7677, +7676, +7645, +7646, +7679, +7678, +7647, +7704, +7737, +7736, +7705, +7706, +7739, +7738, +7707, +7708, +7741, +7740, +7709, +7710, +7743, +7742, +7711, +7768, +7801, +7800, +7769, +7770, +7803, +7802, +7771, +7772, +7805, +7804, +7773, +7774, +7807, +7806, +7775, +7832, +7865, +7864, +7833, +7834, +7867, +7866, +7835, +7836, +7869, +7868, +7837, +7838, +7871, +7870, +7839, +7896, +7929, +7928, +7897, +7898, +7931, +7930, +7899, +7900, +7933, +7932, +7901, +7902, +7935, +7934, +7903, +7960, +7993, +7992, +7961, +7962, +7995, +7994, +7963, +7964, +7997, +7996, +7965, +7966, +7999, +7998, +7967, +8024, +8057, +8056, +8025, +8026, +8059, +8058, +8027, +8028, +8061, +8060, +8029, +8030, +8063, +8062, +8031, +8088, +8121, +8120, +8089, +8090, +8123, +8122, +8091, +8092, +8125, +8124, +8093, +8094, +8127, +8126, +8095, +8152, +8185, +8184, +8153, +8154, +8187, +8186, +8155, +8156, +8189, +8188, +8157, +8158, +8191, +8190, +8159, +8192, +8225, +8224, +8193, +8194, +8227, +8226, +8195, +8196, +8229, +8228, +8197, +8198, +8231, +8230, +8199, +8256, +8289, +8288, +8257, +8258, +8291, +8290, +8259, +8260, +8293, +8292, +8261, +8262, +8295, +8294, +8263, +8320, +8353, +8352, +8321, +8322, +8355, +8354, +8323, +8324, +8357, +8356, +8325, +8326, +8359, +8358, +8327, +8384, +8417, +8416, +8385, +8386, +8419, +8418, +8387, +8388, +8421, +8420, +8389, +8390, +8423, +8422, +8391, +8448, +8481, +8480, +8449, +8450, +8483, +8482, +8451, +8452, +8485, +8484, +8453, +8454, +8487, +8486, +8455, +8512, +8545, +8544, +8513, +8514, +8547, +8546, +8515, +8516, +8549, +8548, +8517, +8518, +8551, +8550, +8519, +8576, +8609, +8608, +8577, +8578, +8611, +8610, +8579, +8580, +8613, +8612, +8581, +8582, +8615, +8614, +8583, +8640, +8673, +8672, +8641, +8642, +8675, +8674, +8643, +8644, +8677, +8676, +8645, +8646, +8679, +8678, +8647, +8704, +8737, +8736, +8705, +8706, +8739, +8738, +8707, +8708, +8741, +8740, +8709, +8710, +8743, +8742, +8711, +8768, +8801, +8800, +8769, +8770, +8803, +8802, +8771, +8772, +8805, +8804, +8773, +8774, +8807, +8806, +8775, +8832, +8865, +8864, +8833, +8834, +8867, +8866, +8835, +8836, +8869, +8868, +8837, +8838, +8871, +8870, +8839, +8896, +8929, +8928, +8897, +8898, +8931, +8930, +8899, +8900, +8933, +8932, +8901, +8902, +8935, +8934, +8903, +8960, +8993, +8992, +8961, +8962, +8995, +8994, +8963, +8964, +8997, +8996, +8965, +8966, +8999, +8998, +8967, +9024, +9057, +9056, +9025, +9026, +9059, +9058, +9027, +9028, +9061, +9060, +9029, +9030, +9063, +9062, +9031, +9088, +9121, +9120, +9089, +9090, +9123, +9122, +9091, +9092, +9125, +9124, +9093, +9094, +9127, +9126, +9095, +9152, +9185, +9184, +9153, +9154, +9187, +9186, +9155, +9156, +9189, +9188, +9157, +9158, +9191, +9190, +9159, +9216, +9249, +9248, +9217, +9218, +9251, +9250, +9219, +9220, +9253, +9252, +9221, +9222, +9255, +9254, +9223, +9280, +9313, +9312, +9281, +9282, +9315, +9314, +9283, +9284, +9317, +9316, +9285, +9286, +9319, +9318, +9287, +9344, +9377, +9376, +9345, +9346, +9379, +9378, +9347, +9348, +9381, +9380, +9349, +9350, +9383, +9382, +9351, +9408, +9441, +9440, +9409, +9410, +9443, +9442, +9411, +9412, +9445, +9444, +9413, +9414, +9447, +9446, +9415, +9472, +9505, +9504, +9473, +9474, +9507, +9506, +9475, +9476, +9509, +9508, +9477, +9478, +9511, +9510, +9479, +9536, +9569, +9568, +9537, +9538, +9571, +9570, +9539, +9540, +9573, +9572, +9541, +9542, +9575, +9574, +9543, +9600, +9633, +9632, +9601, +9602, +9635, +9634, +9603, +9604, +9637, +9636, +9605, +9606, +9639, +9638, +9607, +9664, +9697, +9696, +9665, +9666, +9699, +9698, +9667, +9668, +9701, +9700, +9669, +9670, +9703, +9702, +9671, +9728, +9761, +9760, +9729, +9730, +9763, +9762, +9731, +9732, +9765, +9764, +9733, +9734, +9767, +9766, +9735, +9792, +9825, +9824, +9793, +9794, +9827, +9826, +9795, +9796, +9829, +9828, +9797, +9798, +9831, +9830, +9799, +9856, +9889, +9888, +9857, +9858, +9891, +9890, +9859, +9860, +9893, +9892, +9861, +9862, +9895, +9894, +9863, +9920, +9953, +9952, +9921, +9922, +9955, +9954, +9923, +9924, +9957, +9956, +9925, +9926, +9959, +9958, +9927, +9984, +10017, +10016, +9985, +9986, +10019, +10018, +9987, +9988, +10021, +10020, +9989, +9990, +10023, +10022, +9991, +10048, +10081, +10080, +10049, +10050, +10083, +10082, +10051, +10052, +10085, +10084, +10053, +10054, +10087, +10086, +10055, +10112, +10145, +10144, +10113, +10114, +10147, +10146, +10115, +10116, +10149, +10148, +10117, +10118, +10151, +10150, +10119, +10176, +10209, +10208, +10177, +10178, +10211, +10210, +10179, +10180, +10213, +10212, +10181, +10182, +10215, +10214, +10183, +8200, +8233, +8232, +8201, +8202, +8235, +8234, +8203, +8204, +8237, +8236, +8205, +8206, +8239, +8238, +8207, +8264, +8297, +8296, +8265, +8266, +8299, +8298, +8267, +8268, +8301, +8300, +8269, +8270, +8303, +8302, +8271, +8328, +8361, +8360, +8329, +8330, +8363, +8362, +8331, +8332, +8365, +8364, +8333, +8334, +8367, +8366, +8335, +8392, +8425, +8424, +8393, +8394, +8427, +8426, +8395, +8396, +8429, +8428, +8397, +8398, +8431, +8430, +8399, +8456, +8489, +8488, +8457, +8458, +8491, +8490, +8459, +8460, +8493, +8492, +8461, +8462, +8495, +8494, +8463, +8520, +8553, +8552, +8521, +8522, +8555, +8554, +8523, +8524, +8557, +8556, +8525, +8526, +8559, +8558, +8527, +8584, +8617, +8616, +8585, +8586, +8619, +8618, +8587, +8588, +8621, +8620, +8589, +8590, +8623, +8622, +8591, +8648, +8681, +8680, +8649, +8650, +8683, +8682, +8651, +8652, +8685, +8684, +8653, +8654, +8687, +8686, +8655, +8712, +8745, +8744, +8713, +8714, +8747, +8746, +8715, +8716, +8749, +8748, +8717, +8718, +8751, +8750, +8719, +8776, +8809, +8808, +8777, +8778, +8811, +8810, +8779, +8780, +8813, +8812, +8781, +8782, +8815, +8814, +8783, +8840, +8873, +8872, +8841, +8842, +8875, +8874, +8843, +8844, +8877, +8876, +8845, +8846, +8879, +8878, +8847, +8904, +8937, +8936, +8905, +8906, +8939, +8938, +8907, +8908, +8941, +8940, +8909, +8910, +8943, +8942, +8911, +8968, +9001, +9000, +8969, +8970, +9003, +9002, +8971, +8972, +9005, +9004, +8973, +8974, +9007, +9006, +8975, +9032, +9065, +9064, +9033, +9034, +9067, +9066, +9035, +9036, +9069, +9068, +9037, +9038, +9071, +9070, +9039, +9096, +9129, +9128, +9097, +9098, +9131, +9130, +9099, +9100, +9133, +9132, +9101, +9102, +9135, +9134, +9103, +9160, +9193, +9192, +9161, +9162, +9195, +9194, +9163, +9164, +9197, +9196, +9165, +9166, +9199, +9198, +9167, +9224, +9257, +9256, +9225, +9226, +9259, +9258, +9227, +9228, +9261, +9260, +9229, +9230, +9263, +9262, +9231, +9288, +9321, +9320, +9289, +9290, +9323, +9322, +9291, +9292, +9325, +9324, +9293, +9294, +9327, +9326, +9295, +9352, +9385, +9384, +9353, +9354, +9387, +9386, +9355, +9356, +9389, +9388, +9357, +9358, +9391, +9390, +9359, +9416, +9449, +9448, +9417, +9418, +9451, +9450, +9419, +9420, +9453, +9452, +9421, +9422, +9455, +9454, +9423, +9480, +9513, +9512, +9481, +9482, +9515, +9514, +9483, +9484, +9517, +9516, +9485, +9486, +9519, +9518, +9487, +9544, +9577, +9576, +9545, +9546, +9579, +9578, +9547, +9548, +9581, +9580, +9549, +9550, +9583, +9582, +9551, +9608, +9641, +9640, +9609, +9610, +9643, +9642, +9611, +9612, +9645, +9644, +9613, +9614, +9647, +9646, +9615, +9672, +9705, +9704, +9673, +9674, +9707, +9706, +9675, +9676, +9709, +9708, +9677, +9678, +9711, +9710, +9679, +9736, +9769, +9768, +9737, +9738, +9771, +9770, +9739, +9740, +9773, +9772, +9741, +9742, +9775, +9774, +9743, +9800, +9833, +9832, +9801, +9802, +9835, +9834, +9803, +9804, +9837, +9836, +9805, +9806, +9839, +9838, +9807, +9864, +9897, +9896, +9865, +9866, +9899, +9898, +9867, +9868, +9901, +9900, +9869, +9870, +9903, +9902, +9871, +9928, +9961, +9960, +9929, +9930, +9963, +9962, +9931, +9932, +9965, +9964, +9933, +9934, +9967, +9966, +9935, +9992, +10025, +10024, +9993, +9994, +10027, +10026, +9995, +9996, +10029, +10028, +9997, +9998, +10031, +10030, +9999, +10056, +10089, +10088, +10057, +10058, +10091, +10090, +10059, +10060, +10093, +10092, +10061, +10062, +10095, +10094, +10063, +10120, +10153, +10152, +10121, +10122, +10155, +10154, +10123, +10124, +10157, +10156, +10125, +10126, +10159, +10158, +10127, +10184, +10217, +10216, +10185, +10186, +10219, +10218, +10187, +10188, +10221, +10220, +10189, +10190, +10223, +10222, +10191, +8208, +8241, +8240, +8209, +8210, +8243, +8242, +8211, +8212, +8245, +8244, +8213, +8214, +8247, +8246, +8215, +8272, +8305, +8304, +8273, +8274, +8307, +8306, +8275, +8276, +8309, +8308, +8277, +8278, +8311, +8310, +8279, +8336, +8369, +8368, +8337, +8338, +8371, +8370, +8339, +8340, +8373, +8372, +8341, +8342, +8375, +8374, +8343, +8400, +8433, +8432, +8401, +8402, +8435, +8434, +8403, +8404, +8437, +8436, +8405, +8406, +8439, +8438, +8407, +8464, +8497, +8496, +8465, +8466, +8499, +8498, +8467, +8468, +8501, +8500, +8469, +8470, +8503, +8502, +8471, +8528, +8561, +8560, +8529, +8530, +8563, +8562, +8531, +8532, +8565, +8564, +8533, +8534, +8567, +8566, +8535, +8592, +8625, +8624, +8593, +8594, +8627, +8626, +8595, +8596, +8629, +8628, +8597, +8598, +8631, +8630, +8599, +8656, +8689, +8688, +8657, +8658, +8691, +8690, +8659, +8660, +8693, +8692, +8661, +8662, +8695, +8694, +8663, +8720, +8753, +8752, +8721, +8722, +8755, +8754, +8723, +8724, +8757, +8756, +8725, +8726, +8759, +8758, +8727, +8784, +8817, +8816, +8785, +8786, +8819, +8818, +8787, +8788, +8821, +8820, +8789, +8790, +8823, +8822, +8791, +8848, +8881, +8880, +8849, +8850, +8883, +8882, +8851, +8852, +8885, +8884, +8853, +8854, +8887, +8886, +8855, +8912, +8945, +8944, +8913, +8914, +8947, +8946, +8915, +8916, +8949, +8948, +8917, +8918, +8951, +8950, +8919, +8976, +9009, +9008, +8977, +8978, +9011, +9010, +8979, +8980, +9013, +9012, +8981, +8982, +9015, +9014, +8983, +9040, +9073, +9072, +9041, +9042, +9075, +9074, +9043, +9044, +9077, +9076, +9045, +9046, +9079, +9078, +9047, +9104, +9137, +9136, +9105, +9106, +9139, +9138, +9107, +9108, +9141, +9140, +9109, +9110, +9143, +9142, +9111, +9168, +9201, +9200, +9169, +9170, +9203, +9202, +9171, +9172, +9205, +9204, +9173, +9174, +9207, +9206, +9175, +9232, +9265, +9264, +9233, +9234, +9267, +9266, +9235, +9236, +9269, +9268, +9237, +9238, +9271, +9270, +9239, +9296, +9329, +9328, +9297, +9298, +9331, +9330, +9299, +9300, +9333, +9332, +9301, +9302, +9335, +9334, +9303, +9360, +9393, +9392, +9361, +9362, +9395, +9394, +9363, +9364, +9397, +9396, +9365, +9366, +9399, +9398, +9367, +9424, +9457, +9456, +9425, +9426, +9459, +9458, +9427, +9428, +9461, +9460, +9429, +9430, +9463, +9462, +9431, +9488, +9521, +9520, +9489, +9490, +9523, +9522, +9491, +9492, +9525, +9524, +9493, +9494, +9527, +9526, +9495, +9552, +9585, +9584, +9553, +9554, +9587, +9586, +9555, +9556, +9589, +9588, +9557, +9558, +9591, +9590, +9559, +9616, +9649, +9648, +9617, +9618, +9651, +9650, +9619, +9620, +9653, +9652, +9621, +9622, +9655, +9654, +9623, +9680, +9713, +9712, +9681, +9682, +9715, +9714, +9683, +9684, +9717, +9716, +9685, +9686, +9719, +9718, +9687, +9744, +9777, +9776, +9745, +9746, +9779, +9778, +9747, +9748, +9781, +9780, +9749, +9750, +9783, +9782, +9751, +9808, +9841, +9840, +9809, +9810, +9843, +9842, +9811, +9812, +9845, +9844, +9813, +9814, +9847, +9846, +9815, +9872, +9905, +9904, +9873, +9874, +9907, +9906, +9875, +9876, +9909, +9908, +9877, +9878, +9911, +9910, +9879, +9936, +9969, +9968, +9937, +9938, +9971, +9970, +9939, +9940, +9973, +9972, +9941, +9942, +9975, +9974, +9943, +10000, +10033, +10032, +10001, +10002, +10035, +10034, +10003, +10004, +10037, +10036, +10005, +10006, +10039, +10038, +10007, +10064, +10097, +10096, +10065, +10066, +10099, +10098, +10067, +10068, +10101, +10100, +10069, +10070, +10103, +10102, +10071, +10128, +10161, +10160, +10129, +10130, +10163, +10162, +10131, +10132, +10165, +10164, +10133, +10134, +10167, +10166, +10135, +10192, +10225, +10224, +10193, +10194, +10227, +10226, +10195, +10196, +10229, +10228, +10197, +10198, +10231, +10230, +10199, +8216, +8249, +8248, +8217, +8218, +8251, +8250, +8219, +8220, +8253, +8252, +8221, +8222, +8255, +8254, +8223, +8280, +8313, +8312, +8281, +8282, +8315, +8314, +8283, +8284, +8317, +8316, +8285, +8286, +8319, +8318, +8287, +8344, +8377, +8376, +8345, +8346, +8379, +8378, +8347, +8348, +8381, +8380, +8349, +8350, +8383, +8382, +8351, +8408, +8441, +8440, +8409, +8410, +8443, +8442, +8411, +8412, +8445, +8444, +8413, +8414, +8447, +8446, +8415, +8472, +8505, +8504, +8473, +8474, +8507, +8506, +8475, +8476, +8509, +8508, +8477, +8478, +8511, +8510, +8479, +8536, +8569, +8568, +8537, +8538, +8571, +8570, +8539, +8540, +8573, +8572, +8541, +8542, +8575, +8574, +8543, +8600, +8633, +8632, +8601, +8602, +8635, +8634, +8603, +8604, +8637, +8636, +8605, +8606, +8639, +8638, +8607, +8664, +8697, +8696, +8665, +8666, +8699, +8698, +8667, +8668, +8701, +8700, +8669, +8670, +8703, +8702, +8671, +8728, +8761, +8760, +8729, +8730, +8763, +8762, +8731, +8732, +8765, +8764, +8733, +8734, +8767, +8766, +8735, +8792, +8825, +8824, +8793, +8794, +8827, +8826, +8795, +8796, +8829, +8828, +8797, +8798, +8831, +8830, +8799, +8856, +8889, +8888, +8857, +8858, +8891, +8890, +8859, +8860, +8893, +8892, +8861, +8862, +8895, +8894, +8863, +8920, +8953, +8952, +8921, +8922, +8955, +8954, +8923, +8924, +8957, +8956, +8925, +8926, +8959, +8958, +8927, +8984, +9017, +9016, +8985, +8986, +9019, +9018, +8987, +8988, +9021, +9020, +8989, +8990, +9023, +9022, +8991, +9048, +9081, +9080, +9049, +9050, +9083, +9082, +9051, +9052, +9085, +9084, +9053, +9054, +9087, +9086, +9055, +9112, +9145, +9144, +9113, +9114, +9147, +9146, +9115, +9116, +9149, +9148, +9117, +9118, +9151, +9150, +9119, +9176, +9209, +9208, +9177, +9178, +9211, +9210, +9179, +9180, +9213, +9212, +9181, +9182, +9215, +9214, +9183, +9240, +9273, +9272, +9241, +9242, +9275, +9274, +9243, +9244, +9277, +9276, +9245, +9246, +9279, +9278, +9247, +9304, +9337, +9336, +9305, +9306, +9339, +9338, +9307, +9308, +9341, +9340, +9309, +9310, +9343, +9342, +9311, +9368, +9401, +9400, +9369, +9370, +9403, +9402, +9371, +9372, +9405, +9404, +9373, +9374, +9407, +9406, +9375, +9432, +9465, +9464, +9433, +9434, +9467, +9466, +9435, +9436, +9469, +9468, +9437, +9438, +9471, +9470, +9439, +9496, +9529, +9528, +9497, +9498, +9531, +9530, +9499, +9500, +9533, +9532, +9501, +9502, +9535, +9534, +9503, +9560, +9593, +9592, +9561, +9562, +9595, +9594, +9563, +9564, +9597, +9596, +9565, +9566, +9599, +9598, +9567, +9624, +9657, +9656, +9625, +9626, +9659, +9658, +9627, +9628, +9661, +9660, +9629, +9630, +9663, +9662, +9631, +9688, +9721, +9720, +9689, +9690, +9723, +9722, +9691, +9692, +9725, +9724, +9693, +9694, +9727, +9726, +9695, +9752, +9785, +9784, +9753, +9754, +9787, +9786, +9755, +9756, +9789, +9788, +9757, +9758, +9791, +9790, +9759, +9816, +9849, +9848, +9817, +9818, +9851, +9850, +9819, +9820, +9853, +9852, +9821, +9822, +9855, +9854, +9823, +9880, +9913, +9912, +9881, +9882, +9915, +9914, +9883, +9884, +9917, +9916, +9885, +9886, +9919, +9918, +9887, +9944, +9977, +9976, +9945, +9946, +9979, +9978, +9947, +9948, +9981, +9980, +9949, +9950, +9983, +9982, +9951, +10008, +10041, +10040, +10009, +10010, +10043, +10042, +10011, +10012, +10045, +10044, +10013, +10014, +10047, +10046, +10015, +10072, +10105, +10104, +10073, +10074, +10107, +10106, +10075, +10076, +10109, +10108, +10077, +10078, +10111, +10110, +10079, +10136, +10169, +10168, +10137, +10138, +10171, +10170, +10139, +10140, +10173, +10172, +10141, +10142, +10175, +10174, +10143, +10200, +10233, +10232, +10201, +10202, +10235, +10234, +10203, +10204, +10237, +10236, +10205, +10206, +10239, +10238, +10207, +10240, +10273, +10272, +10241, +10242, +10275, +10274, +10243, +10244, +10277, +10276, +10245, +10246, +10279, +10278, +10247, +10304, +10337, +10336, +10305, +10306, +10339, +10338, +10307, +10308, +10341, +10340, +10309, +10310, +10343, +10342, +10311, +10368, +10401, +10400, +10369, +10370, +10403, +10402, +10371, +10372, +10405, +10404, +10373, +10374, +10407, +10406, +10375, +10432, +10465, +10464, +10433, +10434, +10467, +10466, +10435, +10436, +10469, +10468, +10437, +10438, +10471, +10470, +10439, +10496, +10529, +10528, +10497, +10498, +10531, +10530, +10499, +10500, +10533, +10532, +10501, +10502, +10535, +10534, +10503, +10560, +10593, +10592, +10561, +10562, +10595, +10594, +10563, +10564, +10597, +10596, +10565, +10566, +10599, +10598, +10567, +10624, +10657, +10656, +10625, +10626, +10659, +10658, +10627, +10628, +10661, +10660, +10629, +10630, +10663, +10662, +10631, +10688, +10721, +10720, +10689, +10690, +10723, +10722, +10691, +10692, +10725, +10724, +10693, +10694, +10727, +10726, +10695, +10752, +10785, +10784, +10753, +10754, +10787, +10786, +10755, +10756, +10789, +10788, +10757, +10758, +10791, +10790, +10759, +10816, +10849, +10848, +10817, +10818, +10851, +10850, +10819, +10820, +10853, +10852, +10821, +10822, +10855, +10854, +10823, +10880, +10913, +10912, +10881, +10882, +10915, +10914, +10883, +10884, +10917, +10916, +10885, +10886, +10919, +10918, +10887, +10944, +10977, +10976, +10945, +10946, +10979, +10978, +10947, +10948, +10981, +10980, +10949, +10950, +10983, +10982, +10951, +11008, +11041, +11040, +11009, +11010, +11043, +11042, +11011, +11012, +11045, +11044, +11013, +11014, +11047, +11046, +11015, +11072, +11105, +11104, +11073, +11074, +11107, +11106, +11075, +11076, +11109, +11108, +11077, +11078, +11111, +11110, +11079, +11136, +11169, +11168, +11137, +11138, +11171, +11170, +11139, +11140, +11173, +11172, +11141, +11142, +11175, +11174, +11143, +11200, +11233, +11232, +11201, +11202, +11235, +11234, +11203, +11204, +11237, +11236, +11205, +11206, +11239, +11238, +11207, +11264, +11297, +11296, +11265, +11266, +11299, +11298, +11267, +11268, +11301, +11300, +11269, +11270, +11303, +11302, +11271, +11328, +11361, +11360, +11329, +11330, +11363, +11362, +11331, +11332, +11365, +11364, +11333, +11334, +11367, +11366, +11335, +11392, +11425, +11424, +11393, +11394, +11427, +11426, +11395, +11396, +11429, +11428, +11397, +11398, +11431, +11430, +11399, +11456, +11489, +11488, +11457, +11458, +11491, +11490, +11459, +11460, +11493, +11492, +11461, +11462, +11495, +11494, +11463, +11520, +11553, +11552, +11521, +11522, +11555, +11554, +11523, +11524, +11557, +11556, +11525, +11526, +11559, +11558, +11527, +11584, +11617, +11616, +11585, +11586, +11619, +11618, +11587, +11588, +11621, +11620, +11589, +11590, +11623, +11622, +11591, +11648, +11681, +11680, +11649, +11650, +11683, +11682, +11651, +11652, +11685, +11684, +11653, +11654, +11687, +11686, +11655, +11712, +11745, +11744, +11713, +11714, +11747, +11746, +11715, +11716, +11749, +11748, +11717, +11718, +11751, +11750, +11719, +11776, +11809, +11808, +11777, +11778, +11811, +11810, +11779, +11780, +11813, +11812, +11781, +11782, +11815, +11814, +11783, +11840, +11873, +11872, +11841, +11842, +11875, +11874, +11843, +11844, +11877, +11876, +11845, +11846, +11879, +11878, +11847, +11904, +11937, +11936, +11905, +11906, +11939, +11938, +11907, +11908, +11941, +11940, +11909, +11910, +11943, +11942, +11911, +11968, +12001, +12000, +11969, +11970, +12003, +12002, +11971, +11972, +12005, +12004, +11973, +11974, +12007, +12006, +11975, +12032, +12065, +12064, +12033, +12034, +12067, +12066, +12035, +12036, +12069, +12068, +12037, +12038, +12071, +12070, +12039, +12096, +12129, +12128, +12097, +12098, +12131, +12130, +12099, +12100, +12133, +12132, +12101, +12102, +12135, +12134, +12103, +12160, +12193, +12192, +12161, +12162, +12195, +12194, +12163, +12164, +12197, +12196, +12165, +12166, +12199, +12198, +12167, +12224, +12257, +12256, +12225, +12226, +12259, +12258, +12227, +12228, +12261, +12260, +12229, +12230, +12263, +12262, +12231, +10248, +10281, +10280, +10249, +10250, +10283, +10282, +10251, +10252, +10285, +10284, +10253, +10254, +10287, +10286, +10255, +10312, +10345, +10344, +10313, +10314, +10347, +10346, +10315, +10316, +10349, +10348, +10317, +10318, +10351, +10350, +10319, +10376, +10409, +10408, +10377, +10378, +10411, +10410, +10379, +10380, +10413, +10412, +10381, +10382, +10415, +10414, +10383, +10440, +10473, +10472, +10441, +10442, +10475, +10474, +10443, +10444, +10477, +10476, +10445, +10446, +10479, +10478, +10447, +10504, +10537, +10536, +10505, +10506, +10539, +10538, +10507, +10508, +10541, +10540, +10509, +10510, +10543, +10542, +10511, +10568, +10601, +10600, +10569, +10570, +10603, +10602, +10571, +10572, +10605, +10604, +10573, +10574, +10607, +10606, +10575, +10632, +10665, +10664, +10633, +10634, +10667, +10666, +10635, +10636, +10669, +10668, +10637, +10638, +10671, +10670, +10639, +10696, +10729, +10728, +10697, +10698, +10731, +10730, +10699, +10700, +10733, +10732, +10701, +10702, +10735, +10734, +10703, +10760, +10793, +10792, +10761, +10762, +10795, +10794, +10763, +10764, +10797, +10796, +10765, +10766, +10799, +10798, +10767, +10824, +10857, +10856, +10825, +10826, +10859, +10858, +10827, +10828, +10861, +10860, +10829, +10830, +10863, +10862, +10831, +10888, +10921, +10920, +10889, +10890, +10923, +10922, +10891, +10892, +10925, +10924, +10893, +10894, +10927, +10926, +10895, +10952, +10985, +10984, +10953, +10954, +10987, +10986, +10955, +10956, +10989, +10988, +10957, +10958, +10991, +10990, +10959, +11016, +11049, +11048, +11017, +11018, +11051, +11050, +11019, +11020, +11053, +11052, +11021, +11022, +11055, +11054, +11023, +11080, +11113, +11112, +11081, +11082, +11115, +11114, +11083, +11084, +11117, +11116, +11085, +11086, +11119, +11118, +11087, +11144, +11177, +11176, +11145, +11146, +11179, +11178, +11147, +11148, +11181, +11180, +11149, +11150, +11183, +11182, +11151, +11208, +11241, +11240, +11209, +11210, +11243, +11242, +11211, +11212, +11245, +11244, +11213, +11214, +11247, +11246, +11215, +11272, +11305, +11304, +11273, +11274, +11307, +11306, +11275, +11276, +11309, +11308, +11277, +11278, +11311, +11310, +11279, +11336, +11369, +11368, +11337, +11338, +11371, +11370, +11339, +11340, +11373, +11372, +11341, +11342, +11375, +11374, +11343, +11400, +11433, +11432, +11401, +11402, +11435, +11434, +11403, +11404, +11437, +11436, +11405, +11406, +11439, +11438, +11407, +11464, +11497, +11496, +11465, +11466, +11499, +11498, +11467, +11468, +11501, +11500, +11469, +11470, +11503, +11502, +11471, +11528, +11561, +11560, +11529, +11530, +11563, +11562, +11531, +11532, +11565, +11564, +11533, +11534, +11567, +11566, +11535, +11592, +11625, +11624, +11593, +11594, +11627, +11626, +11595, +11596, +11629, +11628, +11597, +11598, +11631, +11630, +11599, +11656, +11689, +11688, +11657, +11658, +11691, +11690, +11659, +11660, +11693, +11692, +11661, +11662, +11695, +11694, +11663, +11720, +11753, +11752, +11721, +11722, +11755, +11754, +11723, +11724, +11757, +11756, +11725, +11726, +11759, +11758, +11727, +11784, +11817, +11816, +11785, +11786, +11819, +11818, +11787, +11788, +11821, +11820, +11789, +11790, +11823, +11822, +11791, +11848, +11881, +11880, +11849, +11850, +11883, +11882, +11851, +11852, +11885, +11884, +11853, +11854, +11887, +11886, +11855, +11912, +11945, +11944, +11913, +11914, +11947, +11946, +11915, +11916, +11949, +11948, +11917, +11918, +11951, +11950, +11919, +11976, +12009, +12008, +11977, +11978, +12011, +12010, +11979, +11980, +12013, +12012, +11981, +11982, +12015, +12014, +11983, +12040, +12073, +12072, +12041, +12042, +12075, +12074, +12043, +12044, +12077, +12076, +12045, +12046, +12079, +12078, +12047, +12104, +12137, +12136, +12105, +12106, +12139, +12138, +12107, +12108, +12141, +12140, +12109, +12110, +12143, +12142, +12111, +12168, +12201, +12200, +12169, +12170, +12203, +12202, +12171, +12172, +12205, +12204, +12173, +12174, +12207, +12206, +12175, +12232, +12265, +12264, +12233, +12234, +12267, +12266, +12235, +12236, +12269, +12268, +12237, +12238, +12271, +12270, +12239, +10256, +10289, +10288, +10257, +10258, +10291, +10290, +10259, +10260, +10293, +10292, +10261, +10262, +10295, +10294, +10263, +10320, +10353, +10352, +10321, +10322, +10355, +10354, +10323, +10324, +10357, +10356, +10325, +10326, +10359, +10358, +10327, +10384, +10417, +10416, +10385, +10386, +10419, +10418, +10387, +10388, +10421, +10420, +10389, +10390, +10423, +10422, +10391, +10448, +10481, +10480, +10449, +10450, +10483, +10482, +10451, +10452, +10485, +10484, +10453, +10454, +10487, +10486, +10455, +10512, +10545, +10544, +10513, +10514, +10547, +10546, +10515, +10516, +10549, +10548, +10517, +10518, +10551, +10550, +10519, +10576, +10609, +10608, +10577, +10578, +10611, +10610, +10579, +10580, +10613, +10612, +10581, +10582, +10615, +10614, +10583, +10640, +10673, +10672, +10641, +10642, +10675, +10674, +10643, +10644, +10677, +10676, +10645, +10646, +10679, +10678, +10647, +10704, +10737, +10736, +10705, +10706, +10739, +10738, +10707, +10708, +10741, +10740, +10709, +10710, +10743, +10742, +10711, +10768, +10801, +10800, +10769, +10770, +10803, +10802, +10771, +10772, +10805, +10804, +10773, +10774, +10807, +10806, +10775, +10832, +10865, +10864, +10833, +10834, +10867, +10866, +10835, +10836, +10869, +10868, +10837, +10838, +10871, +10870, +10839, +10896, +10929, +10928, +10897, +10898, +10931, +10930, +10899, +10900, +10933, +10932, +10901, +10902, +10935, +10934, +10903, +10960, +10993, +10992, +10961, +10962, +10995, +10994, +10963, +10964, +10997, +10996, +10965, +10966, +10999, +10998, +10967, +11024, +11057, +11056, +11025, +11026, +11059, +11058, +11027, +11028, +11061, +11060, +11029, +11030, +11063, +11062, +11031, +11088, +11121, +11120, +11089, +11090, +11123, +11122, +11091, +11092, +11125, +11124, +11093, +11094, +11127, +11126, +11095, +11152, +11185, +11184, +11153, +11154, +11187, +11186, +11155, +11156, +11189, +11188, +11157, +11158, +11191, +11190, +11159, +11216, +11249, +11248, +11217, +11218, +11251, +11250, +11219, +11220, +11253, +11252, +11221, +11222, +11255, +11254, +11223, +11280, +11313, +11312, +11281, +11282, +11315, +11314, +11283, +11284, +11317, +11316, +11285, +11286, +11319, +11318, +11287, +11344, +11377, +11376, +11345, +11346, +11379, +11378, +11347, +11348, +11381, +11380, +11349, +11350, +11383, +11382, +11351, +11408, +11441, +11440, +11409, +11410, +11443, +11442, +11411, +11412, +11445, +11444, +11413, +11414, +11447, +11446, +11415, +11472, +11505, +11504, +11473, +11474, +11507, +11506, +11475, +11476, +11509, +11508, +11477, +11478, +11511, +11510, +11479, +11536, +11569, +11568, +11537, +11538, +11571, +11570, +11539, +11540, +11573, +11572, +11541, +11542, +11575, +11574, +11543, +11600, +11633, +11632, +11601, +11602, +11635, +11634, +11603, +11604, +11637, +11636, +11605, +11606, +11639, +11638, +11607, +11664, +11697, +11696, +11665, +11666, +11699, +11698, +11667, +11668, +11701, +11700, +11669, +11670, +11703, +11702, +11671, +11728, +11761, +11760, +11729, +11730, +11763, +11762, +11731, +11732, +11765, +11764, +11733, +11734, +11767, +11766, +11735, +11792, +11825, +11824, +11793, +11794, +11827, +11826, +11795, +11796, +11829, +11828, +11797, +11798, +11831, +11830, +11799, +11856, +11889, +11888, +11857, +11858, +11891, +11890, +11859, +11860, +11893, +11892, +11861, +11862, +11895, +11894, +11863, +11920, +11953, +11952, +11921, +11922, +11955, +11954, +11923, +11924, +11957, +11956, +11925, +11926, +11959, +11958, +11927, +11984, +12017, +12016, +11985, +11986, +12019, +12018, +11987, +11988, +12021, +12020, +11989, +11990, +12023, +12022, +11991, +12048, +12081, +12080, +12049, +12050, +12083, +12082, +12051, +12052, +12085, +12084, +12053, +12054, +12087, +12086, +12055, +12112, +12145, +12144, +12113, +12114, +12147, +12146, +12115, +12116, +12149, +12148, +12117, +12118, +12151, +12150, +12119, +12176, +12209, +12208, +12177, +12178, +12211, +12210, +12179, +12180, +12213, +12212, +12181, +12182, +12215, +12214, +12183, +12240, +12273, +12272, +12241, +12242, +12275, +12274, +12243, +12244, +12277, +12276, +12245, +12246, +12279, +12278, +12247, +10264, +10297, +10296, +10265, +10266, +10299, +10298, +10267, +10268, +10301, +10300, +10269, +10270, +10303, +10302, +10271, +10328, +10361, +10360, +10329, +10330, +10363, +10362, +10331, +10332, +10365, +10364, +10333, +10334, +10367, +10366, +10335, +10392, +10425, +10424, +10393, +10394, +10427, +10426, +10395, +10396, +10429, +10428, +10397, +10398, +10431, +10430, +10399, +10456, +10489, +10488, +10457, +10458, +10491, +10490, +10459, +10460, +10493, +10492, +10461, +10462, +10495, +10494, +10463, +10520, +10553, +10552, +10521, +10522, +10555, +10554, +10523, +10524, +10557, +10556, +10525, +10526, +10559, +10558, +10527, +10584, +10617, +10616, +10585, +10586, +10619, +10618, +10587, +10588, +10621, +10620, +10589, +10590, +10623, +10622, +10591, +10648, +10681, +10680, +10649, +10650, +10683, +10682, +10651, +10652, +10685, +10684, +10653, +10654, +10687, +10686, +10655, +10712, +10745, +10744, +10713, +10714, +10747, +10746, +10715, +10716, +10749, +10748, +10717, +10718, +10751, +10750, +10719, +10776, +10809, +10808, +10777, +10778, +10811, +10810, +10779, +10780, +10813, +10812, +10781, +10782, +10815, +10814, +10783, +10840, +10873, +10872, +10841, +10842, +10875, +10874, +10843, +10844, +10877, +10876, +10845, +10846, +10879, +10878, +10847, +10904, +10937, +10936, +10905, +10906, +10939, +10938, +10907, +10908, +10941, +10940, +10909, +10910, +10943, +10942, +10911, +10968, +11001, +11000, +10969, +10970, +11003, +11002, +10971, +10972, +11005, +11004, +10973, +10974, +11007, +11006, +10975, +11032, +11065, +11064, +11033, +11034, +11067, +11066, +11035, +11036, +11069, +11068, +11037, +11038, +11071, +11070, +11039, +11096, +11129, +11128, +11097, +11098, +11131, +11130, +11099, +11100, +11133, +11132, +11101, +11102, +11135, +11134, +11103, +11160, +11193, +11192, +11161, +11162, +11195, +11194, +11163, +11164, +11197, +11196, +11165, +11166, +11199, +11198, +11167, +11224, +11257, +11256, +11225, +11226, +11259, +11258, +11227, +11228, +11261, +11260, +11229, +11230, +11263, +11262, +11231, +11288, +11321, +11320, +11289, +11290, +11323, +11322, +11291, +11292, +11325, +11324, +11293, +11294, +11327, +11326, +11295, +11352, +11385, +11384, +11353, +11354, +11387, +11386, +11355, +11356, +11389, +11388, +11357, +11358, +11391, +11390, +11359, +11416, +11449, +11448, +11417, +11418, +11451, +11450, +11419, +11420, +11453, +11452, +11421, +11422, +11455, +11454, +11423, +11480, +11513, +11512, +11481, +11482, +11515, +11514, +11483, +11484, +11517, +11516, +11485, +11486, +11519, +11518, +11487, +11544, +11577, +11576, +11545, +11546, +11579, +11578, +11547, +11548, +11581, +11580, +11549, +11550, +11583, +11582, +11551, +11608, +11641, +11640, +11609, +11610, +11643, +11642, +11611, +11612, +11645, +11644, +11613, +11614, +11647, +11646, +11615, +11672, +11705, +11704, +11673, +11674, +11707, +11706, +11675, +11676, +11709, +11708, +11677, +11678, +11711, +11710, +11679, +11736, +11769, +11768, +11737, +11738, +11771, +11770, +11739, +11740, +11773, +11772, +11741, +11742, +11775, +11774, +11743, +11800, +11833, +11832, +11801, +11802, +11835, +11834, +11803, +11804, +11837, +11836, +11805, +11806, +11839, +11838, +11807, +11864, +11897, +11896, +11865, +11866, +11899, +11898, +11867, +11868, +11901, +11900, +11869, +11870, +11903, +11902, +11871, +11928, +11961, +11960, +11929, +11930, +11963, +11962, +11931, +11932, +11965, +11964, +11933, +11934, +11967, +11966, +11935, +11992, +12025, +12024, +11993, +11994, +12027, +12026, +11995, +11996, +12029, +12028, +11997, +11998, +12031, +12030, +11999, +12056, +12089, +12088, +12057, +12058, +12091, +12090, +12059, +12060, +12093, +12092, +12061, +12062, +12095, +12094, +12063, +12120, +12153, +12152, +12121, +12122, +12155, +12154, +12123, +12124, +12157, +12156, +12125, +12126, +12159, +12158, +12127, +12184, +12217, +12216, +12185, +12186, +12219, +12218, +12187, +12188, +12221, +12220, +12189, +12190, +12223, +12222, +12191, +12248, +12281, +12280, +12249, +12250, +12283, +12282, +12251, +12252, +12285, +12284, +12253, +12254, +12287, +12286, +12255, +12288, +12321, +12320, +12289, +12290, +12323, +12322, +12291, +12292, +12325, +12324, +12293, +12294, +12327, +12326, +12295, +12352, +12385, +12384, +12353, +12354, +12387, +12386, +12355, +12356, +12389, +12388, +12357, +12358, +12391, +12390, +12359, +12416, +12449, +12448, +12417, +12418, +12451, +12450, +12419, +12420, +12453, +12452, +12421, +12422, +12455, +12454, +12423, +12480, +12513, +12512, +12481, +12482, +12515, +12514, +12483, +12484, +12517, +12516, +12485, +12486, +12519, +12518, +12487, +12544, +12577, +12576, +12545, +12546, +12579, +12578, +12547, +12548, +12581, +12580, +12549, +12550, +12583, +12582, +12551, +12608, +12641, +12640, +12609, +12610, +12643, +12642, +12611, +12612, +12645, +12644, +12613, +12614, +12647, +12646, +12615, +12672, +12705, +12704, +12673, +12674, +12707, +12706, +12675, +12676, +12709, +12708, +12677, +12678, +12711, +12710, +12679, +12736, +12769, +12768, +12737, +12738, +12771, +12770, +12739, +12740, +12773, +12772, +12741, +12742, +12775, +12774, +12743, +12800, +12833, +12832, +12801, +12802, +12835, +12834, +12803, +12804, +12837, +12836, +12805, +12806, +12839, +12838, +12807, +12864, +12897, +12896, +12865, +12866, +12899, +12898, +12867, +12868, +12901, +12900, +12869, +12870, +12903, +12902, +12871, +12928, +12961, +12960, +12929, +12930, +12963, +12962, +12931, +12932, +12965, +12964, +12933, +12934, +12967, +12966, +12935, +12992, +13025, +13024, +12993, +12994, +13027, +13026, +12995, +12996, +13029, +13028, +12997, +12998, +13031, +13030, +12999, +13056, +13089, +13088, +13057, +13058, +13091, +13090, +13059, +13060, +13093, +13092, +13061, +13062, +13095, +13094, +13063, +13120, +13153, +13152, +13121, +13122, +13155, +13154, +13123, +13124, +13157, +13156, +13125, +13126, +13159, +13158, +13127, +13184, +13217, +13216, +13185, +13186, +13219, +13218, +13187, +13188, +13221, +13220, +13189, +13190, +13223, +13222, +13191, +13248, +13281, +13280, +13249, +13250, +13283, +13282, +13251, +13252, +13285, +13284, +13253, +13254, +13287, +13286, +13255, +13312, +13345, +13344, +13313, +13314, +13347, +13346, +13315, +13316, +13349, +13348, +13317, +13318, +13351, +13350, +13319, +13376, +13409, +13408, +13377, +13378, +13411, +13410, +13379, +13380, +13413, +13412, +13381, +13382, +13415, +13414, +13383, +13440, +13473, +13472, +13441, +13442, +13475, +13474, +13443, +13444, +13477, +13476, +13445, +13446, +13479, +13478, +13447, +13504, +13537, +13536, +13505, +13506, +13539, +13538, +13507, +13508, +13541, +13540, +13509, +13510, +13543, +13542, +13511, +13568, +13601, +13600, +13569, +13570, +13603, +13602, +13571, +13572, +13605, +13604, +13573, +13574, +13607, +13606, +13575, +13632, +13665, +13664, +13633, +13634, +13667, +13666, +13635, +13636, +13669, +13668, +13637, +13638, +13671, +13670, +13639, +13696, +13729, +13728, +13697, +13698, +13731, +13730, +13699, +13700, +13733, +13732, +13701, +13702, +13735, +13734, +13703, +13760, +13793, +13792, +13761, +13762, +13795, +13794, +13763, +13764, +13797, +13796, +13765, +13766, +13799, +13798, +13767, +13824, +13857, +13856, +13825, +13826, +13859, +13858, +13827, +13828, +13861, +13860, +13829, +13830, +13863, +13862, +13831, +13888, +13921, +13920, +13889, +13890, +13923, +13922, +13891, +13892, +13925, +13924, +13893, +13894, +13927, +13926, +13895, +13952, +13985, +13984, +13953, +13954, +13987, +13986, +13955, +13956, +13989, +13988, +13957, +13958, +13991, +13990, +13959, +14016, +14049, +14048, +14017, +14018, +14051, +14050, +14019, +14020, +14053, +14052, +14021, +14022, +14055, +14054, +14023, +14080, +14113, +14112, +14081, +14082, +14115, +14114, +14083, +14084, +14117, +14116, +14085, +14086, +14119, +14118, +14087, +14144, +14177, +14176, +14145, +14146, +14179, +14178, +14147, +14148, +14181, +14180, +14149, +14150, +14183, +14182, +14151, +14208, +14241, +14240, +14209, +14210, +14243, +14242, +14211, +14212, +14245, +14244, +14213, +14214, +14247, +14246, +14215, +14272, +14305, +14304, +14273, +14274, +14307, +14306, +14275, +14276, +14309, +14308, +14277, +14278, +14311, +14310, +14279, +12296, +12329, +12328, +12297, +12298, +12331, +12330, +12299, +12300, +12333, +12332, +12301, +12302, +12335, +12334, +12303, +12360, +12393, +12392, +12361, +12362, +12395, +12394, +12363, +12364, +12397, +12396, +12365, +12366, +12399, +12398, +12367, +12424, +12457, +12456, +12425, +12426, +12459, +12458, +12427, +12428, +12461, +12460, +12429, +12430, +12463, +12462, +12431, +12488, +12521, +12520, +12489, +12490, +12523, +12522, +12491, +12492, +12525, +12524, +12493, +12494, +12527, +12526, +12495, +12552, +12585, +12584, +12553, +12554, +12587, +12586, +12555, +12556, +12589, +12588, +12557, +12558, +12591, +12590, +12559, +12616, +12649, +12648, +12617, +12618, +12651, +12650, +12619, +12620, +12653, +12652, +12621, +12622, +12655, +12654, +12623, +12680, +12713, +12712, +12681, +12682, +12715, +12714, +12683, +12684, +12717, +12716, +12685, +12686, +12719, +12718, +12687, +12744, +12777, +12776, +12745, +12746, +12779, +12778, +12747, +12748, +12781, +12780, +12749, +12750, +12783, +12782, +12751, +12808, +12841, +12840, +12809, +12810, +12843, +12842, +12811, +12812, +12845, +12844, +12813, +12814, +12847, +12846, +12815, +12872, +12905, +12904, +12873, +12874, +12907, +12906, +12875, +12876, +12909, +12908, +12877, +12878, +12911, +12910, +12879, +12936, +12969, +12968, +12937, +12938, +12971, +12970, +12939, +12940, +12973, +12972, +12941, +12942, +12975, +12974, +12943, +13000, +13033, +13032, +13001, +13002, +13035, +13034, +13003, +13004, +13037, +13036, +13005, +13006, +13039, +13038, +13007, +13064, +13097, +13096, +13065, +13066, +13099, +13098, +13067, +13068, +13101, +13100, +13069, +13070, +13103, +13102, +13071, +13128, +13161, +13160, +13129, +13130, +13163, +13162, +13131, +13132, +13165, +13164, +13133, +13134, +13167, +13166, +13135, +13192, +13225, +13224, +13193, +13194, +13227, +13226, +13195, +13196, +13229, +13228, +13197, +13198, +13231, +13230, +13199, +13256, +13289, +13288, +13257, +13258, +13291, +13290, +13259, +13260, +13293, +13292, +13261, +13262, +13295, +13294, +13263, +13320, +13353, +13352, +13321, +13322, +13355, +13354, +13323, +13324, +13357, +13356, +13325, +13326, +13359, +13358, +13327, +13384, +13417, +13416, +13385, +13386, +13419, +13418, +13387, +13388, +13421, +13420, +13389, +13390, +13423, +13422, +13391, +13448, +13481, +13480, +13449, +13450, +13483, +13482, +13451, +13452, +13485, +13484, +13453, +13454, +13487, +13486, +13455, +13512, +13545, +13544, +13513, +13514, +13547, +13546, +13515, +13516, +13549, +13548, +13517, +13518, +13551, +13550, +13519, +13576, +13609, +13608, +13577, +13578, +13611, +13610, +13579, +13580, +13613, +13612, +13581, +13582, +13615, +13614, +13583, +13640, +13673, +13672, +13641, +13642, +13675, +13674, +13643, +13644, +13677, +13676, +13645, +13646, +13679, +13678, +13647, +13704, +13737, +13736, +13705, +13706, +13739, +13738, +13707, +13708, +13741, +13740, +13709, +13710, +13743, +13742, +13711, +13768, +13801, +13800, +13769, +13770, +13803, +13802, +13771, +13772, +13805, +13804, +13773, +13774, +13807, +13806, +13775, +13832, +13865, +13864, +13833, +13834, +13867, +13866, +13835, +13836, +13869, +13868, +13837, +13838, +13871, +13870, +13839, +13896, +13929, +13928, +13897, +13898, +13931, +13930, +13899, +13900, +13933, +13932, +13901, +13902, +13935, +13934, +13903, +13960, +13993, +13992, +13961, +13962, +13995, +13994, +13963, +13964, +13997, +13996, +13965, +13966, +13999, +13998, +13967, +14024, +14057, +14056, +14025, +14026, +14059, +14058, +14027, +14028, +14061, +14060, +14029, +14030, +14063, +14062, +14031, +14088, +14121, +14120, +14089, +14090, +14123, +14122, +14091, +14092, +14125, +14124, +14093, +14094, +14127, +14126, +14095, +14152, +14185, +14184, +14153, +14154, +14187, +14186, +14155, +14156, +14189, +14188, +14157, +14158, +14191, +14190, +14159, +14216, +14249, +14248, +14217, +14218, +14251, +14250, +14219, +14220, +14253, +14252, +14221, +14222, +14255, +14254, +14223, +14280, +14313, +14312, +14281, +14282, +14315, +14314, +14283, +14284, +14317, +14316, +14285, +14286, +14319, +14318, +14287, +12304, +12337, +12336, +12305, +12306, +12339, +12338, +12307, +12308, +12341, +12340, +12309, +12310, +12343, +12342, +12311, +12368, +12401, +12400, +12369, +12370, +12403, +12402, +12371, +12372, +12405, +12404, +12373, +12374, +12407, +12406, +12375, +12432, +12465, +12464, +12433, +12434, +12467, +12466, +12435, +12436, +12469, +12468, +12437, +12438, +12471, +12470, +12439, +12496, +12529, +12528, +12497, +12498, +12531, +12530, +12499, +12500, +12533, +12532, +12501, +12502, +12535, +12534, +12503, +12560, +12593, +12592, +12561, +12562, +12595, +12594, +12563, +12564, +12597, +12596, +12565, +12566, +12599, +12598, +12567, +12624, +12657, +12656, +12625, +12626, +12659, +12658, +12627, +12628, +12661, +12660, +12629, +12630, +12663, +12662, +12631, +12688, +12721, +12720, +12689, +12690, +12723, +12722, +12691, +12692, +12725, +12724, +12693, +12694, +12727, +12726, +12695, +12752, +12785, +12784, +12753, +12754, +12787, +12786, +12755, +12756, +12789, +12788, +12757, +12758, +12791, +12790, +12759, +12816, +12849, +12848, +12817, +12818, +12851, +12850, +12819, +12820, +12853, +12852, +12821, +12822, +12855, +12854, +12823, +12880, +12913, +12912, +12881, +12882, +12915, +12914, +12883, +12884, +12917, +12916, +12885, +12886, +12919, +12918, +12887, +12944, +12977, +12976, +12945, +12946, +12979, +12978, +12947, +12948, +12981, +12980, +12949, +12950, +12983, +12982, +12951, +13008, +13041, +13040, +13009, +13010, +13043, +13042, +13011, +13012, +13045, +13044, +13013, +13014, +13047, +13046, +13015, +13072, +13105, +13104, +13073, +13074, +13107, +13106, +13075, +13076, +13109, +13108, +13077, +13078, +13111, +13110, +13079, +13136, +13169, +13168, +13137, +13138, +13171, +13170, +13139, +13140, +13173, +13172, +13141, +13142, +13175, +13174, +13143, +13200, +13233, +13232, +13201, +13202, +13235, +13234, +13203, +13204, +13237, +13236, +13205, +13206, +13239, +13238, +13207, +13264, +13297, +13296, +13265, +13266, +13299, +13298, +13267, +13268, +13301, +13300, +13269, +13270, +13303, +13302, +13271, +13328, +13361, +13360, +13329, +13330, +13363, +13362, +13331, +13332, +13365, +13364, +13333, +13334, +13367, +13366, +13335, +13392, +13425, +13424, +13393, +13394, +13427, +13426, +13395, +13396, +13429, +13428, +13397, +13398, +13431, +13430, +13399, +13456, +13489, +13488, +13457, +13458, +13491, +13490, +13459, +13460, +13493, +13492, +13461, +13462, +13495, +13494, +13463, +13520, +13553, +13552, +13521, +13522, +13555, +13554, +13523, +13524, +13557, +13556, +13525, +13526, +13559, +13558, +13527, +13584, +13617, +13616, +13585, +13586, +13619, +13618, +13587, +13588, +13621, +13620, +13589, +13590, +13623, +13622, +13591, +13648, +13681, +13680, +13649, +13650, +13683, +13682, +13651, +13652, +13685, +13684, +13653, +13654, +13687, +13686, +13655, +13712, +13745, +13744, +13713, +13714, +13747, +13746, +13715, +13716, +13749, +13748, +13717, +13718, +13751, +13750, +13719, +13776, +13809, +13808, +13777, +13778, +13811, +13810, +13779, +13780, +13813, +13812, +13781, +13782, +13815, +13814, +13783, +13840, +13873, +13872, +13841, +13842, +13875, +13874, +13843, +13844, +13877, +13876, +13845, +13846, +13879, +13878, +13847, +13904, +13937, +13936, +13905, +13906, +13939, +13938, +13907, +13908, +13941, +13940, +13909, +13910, +13943, +13942, +13911, +13968, +14001, +14000, +13969, +13970, +14003, +14002, +13971, +13972, +14005, +14004, +13973, +13974, +14007, +14006, +13975, +14032, +14065, +14064, +14033, +14034, +14067, +14066, +14035, +14036, +14069, +14068, +14037, +14038, +14071, +14070, +14039, +14096, +14129, +14128, +14097, +14098, +14131, +14130, +14099, +14100, +14133, +14132, +14101, +14102, +14135, +14134, +14103, +14160, +14193, +14192, +14161, +14162, +14195, +14194, +14163, +14164, +14197, +14196, +14165, +14166, +14199, +14198, +14167, +14224, +14257, +14256, +14225, +14226, +14259, +14258, +14227, +14228, +14261, +14260, +14229, +14230, +14263, +14262, +14231, +14288, +14321, +14320, +14289, +14290, +14323, +14322, +14291, +14292, +14325, +14324, +14293, +14294, +14327, +14326, +14295, +12312, +12345, +12344, +12313, +12314, +12347, +12346, +12315, +12316, +12349, +12348, +12317, +12318, +12351, +12350, +12319, +12376, +12409, +12408, +12377, +12378, +12411, +12410, +12379, +12380, +12413, +12412, +12381, +12382, +12415, +12414, +12383, +12440, +12473, +12472, +12441, +12442, +12475, +12474, +12443, +12444, +12477, +12476, +12445, +12446, +12479, +12478, +12447, +12504, +12537, +12536, +12505, +12506, +12539, +12538, +12507, +12508, +12541, +12540, +12509, +12510, +12543, +12542, +12511, +12568, +12601, +12600, +12569, +12570, +12603, +12602, +12571, +12572, +12605, +12604, +12573, +12574, +12607, +12606, +12575, +12632, +12665, +12664, +12633, +12634, +12667, +12666, +12635, +12636, +12669, +12668, +12637, +12638, +12671, +12670, +12639, +12696, +12729, +12728, +12697, +12698, +12731, +12730, +12699, +12700, +12733, +12732, +12701, +12702, +12735, +12734, +12703, +12760, +12793, +12792, +12761, +12762, +12795, +12794, +12763, +12764, +12797, +12796, +12765, +12766, +12799, +12798, +12767, +12824, +12857, +12856, +12825, +12826, +12859, +12858, +12827, +12828, +12861, +12860, +12829, +12830, +12863, +12862, +12831, +12888, +12921, +12920, +12889, +12890, +12923, +12922, +12891, +12892, +12925, +12924, +12893, +12894, +12927, +12926, +12895, +12952, +12985, +12984, +12953, +12954, +12987, +12986, +12955, +12956, +12989, +12988, +12957, +12958, +12991, +12990, +12959, +13016, +13049, +13048, +13017, +13018, +13051, +13050, +13019, +13020, +13053, +13052, +13021, +13022, +13055, +13054, +13023, +13080, +13113, +13112, +13081, +13082, +13115, +13114, +13083, +13084, +13117, +13116, +13085, +13086, +13119, +13118, +13087, +13144, +13177, +13176, +13145, +13146, +13179, +13178, +13147, +13148, +13181, +13180, +13149, +13150, +13183, +13182, +13151, +13208, +13241, +13240, +13209, +13210, +13243, +13242, +13211, +13212, +13245, +13244, +13213, +13214, +13247, +13246, +13215, +13272, +13305, +13304, +13273, +13274, +13307, +13306, +13275, +13276, +13309, +13308, +13277, +13278, +13311, +13310, +13279, +13336, +13369, +13368, +13337, +13338, +13371, +13370, +13339, +13340, +13373, +13372, +13341, +13342, +13375, +13374, +13343, +13400, +13433, +13432, +13401, +13402, +13435, +13434, +13403, +13404, +13437, +13436, +13405, +13406, +13439, +13438, +13407, +13464, +13497, +13496, +13465, +13466, +13499, +13498, +13467, +13468, +13501, +13500, +13469, +13470, +13503, +13502, +13471, +13528, +13561, +13560, +13529, +13530, +13563, +13562, +13531, +13532, +13565, +13564, +13533, +13534, +13567, +13566, +13535, +13592, +13625, +13624, +13593, +13594, +13627, +13626, +13595, +13596, +13629, +13628, +13597, +13598, +13631, +13630, +13599, +13656, +13689, +13688, +13657, +13658, +13691, +13690, +13659, +13660, +13693, +13692, +13661, +13662, +13695, +13694, +13663, +13720, +13753, +13752, +13721, +13722, +13755, +13754, +13723, +13724, +13757, +13756, +13725, +13726, +13759, +13758, +13727, +13784, +13817, +13816, +13785, +13786, +13819, +13818, +13787, +13788, +13821, +13820, +13789, +13790, +13823, +13822, +13791, +13848, +13881, +13880, +13849, +13850, +13883, +13882, +13851, +13852, +13885, +13884, +13853, +13854, +13887, +13886, +13855, +13912, +13945, +13944, +13913, +13914, +13947, +13946, +13915, +13916, +13949, +13948, +13917, +13918, +13951, +13950, +13919, +13976, +14009, +14008, +13977, +13978, +14011, +14010, +13979, +13980, +14013, +14012, +13981, +13982, +14015, +14014, +13983, +14040, +14073, +14072, +14041, +14042, +14075, +14074, +14043, +14044, +14077, +14076, +14045, +14046, +14079, +14078, +14047, +14104, +14137, +14136, +14105, +14106, +14139, +14138, +14107, +14108, +14141, +14140, +14109, +14110, +14143, +14142, +14111, +14168, +14201, +14200, +14169, +14170, +14203, +14202, +14171, +14172, +14205, +14204, +14173, +14174, +14207, +14206, +14175, +14232, +14265, +14264, +14233, +14234, +14267, +14266, +14235, +14236, +14269, +14268, +14237, +14238, +14271, +14270, +14239, +14296, +14329, +14328, +14297, +14298, +14331, +14330, +14299, +14300, +14333, +14332, +14301, +14302, +14335, +14334, +14303, +14336, +14369, +14368, +14337, +14338, +14371, +14370, +14339, +14340, +14373, +14372, +14341, +14342, +14375, +14374, +14343, +14400, +14433, +14432, +14401, +14402, +14435, +14434, +14403, +14404, +14437, +14436, +14405, +14406, +14439, +14438, +14407, +14464, +14497, +14496, +14465, +14466, +14499, +14498, +14467, +14468, +14501, +14500, +14469, +14470, +14503, +14502, +14471, +14528, +14561, +14560, +14529, +14530, +14563, +14562, +14531, +14532, +14565, +14564, +14533, +14534, +14567, +14566, +14535, +14592, +14625, +14624, +14593, +14594, +14627, +14626, +14595, +14596, +14629, +14628, +14597, +14598, +14631, +14630, +14599, +14656, +14689, +14688, +14657, +14658, +14691, +14690, +14659, +14660, +14693, +14692, +14661, +14662, +14695, +14694, +14663, +14720, +14753, +14752, +14721, +14722, +14755, +14754, +14723, +14724, +14757, +14756, +14725, +14726, +14759, +14758, +14727, +14784, +14817, +14816, +14785, +14786, +14819, +14818, +14787, +14788, +14821, +14820, +14789, +14790, +14823, +14822, +14791, +14848, +14881, +14880, +14849, +14850, +14883, +14882, +14851, +14852, +14885, +14884, +14853, +14854, +14887, +14886, +14855, +14912, +14945, +14944, +14913, +14914, +14947, +14946, +14915, +14916, +14949, +14948, +14917, +14918, +14951, +14950, +14919, +14976, +15009, +15008, +14977, +14978, +15011, +15010, +14979, +14980, +15013, +15012, +14981, +14982, +15015, +15014, +14983, +15040, +15073, +15072, +15041, +15042, +15075, +15074, +15043, +15044, +15077, +15076, +15045, +15046, +15079, +15078, +15047, +15104, +15137, +15136, +15105, +15106, +15139, +15138, +15107, +15108, +15141, +15140, +15109, +15110, +15143, +15142, +15111, +15168, +15201, +15200, +15169, +15170, +15203, +15202, +15171, +15172, +15205, +15204, +15173, +15174, +15207, +15206, +15175, +15232, +15265, +15264, +15233, +15234, +15267, +15266, +15235, +15236, +15269, +15268, +15237, +15238, +15271, +15270, +15239, +15296, +15329, +15328, +15297, +15298, +15331, +15330, +15299, +15300, +15333, +15332, +15301, +15302, +15335, +15334, +15303, +15360, +15393, +15392, +15361, +15362, +15395, +15394, +15363, +15364, +15397, +15396, +15365, +15366, +15399, +15398, +15367, +15424, +15457, +15456, +15425, +15426, +15459, +15458, +15427, +15428, +15461, +15460, +15429, +15430, +15463, +15462, +15431, +15488, +15521, +15520, +15489, +15490, +15523, +15522, +15491, +15492, +15525, +15524, +15493, +15494, +15527, +15526, +15495, +15552, +15585, +15584, +15553, +15554, +15587, +15586, +15555, +15556, +15589, +15588, +15557, +15558, +15591, +15590, +15559, +15616, +15649, +15648, +15617, +15618, +15651, +15650, +15619, +15620, +15653, +15652, +15621, +15622, +15655, +15654, +15623, +15680, +15713, +15712, +15681, +15682, +15715, +15714, +15683, +15684, +15717, +15716, +15685, +15686, +15719, +15718, +15687, +15744, +15777, +15776, +15745, +15746, +15779, +15778, +15747, +15748, +15781, +15780, +15749, +15750, +15783, +15782, +15751, +15808, +15841, +15840, +15809, +15810, +15843, +15842, +15811, +15812, +15845, +15844, +15813, +15814, +15847, +15846, +15815, +15872, +15905, +15904, +15873, +15874, +15907, +15906, +15875, +15876, +15909, +15908, +15877, +15878, +15911, +15910, +15879, +15936, +15969, +15968, +15937, +15938, +15971, +15970, +15939, +15940, +15973, +15972, +15941, +15942, +15975, +15974, +15943, +16000, +16033, +16032, +16001, +16002, +16035, +16034, +16003, +16004, +16037, +16036, +16005, +16006, +16039, +16038, +16007, +16064, +16097, +16096, +16065, +16066, +16099, +16098, +16067, +16068, +16101, +16100, +16069, +16070, +16103, +16102, +16071, +16128, +16161, +16160, +16129, +16130, +16163, +16162, +16131, +16132, +16165, +16164, +16133, +16134, +16167, +16166, +16135, +16192, +16225, +16224, +16193, +16194, +16227, +16226, +16195, +16196, +16229, +16228, +16197, +16198, +16231, +16230, +16199, +16256, +16289, +16288, +16257, +16258, +16291, +16290, +16259, +16260, +16293, +16292, +16261, +16262, +16295, +16294, +16263, +16320, +16353, +16352, +16321, +16322, +16355, +16354, +16323, +16324, +16357, +16356, +16325, +16326, +16359, +16358, +16327, +14344, +14377, +14376, +14345, +14346, +14379, +14378, +14347, +14348, +14381, +14380, +14349, +14350, +14383, +14382, +14351, +14408, +14441, +14440, +14409, +14410, +14443, +14442, +14411, +14412, +14445, +14444, +14413, +14414, +14447, +14446, +14415, +14472, +14505, +14504, +14473, +14474, +14507, +14506, +14475, +14476, +14509, +14508, +14477, +14478, +14511, +14510, +14479, +14536, +14569, +14568, +14537, +14538, +14571, +14570, +14539, +14540, +14573, +14572, +14541, +14542, +14575, +14574, +14543, +14600, +14633, +14632, +14601, +14602, +14635, +14634, +14603, +14604, +14637, +14636, +14605, +14606, +14639, +14638, +14607, +14664, +14697, +14696, +14665, +14666, +14699, +14698, +14667, +14668, +14701, +14700, +14669, +14670, +14703, +14702, +14671, +14728, +14761, +14760, +14729, +14730, +14763, +14762, +14731, +14732, +14765, +14764, +14733, +14734, +14767, +14766, +14735, +14792, +14825, +14824, +14793, +14794, +14827, +14826, +14795, +14796, +14829, +14828, +14797, +14798, +14831, +14830, +14799, +14856, +14889, +14888, +14857, +14858, +14891, +14890, +14859, +14860, +14893, +14892, +14861, +14862, +14895, +14894, +14863, +14920, +14953, +14952, +14921, +14922, +14955, +14954, +14923, +14924, +14957, +14956, +14925, +14926, +14959, +14958, +14927, +14984, +15017, +15016, +14985, +14986, +15019, +15018, +14987, +14988, +15021, +15020, +14989, +14990, +15023, +15022, +14991, +15048, +15081, +15080, +15049, +15050, +15083, +15082, +15051, +15052, +15085, +15084, +15053, +15054, +15087, +15086, +15055, +15112, +15145, +15144, +15113, +15114, +15147, +15146, +15115, +15116, +15149, +15148, +15117, +15118, +15151, +15150, +15119, +15176, +15209, +15208, +15177, +15178, +15211, +15210, +15179, +15180, +15213, +15212, +15181, +15182, +15215, +15214, +15183, +15240, +15273, +15272, +15241, +15242, +15275, +15274, +15243, +15244, +15277, +15276, +15245, +15246, +15279, +15278, +15247, +15304, +15337, +15336, +15305, +15306, +15339, +15338, +15307, +15308, +15341, +15340, +15309, +15310, +15343, +15342, +15311, +15368, +15401, +15400, +15369, +15370, +15403, +15402, +15371, +15372, +15405, +15404, +15373, +15374, +15407, +15406, +15375, +15432, +15465, +15464, +15433, +15434, +15467, +15466, +15435, +15436, +15469, +15468, +15437, +15438, +15471, +15470, +15439, +15496, +15529, +15528, +15497, +15498, +15531, +15530, +15499, +15500, +15533, +15532, +15501, +15502, +15535, +15534, +15503, +15560, +15593, +15592, +15561, +15562, +15595, +15594, +15563, +15564, +15597, +15596, +15565, +15566, +15599, +15598, +15567, +15624, +15657, +15656, +15625, +15626, +15659, +15658, +15627, +15628, +15661, +15660, +15629, +15630, +15663, +15662, +15631, +15688, +15721, +15720, +15689, +15690, +15723, +15722, +15691, +15692, +15725, +15724, +15693, +15694, +15727, +15726, +15695, +15752, +15785, +15784, +15753, +15754, +15787, +15786, +15755, +15756, +15789, +15788, +15757, +15758, +15791, +15790, +15759, +15816, +15849, +15848, +15817, +15818, +15851, +15850, +15819, +15820, +15853, +15852, +15821, +15822, +15855, +15854, +15823, +15880, +15913, +15912, +15881, +15882, +15915, +15914, +15883, +15884, +15917, +15916, +15885, +15886, +15919, +15918, +15887, +15944, +15977, +15976, +15945, +15946, +15979, +15978, +15947, +15948, +15981, +15980, +15949, +15950, +15983, +15982, +15951, +16008, +16041, +16040, +16009, +16010, +16043, +16042, +16011, +16012, +16045, +16044, +16013, +16014, +16047, +16046, +16015, +16072, +16105, +16104, +16073, +16074, +16107, +16106, +16075, +16076, +16109, +16108, +16077, +16078, +16111, +16110, +16079, +16136, +16169, +16168, +16137, +16138, +16171, +16170, +16139, +16140, +16173, +16172, +16141, +16142, +16175, +16174, +16143, +16200, +16233, +16232, +16201, +16202, +16235, +16234, +16203, +16204, +16237, +16236, +16205, +16206, +16239, +16238, +16207, +16264, +16297, +16296, +16265, +16266, +16299, +16298, +16267, +16268, +16301, +16300, +16269, +16270, +16303, +16302, +16271, +16328, +16361, +16360, +16329, +16330, +16363, +16362, +16331, +16332, +16365, +16364, +16333, +16334, +16367, +16366, +16335, +14352, +14385, +14384, +14353, +14354, +14387, +14386, +14355, +14356, +14389, +14388, +14357, +14358, +14391, +14390, +14359, +14416, +14449, +14448, +14417, +14418, +14451, +14450, +14419, +14420, +14453, +14452, +14421, +14422, +14455, +14454, +14423, +14480, +14513, +14512, +14481, +14482, +14515, +14514, +14483, +14484, +14517, +14516, +14485, +14486, +14519, +14518, +14487, +14544, +14577, +14576, +14545, +14546, +14579, +14578, +14547, +14548, +14581, +14580, +14549, +14550, +14583, +14582, +14551, +14608, +14641, +14640, +14609, +14610, +14643, +14642, +14611, +14612, +14645, +14644, +14613, +14614, +14647, +14646, +14615, +14672, +14705, +14704, +14673, +14674, +14707, +14706, +14675, +14676, +14709, +14708, +14677, +14678, +14711, +14710, +14679, +14736, +14769, +14768, +14737, +14738, +14771, +14770, +14739, +14740, +14773, +14772, +14741, +14742, +14775, +14774, +14743, +14800, +14833, +14832, +14801, +14802, +14835, +14834, +14803, +14804, +14837, +14836, +14805, +14806, +14839, +14838, +14807, +14864, +14897, +14896, +14865, +14866, +14899, +14898, +14867, +14868, +14901, +14900, +14869, +14870, +14903, +14902, +14871, +14928, +14961, +14960, +14929, +14930, +14963, +14962, +14931, +14932, +14965, +14964, +14933, +14934, +14967, +14966, +14935, +14992, +15025, +15024, +14993, +14994, +15027, +15026, +14995, +14996, +15029, +15028, +14997, +14998, +15031, +15030, +14999, +15056, +15089, +15088, +15057, +15058, +15091, +15090, +15059, +15060, +15093, +15092, +15061, +15062, +15095, +15094, +15063, +15120, +15153, +15152, +15121, +15122, +15155, +15154, +15123, +15124, +15157, +15156, +15125, +15126, +15159, +15158, +15127, +15184, +15217, +15216, +15185, +15186, +15219, +15218, +15187, +15188, +15221, +15220, +15189, +15190, +15223, +15222, +15191, +15248, +15281, +15280, +15249, +15250, +15283, +15282, +15251, +15252, +15285, +15284, +15253, +15254, +15287, +15286, +15255, +15312, +15345, +15344, +15313, +15314, +15347, +15346, +15315, +15316, +15349, +15348, +15317, +15318, +15351, +15350, +15319, +15376, +15409, +15408, +15377, +15378, +15411, +15410, +15379, +15380, +15413, +15412, +15381, +15382, +15415, +15414, +15383, +15440, +15473, +15472, +15441, +15442, +15475, +15474, +15443, +15444, +15477, +15476, +15445, +15446, +15479, +15478, +15447, +15504, +15537, +15536, +15505, +15506, +15539, +15538, +15507, +15508, +15541, +15540, +15509, +15510, +15543, +15542, +15511, +15568, +15601, +15600, +15569, +15570, +15603, +15602, +15571, +15572, +15605, +15604, +15573, +15574, +15607, +15606, +15575, +15632, +15665, +15664, +15633, +15634, +15667, +15666, +15635, +15636, +15669, +15668, +15637, +15638, +15671, +15670, +15639, +15696, +15729, +15728, +15697, +15698, +15731, +15730, +15699, +15700, +15733, +15732, +15701, +15702, +15735, +15734, +15703, +15760, +15793, +15792, +15761, +15762, +15795, +15794, +15763, +15764, +15797, +15796, +15765, +15766, +15799, +15798, +15767, +15824, +15857, +15856, +15825, +15826, +15859, +15858, +15827, +15828, +15861, +15860, +15829, +15830, +15863, +15862, +15831, +15888, +15921, +15920, +15889, +15890, +15923, +15922, +15891, +15892, +15925, +15924, +15893, +15894, +15927, +15926, +15895, +15952, +15985, +15984, +15953, +15954, +15987, +15986, +15955, +15956, +15989, +15988, +15957, +15958, +15991, +15990, +15959, +16016, +16049, +16048, +16017, +16018, +16051, +16050, +16019, +16020, +16053, +16052, +16021, +16022, +16055, +16054, +16023, +16080, +16113, +16112, +16081, +16082, +16115, +16114, +16083, +16084, +16117, +16116, +16085, +16086, +16119, +16118, +16087, +16144, +16177, +16176, +16145, +16146, +16179, +16178, +16147, +16148, +16181, +16180, +16149, +16150, +16183, +16182, +16151, +16208, +16241, +16240, +16209, +16210, +16243, +16242, +16211, +16212, +16245, +16244, +16213, +16214, +16247, +16246, +16215, +16272, +16305, +16304, +16273, +16274, +16307, +16306, +16275, +16276, +16309, +16308, +16277, +16278, +16311, +16310, +16279, +16336, +16369, +16368, +16337, +16338, +16371, +16370, +16339, +16340, +16373, +16372, +16341, +16342, +16375, +16374, +16343, +14360, +14393, +14392, +14361, +14362, +14395, +14394, +14363, +14364, +14397, +14396, +14365, +14366, +14399, +14398, +14367, +14424, +14457, +14456, +14425, +14426, +14459, +14458, +14427, +14428, +14461, +14460, +14429, +14430, +14463, +14462, +14431, +14488, +14521, +14520, +14489, +14490, +14523, +14522, +14491, +14492, +14525, +14524, +14493, +14494, +14527, +14526, +14495, +14552, +14585, +14584, +14553, +14554, +14587, +14586, +14555, +14556, +14589, +14588, +14557, +14558, +14591, +14590, +14559, +14616, +14649, +14648, +14617, +14618, +14651, +14650, +14619, +14620, +14653, +14652, +14621, +14622, +14655, +14654, +14623, +14680, +14713, +14712, +14681, +14682, +14715, +14714, +14683, +14684, +14717, +14716, +14685, +14686, +14719, +14718, +14687, +14744, +14777, +14776, +14745, +14746, +14779, +14778, +14747, +14748, +14781, +14780, +14749, +14750, +14783, +14782, +14751, +14808, +14841, +14840, +14809, +14810, +14843, +14842, +14811, +14812, +14845, +14844, +14813, +14814, +14847, +14846, +14815, +14872, +14905, +14904, +14873, +14874, +14907, +14906, +14875, +14876, +14909, +14908, +14877, +14878, +14911, +14910, +14879, +14936, +14969, +14968, +14937, +14938, +14971, +14970, +14939, +14940, +14973, +14972, +14941, +14942, +14975, +14974, +14943, +15000, +15033, +15032, +15001, +15002, +15035, +15034, +15003, +15004, +15037, +15036, +15005, +15006, +15039, +15038, +15007, +15064, +15097, +15096, +15065, +15066, +15099, +15098, +15067, +15068, +15101, +15100, +15069, +15070, +15103, +15102, +15071, +15128, +15161, +15160, +15129, +15130, +15163, +15162, +15131, +15132, +15165, +15164, +15133, +15134, +15167, +15166, +15135, +15192, +15225, +15224, +15193, +15194, +15227, +15226, +15195, +15196, +15229, +15228, +15197, +15198, +15231, +15230, +15199, +15256, +15289, +15288, +15257, +15258, +15291, +15290, +15259, +15260, +15293, +15292, +15261, +15262, +15295, +15294, +15263, +15320, +15353, +15352, +15321, +15322, +15355, +15354, +15323, +15324, +15357, +15356, +15325, +15326, +15359, +15358, +15327, +15384, +15417, +15416, +15385, +15386, +15419, +15418, +15387, +15388, +15421, +15420, +15389, +15390, +15423, +15422, +15391, +15448, +15481, +15480, +15449, +15450, +15483, +15482, +15451, +15452, +15485, +15484, +15453, +15454, +15487, +15486, +15455, +15512, +15545, +15544, +15513, +15514, +15547, +15546, +15515, +15516, +15549, +15548, +15517, +15518, +15551, +15550, +15519, +15576, +15609, +15608, +15577, +15578, +15611, +15610, +15579, +15580, +15613, +15612, +15581, +15582, +15615, +15614, +15583, +15640, +15673, +15672, +15641, +15642, +15675, +15674, +15643, +15644, +15677, +15676, +15645, +15646, +15679, +15678, +15647, +15704, +15737, +15736, +15705, +15706, +15739, +15738, +15707, +15708, +15741, +15740, +15709, +15710, +15743, +15742, +15711, +15768, +15801, +15800, +15769, +15770, +15803, +15802, +15771, +15772, +15805, +15804, +15773, +15774, +15807, +15806, +15775, +15832, +15865, +15864, +15833, +15834, +15867, +15866, +15835, +15836, +15869, +15868, +15837, +15838, +15871, +15870, +15839, +15896, +15929, +15928, +15897, +15898, +15931, +15930, +15899, +15900, +15933, +15932, +15901, +15902, +15935, +15934, +15903, +15960, +15993, +15992, +15961, +15962, +15995, +15994, +15963, +15964, +15997, +15996, +15965, +15966, +15999, +15998, +15967, +16024, +16057, +16056, +16025, +16026, +16059, +16058, +16027, +16028, +16061, +16060, +16029, +16030, +16063, +16062, +16031, +16088, +16121, +16120, +16089, +16090, +16123, +16122, +16091, +16092, +16125, +16124, +16093, +16094, +16127, +16126, +16095, +16152, +16185, +16184, +16153, +16154, +16187, +16186, +16155, +16156, +16189, +16188, +16157, +16158, +16191, +16190, +16159, +16216, +16249, +16248, +16217, +16218, +16251, +16250, +16219, +16220, +16253, +16252, +16221, +16222, +16255, +16254, +16223, +16280, +16313, +16312, +16281, +16282, +16315, +16314, +16283, +16284, +16317, +16316, +16285, +16286, +16319, +16318, +16287, +16344, +16377, +16376, +16345, +16346, +16379, +16378, +16347, +16348, +16381, +16380, +16349, +16350, +16383, +16382, +16351, +16384, +16417, +16416, +16385, +16386, +16419, +16418, +16387, +16388, +16421, +16420, +16389, +16390, +16423, +16422, +16391, +16448, +16481, +16480, +16449, +16450, +16483, +16482, +16451, +16452, +16485, +16484, +16453, +16454, +16487, +16486, +16455, +16512, +16545, +16544, +16513, +16514, +16547, +16546, +16515, +16516, +16549, +16548, +16517, +16518, +16551, +16550, +16519, +16576, +16609, +16608, +16577, +16578, +16611, +16610, +16579, +16580, +16613, +16612, +16581, +16582, +16615, +16614, +16583, +16640, +16673, +16672, +16641, +16642, +16675, +16674, +16643, +16644, +16677, +16676, +16645, +16646, +16679, +16678, +16647, +16704, +16737, +16736, +16705, +16706, +16739, +16738, +16707, +16708, +16741, +16740, +16709, +16710, +16743, +16742, +16711, +16768, +16801, +16800, +16769, +16770, +16803, +16802, +16771, +16772, +16805, +16804, +16773, +16774, +16807, +16806, +16775, +16832, +16865, +16864, +16833, +16834, +16867, +16866, +16835, +16836, +16869, +16868, +16837, +16838, +16871, +16870, +16839, +16896, +16929, +16928, +16897, +16898, +16931, +16930, +16899, +16900, +16933, +16932, +16901, +16902, +16935, +16934, +16903, +16960, +16993, +16992, +16961, +16962, +16995, +16994, +16963, +16964, +16997, +16996, +16965, +16966, +16999, +16998, +16967, +17024, +17057, +17056, +17025, +17026, +17059, +17058, +17027, +17028, +17061, +17060, +17029, +17030, +17063, +17062, +17031, +17088, +17121, +17120, +17089, +17090, +17123, +17122, +17091, +17092, +17125, +17124, +17093, +17094, +17127, +17126, +17095, +17152, +17185, +17184, +17153, +17154, +17187, +17186, +17155, +17156, +17189, +17188, +17157, +17158, +17191, +17190, +17159, +17216, +17249, +17248, +17217, +17218, +17251, +17250, +17219, +17220, +17253, +17252, +17221, +17222, +17255, +17254, +17223, +17280, +17313, +17312, +17281, +17282, +17315, +17314, +17283, +17284, +17317, +17316, +17285, +17286, +17319, +17318, +17287, +17344, +17377, +17376, +17345, +17346, +17379, +17378, +17347, +17348, +17381, +17380, +17349, +17350, +17383, +17382, +17351, +17408, +17441, +17440, +17409, +17410, +17443, +17442, +17411, +17412, +17445, +17444, +17413, +17414, +17447, +17446, +17415, +17472, +17505, +17504, +17473, +17474, +17507, +17506, +17475, +17476, +17509, +17508, +17477, +17478, +17511, +17510, +17479, +17536, +17569, +17568, +17537, +17538, +17571, +17570, +17539, +17540, +17573, +17572, +17541, +17542, +17575, +17574, +17543, +17600, +17633, +17632, +17601, +17602, +17635, +17634, +17603, +17604, +17637, +17636, +17605, +17606, +17639, +17638, +17607, +17664, +17697, +17696, +17665, +17666, +17699, +17698, +17667, +17668, +17701, +17700, +17669, +17670, +17703, +17702, +17671, +17728, +17761, +17760, +17729, +17730, +17763, +17762, +17731, +17732, +17765, +17764, +17733, +17734, +17767, +17766, +17735, +17792, +17825, +17824, +17793, +17794, +17827, +17826, +17795, +17796, +17829, +17828, +17797, +17798, +17831, +17830, +17799, +17856, +17889, +17888, +17857, +17858, +17891, +17890, +17859, +17860, +17893, +17892, +17861, +17862, +17895, +17894, +17863, +17920, +17953, +17952, +17921, +17922, +17955, +17954, +17923, +17924, +17957, +17956, +17925, +17926, +17959, +17958, +17927, +17984, +18017, +18016, +17985, +17986, +18019, +18018, +17987, +17988, +18021, +18020, +17989, +17990, +18023, +18022, +17991, +18048, +18081, +18080, +18049, +18050, +18083, +18082, +18051, +18052, +18085, +18084, +18053, +18054, +18087, +18086, +18055, +18112, +18145, +18144, +18113, +18114, +18147, +18146, +18115, +18116, +18149, +18148, +18117, +18118, +18151, +18150, +18119, +18176, +18209, +18208, +18177, +18178, +18211, +18210, +18179, +18180, +18213, +18212, +18181, +18182, +18215, +18214, +18183, +18240, +18273, +18272, +18241, +18242, +18275, +18274, +18243, +18244, +18277, +18276, +18245, +18246, +18279, +18278, +18247, +18304, +18337, +18336, +18305, +18306, +18339, +18338, +18307, +18308, +18341, +18340, +18309, +18310, +18343, +18342, +18311, +18368, +18401, +18400, +18369, +18370, +18403, +18402, +18371, +18372, +18405, +18404, +18373, +18374, +18407, +18406, +18375, +16392, +16425, +16424, +16393, +16394, +16427, +16426, +16395, +16396, +16429, +16428, +16397, +16398, +16431, +16430, +16399, +16456, +16489, +16488, +16457, +16458, +16491, +16490, +16459, +16460, +16493, +16492, +16461, +16462, +16495, +16494, +16463, +16520, +16553, +16552, +16521, +16522, +16555, +16554, +16523, +16524, +16557, +16556, +16525, +16526, +16559, +16558, +16527, +16584, +16617, +16616, +16585, +16586, +16619, +16618, +16587, +16588, +16621, +16620, +16589, +16590, +16623, +16622, +16591, +16648, +16681, +16680, +16649, +16650, +16683, +16682, +16651, +16652, +16685, +16684, +16653, +16654, +16687, +16686, +16655, +16712, +16745, +16744, +16713, +16714, +16747, +16746, +16715, +16716, +16749, +16748, +16717, +16718, +16751, +16750, +16719, +16776, +16809, +16808, +16777, +16778, +16811, +16810, +16779, +16780, +16813, +16812, +16781, +16782, +16815, +16814, +16783, +16840, +16873, +16872, +16841, +16842, +16875, +16874, +16843, +16844, +16877, +16876, +16845, +16846, +16879, +16878, +16847, +16904, +16937, +16936, +16905, +16906, +16939, +16938, +16907, +16908, +16941, +16940, +16909, +16910, +16943, +16942, +16911, +16968, +17001, +17000, +16969, +16970, +17003, +17002, +16971, +16972, +17005, +17004, +16973, +16974, +17007, +17006, +16975, +17032, +17065, +17064, +17033, +17034, +17067, +17066, +17035, +17036, +17069, +17068, +17037, +17038, +17071, +17070, +17039, +17096, +17129, +17128, +17097, +17098, +17131, +17130, +17099, +17100, +17133, +17132, +17101, +17102, +17135, +17134, +17103, +17160, +17193, +17192, +17161, +17162, +17195, +17194, +17163, +17164, +17197, +17196, +17165, +17166, +17199, +17198, +17167, +17224, +17257, +17256, +17225, +17226, +17259, +17258, +17227, +17228, +17261, +17260, +17229, +17230, +17263, +17262, +17231, +17288, +17321, +17320, +17289, +17290, +17323, +17322, +17291, +17292, +17325, +17324, +17293, +17294, +17327, +17326, +17295, +17352, +17385, +17384, +17353, +17354, +17387, +17386, +17355, +17356, +17389, +17388, +17357, +17358, +17391, +17390, +17359, +17416, +17449, +17448, +17417, +17418, +17451, +17450, +17419, +17420, +17453, +17452, +17421, +17422, +17455, +17454, +17423, +17480, +17513, +17512, +17481, +17482, +17515, +17514, +17483, +17484, +17517, +17516, +17485, +17486, +17519, +17518, +17487, +17544, +17577, +17576, +17545, +17546, +17579, +17578, +17547, +17548, +17581, +17580, +17549, +17550, +17583, +17582, +17551, +17608, +17641, +17640, +17609, +17610, +17643, +17642, +17611, +17612, +17645, +17644, +17613, +17614, +17647, +17646, +17615, +17672, +17705, +17704, +17673, +17674, +17707, +17706, +17675, +17676, +17709, +17708, +17677, +17678, +17711, +17710, +17679, +17736, +17769, +17768, +17737, +17738, +17771, +17770, +17739, +17740, +17773, +17772, +17741, +17742, +17775, +17774, +17743, +17800, +17833, +17832, +17801, +17802, +17835, +17834, +17803, +17804, +17837, +17836, +17805, +17806, +17839, +17838, +17807, +17864, +17897, +17896, +17865, +17866, +17899, +17898, +17867, +17868, +17901, +17900, +17869, +17870, +17903, +17902, +17871, +17928, +17961, +17960, +17929, +17930, +17963, +17962, +17931, +17932, +17965, +17964, +17933, +17934, +17967, +17966, +17935, +17992, +18025, +18024, +17993, +17994, +18027, +18026, +17995, +17996, +18029, +18028, +17997, +17998, +18031, +18030, +17999, +18056, +18089, +18088, +18057, +18058, +18091, +18090, +18059, +18060, +18093, +18092, +18061, +18062, +18095, +18094, +18063, +18120, +18153, +18152, +18121, +18122, +18155, +18154, +18123, +18124, +18157, +18156, +18125, +18126, +18159, +18158, +18127, +18184, +18217, +18216, +18185, +18186, +18219, +18218, +18187, +18188, +18221, +18220, +18189, +18190, +18223, +18222, +18191, +18248, +18281, +18280, +18249, +18250, +18283, +18282, +18251, +18252, +18285, +18284, +18253, +18254, +18287, +18286, +18255, +18312, +18345, +18344, +18313, +18314, +18347, +18346, +18315, +18316, +18349, +18348, +18317, +18318, +18351, +18350, +18319, +18376, +18409, +18408, +18377, +18378, +18411, +18410, +18379, +18380, +18413, +18412, +18381, +18382, +18415, +18414, +18383, +16400, +16433, +16432, +16401, +16402, +16435, +16434, +16403, +16404, +16437, +16436, +16405, +16406, +16439, +16438, +16407, +16464, +16497, +16496, +16465, +16466, +16499, +16498, +16467, +16468, +16501, +16500, +16469, +16470, +16503, +16502, +16471, +16528, +16561, +16560, +16529, +16530, +16563, +16562, +16531, +16532, +16565, +16564, +16533, +16534, +16567, +16566, +16535, +16592, +16625, +16624, +16593, +16594, +16627, +16626, +16595, +16596, +16629, +16628, +16597, +16598, +16631, +16630, +16599, +16656, +16689, +16688, +16657, +16658, +16691, +16690, +16659, +16660, +16693, +16692, +16661, +16662, +16695, +16694, +16663, +16720, +16753, +16752, +16721, +16722, +16755, +16754, +16723, +16724, +16757, +16756, +16725, +16726, +16759, +16758, +16727, +16784, +16817, +16816, +16785, +16786, +16819, +16818, +16787, +16788, +16821, +16820, +16789, +16790, +16823, +16822, +16791, +16848, +16881, +16880, +16849, +16850, +16883, +16882, +16851, +16852, +16885, +16884, +16853, +16854, +16887, +16886, +16855, +16912, +16945, +16944, +16913, +16914, +16947, +16946, +16915, +16916, +16949, +16948, +16917, +16918, +16951, +16950, +16919, +16976, +17009, +17008, +16977, +16978, +17011, +17010, +16979, +16980, +17013, +17012, +16981, +16982, +17015, +17014, +16983, +17040, +17073, +17072, +17041, +17042, +17075, +17074, +17043, +17044, +17077, +17076, +17045, +17046, +17079, +17078, +17047, +17104, +17137, +17136, +17105, +17106, +17139, +17138, +17107, +17108, +17141, +17140, +17109, +17110, +17143, +17142, +17111, +17168, +17201, +17200, +17169, +17170, +17203, +17202, +17171, +17172, +17205, +17204, +17173, +17174, +17207, +17206, +17175, +17232, +17265, +17264, +17233, +17234, +17267, +17266, +17235, +17236, +17269, +17268, +17237, +17238, +17271, +17270, +17239, +17296, +17329, +17328, +17297, +17298, +17331, +17330, +17299, +17300, +17333, +17332, +17301, +17302, +17335, +17334, +17303, +17360, +17393, +17392, +17361, +17362, +17395, +17394, +17363, +17364, +17397, +17396, +17365, +17366, +17399, +17398, +17367, +17424, +17457, +17456, +17425, +17426, +17459, +17458, +17427, +17428, +17461, +17460, +17429, +17430, +17463, +17462, +17431, +17488, +17521, +17520, +17489, +17490, +17523, +17522, +17491, +17492, +17525, +17524, +17493, +17494, +17527, +17526, +17495, +17552, +17585, +17584, +17553, +17554, +17587, +17586, +17555, +17556, +17589, +17588, +17557, +17558, +17591, +17590, +17559, +17616, +17649, +17648, +17617, +17618, +17651, +17650, +17619, +17620, +17653, +17652, +17621, +17622, +17655, +17654, +17623, +17680, +17713, +17712, +17681, +17682, +17715, +17714, +17683, +17684, +17717, +17716, +17685, +17686, +17719, +17718, +17687, +17744, +17777, +17776, +17745, +17746, +17779, +17778, +17747, +17748, +17781, +17780, +17749, +17750, +17783, +17782, +17751, +17808, +17841, +17840, +17809, +17810, +17843, +17842, +17811, +17812, +17845, +17844, +17813, +17814, +17847, +17846, +17815, +17872, +17905, +17904, +17873, +17874, +17907, +17906, +17875, +17876, +17909, +17908, +17877, +17878, +17911, +17910, +17879, +17936, +17969, +17968, +17937, +17938, +17971, +17970, +17939, +17940, +17973, +17972, +17941, +17942, +17975, +17974, +17943, +18000, +18033, +18032, +18001, +18002, +18035, +18034, +18003, +18004, +18037, +18036, +18005, +18006, +18039, +18038, +18007, +18064, +18097, +18096, +18065, +18066, +18099, +18098, +18067, +18068, +18101, +18100, +18069, +18070, +18103, +18102, +18071, +18128, +18161, +18160, +18129, +18130, +18163, +18162, +18131, +18132, +18165, +18164, +18133, +18134, +18167, +18166, +18135, +18192, +18225, +18224, +18193, +18194, +18227, +18226, +18195, +18196, +18229, +18228, +18197, +18198, +18231, +18230, +18199, +18256, +18289, +18288, +18257, +18258, +18291, +18290, +18259, +18260, +18293, +18292, +18261, +18262, +18295, +18294, +18263, +18320, +18353, +18352, +18321, +18322, +18355, +18354, +18323, +18324, +18357, +18356, +18325, +18326, +18359, +18358, +18327, +18384, +18417, +18416, +18385, +18386, +18419, +18418, +18387, +18388, +18421, +18420, +18389, +18390, +18423, +18422, +18391, +16408, +16441, +16440, +16409, +16410, +16443, +16442, +16411, +16412, +16445, +16444, +16413, +16414, +16447, +16446, +16415, +16472, +16505, +16504, +16473, +16474, +16507, +16506, +16475, +16476, +16509, +16508, +16477, +16478, +16511, +16510, +16479, +16536, +16569, +16568, +16537, +16538, +16571, +16570, +16539, +16540, +16573, +16572, +16541, +16542, +16575, +16574, +16543, +16600, +16633, +16632, +16601, +16602, +16635, +16634, +16603, +16604, +16637, +16636, +16605, +16606, +16639, +16638, +16607, +16664, +16697, +16696, +16665, +16666, +16699, +16698, +16667, +16668, +16701, +16700, +16669, +16670, +16703, +16702, +16671, +16728, +16761, +16760, +16729, +16730, +16763, +16762, +16731, +16732, +16765, +16764, +16733, +16734, +16767, +16766, +16735, +16792, +16825, +16824, +16793, +16794, +16827, +16826, +16795, +16796, +16829, +16828, +16797, +16798, +16831, +16830, +16799, +16856, +16889, +16888, +16857, +16858, +16891, +16890, +16859, +16860, +16893, +16892, +16861, +16862, +16895, +16894, +16863, +16920, +16953, +16952, +16921, +16922, +16955, +16954, +16923, +16924, +16957, +16956, +16925, +16926, +16959, +16958, +16927, +16984, +17017, +17016, +16985, +16986, +17019, +17018, +16987, +16988, +17021, +17020, +16989, +16990, +17023, +17022, +16991, +17048, +17081, +17080, +17049, +17050, +17083, +17082, +17051, +17052, +17085, +17084, +17053, +17054, +17087, +17086, +17055, +17112, +17145, +17144, +17113, +17114, +17147, +17146, +17115, +17116, +17149, +17148, +17117, +17118, +17151, +17150, +17119, +17176, +17209, +17208, +17177, +17178, +17211, +17210, +17179, +17180, +17213, +17212, +17181, +17182, +17215, +17214, +17183, +17240, +17273, +17272, +17241, +17242, +17275, +17274, +17243, +17244, +17277, +17276, +17245, +17246, +17279, +17278, +17247, +17304, +17337, +17336, +17305, +17306, +17339, +17338, +17307, +17308, +17341, +17340, +17309, +17310, +17343, +17342, +17311, +17368, +17401, +17400, +17369, +17370, +17403, +17402, +17371, +17372, +17405, +17404, +17373, +17374, +17407, +17406, +17375, +17432, +17465, +17464, +17433, +17434, +17467, +17466, +17435, +17436, +17469, +17468, +17437, +17438, +17471, +17470, +17439, +17496, +17529, +17528, +17497, +17498, +17531, +17530, +17499, +17500, +17533, +17532, +17501, +17502, +17535, +17534, +17503, +17560, +17593, +17592, +17561, +17562, +17595, +17594, +17563, +17564, +17597, +17596, +17565, +17566, +17599, +17598, +17567, +17624, +17657, +17656, +17625, +17626, +17659, +17658, +17627, +17628, +17661, +17660, +17629, +17630, +17663, +17662, +17631, +17688, +17721, +17720, +17689, +17690, +17723, +17722, +17691, +17692, +17725, +17724, +17693, +17694, +17727, +17726, +17695, +17752, +17785, +17784, +17753, +17754, +17787, +17786, +17755, +17756, +17789, +17788, +17757, +17758, +17791, +17790, +17759, +17816, +17849, +17848, +17817, +17818, +17851, +17850, +17819, +17820, +17853, +17852, +17821, +17822, +17855, +17854, +17823, +17880, +17913, +17912, +17881, +17882, +17915, +17914, +17883, +17884, +17917, +17916, +17885, +17886, +17919, +17918, +17887, +17944, +17977, +17976, +17945, +17946, +17979, +17978, +17947, +17948, +17981, +17980, +17949, +17950, +17983, +17982, +17951, +18008, +18041, +18040, +18009, +18010, +18043, +18042, +18011, +18012, +18045, +18044, +18013, +18014, +18047, +18046, +18015, +18072, +18105, +18104, +18073, +18074, +18107, +18106, +18075, +18076, +18109, +18108, +18077, +18078, +18111, +18110, +18079, +18136, +18169, +18168, +18137, +18138, +18171, +18170, +18139, +18140, +18173, +18172, +18141, +18142, +18175, +18174, +18143, +18200, +18233, +18232, +18201, +18202, +18235, +18234, +18203, +18204, +18237, +18236, +18205, +18206, +18239, +18238, +18207, +18264, +18297, +18296, +18265, +18266, +18299, +18298, +18267, +18268, +18301, +18300, +18269, +18270, +18303, +18302, +18271, +18328, +18361, +18360, +18329, +18330, +18363, +18362, +18331, +18332, +18365, +18364, +18333, +18334, +18367, +18366, +18335, +18392, +18425, +18424, +18393, +18394, +18427, +18426, +18395, +18396, +18429, +18428, +18397, +18398, +18431, +18430, +18399, +18432, +18465, +18464, +18433, +18434, +18467, +18466, +18435, +18436, +18469, +18468, +18437, +18438, +18471, +18470, +18439, +18496, +18529, +18528, +18497, +18498, +18531, +18530, +18499, +18500, +18533, +18532, +18501, +18502, +18535, +18534, +18503, +18560, +18593, +18592, +18561, +18562, +18595, +18594, +18563, +18564, +18597, +18596, +18565, +18566, +18599, +18598, +18567, +18624, +18657, +18656, +18625, +18626, +18659, +18658, +18627, +18628, +18661, +18660, +18629, +18630, +18663, +18662, +18631, +18688, +18721, +18720, +18689, +18690, +18723, +18722, +18691, +18692, +18725, +18724, +18693, +18694, +18727, +18726, +18695, +18752, +18785, +18784, +18753, +18754, +18787, +18786, +18755, +18756, +18789, +18788, +18757, +18758, +18791, +18790, +18759, +18816, +18849, +18848, +18817, +18818, +18851, +18850, +18819, +18820, +18853, +18852, +18821, +18822, +18855, +18854, +18823, +18880, +18913, +18912, +18881, +18882, +18915, +18914, +18883, +18884, +18917, +18916, +18885, +18886, +18919, +18918, +18887, +18944, +18977, +18976, +18945, +18946, +18979, +18978, +18947, +18948, +18981, +18980, +18949, +18950, +18983, +18982, +18951, +19008, +19041, +19040, +19009, +19010, +19043, +19042, +19011, +19012, +19045, +19044, +19013, +19014, +19047, +19046, +19015, +19072, +19105, +19104, +19073, +19074, +19107, +19106, +19075, +19076, +19109, +19108, +19077, +19078, +19111, +19110, +19079, +19136, +19169, +19168, +19137, +19138, +19171, +19170, +19139, +19140, +19173, +19172, +19141, +19142, +19175, +19174, +19143, +19200, +19233, +19232, +19201, +19202, +19235, +19234, +19203, +19204, +19237, +19236, +19205, +19206, +19239, +19238, +19207, +19264, +19297, +19296, +19265, +19266, +19299, +19298, +19267, +19268, +19301, +19300, +19269, +19270, +19303, +19302, +19271, +19328, +19361, +19360, +19329, +19330, +19363, +19362, +19331, +19332, +19365, +19364, +19333, +19334, +19367, +19366, +19335, +19392, +19425, +19424, +19393, +19394, +19427, +19426, +19395, +19396, +19429, +19428, +19397, +19398, +19431, +19430, +19399, +19456, +19489, +19488, +19457, +19458, +19491, +19490, +19459, +19460, +19493, +19492, +19461, +19462, +19495, +19494, +19463, +19520, +19553, +19552, +19521, +19522, +19555, +19554, +19523, +19524, +19557, +19556, +19525, +19526, +19559, +19558, +19527, +19584, +19617, +19616, +19585, +19586, +19619, +19618, +19587, +19588, +19621, +19620, +19589, +19590, +19623, +19622, +19591, +19648, +19681, +19680, +19649, +19650, +19683, +19682, +19651, +19652, +19685, +19684, +19653, +19654, +19687, +19686, +19655, +19712, +19745, +19744, +19713, +19714, +19747, +19746, +19715, +19716, +19749, +19748, +19717, +19718, +19751, +19750, +19719, +19776, +19809, +19808, +19777, +19778, +19811, +19810, +19779, +19780, +19813, +19812, +19781, +19782, +19815, +19814, +19783, +19840, +19873, +19872, +19841, +19842, +19875, +19874, +19843, +19844, +19877, +19876, +19845, +19846, +19879, +19878, +19847, +19904, +19937, +19936, +19905, +19906, +19939, +19938, +19907, +19908, +19941, +19940, +19909, +19910, +19943, +19942, +19911, +19968, +20001, +20000, +19969, +19970, +20003, +20002, +19971, +19972, +20005, +20004, +19973, +19974, +20007, +20006, +19975, +20032, +20065, +20064, +20033, +20034, +20067, +20066, +20035, +20036, +20069, +20068, +20037, +20038, +20071, +20070, +20039, +20096, +20129, +20128, +20097, +20098, +20131, +20130, +20099, +20100, +20133, +20132, +20101, +20102, +20135, +20134, +20103, +20160, +20193, +20192, +20161, +20162, +20195, +20194, +20163, +20164, +20197, +20196, +20165, +20166, +20199, +20198, +20167, +20224, +20257, +20256, +20225, +20226, +20259, +20258, +20227, +20228, +20261, +20260, +20229, +20230, +20263, +20262, +20231, +20288, +20321, +20320, +20289, +20290, +20323, +20322, +20291, +20292, +20325, +20324, +20293, +20294, +20327, +20326, +20295, +20352, +20385, +20384, +20353, +20354, +20387, +20386, +20355, +20356, +20389, +20388, +20357, +20358, +20391, +20390, +20359, +20416, +20449, +20448, +20417, +20418, +20451, +20450, +20419, +20420, +20453, +20452, +20421, +20422, +20455, +20454, +20423, +18440, +18473, +18472, +18441, +18442, +18475, +18474, +18443, +18444, +18477, +18476, +18445, +18446, +18479, +18478, +18447, +18504, +18537, +18536, +18505, +18506, +18539, +18538, +18507, +18508, +18541, +18540, +18509, +18510, +18543, +18542, +18511, +18568, +18601, +18600, +18569, +18570, +18603, +18602, +18571, +18572, +18605, +18604, +18573, +18574, +18607, +18606, +18575, +18632, +18665, +18664, +18633, +18634, +18667, +18666, +18635, +18636, +18669, +18668, +18637, +18638, +18671, +18670, +18639, +18696, +18729, +18728, +18697, +18698, +18731, +18730, +18699, +18700, +18733, +18732, +18701, +18702, +18735, +18734, +18703, +18760, +18793, +18792, +18761, +18762, +18795, +18794, +18763, +18764, +18797, +18796, +18765, +18766, +18799, +18798, +18767, +18824, +18857, +18856, +18825, +18826, +18859, +18858, +18827, +18828, +18861, +18860, +18829, +18830, +18863, +18862, +18831, +18888, +18921, +18920, +18889, +18890, +18923, +18922, +18891, +18892, +18925, +18924, +18893, +18894, +18927, +18926, +18895, +18952, +18985, +18984, +18953, +18954, +18987, +18986, +18955, +18956, +18989, +18988, +18957, +18958, +18991, +18990, +18959, +19016, +19049, +19048, +19017, +19018, +19051, +19050, +19019, +19020, +19053, +19052, +19021, +19022, +19055, +19054, +19023, +19080, +19113, +19112, +19081, +19082, +19115, +19114, +19083, +19084, +19117, +19116, +19085, +19086, +19119, +19118, +19087, +19144, +19177, +19176, +19145, +19146, +19179, +19178, +19147, +19148, +19181, +19180, +19149, +19150, +19183, +19182, +19151, +19208, +19241, +19240, +19209, +19210, +19243, +19242, +19211, +19212, +19245, +19244, +19213, +19214, +19247, +19246, +19215, +19272, +19305, +19304, +19273, +19274, +19307, +19306, +19275, +19276, +19309, +19308, +19277, +19278, +19311, +19310, +19279, +19336, +19369, +19368, +19337, +19338, +19371, +19370, +19339, +19340, +19373, +19372, +19341, +19342, +19375, +19374, +19343, +19400, +19433, +19432, +19401, +19402, +19435, +19434, +19403, +19404, +19437, +19436, +19405, +19406, +19439, +19438, +19407, +19464, +19497, +19496, +19465, +19466, +19499, +19498, +19467, +19468, +19501, +19500, +19469, +19470, +19503, +19502, +19471, +19528, +19561, +19560, +19529, +19530, +19563, +19562, +19531, +19532, +19565, +19564, +19533, +19534, +19567, +19566, +19535, +19592, +19625, +19624, +19593, +19594, +19627, +19626, +19595, +19596, +19629, +19628, +19597, +19598, +19631, +19630, +19599, +19656, +19689, +19688, +19657, +19658, +19691, +19690, +19659, +19660, +19693, +19692, +19661, +19662, +19695, +19694, +19663, +19720, +19753, +19752, +19721, +19722, +19755, +19754, +19723, +19724, +19757, +19756, +19725, +19726, +19759, +19758, +19727, +19784, +19817, +19816, +19785, +19786, +19819, +19818, +19787, +19788, +19821, +19820, +19789, +19790, +19823, +19822, +19791, +19848, +19881, +19880, +19849, +19850, +19883, +19882, +19851, +19852, +19885, +19884, +19853, +19854, +19887, +19886, +19855, +19912, +19945, +19944, +19913, +19914, +19947, +19946, +19915, +19916, +19949, +19948, +19917, +19918, +19951, +19950, +19919, +19976, +20009, +20008, +19977, +19978, +20011, +20010, +19979, +19980, +20013, +20012, +19981, +19982, +20015, +20014, +19983, +20040, +20073, +20072, +20041, +20042, +20075, +20074, +20043, +20044, +20077, +20076, +20045, +20046, +20079, +20078, +20047, +20104, +20137, +20136, +20105, +20106, +20139, +20138, +20107, +20108, +20141, +20140, +20109, +20110, +20143, +20142, +20111, +20168, +20201, +20200, +20169, +20170, +20203, +20202, +20171, +20172, +20205, +20204, +20173, +20174, +20207, +20206, +20175, +20232, +20265, +20264, +20233, +20234, +20267, +20266, +20235, +20236, +20269, +20268, +20237, +20238, +20271, +20270, +20239, +20296, +20329, +20328, +20297, +20298, +20331, +20330, +20299, +20300, +20333, +20332, +20301, +20302, +20335, +20334, +20303, +20360, +20393, +20392, +20361, +20362, +20395, +20394, +20363, +20364, +20397, +20396, +20365, +20366, +20399, +20398, +20367, +20424, +20457, +20456, +20425, +20426, +20459, +20458, +20427, +20428, +20461, +20460, +20429, +20430, +20463, +20462, +20431, +18448, +18481, +18480, +18449, +18450, +18483, +18482, +18451, +18452, +18485, +18484, +18453, +18454, +18487, +18486, +18455, +18512, +18545, +18544, +18513, +18514, +18547, +18546, +18515, +18516, +18549, +18548, +18517, +18518, +18551, +18550, +18519, +18576, +18609, +18608, +18577, +18578, +18611, +18610, +18579, +18580, +18613, +18612, +18581, +18582, +18615, +18614, +18583, +18640, +18673, +18672, +18641, +18642, +18675, +18674, +18643, +18644, +18677, +18676, +18645, +18646, +18679, +18678, +18647, +18704, +18737, +18736, +18705, +18706, +18739, +18738, +18707, +18708, +18741, +18740, +18709, +18710, +18743, +18742, +18711, +18768, +18801, +18800, +18769, +18770, +18803, +18802, +18771, +18772, +18805, +18804, +18773, +18774, +18807, +18806, +18775, +18832, +18865, +18864, +18833, +18834, +18867, +18866, +18835, +18836, +18869, +18868, +18837, +18838, +18871, +18870, +18839, +18896, +18929, +18928, +18897, +18898, +18931, +18930, +18899, +18900, +18933, +18932, +18901, +18902, +18935, +18934, +18903, +18960, +18993, +18992, +18961, +18962, +18995, +18994, +18963, +18964, +18997, +18996, +18965, +18966, +18999, +18998, +18967, +19024, +19057, +19056, +19025, +19026, +19059, +19058, +19027, +19028, +19061, +19060, +19029, +19030, +19063, +19062, +19031, +19088, +19121, +19120, +19089, +19090, +19123, +19122, +19091, +19092, +19125, +19124, +19093, +19094, +19127, +19126, +19095, +19152, +19185, +19184, +19153, +19154, +19187, +19186, +19155, +19156, +19189, +19188, +19157, +19158, +19191, +19190, +19159, +19216, +19249, +19248, +19217, +19218, +19251, +19250, +19219, +19220, +19253, +19252, +19221, +19222, +19255, +19254, +19223, +19280, +19313, +19312, +19281, +19282, +19315, +19314, +19283, +19284, +19317, +19316, +19285, +19286, +19319, +19318, +19287, +19344, +19377, +19376, +19345, +19346, +19379, +19378, +19347, +19348, +19381, +19380, +19349, +19350, +19383, +19382, +19351, +19408, +19441, +19440, +19409, +19410, +19443, +19442, +19411, +19412, +19445, +19444, +19413, +19414, +19447, +19446, +19415, +19472, +19505, +19504, +19473, +19474, +19507, +19506, +19475, +19476, +19509, +19508, +19477, +19478, +19511, +19510, +19479, +19536, +19569, +19568, +19537, +19538, +19571, +19570, +19539, +19540, +19573, +19572, +19541, +19542, +19575, +19574, +19543, +19600, +19633, +19632, +19601, +19602, +19635, +19634, +19603, +19604, +19637, +19636, +19605, +19606, +19639, +19638, +19607, +19664, +19697, +19696, +19665, +19666, +19699, +19698, +19667, +19668, +19701, +19700, +19669, +19670, +19703, +19702, +19671, +19728, +19761, +19760, +19729, +19730, +19763, +19762, +19731, +19732, +19765, +19764, +19733, +19734, +19767, +19766, +19735, +19792, +19825, +19824, +19793, +19794, +19827, +19826, +19795, +19796, +19829, +19828, +19797, +19798, +19831, +19830, +19799, +19856, +19889, +19888, +19857, +19858, +19891, +19890, +19859, +19860, +19893, +19892, +19861, +19862, +19895, +19894, +19863, +19920, +19953, +19952, +19921, +19922, +19955, +19954, +19923, +19924, +19957, +19956, +19925, +19926, +19959, +19958, +19927, +19984, +20017, +20016, +19985, +19986, +20019, +20018, +19987, +19988, +20021, +20020, +19989, +19990, +20023, +20022, +19991, +20048, +20081, +20080, +20049, +20050, +20083, +20082, +20051, +20052, +20085, +20084, +20053, +20054, +20087, +20086, +20055, +20112, +20145, +20144, +20113, +20114, +20147, +20146, +20115, +20116, +20149, +20148, +20117, +20118, +20151, +20150, +20119, +20176, +20209, +20208, +20177, +20178, +20211, +20210, +20179, +20180, +20213, +20212, +20181, +20182, +20215, +20214, +20183, +20240, +20273, +20272, +20241, +20242, +20275, +20274, +20243, +20244, +20277, +20276, +20245, +20246, +20279, +20278, +20247, +20304, +20337, +20336, +20305, +20306, +20339, +20338, +20307, +20308, +20341, +20340, +20309, +20310, +20343, +20342, +20311, +20368, +20401, +20400, +20369, +20370, +20403, +20402, +20371, +20372, +20405, +20404, +20373, +20374, +20407, +20406, +20375, +20432, +20465, +20464, +20433, +20434, +20467, +20466, +20435, +20436, +20469, +20468, +20437, +20438, +20471, +20470, +20439, +18456, +18489, +18488, +18457, +18458, +18491, +18490, +18459, +18460, +18493, +18492, +18461, +18462, +18495, +18494, +18463, +18520, +18553, +18552, +18521, +18522, +18555, +18554, +18523, +18524, +18557, +18556, +18525, +18526, +18559, +18558, +18527, +18584, +18617, +18616, +18585, +18586, +18619, +18618, +18587, +18588, +18621, +18620, +18589, +18590, +18623, +18622, +18591, +18648, +18681, +18680, +18649, +18650, +18683, +18682, +18651, +18652, +18685, +18684, +18653, +18654, +18687, +18686, +18655, +18712, +18745, +18744, +18713, +18714, +18747, +18746, +18715, +18716, +18749, +18748, +18717, +18718, +18751, +18750, +18719, +18776, +18809, +18808, +18777, +18778, +18811, +18810, +18779, +18780, +18813, +18812, +18781, +18782, +18815, +18814, +18783, +18840, +18873, +18872, +18841, +18842, +18875, +18874, +18843, +18844, +18877, +18876, +18845, +18846, +18879, +18878, +18847, +18904, +18937, +18936, +18905, +18906, +18939, +18938, +18907, +18908, +18941, +18940, +18909, +18910, +18943, +18942, +18911, +18968, +19001, +19000, +18969, +18970, +19003, +19002, +18971, +18972, +19005, +19004, +18973, +18974, +19007, +19006, +18975, +19032, +19065, +19064, +19033, +19034, +19067, +19066, +19035, +19036, +19069, +19068, +19037, +19038, +19071, +19070, +19039, +19096, +19129, +19128, +19097, +19098, +19131, +19130, +19099, +19100, +19133, +19132, +19101, +19102, +19135, +19134, +19103, +19160, +19193, +19192, +19161, +19162, +19195, +19194, +19163, +19164, +19197, +19196, +19165, +19166, +19199, +19198, +19167, +19224, +19257, +19256, +19225, +19226, +19259, +19258, +19227, +19228, +19261, +19260, +19229, +19230, +19263, +19262, +19231, +19288, +19321, +19320, +19289, +19290, +19323, +19322, +19291, +19292, +19325, +19324, +19293, +19294, +19327, +19326, +19295, +19352, +19385, +19384, +19353, +19354, +19387, +19386, +19355, +19356, +19389, +19388, +19357, +19358, +19391, +19390, +19359, +19416, +19449, +19448, +19417, +19418, +19451, +19450, +19419, +19420, +19453, +19452, +19421, +19422, +19455, +19454, +19423, +19480, +19513, +19512, +19481, +19482, +19515, +19514, +19483, +19484, +19517, +19516, +19485, +19486, +19519, +19518, +19487, +19544, +19577, +19576, +19545, +19546, +19579, +19578, +19547, +19548, +19581, +19580, +19549, +19550, +19583, +19582, +19551, +19608, +19641, +19640, +19609, +19610, +19643, +19642, +19611, +19612, +19645, +19644, +19613, +19614, +19647, +19646, +19615, +19672, +19705, +19704, +19673, +19674, +19707, +19706, +19675, +19676, +19709, +19708, +19677, +19678, +19711, +19710, +19679, +19736, +19769, +19768, +19737, +19738, +19771, +19770, +19739, +19740, +19773, +19772, +19741, +19742, +19775, +19774, +19743, +19800, +19833, +19832, +19801, +19802, +19835, +19834, +19803, +19804, +19837, +19836, +19805, +19806, +19839, +19838, +19807, +19864, +19897, +19896, +19865, +19866, +19899, +19898, +19867, +19868, +19901, +19900, +19869, +19870, +19903, +19902, +19871, +19928, +19961, +19960, +19929, +19930, +19963, +19962, +19931, +19932, +19965, +19964, +19933, +19934, +19967, +19966, +19935, +19992, +20025, +20024, +19993, +19994, +20027, +20026, +19995, +19996, +20029, +20028, +19997, +19998, +20031, +20030, +19999, +20056, +20089, +20088, +20057, +20058, +20091, +20090, +20059, +20060, +20093, +20092, +20061, +20062, +20095, +20094, +20063, +20120, +20153, +20152, +20121, +20122, +20155, +20154, +20123, +20124, +20157, +20156, +20125, +20126, +20159, +20158, +20127, +20184, +20217, +20216, +20185, +20186, +20219, +20218, +20187, +20188, +20221, +20220, +20189, +20190, +20223, +20222, +20191, +20248, +20281, +20280, +20249, +20250, +20283, +20282, +20251, +20252, +20285, +20284, +20253, +20254, +20287, +20286, +20255, +20312, +20345, +20344, +20313, +20314, +20347, +20346, +20315, +20316, +20349, +20348, +20317, +20318, +20351, +20350, +20319, +20376, +20409, +20408, +20377, +20378, +20411, +20410, +20379, +20380, +20413, +20412, +20381, +20382, +20415, +20414, +20383, +20440, +20473, +20472, +20441, +20442, +20475, +20474, +20443, +20444, +20477, +20476, +20445, +20446, +20479, +20478, +20447, +20480, +20513, +20512, +20481, +20482, +20515, +20514, +20483, +20484, +20517, +20516, +20485, +20486, +20519, +20518, +20487, +20544, +20577, +20576, +20545, +20546, +20579, +20578, +20547, +20548, +20581, +20580, +20549, +20550, +20583, +20582, +20551, +20608, +20641, +20640, +20609, +20610, +20643, +20642, +20611, +20612, +20645, +20644, +20613, +20614, +20647, +20646, +20615, +20672, +20705, +20704, +20673, +20674, +20707, +20706, +20675, +20676, +20709, +20708, +20677, +20678, +20711, +20710, +20679, +20736, +20769, +20768, +20737, +20738, +20771, +20770, +20739, +20740, +20773, +20772, +20741, +20742, +20775, +20774, +20743, +20800, +20833, +20832, +20801, +20802, +20835, +20834, +20803, +20804, +20837, +20836, +20805, +20806, +20839, +20838, +20807, +20864, +20897, +20896, +20865, +20866, +20899, +20898, +20867, +20868, +20901, +20900, +20869, +20870, +20903, +20902, +20871, +20928, +20961, +20960, +20929, +20930, +20963, +20962, +20931, +20932, +20965, +20964, +20933, +20934, +20967, +20966, +20935, +20992, +21025, +21024, +20993, +20994, +21027, +21026, +20995, +20996, +21029, +21028, +20997, +20998, +21031, +21030, +20999, +21056, +21089, +21088, +21057, +21058, +21091, +21090, +21059, +21060, +21093, +21092, +21061, +21062, +21095, +21094, +21063, +21120, +21153, +21152, +21121, +21122, +21155, +21154, +21123, +21124, +21157, +21156, +21125, +21126, +21159, +21158, +21127, +21184, +21217, +21216, +21185, +21186, +21219, +21218, +21187, +21188, +21221, +21220, +21189, +21190, +21223, +21222, +21191, +21248, +21281, +21280, +21249, +21250, +21283, +21282, +21251, +21252, +21285, +21284, +21253, +21254, +21287, +21286, +21255, +21312, +21345, +21344, +21313, +21314, +21347, +21346, +21315, +21316, +21349, +21348, +21317, +21318, +21351, +21350, +21319, +21376, +21409, +21408, +21377, +21378, +21411, +21410, +21379, +21380, +21413, +21412, +21381, +21382, +21415, +21414, +21383, +21440, +21473, +21472, +21441, +21442, +21475, +21474, +21443, +21444, +21477, +21476, +21445, +21446, +21479, +21478, +21447, +21504, +21537, +21536, +21505, +21506, +21539, +21538, +21507, +21508, +21541, +21540, +21509, +21510, +21543, +21542, +21511, +21568, +21601, +21600, +21569, +21570, +21603, +21602, +21571, +21572, +21605, +21604, +21573, +21574, +21607, +21606, +21575, +21632, +21665, +21664, +21633, +21634, +21667, +21666, +21635, +21636, +21669, +21668, +21637, +21638, +21671, +21670, +21639, +21696, +21729, +21728, +21697, +21698, +21731, +21730, +21699, +21700, +21733, +21732, +21701, +21702, +21735, +21734, +21703, +21760, +21793, +21792, +21761, +21762, +21795, +21794, +21763, +21764, +21797, +21796, +21765, +21766, +21799, +21798, +21767, +21824, +21857, +21856, +21825, +21826, +21859, +21858, +21827, +21828, +21861, +21860, +21829, +21830, +21863, +21862, +21831, +21888, +21921, +21920, +21889, +21890, +21923, +21922, +21891, +21892, +21925, +21924, +21893, +21894, +21927, +21926, +21895, +21952, +21985, +21984, +21953, +21954, +21987, +21986, +21955, +21956, +21989, +21988, +21957, +21958, +21991, +21990, +21959, +22016, +22049, +22048, +22017, +22018, +22051, +22050, +22019, +22020, +22053, +22052, +22021, +22022, +22055, +22054, +22023, +22080, +22113, +22112, +22081, +22082, +22115, +22114, +22083, +22084, +22117, +22116, +22085, +22086, +22119, +22118, +22087, +22144, +22177, +22176, +22145, +22146, +22179, +22178, +22147, +22148, +22181, +22180, +22149, +22150, +22183, +22182, +22151, +22208, +22241, +22240, +22209, +22210, +22243, +22242, +22211, +22212, +22245, +22244, +22213, +22214, +22247, +22246, +22215, +22272, +22305, +22304, +22273, +22274, +22307, +22306, +22275, +22276, +22309, +22308, +22277, +22278, +22311, +22310, +22279, +22336, +22369, +22368, +22337, +22338, +22371, +22370, +22339, +22340, +22373, +22372, +22341, +22342, +22375, +22374, +22343, +22400, +22433, +22432, +22401, +22402, +22435, +22434, +22403, +22404, +22437, +22436, +22405, +22406, +22439, +22438, +22407, +22464, +22497, +22496, +22465, +22466, +22499, +22498, +22467, +22468, +22501, +22500, +22469, +22470, +22503, +22502, +22471, +20488, +20521, +20520, +20489, +20490, +20523, +20522, +20491, +20492, +20525, +20524, +20493, +20494, +20527, +20526, +20495, +20552, +20585, +20584, +20553, +20554, +20587, +20586, +20555, +20556, +20589, +20588, +20557, +20558, +20591, +20590, +20559, +20616, +20649, +20648, +20617, +20618, +20651, +20650, +20619, +20620, +20653, +20652, +20621, +20622, +20655, +20654, +20623, +20680, +20713, +20712, +20681, +20682, +20715, +20714, +20683, +20684, +20717, +20716, +20685, +20686, +20719, +20718, +20687, +20744, +20777, +20776, +20745, +20746, +20779, +20778, +20747, +20748, +20781, +20780, +20749, +20750, +20783, +20782, +20751, +20808, +20841, +20840, +20809, +20810, +20843, +20842, +20811, +20812, +20845, +20844, +20813, +20814, +20847, +20846, +20815, +20872, +20905, +20904, +20873, +20874, +20907, +20906, +20875, +20876, +20909, +20908, +20877, +20878, +20911, +20910, +20879, +20936, +20969, +20968, +20937, +20938, +20971, +20970, +20939, +20940, +20973, +20972, +20941, +20942, +20975, +20974, +20943, +21000, +21033, +21032, +21001, +21002, +21035, +21034, +21003, +21004, +21037, +21036, +21005, +21006, +21039, +21038, +21007, +21064, +21097, +21096, +21065, +21066, +21099, +21098, +21067, +21068, +21101, +21100, +21069, +21070, +21103, +21102, +21071, +21128, +21161, +21160, +21129, +21130, +21163, +21162, +21131, +21132, +21165, +21164, +21133, +21134, +21167, +21166, +21135, +21192, +21225, +21224, +21193, +21194, +21227, +21226, +21195, +21196, +21229, +21228, +21197, +21198, +21231, +21230, +21199, +21256, +21289, +21288, +21257, +21258, +21291, +21290, +21259, +21260, +21293, +21292, +21261, +21262, +21295, +21294, +21263, +21320, +21353, +21352, +21321, +21322, +21355, +21354, +21323, +21324, +21357, +21356, +21325, +21326, +21359, +21358, +21327, +21384, +21417, +21416, +21385, +21386, +21419, +21418, +21387, +21388, +21421, +21420, +21389, +21390, +21423, +21422, +21391, +21448, +21481, +21480, +21449, +21450, +21483, +21482, +21451, +21452, +21485, +21484, +21453, +21454, +21487, +21486, +21455, +21512, +21545, +21544, +21513, +21514, +21547, +21546, +21515, +21516, +21549, +21548, +21517, +21518, +21551, +21550, +21519, +21576, +21609, +21608, +21577, +21578, +21611, +21610, +21579, +21580, +21613, +21612, +21581, +21582, +21615, +21614, +21583, +21640, +21673, +21672, +21641, +21642, +21675, +21674, +21643, +21644, +21677, +21676, +21645, +21646, +21679, +21678, +21647, +21704, +21737, +21736, +21705, +21706, +21739, +21738, +21707, +21708, +21741, +21740, +21709, +21710, +21743, +21742, +21711, +21768, +21801, +21800, +21769, +21770, +21803, +21802, +21771, +21772, +21805, +21804, +21773, +21774, +21807, +21806, +21775, +21832, +21865, +21864, +21833, +21834, +21867, +21866, +21835, +21836, +21869, +21868, +21837, +21838, +21871, +21870, +21839, +21896, +21929, +21928, +21897, +21898, +21931, +21930, +21899, +21900, +21933, +21932, +21901, +21902, +21935, +21934, +21903, +21960, +21993, +21992, +21961, +21962, +21995, +21994, +21963, +21964, +21997, +21996, +21965, +21966, +21999, +21998, +21967, +22024, +22057, +22056, +22025, +22026, +22059, +22058, +22027, +22028, +22061, +22060, +22029, +22030, +22063, +22062, +22031, +22088, +22121, +22120, +22089, +22090, +22123, +22122, +22091, +22092, +22125, +22124, +22093, +22094, +22127, +22126, +22095, +22152, +22185, +22184, +22153, +22154, +22187, +22186, +22155, +22156, +22189, +22188, +22157, +22158, +22191, +22190, +22159, +22216, +22249, +22248, +22217, +22218, +22251, +22250, +22219, +22220, +22253, +22252, +22221, +22222, +22255, +22254, +22223, +22280, +22313, +22312, +22281, +22282, +22315, +22314, +22283, +22284, +22317, +22316, +22285, +22286, +22319, +22318, +22287, +22344, +22377, +22376, +22345, +22346, +22379, +22378, +22347, +22348, +22381, +22380, +22349, +22350, +22383, +22382, +22351, +22408, +22441, +22440, +22409, +22410, +22443, +22442, +22411, +22412, +22445, +22444, +22413, +22414, +22447, +22446, +22415, +22472, +22505, +22504, +22473, +22474, +22507, +22506, +22475, +22476, +22509, +22508, +22477, +22478, +22511, +22510, +22479, +20496, +20529, +20528, +20497, +20498, +20531, +20530, +20499, +20500, +20533, +20532, +20501, +20502, +20535, +20534, +20503, +20560, +20593, +20592, +20561, +20562, +20595, +20594, +20563, +20564, +20597, +20596, +20565, +20566, +20599, +20598, +20567, +20624, +20657, +20656, +20625, +20626, +20659, +20658, +20627, +20628, +20661, +20660, +20629, +20630, +20663, +20662, +20631, +20688, +20721, +20720, +20689, +20690, +20723, +20722, +20691, +20692, +20725, +20724, +20693, +20694, +20727, +20726, +20695, +20752, +20785, +20784, +20753, +20754, +20787, +20786, +20755, +20756, +20789, +20788, +20757, +20758, +20791, +20790, +20759, +20816, +20849, +20848, +20817, +20818, +20851, +20850, +20819, +20820, +20853, +20852, +20821, +20822, +20855, +20854, +20823, +20880, +20913, +20912, +20881, +20882, +20915, +20914, +20883, +20884, +20917, +20916, +20885, +20886, +20919, +20918, +20887, +20944, +20977, +20976, +20945, +20946, +20979, +20978, +20947, +20948, +20981, +20980, +20949, +20950, +20983, +20982, +20951, +21008, +21041, +21040, +21009, +21010, +21043, +21042, +21011, +21012, +21045, +21044, +21013, +21014, +21047, +21046, +21015, +21072, +21105, +21104, +21073, +21074, +21107, +21106, +21075, +21076, +21109, +21108, +21077, +21078, +21111, +21110, +21079, +21136, +21169, +21168, +21137, +21138, +21171, +21170, +21139, +21140, +21173, +21172, +21141, +21142, +21175, +21174, +21143, +21200, +21233, +21232, +21201, +21202, +21235, +21234, +21203, +21204, +21237, +21236, +21205, +21206, +21239, +21238, +21207, +21264, +21297, +21296, +21265, +21266, +21299, +21298, +21267, +21268, +21301, +21300, +21269, +21270, +21303, +21302, +21271, +21328, +21361, +21360, +21329, +21330, +21363, +21362, +21331, +21332, +21365, +21364, +21333, +21334, +21367, +21366, +21335, +21392, +21425, +21424, +21393, +21394, +21427, +21426, +21395, +21396, +21429, +21428, +21397, +21398, +21431, +21430, +21399, +21456, +21489, +21488, +21457, +21458, +21491, +21490, +21459, +21460, +21493, +21492, +21461, +21462, +21495, +21494, +21463, +21520, +21553, +21552, +21521, +21522, +21555, +21554, +21523, +21524, +21557, +21556, +21525, +21526, +21559, +21558, +21527, +21584, +21617, +21616, +21585, +21586, +21619, +21618, +21587, +21588, +21621, +21620, +21589, +21590, +21623, +21622, +21591, +21648, +21681, +21680, +21649, +21650, +21683, +21682, +21651, +21652, +21685, +21684, +21653, +21654, +21687, +21686, +21655, +21712, +21745, +21744, +21713, +21714, +21747, +21746, +21715, +21716, +21749, +21748, +21717, +21718, +21751, +21750, +21719, +21776, +21809, +21808, +21777, +21778, +21811, +21810, +21779, +21780, +21813, +21812, +21781, +21782, +21815, +21814, +21783, +21840, +21873, +21872, +21841, +21842, +21875, +21874, +21843, +21844, +21877, +21876, +21845, +21846, +21879, +21878, +21847, +21904, +21937, +21936, +21905, +21906, +21939, +21938, +21907, +21908, +21941, +21940, +21909, +21910, +21943, +21942, +21911, +21968, +22001, +22000, +21969, +21970, +22003, +22002, +21971, +21972, +22005, +22004, +21973, +21974, +22007, +22006, +21975, +22032, +22065, +22064, +22033, +22034, +22067, +22066, +22035, +22036, +22069, +22068, +22037, +22038, +22071, +22070, +22039, +22096, +22129, +22128, +22097, +22098, +22131, +22130, +22099, +22100, +22133, +22132, +22101, +22102, +22135, +22134, +22103, +22160, +22193, +22192, +22161, +22162, +22195, +22194, +22163, +22164, +22197, +22196, +22165, +22166, +22199, +22198, +22167, +22224, +22257, +22256, +22225, +22226, +22259, +22258, +22227, +22228, +22261, +22260, +22229, +22230, +22263, +22262, +22231, +22288, +22321, +22320, +22289, +22290, +22323, +22322, +22291, +22292, +22325, +22324, +22293, +22294, +22327, +22326, +22295, +22352, +22385, +22384, +22353, +22354, +22387, +22386, +22355, +22356, +22389, +22388, +22357, +22358, +22391, +22390, +22359, +22416, +22449, +22448, +22417, +22418, +22451, +22450, +22419, +22420, +22453, +22452, +22421, +22422, +22455, +22454, +22423, +22480, +22513, +22512, +22481, +22482, +22515, +22514, +22483, +22484, +22517, +22516, +22485, +22486, +22519, +22518, +22487, +20504, +20537, +20536, +20505, +20506, +20539, +20538, +20507, +20508, +20541, +20540, +20509, +20510, +20543, +20542, +20511, +20568, +20601, +20600, +20569, +20570, +20603, +20602, +20571, +20572, +20605, +20604, +20573, +20574, +20607, +20606, +20575, +20632, +20665, +20664, +20633, +20634, +20667, +20666, +20635, +20636, +20669, +20668, +20637, +20638, +20671, +20670, +20639, +20696, +20729, +20728, +20697, +20698, +20731, +20730, +20699, +20700, +20733, +20732, +20701, +20702, +20735, +20734, +20703, +20760, +20793, +20792, +20761, +20762, +20795, +20794, +20763, +20764, +20797, +20796, +20765, +20766, +20799, +20798, +20767, +20824, +20857, +20856, +20825, +20826, +20859, +20858, +20827, +20828, +20861, +20860, +20829, +20830, +20863, +20862, +20831, +20888, +20921, +20920, +20889, +20890, +20923, +20922, +20891, +20892, +20925, +20924, +20893, +20894, +20927, +20926, +20895, +20952, +20985, +20984, +20953, +20954, +20987, +20986, +20955, +20956, +20989, +20988, +20957, +20958, +20991, +20990, +20959, +21016, +21049, +21048, +21017, +21018, +21051, +21050, +21019, +21020, +21053, +21052, +21021, +21022, +21055, +21054, +21023, +21080, +21113, +21112, +21081, +21082, +21115, +21114, +21083, +21084, +21117, +21116, +21085, +21086, +21119, +21118, +21087, +21144, +21177, +21176, +21145, +21146, +21179, +21178, +21147, +21148, +21181, +21180, +21149, +21150, +21183, +21182, +21151, +21208, +21241, +21240, +21209, +21210, +21243, +21242, +21211, +21212, +21245, +21244, +21213, +21214, +21247, +21246, +21215, +21272, +21305, +21304, +21273, +21274, +21307, +21306, +21275, +21276, +21309, +21308, +21277, +21278, +21311, +21310, +21279, +21336, +21369, +21368, +21337, +21338, +21371, +21370, +21339, +21340, +21373, +21372, +21341, +21342, +21375, +21374, +21343, +21400, +21433, +21432, +21401, +21402, +21435, +21434, +21403, +21404, +21437, +21436, +21405, +21406, +21439, +21438, +21407, +21464, +21497, +21496, +21465, +21466, +21499, +21498, +21467, +21468, +21501, +21500, +21469, +21470, +21503, +21502, +21471, +21528, +21561, +21560, +21529, +21530, +21563, +21562, +21531, +21532, +21565, +21564, +21533, +21534, +21567, +21566, +21535, +21592, +21625, +21624, +21593, +21594, +21627, +21626, +21595, +21596, +21629, +21628, +21597, +21598, +21631, +21630, +21599, +21656, +21689, +21688, +21657, +21658, +21691, +21690, +21659, +21660, +21693, +21692, +21661, +21662, +21695, +21694, +21663, +21720, +21753, +21752, +21721, +21722, +21755, +21754, +21723, +21724, +21757, +21756, +21725, +21726, +21759, +21758, +21727, +21784, +21817, +21816, +21785, +21786, +21819, +21818, +21787, +21788, +21821, +21820, +21789, +21790, +21823, +21822, +21791, +21848, +21881, +21880, +21849, +21850, +21883, +21882, +21851, +21852, +21885, +21884, +21853, +21854, +21887, +21886, +21855, +21912, +21945, +21944, +21913, +21914, +21947, +21946, +21915, +21916, +21949, +21948, +21917, +21918, +21951, +21950, +21919, +21976, +22009, +22008, +21977, +21978, +22011, +22010, +21979, +21980, +22013, +22012, +21981, +21982, +22015, +22014, +21983, +22040, +22073, +22072, +22041, +22042, +22075, +22074, +22043, +22044, +22077, +22076, +22045, +22046, +22079, +22078, +22047, +22104, +22137, +22136, +22105, +22106, +22139, +22138, +22107, +22108, +22141, +22140, +22109, +22110, +22143, +22142, +22111, +22168, +22201, +22200, +22169, +22170, +22203, +22202, +22171, +22172, +22205, +22204, +22173, +22174, +22207, +22206, +22175, +22232, +22265, +22264, +22233, +22234, +22267, +22266, +22235, +22236, +22269, +22268, +22237, +22238, +22271, +22270, +22239, +22296, +22329, +22328, +22297, +22298, +22331, +22330, +22299, +22300, +22333, +22332, +22301, +22302, +22335, +22334, +22303, +22360, +22393, +22392, +22361, +22362, +22395, +22394, +22363, +22364, +22397, +22396, +22365, +22366, +22399, +22398, +22367, +22424, +22457, +22456, +22425, +22426, +22459, +22458, +22427, +22428, +22461, +22460, +22429, +22430, +22463, +22462, +22431, +22488, +22521, +22520, +22489, +22490, +22523, +22522, +22491, +22492, +22525, +22524, +22493, +22494, +22527, +22526, +22495, +22528, +22561, +22560, +22529, +22530, +22563, +22562, +22531, +22532, +22565, +22564, +22533, +22534, +22567, +22566, +22535, +22592, +22625, +22624, +22593, +22594, +22627, +22626, +22595, +22596, +22629, +22628, +22597, +22598, +22631, +22630, +22599, +22656, +22689, +22688, +22657, +22658, +22691, +22690, +22659, +22660, +22693, +22692, +22661, +22662, +22695, +22694, +22663, +22720, +22753, +22752, +22721, +22722, +22755, +22754, +22723, +22724, +22757, +22756, +22725, +22726, +22759, +22758, +22727, +22784, +22817, +22816, +22785, +22786, +22819, +22818, +22787, +22788, +22821, +22820, +22789, +22790, +22823, +22822, +22791, +22848, +22881, +22880, +22849, +22850, +22883, +22882, +22851, +22852, +22885, +22884, +22853, +22854, +22887, +22886, +22855, +22912, +22945, +22944, +22913, +22914, +22947, +22946, +22915, +22916, +22949, +22948, +22917, +22918, +22951, +22950, +22919, +22976, +23009, +23008, +22977, +22978, +23011, +23010, +22979, +22980, +23013, +23012, +22981, +22982, +23015, +23014, +22983, +23040, +23073, +23072, +23041, +23042, +23075, +23074, +23043, +23044, +23077, +23076, +23045, +23046, +23079, +23078, +23047, +23104, +23137, +23136, +23105, +23106, +23139, +23138, +23107, +23108, +23141, +23140, +23109, +23110, +23143, +23142, +23111, +23168, +23201, +23200, +23169, +23170, +23203, +23202, +23171, +23172, +23205, +23204, +23173, +23174, +23207, +23206, +23175, +23232, +23265, +23264, +23233, +23234, +23267, +23266, +23235, +23236, +23269, +23268, +23237, +23238, +23271, +23270, +23239, +23296, +23329, +23328, +23297, +23298, +23331, +23330, +23299, +23300, +23333, +23332, +23301, +23302, +23335, +23334, +23303, +23360, +23393, +23392, +23361, +23362, +23395, +23394, +23363, +23364, +23397, +23396, +23365, +23366, +23399, +23398, +23367, +23424, +23457, +23456, +23425, +23426, +23459, +23458, +23427, +23428, +23461, +23460, +23429, +23430, +23463, +23462, +23431, +23488, +23521, +23520, +23489, +23490, +23523, +23522, +23491, +23492, +23525, +23524, +23493, +23494, +23527, +23526, +23495, +23552, +23585, +23584, +23553, +23554, +23587, +23586, +23555, +23556, +23589, +23588, +23557, +23558, +23591, +23590, +23559, +23616, +23649, +23648, +23617, +23618, +23651, +23650, +23619, +23620, +23653, +23652, +23621, +23622, +23655, +23654, +23623, +23680, +23713, +23712, +23681, +23682, +23715, +23714, +23683, +23684, +23717, +23716, +23685, +23686, +23719, +23718, +23687, +23744, +23777, +23776, +23745, +23746, +23779, +23778, +23747, +23748, +23781, +23780, +23749, +23750, +23783, +23782, +23751, +23808, +23841, +23840, +23809, +23810, +23843, +23842, +23811, +23812, +23845, +23844, +23813, +23814, +23847, +23846, +23815, +23872, +23905, +23904, +23873, +23874, +23907, +23906, +23875, +23876, +23909, +23908, +23877, +23878, +23911, +23910, +23879, +23936, +23969, +23968, +23937, +23938, +23971, +23970, +23939, +23940, +23973, +23972, +23941, +23942, +23975, +23974, +23943, +24000, +24033, +24032, +24001, +24002, +24035, +24034, +24003, +24004, +24037, +24036, +24005, +24006, +24039, +24038, +24007, +24064, +24097, +24096, +24065, +24066, +24099, +24098, +24067, +24068, +24101, +24100, +24069, +24070, +24103, +24102, +24071, +24128, +24161, +24160, +24129, +24130, +24163, +24162, +24131, +24132, +24165, +24164, +24133, +24134, +24167, +24166, +24135, +24192, +24225, +24224, +24193, +24194, +24227, +24226, +24195, +24196, +24229, +24228, +24197, +24198, +24231, +24230, +24199, +24256, +24289, +24288, +24257, +24258, +24291, +24290, +24259, +24260, +24293, +24292, +24261, +24262, +24295, +24294, +24263, +24320, +24353, +24352, +24321, +24322, +24355, +24354, +24323, +24324, +24357, +24356, +24325, +24326, +24359, +24358, +24327, +24384, +24417, +24416, +24385, +24386, +24419, +24418, +24387, +24388, +24421, +24420, +24389, +24390, +24423, +24422, +24391, +24448, +24481, +24480, +24449, +24450, +24483, +24482, +24451, +24452, +24485, +24484, +24453, +24454, +24487, +24486, +24455, +24512, +24545, +24544, +24513, +24514, +24547, +24546, +24515, +24516, +24549, +24548, +24517, +24518, +24551, +24550, +24519, +22536, +22569, +22568, +22537, +22538, +22571, +22570, +22539, +22540, +22573, +22572, +22541, +22542, +22575, +22574, +22543, +22600, +22633, +22632, +22601, +22602, +22635, +22634, +22603, +22604, +22637, +22636, +22605, +22606, +22639, +22638, +22607, +22664, +22697, +22696, +22665, +22666, +22699, +22698, +22667, +22668, +22701, +22700, +22669, +22670, +22703, +22702, +22671, +22728, +22761, +22760, +22729, +22730, +22763, +22762, +22731, +22732, +22765, +22764, +22733, +22734, +22767, +22766, +22735, +22792, +22825, +22824, +22793, +22794, +22827, +22826, +22795, +22796, +22829, +22828, +22797, +22798, +22831, +22830, +22799, +22856, +22889, +22888, +22857, +22858, +22891, +22890, +22859, +22860, +22893, +22892, +22861, +22862, +22895, +22894, +22863, +22920, +22953, +22952, +22921, +22922, +22955, +22954, +22923, +22924, +22957, +22956, +22925, +22926, +22959, +22958, +22927, +22984, +23017, +23016, +22985, +22986, +23019, +23018, +22987, +22988, +23021, +23020, +22989, +22990, +23023, +23022, +22991, +23048, +23081, +23080, +23049, +23050, +23083, +23082, +23051, +23052, +23085, +23084, +23053, +23054, +23087, +23086, +23055, +23112, +23145, +23144, +23113, +23114, +23147, +23146, +23115, +23116, +23149, +23148, +23117, +23118, +23151, +23150, +23119, +23176, +23209, +23208, +23177, +23178, +23211, +23210, +23179, +23180, +23213, +23212, +23181, +23182, +23215, +23214, +23183, +23240, +23273, +23272, +23241, +23242, +23275, +23274, +23243, +23244, +23277, +23276, +23245, +23246, +23279, +23278, +23247, +23304, +23337, +23336, +23305, +23306, +23339, +23338, +23307, +23308, +23341, +23340, +23309, +23310, +23343, +23342, +23311, +23368, +23401, +23400, +23369, +23370, +23403, +23402, +23371, +23372, +23405, +23404, +23373, +23374, +23407, +23406, +23375, +23432, +23465, +23464, +23433, +23434, +23467, +23466, +23435, +23436, +23469, +23468, +23437, +23438, +23471, +23470, +23439, +23496, +23529, +23528, +23497, +23498, +23531, +23530, +23499, +23500, +23533, +23532, +23501, +23502, +23535, +23534, +23503, +23560, +23593, +23592, +23561, +23562, +23595, +23594, +23563, +23564, +23597, +23596, +23565, +23566, +23599, +23598, +23567, +23624, +23657, +23656, +23625, +23626, +23659, +23658, +23627, +23628, +23661, +23660, +23629, +23630, +23663, +23662, +23631, +23688, +23721, +23720, +23689, +23690, +23723, +23722, +23691, +23692, +23725, +23724, +23693, +23694, +23727, +23726, +23695, +23752, +23785, +23784, +23753, +23754, +23787, +23786, +23755, +23756, +23789, +23788, +23757, +23758, +23791, +23790, +23759, +23816, +23849, +23848, +23817, +23818, +23851, +23850, +23819, +23820, +23853, +23852, +23821, +23822, +23855, +23854, +23823, +23880, +23913, +23912, +23881, +23882, +23915, +23914, +23883, +23884, +23917, +23916, +23885, +23886, +23919, +23918, +23887, +23944, +23977, +23976, +23945, +23946, +23979, +23978, +23947, +23948, +23981, +23980, +23949, +23950, +23983, +23982, +23951, +24008, +24041, +24040, +24009, +24010, +24043, +24042, +24011, +24012, +24045, +24044, +24013, +24014, +24047, +24046, +24015, +24072, +24105, +24104, +24073, +24074, +24107, +24106, +24075, +24076, +24109, +24108, +24077, +24078, +24111, +24110, +24079, +24136, +24169, +24168, +24137, +24138, +24171, +24170, +24139, +24140, +24173, +24172, +24141, +24142, +24175, +24174, +24143, +24200, +24233, +24232, +24201, +24202, +24235, +24234, +24203, +24204, +24237, +24236, +24205, +24206, +24239, +24238, +24207, +24264, +24297, +24296, +24265, +24266, +24299, +24298, +24267, +24268, +24301, +24300, +24269, +24270, +24303, +24302, +24271, +24328, +24361, +24360, +24329, +24330, +24363, +24362, +24331, +24332, +24365, +24364, +24333, +24334, +24367, +24366, +24335, +24392, +24425, +24424, +24393, +24394, +24427, +24426, +24395, +24396, +24429, +24428, +24397, +24398, +24431, +24430, +24399, +24456, +24489, +24488, +24457, +24458, +24491, +24490, +24459, +24460, +24493, +24492, +24461, +24462, +24495, +24494, +24463, +24520, +24553, +24552, +24521, +24522, +24555, +24554, +24523, +24524, +24557, +24556, +24525, +24526, +24559, +24558, +24527, +22544, +22577, +22576, +22545, +22546, +22579, +22578, +22547, +22548, +22581, +22580, +22549, +22550, +22583, +22582, +22551, +22608, +22641, +22640, +22609, +22610, +22643, +22642, +22611, +22612, +22645, +22644, +22613, +22614, +22647, +22646, +22615, +22672, +22705, +22704, +22673, +22674, +22707, +22706, +22675, +22676, +22709, +22708, +22677, +22678, +22711, +22710, +22679, +22736, +22769, +22768, +22737, +22738, +22771, +22770, +22739, +22740, +22773, +22772, +22741, +22742, +22775, +22774, +22743, +22800, +22833, +22832, +22801, +22802, +22835, +22834, +22803, +22804, +22837, +22836, +22805, +22806, +22839, +22838, +22807, +22864, +22897, +22896, +22865, +22866, +22899, +22898, +22867, +22868, +22901, +22900, +22869, +22870, +22903, +22902, +22871, +22928, +22961, +22960, +22929, +22930, +22963, +22962, +22931, +22932, +22965, +22964, +22933, +22934, +22967, +22966, +22935, +22992, +23025, +23024, +22993, +22994, +23027, +23026, +22995, +22996, +23029, +23028, +22997, +22998, +23031, +23030, +22999, +23056, +23089, +23088, +23057, +23058, +23091, +23090, +23059, +23060, +23093, +23092, +23061, +23062, +23095, +23094, +23063, +23120, +23153, +23152, +23121, +23122, +23155, +23154, +23123, +23124, +23157, +23156, +23125, +23126, +23159, +23158, +23127, +23184, +23217, +23216, +23185, +23186, +23219, +23218, +23187, +23188, +23221, +23220, +23189, +23190, +23223, +23222, +23191, +23248, +23281, +23280, +23249, +23250, +23283, +23282, +23251, +23252, +23285, +23284, +23253, +23254, +23287, +23286, +23255, +23312, +23345, +23344, +23313, +23314, +23347, +23346, +23315, +23316, +23349, +23348, +23317, +23318, +23351, +23350, +23319, +23376, +23409, +23408, +23377, +23378, +23411, +23410, +23379, +23380, +23413, +23412, +23381, +23382, +23415, +23414, +23383, +23440, +23473, +23472, +23441, +23442, +23475, +23474, +23443, +23444, +23477, +23476, +23445, +23446, +23479, +23478, +23447, +23504, +23537, +23536, +23505, +23506, +23539, +23538, +23507, +23508, +23541, +23540, +23509, +23510, +23543, +23542, +23511, +23568, +23601, +23600, +23569, +23570, +23603, +23602, +23571, +23572, +23605, +23604, +23573, +23574, +23607, +23606, +23575, +23632, +23665, +23664, +23633, +23634, +23667, +23666, +23635, +23636, +23669, +23668, +23637, +23638, +23671, +23670, +23639, +23696, +23729, +23728, +23697, +23698, +23731, +23730, +23699, +23700, +23733, +23732, +23701, +23702, +23735, +23734, +23703, +23760, +23793, +23792, +23761, +23762, +23795, +23794, +23763, +23764, +23797, +23796, +23765, +23766, +23799, +23798, +23767, +23824, +23857, +23856, +23825, +23826, +23859, +23858, +23827, +23828, +23861, +23860, +23829, +23830, +23863, +23862, +23831, +23888, +23921, +23920, +23889, +23890, +23923, +23922, +23891, +23892, +23925, +23924, +23893, +23894, +23927, +23926, +23895, +23952, +23985, +23984, +23953, +23954, +23987, +23986, +23955, +23956, +23989, +23988, +23957, +23958, +23991, +23990, +23959, +24016, +24049, +24048, +24017, +24018, +24051, +24050, +24019, +24020, +24053, +24052, +24021, +24022, +24055, +24054, +24023, +24080, +24113, +24112, +24081, +24082, +24115, +24114, +24083, +24084, +24117, +24116, +24085, +24086, +24119, +24118, +24087, +24144, +24177, +24176, +24145, +24146, +24179, +24178, +24147, +24148, +24181, +24180, +24149, +24150, +24183, +24182, +24151, +24208, +24241, +24240, +24209, +24210, +24243, +24242, +24211, +24212, +24245, +24244, +24213, +24214, +24247, +24246, +24215, +24272, +24305, +24304, +24273, +24274, +24307, +24306, +24275, +24276, +24309, +24308, +24277, +24278, +24311, +24310, +24279, +24336, +24369, +24368, +24337, +24338, +24371, +24370, +24339, +24340, +24373, +24372, +24341, +24342, +24375, +24374, +24343, +24400, +24433, +24432, +24401, +24402, +24435, +24434, +24403, +24404, +24437, +24436, +24405, +24406, +24439, +24438, +24407, +24464, +24497, +24496, +24465, +24466, +24499, +24498, +24467, +24468, +24501, +24500, +24469, +24470, +24503, +24502, +24471, +24528, +24561, +24560, +24529, +24530, +24563, +24562, +24531, +24532, +24565, +24564, +24533, +24534, +24567, +24566, +24535, +22552, +22585, +22584, +22553, +22554, +22587, +22586, +22555, +22556, +22589, +22588, +22557, +22558, +22591, +22590, +22559, +22616, +22649, +22648, +22617, +22618, +22651, +22650, +22619, +22620, +22653, +22652, +22621, +22622, +22655, +22654, +22623, +22680, +22713, +22712, +22681, +22682, +22715, +22714, +22683, +22684, +22717, +22716, +22685, +22686, +22719, +22718, +22687, +22744, +22777, +22776, +22745, +22746, +22779, +22778, +22747, +22748, +22781, +22780, +22749, +22750, +22783, +22782, +22751, +22808, +22841, +22840, +22809, +22810, +22843, +22842, +22811, +22812, +22845, +22844, +22813, +22814, +22847, +22846, +22815, +22872, +22905, +22904, +22873, +22874, +22907, +22906, +22875, +22876, +22909, +22908, +22877, +22878, +22911, +22910, +22879, +22936, +22969, +22968, +22937, +22938, +22971, +22970, +22939, +22940, +22973, +22972, +22941, +22942, +22975, +22974, +22943, +23000, +23033, +23032, +23001, +23002, +23035, +23034, +23003, +23004, +23037, +23036, +23005, +23006, +23039, +23038, +23007, +23064, +23097, +23096, +23065, +23066, +23099, +23098, +23067, +23068, +23101, +23100, +23069, +23070, +23103, +23102, +23071, +23128, +23161, +23160, +23129, +23130, +23163, +23162, +23131, +23132, +23165, +23164, +23133, +23134, +23167, +23166, +23135, +23192, +23225, +23224, +23193, +23194, +23227, +23226, +23195, +23196, +23229, +23228, +23197, +23198, +23231, +23230, +23199, +23256, +23289, +23288, +23257, +23258, +23291, +23290, +23259, +23260, +23293, +23292, +23261, +23262, +23295, +23294, +23263, +23320, +23353, +23352, +23321, +23322, +23355, +23354, +23323, +23324, +23357, +23356, +23325, +23326, +23359, +23358, +23327, +23384, +23417, +23416, +23385, +23386, +23419, +23418, +23387, +23388, +23421, +23420, +23389, +23390, +23423, +23422, +23391, +23448, +23481, +23480, +23449, +23450, +23483, +23482, +23451, +23452, +23485, +23484, +23453, +23454, +23487, +23486, +23455, +23512, +23545, +23544, +23513, +23514, +23547, +23546, +23515, +23516, +23549, +23548, +23517, +23518, +23551, +23550, +23519, +23576, +23609, +23608, +23577, +23578, +23611, +23610, +23579, +23580, +23613, +23612, +23581, +23582, +23615, +23614, +23583, +23640, +23673, +23672, +23641, +23642, +23675, +23674, +23643, +23644, +23677, +23676, +23645, +23646, +23679, +23678, +23647, +23704, +23737, +23736, +23705, +23706, +23739, +23738, +23707, +23708, +23741, +23740, +23709, +23710, +23743, +23742, +23711, +23768, +23801, +23800, +23769, +23770, +23803, +23802, +23771, +23772, +23805, +23804, +23773, +23774, +23807, +23806, +23775, +23832, +23865, +23864, +23833, +23834, +23867, +23866, +23835, +23836, +23869, +23868, +23837, +23838, +23871, +23870, +23839, +23896, +23929, +23928, +23897, +23898, +23931, +23930, +23899, +23900, +23933, +23932, +23901, +23902, +23935, +23934, +23903, +23960, +23993, +23992, +23961, +23962, +23995, +23994, +23963, +23964, +23997, +23996, +23965, +23966, +23999, +23998, +23967, +24024, +24057, +24056, +24025, +24026, +24059, +24058, +24027, +24028, +24061, +24060, +24029, +24030, +24063, +24062, +24031, +24088, +24121, +24120, +24089, +24090, +24123, +24122, +24091, +24092, +24125, +24124, +24093, +24094, +24127, +24126, +24095, +24152, +24185, +24184, +24153, +24154, +24187, +24186, +24155, +24156, +24189, +24188, +24157, +24158, +24191, +24190, +24159, +24216, +24249, +24248, +24217, +24218, +24251, +24250, +24219, +24220, +24253, +24252, +24221, +24222, +24255, +24254, +24223, +24280, +24313, +24312, +24281, +24282, +24315, +24314, +24283, +24284, +24317, +24316, +24285, +24286, +24319, +24318, +24287, +24344, +24377, +24376, +24345, +24346, +24379, +24378, +24347, +24348, +24381, +24380, +24349, +24350, +24383, +24382, +24351, +24408, +24441, +24440, +24409, +24410, +24443, +24442, +24411, +24412, +24445, +24444, +24413, +24414, +24447, +24446, +24415, +24472, +24505, +24504, +24473, +24474, +24507, +24506, +24475, +24476, +24509, +24508, +24477, +24478, +24511, +24510, +24479, +24536, +24569, +24568, +24537, +24538, +24571, +24570, +24539, +24540, +24573, +24572, +24541, +24542, +24575, +24574, +24543, +24576, +24609, +24608, +24577, +24578, +24611, +24610, +24579, +24580, +24613, +24612, +24581, +24582, +24615, +24614, +24583, +24640, +24673, +24672, +24641, +24642, +24675, +24674, +24643, +24644, +24677, +24676, +24645, +24646, +24679, +24678, +24647, +24704, +24737, +24736, +24705, +24706, +24739, +24738, +24707, +24708, +24741, +24740, +24709, +24710, +24743, +24742, +24711, +24768, +24801, +24800, +24769, +24770, +24803, +24802, +24771, +24772, +24805, +24804, +24773, +24774, +24807, +24806, +24775, +24832, +24865, +24864, +24833, +24834, +24867, +24866, +24835, +24836, +24869, +24868, +24837, +24838, +24871, +24870, +24839, +24896, +24929, +24928, +24897, +24898, +24931, +24930, +24899, +24900, +24933, +24932, +24901, +24902, +24935, +24934, +24903, +24960, +24993, +24992, +24961, +24962, +24995, +24994, +24963, +24964, +24997, +24996, +24965, +24966, +24999, +24998, +24967, +25024, +25057, +25056, +25025, +25026, +25059, +25058, +25027, +25028, +25061, +25060, +25029, +25030, +25063, +25062, +25031, +25088, +25121, +25120, +25089, +25090, +25123, +25122, +25091, +25092, +25125, +25124, +25093, +25094, +25127, +25126, +25095, +25152, +25185, +25184, +25153, +25154, +25187, +25186, +25155, +25156, +25189, +25188, +25157, +25158, +25191, +25190, +25159, +25216, +25249, +25248, +25217, +25218, +25251, +25250, +25219, +25220, +25253, +25252, +25221, +25222, +25255, +25254, +25223, +25280, +25313, +25312, +25281, +25282, +25315, +25314, +25283, +25284, +25317, +25316, +25285, +25286, +25319, +25318, +25287, +25344, +25377, +25376, +25345, +25346, +25379, +25378, +25347, +25348, +25381, +25380, +25349, +25350, +25383, +25382, +25351, +25408, +25441, +25440, +25409, +25410, +25443, +25442, +25411, +25412, +25445, +25444, +25413, +25414, +25447, +25446, +25415, +25472, +25505, +25504, +25473, +25474, +25507, +25506, +25475, +25476, +25509, +25508, +25477, +25478, +25511, +25510, +25479, +25536, +25569, +25568, +25537, +25538, +25571, +25570, +25539, +25540, +25573, +25572, +25541, +25542, +25575, +25574, +25543, +25600, +25633, +25632, +25601, +25602, +25635, +25634, +25603, +25604, +25637, +25636, +25605, +25606, +25639, +25638, +25607, +25664, +25697, +25696, +25665, +25666, +25699, +25698, +25667, +25668, +25701, +25700, +25669, +25670, +25703, +25702, +25671, +25728, +25761, +25760, +25729, +25730, +25763, +25762, +25731, +25732, +25765, +25764, +25733, +25734, +25767, +25766, +25735, +25792, +25825, +25824, +25793, +25794, +25827, +25826, +25795, +25796, +25829, +25828, +25797, +25798, +25831, +25830, +25799, +25856, +25889, +25888, +25857, +25858, +25891, +25890, +25859, +25860, +25893, +25892, +25861, +25862, +25895, +25894, +25863, +25920, +25953, +25952, +25921, +25922, +25955, +25954, +25923, +25924, +25957, +25956, +25925, +25926, +25959, +25958, +25927, +25984, +26017, +26016, +25985, +25986, +26019, +26018, +25987, +25988, +26021, +26020, +25989, +25990, +26023, +26022, +25991, +26048, +26081, +26080, +26049, +26050, +26083, +26082, +26051, +26052, +26085, +26084, +26053, +26054, +26087, +26086, +26055, +26112, +26145, +26144, +26113, +26114, +26147, +26146, +26115, +26116, +26149, +26148, +26117, +26118, +26151, +26150, +26119, +26176, +26209, +26208, +26177, +26178, +26211, +26210, +26179, +26180, +26213, +26212, +26181, +26182, +26215, +26214, +26183, +26240, +26273, +26272, +26241, +26242, +26275, +26274, +26243, +26244, +26277, +26276, +26245, +26246, +26279, +26278, +26247, +26304, +26337, +26336, +26305, +26306, +26339, +26338, +26307, +26308, +26341, +26340, +26309, +26310, +26343, +26342, +26311, +26368, +26401, +26400, +26369, +26370, +26403, +26402, +26371, +26372, +26405, +26404, +26373, +26374, +26407, +26406, +26375, +26432, +26465, +26464, +26433, +26434, +26467, +26466, +26435, +26436, +26469, +26468, +26437, +26438, +26471, +26470, +26439, +26496, +26529, +26528, +26497, +26498, +26531, +26530, +26499, +26500, +26533, +26532, +26501, +26502, +26535, +26534, +26503, +26560, +26593, +26592, +26561, +26562, +26595, +26594, +26563, +26564, +26597, +26596, +26565, +26566, +26599, +26598, +26567, +24584, +24617, +24616, +24585, +24586, +24619, +24618, +24587, +24588, +24621, +24620, +24589, +24590, +24623, +24622, +24591, +24648, +24681, +24680, +24649, +24650, +24683, +24682, +24651, +24652, +24685, +24684, +24653, +24654, +24687, +24686, +24655, +24712, +24745, +24744, +24713, +24714, +24747, +24746, +24715, +24716, +24749, +24748, +24717, +24718, +24751, +24750, +24719, +24776, +24809, +24808, +24777, +24778, +24811, +24810, +24779, +24780, +24813, +24812, +24781, +24782, +24815, +24814, +24783, +24840, +24873, +24872, +24841, +24842, +24875, +24874, +24843, +24844, +24877, +24876, +24845, +24846, +24879, +24878, +24847, +24904, +24937, +24936, +24905, +24906, +24939, +24938, +24907, +24908, +24941, +24940, +24909, +24910, +24943, +24942, +24911, +24968, +25001, +25000, +24969, +24970, +25003, +25002, +24971, +24972, +25005, +25004, +24973, +24974, +25007, +25006, +24975, +25032, +25065, +25064, +25033, +25034, +25067, +25066, +25035, +25036, +25069, +25068, +25037, +25038, +25071, +25070, +25039, +25096, +25129, +25128, +25097, +25098, +25131, +25130, +25099, +25100, +25133, +25132, +25101, +25102, +25135, +25134, +25103, +25160, +25193, +25192, +25161, +25162, +25195, +25194, +25163, +25164, +25197, +25196, +25165, +25166, +25199, +25198, +25167, +25224, +25257, +25256, +25225, +25226, +25259, +25258, +25227, +25228, +25261, +25260, +25229, +25230, +25263, +25262, +25231, +25288, +25321, +25320, +25289, +25290, +25323, +25322, +25291, +25292, +25325, +25324, +25293, +25294, +25327, +25326, +25295, +25352, +25385, +25384, +25353, +25354, +25387, +25386, +25355, +25356, +25389, +25388, +25357, +25358, +25391, +25390, +25359, +25416, +25449, +25448, +25417, +25418, +25451, +25450, +25419, +25420, +25453, +25452, +25421, +25422, +25455, +25454, +25423, +25480, +25513, +25512, +25481, +25482, +25515, +25514, +25483, +25484, +25517, +25516, +25485, +25486, +25519, +25518, +25487, +25544, +25577, +25576, +25545, +25546, +25579, +25578, +25547, +25548, +25581, +25580, +25549, +25550, +25583, +25582, +25551, +25608, +25641, +25640, +25609, +25610, +25643, +25642, +25611, +25612, +25645, +25644, +25613, +25614, +25647, +25646, +25615, +25672, +25705, +25704, +25673, +25674, +25707, +25706, +25675, +25676, +25709, +25708, +25677, +25678, +25711, +25710, +25679, +25736, +25769, +25768, +25737, +25738, +25771, +25770, +25739, +25740, +25773, +25772, +25741, +25742, +25775, +25774, +25743, +25800, +25833, +25832, +25801, +25802, +25835, +25834, +25803, +25804, +25837, +25836, +25805, +25806, +25839, +25838, +25807, +25864, +25897, +25896, +25865, +25866, +25899, +25898, +25867, +25868, +25901, +25900, +25869, +25870, +25903, +25902, +25871, +25928, +25961, +25960, +25929, +25930, +25963, +25962, +25931, +25932, +25965, +25964, +25933, +25934, +25967, +25966, +25935, +25992, +26025, +26024, +25993, +25994, +26027, +26026, +25995, +25996, +26029, +26028, +25997, +25998, +26031, +26030, +25999, +26056, +26089, +26088, +26057, +26058, +26091, +26090, +26059, +26060, +26093, +26092, +26061, +26062, +26095, +26094, +26063, +26120, +26153, +26152, +26121, +26122, +26155, +26154, +26123, +26124, +26157, +26156, +26125, +26126, +26159, +26158, +26127, +26184, +26217, +26216, +26185, +26186, +26219, +26218, +26187, +26188, +26221, +26220, +26189, +26190, +26223, +26222, +26191, +26248, +26281, +26280, +26249, +26250, +26283, +26282, +26251, +26252, +26285, +26284, +26253, +26254, +26287, +26286, +26255, +26312, +26345, +26344, +26313, +26314, +26347, +26346, +26315, +26316, +26349, +26348, +26317, +26318, +26351, +26350, +26319, +26376, +26409, +26408, +26377, +26378, +26411, +26410, +26379, +26380, +26413, +26412, +26381, +26382, +26415, +26414, +26383, +26440, +26473, +26472, +26441, +26442, +26475, +26474, +26443, +26444, +26477, +26476, +26445, +26446, +26479, +26478, +26447, +26504, +26537, +26536, +26505, +26506, +26539, +26538, +26507, +26508, +26541, +26540, +26509, +26510, +26543, +26542, +26511, +26568, +26601, +26600, +26569, +26570, +26603, +26602, +26571, +26572, +26605, +26604, +26573, +26574, +26607, +26606, +26575, +24592, +24625, +24624, +24593, +24594, +24627, +24626, +24595, +24596, +24629, +24628, +24597, +24598, +24631, +24630, +24599, +24656, +24689, +24688, +24657, +24658, +24691, +24690, +24659, +24660, +24693, +24692, +24661, +24662, +24695, +24694, +24663, +24720, +24753, +24752, +24721, +24722, +24755, +24754, +24723, +24724, +24757, +24756, +24725, +24726, +24759, +24758, +24727, +24784, +24817, +24816, +24785, +24786, +24819, +24818, +24787, +24788, +24821, +24820, +24789, +24790, +24823, +24822, +24791, +24848, +24881, +24880, +24849, +24850, +24883, +24882, +24851, +24852, +24885, +24884, +24853, +24854, +24887, +24886, +24855, +24912, +24945, +24944, +24913, +24914, +24947, +24946, +24915, +24916, +24949, +24948, +24917, +24918, +24951, +24950, +24919, +24976, +25009, +25008, +24977, +24978, +25011, +25010, +24979, +24980, +25013, +25012, +24981, +24982, +25015, +25014, +24983, +25040, +25073, +25072, +25041, +25042, +25075, +25074, +25043, +25044, +25077, +25076, +25045, +25046, +25079, +25078, +25047, +25104, +25137, +25136, +25105, +25106, +25139, +25138, +25107, +25108, +25141, +25140, +25109, +25110, +25143, +25142, +25111, +25168, +25201, +25200, +25169, +25170, +25203, +25202, +25171, +25172, +25205, +25204, +25173, +25174, +25207, +25206, +25175, +25232, +25265, +25264, +25233, +25234, +25267, +25266, +25235, +25236, +25269, +25268, +25237, +25238, +25271, +25270, +25239, +25296, +25329, +25328, +25297, +25298, +25331, +25330, +25299, +25300, +25333, +25332, +25301, +25302, +25335, +25334, +25303, +25360, +25393, +25392, +25361, +25362, +25395, +25394, +25363, +25364, +25397, +25396, +25365, +25366, +25399, +25398, +25367, +25424, +25457, +25456, +25425, +25426, +25459, +25458, +25427, +25428, +25461, +25460, +25429, +25430, +25463, +25462, +25431, +25488, +25521, +25520, +25489, +25490, +25523, +25522, +25491, +25492, +25525, +25524, +25493, +25494, +25527, +25526, +25495, +25552, +25585, +25584, +25553, +25554, +25587, +25586, +25555, +25556, +25589, +25588, +25557, +25558, +25591, +25590, +25559, +25616, +25649, +25648, +25617, +25618, +25651, +25650, +25619, +25620, +25653, +25652, +25621, +25622, +25655, +25654, +25623, +25680, +25713, +25712, +25681, +25682, +25715, +25714, +25683, +25684, +25717, +25716, +25685, +25686, +25719, +25718, +25687, +25744, +25777, +25776, +25745, +25746, +25779, +25778, +25747, +25748, +25781, +25780, +25749, +25750, +25783, +25782, +25751, +25808, +25841, +25840, +25809, +25810, +25843, +25842, +25811, +25812, +25845, +25844, +25813, +25814, +25847, +25846, +25815, +25872, +25905, +25904, +25873, +25874, +25907, +25906, +25875, +25876, +25909, +25908, +25877, +25878, +25911, +25910, +25879, +25936, +25969, +25968, +25937, +25938, +25971, +25970, +25939, +25940, +25973, +25972, +25941, +25942, +25975, +25974, +25943, +26000, +26033, +26032, +26001, +26002, +26035, +26034, +26003, +26004, +26037, +26036, +26005, +26006, +26039, +26038, +26007, +26064, +26097, +26096, +26065, +26066, +26099, +26098, +26067, +26068, +26101, +26100, +26069, +26070, +26103, +26102, +26071, +26128, +26161, +26160, +26129, +26130, +26163, +26162, +26131, +26132, +26165, +26164, +26133, +26134, +26167, +26166, +26135, +26192, +26225, +26224, +26193, +26194, +26227, +26226, +26195, +26196, +26229, +26228, +26197, +26198, +26231, +26230, +26199, +26256, +26289, +26288, +26257, +26258, +26291, +26290, +26259, +26260, +26293, +26292, +26261, +26262, +26295, +26294, +26263, +26320, +26353, +26352, +26321, +26322, +26355, +26354, +26323, +26324, +26357, +26356, +26325, +26326, +26359, +26358, +26327, +26384, +26417, +26416, +26385, +26386, +26419, +26418, +26387, +26388, +26421, +26420, +26389, +26390, +26423, +26422, +26391, +26448, +26481, +26480, +26449, +26450, +26483, +26482, +26451, +26452, +26485, +26484, +26453, +26454, +26487, +26486, +26455, +26512, +26545, +26544, +26513, +26514, +26547, +26546, +26515, +26516, +26549, +26548, +26517, +26518, +26551, +26550, +26519, +26576, +26609, +26608, +26577, +26578, +26611, +26610, +26579, +26580, +26613, +26612, +26581, +26582, +26615, +26614, +26583, +24600, +24633, +24632, +24601, +24602, +24635, +24634, +24603, +24604, +24637, +24636, +24605, +24606, +24639, +24638, +24607, +24664, +24697, +24696, +24665, +24666, +24699, +24698, +24667, +24668, +24701, +24700, +24669, +24670, +24703, +24702, +24671, +24728, +24761, +24760, +24729, +24730, +24763, +24762, +24731, +24732, +24765, +24764, +24733, +24734, +24767, +24766, +24735, +24792, +24825, +24824, +24793, +24794, +24827, +24826, +24795, +24796, +24829, +24828, +24797, +24798, +24831, +24830, +24799, +24856, +24889, +24888, +24857, +24858, +24891, +24890, +24859, +24860, +24893, +24892, +24861, +24862, +24895, +24894, +24863, +24920, +24953, +24952, +24921, +24922, +24955, +24954, +24923, +24924, +24957, +24956, +24925, +24926, +24959, +24958, +24927, +24984, +25017, +25016, +24985, +24986, +25019, +25018, +24987, +24988, +25021, +25020, +24989, +24990, +25023, +25022, +24991, +25048, +25081, +25080, +25049, +25050, +25083, +25082, +25051, +25052, +25085, +25084, +25053, +25054, +25087, +25086, +25055, +25112, +25145, +25144, +25113, +25114, +25147, +25146, +25115, +25116, +25149, +25148, +25117, +25118, +25151, +25150, +25119, +25176, +25209, +25208, +25177, +25178, +25211, +25210, +25179, +25180, +25213, +25212, +25181, +25182, +25215, +25214, +25183, +25240, +25273, +25272, +25241, +25242, +25275, +25274, +25243, +25244, +25277, +25276, +25245, +25246, +25279, +25278, +25247, +25304, +25337, +25336, +25305, +25306, +25339, +25338, +25307, +25308, +25341, +25340, +25309, +25310, +25343, +25342, +25311, +25368, +25401, +25400, +25369, +25370, +25403, +25402, +25371, +25372, +25405, +25404, +25373, +25374, +25407, +25406, +25375, +25432, +25465, +25464, +25433, +25434, +25467, +25466, +25435, +25436, +25469, +25468, +25437, +25438, +25471, +25470, +25439, +25496, +25529, +25528, +25497, +25498, +25531, +25530, +25499, +25500, +25533, +25532, +25501, +25502, +25535, +25534, +25503, +25560, +25593, +25592, +25561, +25562, +25595, +25594, +25563, +25564, +25597, +25596, +25565, +25566, +25599, +25598, +25567, +25624, +25657, +25656, +25625, +25626, +25659, +25658, +25627, +25628, +25661, +25660, +25629, +25630, +25663, +25662, +25631, +25688, +25721, +25720, +25689, +25690, +25723, +25722, +25691, +25692, +25725, +25724, +25693, +25694, +25727, +25726, +25695, +25752, +25785, +25784, +25753, +25754, +25787, +25786, +25755, +25756, +25789, +25788, +25757, +25758, +25791, +25790, +25759, +25816, +25849, +25848, +25817, +25818, +25851, +25850, +25819, +25820, +25853, +25852, +25821, +25822, +25855, +25854, +25823, +25880, +25913, +25912, +25881, +25882, +25915, +25914, +25883, +25884, +25917, +25916, +25885, +25886, +25919, +25918, +25887, +25944, +25977, +25976, +25945, +25946, +25979, +25978, +25947, +25948, +25981, +25980, +25949, +25950, +25983, +25982, +25951, +26008, +26041, +26040, +26009, +26010, +26043, +26042, +26011, +26012, +26045, +26044, +26013, +26014, +26047, +26046, +26015, +26072, +26105, +26104, +26073, +26074, +26107, +26106, +26075, +26076, +26109, +26108, +26077, +26078, +26111, +26110, +26079, +26136, +26169, +26168, +26137, +26138, +26171, +26170, +26139, +26140, +26173, +26172, +26141, +26142, +26175, +26174, +26143, +26200, +26233, +26232, +26201, +26202, +26235, +26234, +26203, +26204, +26237, +26236, +26205, +26206, +26239, +26238, +26207, +26264, +26297, +26296, +26265, +26266, +26299, +26298, +26267, +26268, +26301, +26300, +26269, +26270, +26303, +26302, +26271, +26328, +26361, +26360, +26329, +26330, +26363, +26362, +26331, +26332, +26365, +26364, +26333, +26334, +26367, +26366, +26335, +26392, +26425, +26424, +26393, +26394, +26427, +26426, +26395, +26396, +26429, +26428, +26397, +26398, +26431, +26430, +26399, +26456, +26489, +26488, +26457, +26458, +26491, +26490, +26459, +26460, +26493, +26492, +26461, +26462, +26495, +26494, +26463, +26520, +26553, +26552, +26521, +26522, +26555, +26554, +26523, +26524, +26557, +26556, +26525, +26526, +26559, +26558, +26527, +26584, +26617, +26616, +26585, +26586, +26619, +26618, +26587, +26588, +26621, +26620, +26589, +26590, +26623, +26622, +26591, +26624, +26657, +26656, +26625, +26626, +26659, +26658, +26627, +26628, +26661, +26660, +26629, +26630, +26663, +26662, +26631, +26688, +26721, +26720, +26689, +26690, +26723, +26722, +26691, +26692, +26725, +26724, +26693, +26694, +26727, +26726, +26695, +26752, +26785, +26784, +26753, +26754, +26787, +26786, +26755, +26756, +26789, +26788, +26757, +26758, +26791, +26790, +26759, +26816, +26849, +26848, +26817, +26818, +26851, +26850, +26819, +26820, +26853, +26852, +26821, +26822, +26855, +26854, +26823, +26880, +26913, +26912, +26881, +26882, +26915, +26914, +26883, +26884, +26917, +26916, +26885, +26886, +26919, +26918, +26887, +26944, +26977, +26976, +26945, +26946, +26979, +26978, +26947, +26948, +26981, +26980, +26949, +26950, +26983, +26982, +26951, +27008, +27041, +27040, +27009, +27010, +27043, +27042, +27011, +27012, +27045, +27044, +27013, +27014, +27047, +27046, +27015, +27072, +27105, +27104, +27073, +27074, +27107, +27106, +27075, +27076, +27109, +27108, +27077, +27078, +27111, +27110, +27079, +27136, +27169, +27168, +27137, +27138, +27171, +27170, +27139, +27140, +27173, +27172, +27141, +27142, +27175, +27174, +27143, +27200, +27233, +27232, +27201, +27202, +27235, +27234, +27203, +27204, +27237, +27236, +27205, +27206, +27239, +27238, +27207, +27264, +27297, +27296, +27265, +27266, +27299, +27298, +27267, +27268, +27301, +27300, +27269, +27270, +27303, +27302, +27271, +27328, +27361, +27360, +27329, +27330, +27363, +27362, +27331, +27332, +27365, +27364, +27333, +27334, +27367, +27366, +27335, +27392, +27425, +27424, +27393, +27394, +27427, +27426, +27395, +27396, +27429, +27428, +27397, +27398, +27431, +27430, +27399, +27456, +27489, +27488, +27457, +27458, +27491, +27490, +27459, +27460, +27493, +27492, +27461, +27462, +27495, +27494, +27463, +27520, +27553, +27552, +27521, +27522, +27555, +27554, +27523, +27524, +27557, +27556, +27525, +27526, +27559, +27558, +27527, +27584, +27617, +27616, +27585, +27586, +27619, +27618, +27587, +27588, +27621, +27620, +27589, +27590, +27623, +27622, +27591, +27648, +27681, +27680, +27649, +27650, +27683, +27682, +27651, +27652, +27685, +27684, +27653, +27654, +27687, +27686, +27655, +27712, +27745, +27744, +27713, +27714, +27747, +27746, +27715, +27716, +27749, +27748, +27717, +27718, +27751, +27750, +27719, +27776, +27809, +27808, +27777, +27778, +27811, +27810, +27779, +27780, +27813, +27812, +27781, +27782, +27815, +27814, +27783, +27840, +27873, +27872, +27841, +27842, +27875, +27874, +27843, +27844, +27877, +27876, +27845, +27846, +27879, +27878, +27847, +27904, +27937, +27936, +27905, +27906, +27939, +27938, +27907, +27908, +27941, +27940, +27909, +27910, +27943, +27942, +27911, +27968, +28001, +28000, +27969, +27970, +28003, +28002, +27971, +27972, +28005, +28004, +27973, +27974, +28007, +28006, +27975, +28032, +28065, +28064, +28033, +28034, +28067, +28066, +28035, +28036, +28069, +28068, +28037, +28038, +28071, +28070, +28039, +28096, +28129, +28128, +28097, +28098, +28131, +28130, +28099, +28100, +28133, +28132, +28101, +28102, +28135, +28134, +28103, +28160, +28193, +28192, +28161, +28162, +28195, +28194, +28163, +28164, +28197, +28196, +28165, +28166, +28199, +28198, +28167, +28224, +28257, +28256, +28225, +28226, +28259, +28258, +28227, +28228, +28261, +28260, +28229, +28230, +28263, +28262, +28231, +28288, +28321, +28320, +28289, +28290, +28323, +28322, +28291, +28292, +28325, +28324, +28293, +28294, +28327, +28326, +28295, +28352, +28385, +28384, +28353, +28354, +28387, +28386, +28355, +28356, +28389, +28388, +28357, +28358, +28391, +28390, +28359, +28416, +28449, +28448, +28417, +28418, +28451, +28450, +28419, +28420, +28453, +28452, +28421, +28422, +28455, +28454, +28423, +28480, +28513, +28512, +28481, +28482, +28515, +28514, +28483, +28484, +28517, +28516, +28485, +28486, +28519, +28518, +28487, +28544, +28577, +28576, +28545, +28546, +28579, +28578, +28547, +28548, +28581, +28580, +28549, +28550, +28583, +28582, +28551, +28608, +28641, +28640, +28609, +28610, +28643, +28642, +28611, +28612, +28645, +28644, +28613, +28614, +28647, +28646, +28615, +26632, +26665, +26664, +26633, +26634, +26667, +26666, +26635, +26636, +26669, +26668, +26637, +26638, +26671, +26670, +26639, +26696, +26729, +26728, +26697, +26698, +26731, +26730, +26699, +26700, +26733, +26732, +26701, +26702, +26735, +26734, +26703, +26760, +26793, +26792, +26761, +26762, +26795, +26794, +26763, +26764, +26797, +26796, +26765, +26766, +26799, +26798, +26767, +26824, +26857, +26856, +26825, +26826, +26859, +26858, +26827, +26828, +26861, +26860, +26829, +26830, +26863, +26862, +26831, +26888, +26921, +26920, +26889, +26890, +26923, +26922, +26891, +26892, +26925, +26924, +26893, +26894, +26927, +26926, +26895, +26952, +26985, +26984, +26953, +26954, +26987, +26986, +26955, +26956, +26989, +26988, +26957, +26958, +26991, +26990, +26959, +27016, +27049, +27048, +27017, +27018, +27051, +27050, +27019, +27020, +27053, +27052, +27021, +27022, +27055, +27054, +27023, +27080, +27113, +27112, +27081, +27082, +27115, +27114, +27083, +27084, +27117, +27116, +27085, +27086, +27119, +27118, +27087, +27144, +27177, +27176, +27145, +27146, +27179, +27178, +27147, +27148, +27181, +27180, +27149, +27150, +27183, +27182, +27151, +27208, +27241, +27240, +27209, +27210, +27243, +27242, +27211, +27212, +27245, +27244, +27213, +27214, +27247, +27246, +27215, +27272, +27305, +27304, +27273, +27274, +27307, +27306, +27275, +27276, +27309, +27308, +27277, +27278, +27311, +27310, +27279, +27336, +27369, +27368, +27337, +27338, +27371, +27370, +27339, +27340, +27373, +27372, +27341, +27342, +27375, +27374, +27343, +27400, +27433, +27432, +27401, +27402, +27435, +27434, +27403, +27404, +27437, +27436, +27405, +27406, +27439, +27438, +27407, +27464, +27497, +27496, +27465, +27466, +27499, +27498, +27467, +27468, +27501, +27500, +27469, +27470, +27503, +27502, +27471, +27528, +27561, +27560, +27529, +27530, +27563, +27562, +27531, +27532, +27565, +27564, +27533, +27534, +27567, +27566, +27535, +27592, +27625, +27624, +27593, +27594, +27627, +27626, +27595, +27596, +27629, +27628, +27597, +27598, +27631, +27630, +27599, +27656, +27689, +27688, +27657, +27658, +27691, +27690, +27659, +27660, +27693, +27692, +27661, +27662, +27695, +27694, +27663, +27720, +27753, +27752, +27721, +27722, +27755, +27754, +27723, +27724, +27757, +27756, +27725, +27726, +27759, +27758, +27727, +27784, +27817, +27816, +27785, +27786, +27819, +27818, +27787, +27788, +27821, +27820, +27789, +27790, +27823, +27822, +27791, +27848, +27881, +27880, +27849, +27850, +27883, +27882, +27851, +27852, +27885, +27884, +27853, +27854, +27887, +27886, +27855, +27912, +27945, +27944, +27913, +27914, +27947, +27946, +27915, +27916, +27949, +27948, +27917, +27918, +27951, +27950, +27919, +27976, +28009, +28008, +27977, +27978, +28011, +28010, +27979, +27980, +28013, +28012, +27981, +27982, +28015, +28014, +27983, +28040, +28073, +28072, +28041, +28042, +28075, +28074, +28043, +28044, +28077, +28076, +28045, +28046, +28079, +28078, +28047, +28104, +28137, +28136, +28105, +28106, +28139, +28138, +28107, +28108, +28141, +28140, +28109, +28110, +28143, +28142, +28111, +28168, +28201, +28200, +28169, +28170, +28203, +28202, +28171, +28172, +28205, +28204, +28173, +28174, +28207, +28206, +28175, +28232, +28265, +28264, +28233, +28234, +28267, +28266, +28235, +28236, +28269, +28268, +28237, +28238, +28271, +28270, +28239, +28296, +28329, +28328, +28297, +28298, +28331, +28330, +28299, +28300, +28333, +28332, +28301, +28302, +28335, +28334, +28303, +28360, +28393, +28392, +28361, +28362, +28395, +28394, +28363, +28364, +28397, +28396, +28365, +28366, +28399, +28398, +28367, +28424, +28457, +28456, +28425, +28426, +28459, +28458, +28427, +28428, +28461, +28460, +28429, +28430, +28463, +28462, +28431, +28488, +28521, +28520, +28489, +28490, +28523, +28522, +28491, +28492, +28525, +28524, +28493, +28494, +28527, +28526, +28495, +28552, +28585, +28584, +28553, +28554, +28587, +28586, +28555, +28556, +28589, +28588, +28557, +28558, +28591, +28590, +28559, +28616, +28649, +28648, +28617, +28618, +28651, +28650, +28619, +28620, +28653, +28652, +28621, +28622, +28655, +28654, +28623, +26640, +26673, +26672, +26641, +26642, +26675, +26674, +26643, +26644, +26677, +26676, +26645, +26646, +26679, +26678, +26647, +26704, +26737, +26736, +26705, +26706, +26739, +26738, +26707, +26708, +26741, +26740, +26709, +26710, +26743, +26742, +26711, +26768, +26801, +26800, +26769, +26770, +26803, +26802, +26771, +26772, +26805, +26804, +26773, +26774, +26807, +26806, +26775, +26832, +26865, +26864, +26833, +26834, +26867, +26866, +26835, +26836, +26869, +26868, +26837, +26838, +26871, +26870, +26839, +26896, +26929, +26928, +26897, +26898, +26931, +26930, +26899, +26900, +26933, +26932, +26901, +26902, +26935, +26934, +26903, +26960, +26993, +26992, +26961, +26962, +26995, +26994, +26963, +26964, +26997, +26996, +26965, +26966, +26999, +26998, +26967, +27024, +27057, +27056, +27025, +27026, +27059, +27058, +27027, +27028, +27061, +27060, +27029, +27030, +27063, +27062, +27031, +27088, +27121, +27120, +27089, +27090, +27123, +27122, +27091, +27092, +27125, +27124, +27093, +27094, +27127, +27126, +27095, +27152, +27185, +27184, +27153, +27154, +27187, +27186, +27155, +27156, +27189, +27188, +27157, +27158, +27191, +27190, +27159, +27216, +27249, +27248, +27217, +27218, +27251, +27250, +27219, +27220, +27253, +27252, +27221, +27222, +27255, +27254, +27223, +27280, +27313, +27312, +27281, +27282, +27315, +27314, +27283, +27284, +27317, +27316, +27285, +27286, +27319, +27318, +27287, +27344, +27377, +27376, +27345, +27346, +27379, +27378, +27347, +27348, +27381, +27380, +27349, +27350, +27383, +27382, +27351, +27408, +27441, +27440, +27409, +27410, +27443, +27442, +27411, +27412, +27445, +27444, +27413, +27414, +27447, +27446, +27415, +27472, +27505, +27504, +27473, +27474, +27507, +27506, +27475, +27476, +27509, +27508, +27477, +27478, +27511, +27510, +27479, +27536, +27569, +27568, +27537, +27538, +27571, +27570, +27539, +27540, +27573, +27572, +27541, +27542, +27575, +27574, +27543, +27600, +27633, +27632, +27601, +27602, +27635, +27634, +27603, +27604, +27637, +27636, +27605, +27606, +27639, +27638, +27607, +27664, +27697, +27696, +27665, +27666, +27699, +27698, +27667, +27668, +27701, +27700, +27669, +27670, +27703, +27702, +27671, +27728, +27761, +27760, +27729, +27730, +27763, +27762, +27731, +27732, +27765, +27764, +27733, +27734, +27767, +27766, +27735, +27792, +27825, +27824, +27793, +27794, +27827, +27826, +27795, +27796, +27829, +27828, +27797, +27798, +27831, +27830, +27799, +27856, +27889, +27888, +27857, +27858, +27891, +27890, +27859, +27860, +27893, +27892, +27861, +27862, +27895, +27894, +27863, +27920, +27953, +27952, +27921, +27922, +27955, +27954, +27923, +27924, +27957, +27956, +27925, +27926, +27959, +27958, +27927, +27984, +28017, +28016, +27985, +27986, +28019, +28018, +27987, +27988, +28021, +28020, +27989, +27990, +28023, +28022, +27991, +28048, +28081, +28080, +28049, +28050, +28083, +28082, +28051, +28052, +28085, +28084, +28053, +28054, +28087, +28086, +28055, +28112, +28145, +28144, +28113, +28114, +28147, +28146, +28115, +28116, +28149, +28148, +28117, +28118, +28151, +28150, +28119, +28176, +28209, +28208, +28177, +28178, +28211, +28210, +28179, +28180, +28213, +28212, +28181, +28182, +28215, +28214, +28183, +28240, +28273, +28272, +28241, +28242, +28275, +28274, +28243, +28244, +28277, +28276, +28245, +28246, +28279, +28278, +28247, +28304, +28337, +28336, +28305, +28306, +28339, +28338, +28307, +28308, +28341, +28340, +28309, +28310, +28343, +28342, +28311, +28368, +28401, +28400, +28369, +28370, +28403, +28402, +28371, +28372, +28405, +28404, +28373, +28374, +28407, +28406, +28375, +28432, +28465, +28464, +28433, +28434, +28467, +28466, +28435, +28436, +28469, +28468, +28437, +28438, +28471, +28470, +28439, +28496, +28529, +28528, +28497, +28498, +28531, +28530, +28499, +28500, +28533, +28532, +28501, +28502, +28535, +28534, +28503, +28560, +28593, +28592, +28561, +28562, +28595, +28594, +28563, +28564, +28597, +28596, +28565, +28566, +28599, +28598, +28567, +28624, +28657, +28656, +28625, +28626, +28659, +28658, +28627, +28628, +28661, +28660, +28629, +28630, +28663, +28662, +28631, +26648, +26681, +26680, +26649, +26650, +26683, +26682, +26651, +26652, +26685, +26684, +26653, +26654, +26687, +26686, +26655, +26712, +26745, +26744, +26713, +26714, +26747, +26746, +26715, +26716, +26749, +26748, +26717, +26718, +26751, +26750, +26719, +26776, +26809, +26808, +26777, +26778, +26811, +26810, +26779, +26780, +26813, +26812, +26781, +26782, +26815, +26814, +26783, +26840, +26873, +26872, +26841, +26842, +26875, +26874, +26843, +26844, +26877, +26876, +26845, +26846, +26879, +26878, +26847, +26904, +26937, +26936, +26905, +26906, +26939, +26938, +26907, +26908, +26941, +26940, +26909, +26910, +26943, +26942, +26911, +26968, +27001, +27000, +26969, +26970, +27003, +27002, +26971, +26972, +27005, +27004, +26973, +26974, +27007, +27006, +26975, +27032, +27065, +27064, +27033, +27034, +27067, +27066, +27035, +27036, +27069, +27068, +27037, +27038, +27071, +27070, +27039, +27096, +27129, +27128, +27097, +27098, +27131, +27130, +27099, +27100, +27133, +27132, +27101, +27102, +27135, +27134, +27103, +27160, +27193, +27192, +27161, +27162, +27195, +27194, +27163, +27164, +27197, +27196, +27165, +27166, +27199, +27198, +27167, +27224, +27257, +27256, +27225, +27226, +27259, +27258, +27227, +27228, +27261, +27260, +27229, +27230, +27263, +27262, +27231, +27288, +27321, +27320, +27289, +27290, +27323, +27322, +27291, +27292, +27325, +27324, +27293, +27294, +27327, +27326, +27295, +27352, +27385, +27384, +27353, +27354, +27387, +27386, +27355, +27356, +27389, +27388, +27357, +27358, +27391, +27390, +27359, +27416, +27449, +27448, +27417, +27418, +27451, +27450, +27419, +27420, +27453, +27452, +27421, +27422, +27455, +27454, +27423, +27480, +27513, +27512, +27481, +27482, +27515, +27514, +27483, +27484, +27517, +27516, +27485, +27486, +27519, +27518, +27487, +27544, +27577, +27576, +27545, +27546, +27579, +27578, +27547, +27548, +27581, +27580, +27549, +27550, +27583, +27582, +27551, +27608, +27641, +27640, +27609, +27610, +27643, +27642, +27611, +27612, +27645, +27644, +27613, +27614, +27647, +27646, +27615, +27672, +27705, +27704, +27673, +27674, +27707, +27706, +27675, +27676, +27709, +27708, +27677, +27678, +27711, +27710, +27679, +27736, +27769, +27768, +27737, +27738, +27771, +27770, +27739, +27740, +27773, +27772, +27741, +27742, +27775, +27774, +27743, +27800, +27833, +27832, +27801, +27802, +27835, +27834, +27803, +27804, +27837, +27836, +27805, +27806, +27839, +27838, +27807, +27864, +27897, +27896, +27865, +27866, +27899, +27898, +27867, +27868, +27901, +27900, +27869, +27870, +27903, +27902, +27871, +27928, +27961, +27960, +27929, +27930, +27963, +27962, +27931, +27932, +27965, +27964, +27933, +27934, +27967, +27966, +27935, +27992, +28025, +28024, +27993, +27994, +28027, +28026, +27995, +27996, +28029, +28028, +27997, +27998, +28031, +28030, +27999, +28056, +28089, +28088, +28057, +28058, +28091, +28090, +28059, +28060, +28093, +28092, +28061, +28062, +28095, +28094, +28063, +28120, +28153, +28152, +28121, +28122, +28155, +28154, +28123, +28124, +28157, +28156, +28125, +28126, +28159, +28158, +28127, +28184, +28217, +28216, +28185, +28186, +28219, +28218, +28187, +28188, +28221, +28220, +28189, +28190, +28223, +28222, +28191, +28248, +28281, +28280, +28249, +28250, +28283, +28282, +28251, +28252, +28285, +28284, +28253, +28254, +28287, +28286, +28255, +28312, +28345, +28344, +28313, +28314, +28347, +28346, +28315, +28316, +28349, +28348, +28317, +28318, +28351, +28350, +28319, +28376, +28409, +28408, +28377, +28378, +28411, +28410, +28379, +28380, +28413, +28412, +28381, +28382, +28415, +28414, +28383, +28440, +28473, +28472, +28441, +28442, +28475, +28474, +28443, +28444, +28477, +28476, +28445, +28446, +28479, +28478, +28447, +28504, +28537, +28536, +28505, +28506, +28539, +28538, +28507, +28508, +28541, +28540, +28509, +28510, +28543, +28542, +28511, +28568, +28601, +28600, +28569, +28570, +28603, +28602, +28571, +28572, +28605, +28604, +28573, +28574, +28607, +28606, +28575, +28632, +28665, +28664, +28633, +28634, +28667, +28666, +28635, +28636, +28669, +28668, +28637, +28638, +28671, +28670, +28639, +28672, +28705, +28704, +28673, +28674, +28707, +28706, +28675, +28676, +28709, +28708, +28677, +28678, +28711, +28710, +28679, +28736, +28769, +28768, +28737, +28738, +28771, +28770, +28739, +28740, +28773, +28772, +28741, +28742, +28775, +28774, +28743, +28800, +28833, +28832, +28801, +28802, +28835, +28834, +28803, +28804, +28837, +28836, +28805, +28806, +28839, +28838, +28807, +28864, +28897, +28896, +28865, +28866, +28899, +28898, +28867, +28868, +28901, +28900, +28869, +28870, +28903, +28902, +28871, +28928, +28961, +28960, +28929, +28930, +28963, +28962, +28931, +28932, +28965, +28964, +28933, +28934, +28967, +28966, +28935, +28992, +29025, +29024, +28993, +28994, +29027, +29026, +28995, +28996, +29029, +29028, +28997, +28998, +29031, +29030, +28999, +29056, +29089, +29088, +29057, +29058, +29091, +29090, +29059, +29060, +29093, +29092, +29061, +29062, +29095, +29094, +29063, +29120, +29153, +29152, +29121, +29122, +29155, +29154, +29123, +29124, +29157, +29156, +29125, +29126, +29159, +29158, +29127, +29184, +29217, +29216, +29185, +29186, +29219, +29218, +29187, +29188, +29221, +29220, +29189, +29190, +29223, +29222, +29191, +29248, +29281, +29280, +29249, +29250, +29283, +29282, +29251, +29252, +29285, +29284, +29253, +29254, +29287, +29286, +29255, +29312, +29345, +29344, +29313, +29314, +29347, +29346, +29315, +29316, +29349, +29348, +29317, +29318, +29351, +29350, +29319, +29376, +29409, +29408, +29377, +29378, +29411, +29410, +29379, +29380, +29413, +29412, +29381, +29382, +29415, +29414, +29383, +29440, +29473, +29472, +29441, +29442, +29475, +29474, +29443, +29444, +29477, +29476, +29445, +29446, +29479, +29478, +29447, +29504, +29537, +29536, +29505, +29506, +29539, +29538, +29507, +29508, +29541, +29540, +29509, +29510, +29543, +29542, +29511, +29568, +29601, +29600, +29569, +29570, +29603, +29602, +29571, +29572, +29605, +29604, +29573, +29574, +29607, +29606, +29575, +29632, +29665, +29664, +29633, +29634, +29667, +29666, +29635, +29636, +29669, +29668, +29637, +29638, +29671, +29670, +29639, +29696, +29729, +29728, +29697, +29698, +29731, +29730, +29699, +29700, +29733, +29732, +29701, +29702, +29735, +29734, +29703, +29760, +29793, +29792, +29761, +29762, +29795, +29794, +29763, +29764, +29797, +29796, +29765, +29766, +29799, +29798, +29767, +29824, +29857, +29856, +29825, +29826, +29859, +29858, +29827, +29828, +29861, +29860, +29829, +29830, +29863, +29862, +29831, +29888, +29921, +29920, +29889, +29890, +29923, +29922, +29891, +29892, +29925, +29924, +29893, +29894, +29927, +29926, +29895, +29952, +29985, +29984, +29953, +29954, +29987, +29986, +29955, +29956, +29989, +29988, +29957, +29958, +29991, +29990, +29959, +30016, +30049, +30048, +30017, +30018, +30051, +30050, +30019, +30020, +30053, +30052, +30021, +30022, +30055, +30054, +30023, +30080, +30113, +30112, +30081, +30082, +30115, +30114, +30083, +30084, +30117, +30116, +30085, +30086, +30119, +30118, +30087, +30144, +30177, +30176, +30145, +30146, +30179, +30178, +30147, +30148, +30181, +30180, +30149, +30150, +30183, +30182, +30151, +30208, +30241, +30240, +30209, +30210, +30243, +30242, +30211, +30212, +30245, +30244, +30213, +30214, +30247, +30246, +30215, +30272, +30305, +30304, +30273, +30274, +30307, +30306, +30275, +30276, +30309, +30308, +30277, +30278, +30311, +30310, +30279, +30336, +30369, +30368, +30337, +30338, +30371, +30370, +30339, +30340, +30373, +30372, +30341, +30342, +30375, +30374, +30343, +30400, +30433, +30432, +30401, +30402, +30435, +30434, +30403, +30404, +30437, +30436, +30405, +30406, +30439, +30438, +30407, +30464, +30497, +30496, +30465, +30466, +30499, +30498, +30467, +30468, +30501, +30500, +30469, +30470, +30503, +30502, +30471, +30528, +30561, +30560, +30529, +30530, +30563, +30562, +30531, +30532, +30565, +30564, +30533, +30534, +30567, +30566, +30535, +30592, +30625, +30624, +30593, +30594, +30627, +30626, +30595, +30596, +30629, +30628, +30597, +30598, +30631, +30630, +30599, +30656, +30689, +30688, +30657, +30658, +30691, +30690, +30659, +30660, +30693, +30692, +30661, +30662, +30695, +30694, +30663, +28680, +28713, +28712, +28681, +28682, +28715, +28714, +28683, +28684, +28717, +28716, +28685, +28686, +28719, +28718, +28687, +28744, +28777, +28776, +28745, +28746, +28779, +28778, +28747, +28748, +28781, +28780, +28749, +28750, +28783, +28782, +28751, +28808, +28841, +28840, +28809, +28810, +28843, +28842, +28811, +28812, +28845, +28844, +28813, +28814, +28847, +28846, +28815, +28872, +28905, +28904, +28873, +28874, +28907, +28906, +28875, +28876, +28909, +28908, +28877, +28878, +28911, +28910, +28879, +28936, +28969, +28968, +28937, +28938, +28971, +28970, +28939, +28940, +28973, +28972, +28941, +28942, +28975, +28974, +28943, +29000, +29033, +29032, +29001, +29002, +29035, +29034, +29003, +29004, +29037, +29036, +29005, +29006, +29039, +29038, +29007, +29064, +29097, +29096, +29065, +29066, +29099, +29098, +29067, +29068, +29101, +29100, +29069, +29070, +29103, +29102, +29071, +29128, +29161, +29160, +29129, +29130, +29163, +29162, +29131, +29132, +29165, +29164, +29133, +29134, +29167, +29166, +29135, +29192, +29225, +29224, +29193, +29194, +29227, +29226, +29195, +29196, +29229, +29228, +29197, +29198, +29231, +29230, +29199, +29256, +29289, +29288, +29257, +29258, +29291, +29290, +29259, +29260, +29293, +29292, +29261, +29262, +29295, +29294, +29263, +29320, +29353, +29352, +29321, +29322, +29355, +29354, +29323, +29324, +29357, +29356, +29325, +29326, +29359, +29358, +29327, +29384, +29417, +29416, +29385, +29386, +29419, +29418, +29387, +29388, +29421, +29420, +29389, +29390, +29423, +29422, +29391, +29448, +29481, +29480, +29449, +29450, +29483, +29482, +29451, +29452, +29485, +29484, +29453, +29454, +29487, +29486, +29455, +29512, +29545, +29544, +29513, +29514, +29547, +29546, +29515, +29516, +29549, +29548, +29517, +29518, +29551, +29550, +29519, +29576, +29609, +29608, +29577, +29578, +29611, +29610, +29579, +29580, +29613, +29612, +29581, +29582, +29615, +29614, +29583, +29640, +29673, +29672, +29641, +29642, +29675, +29674, +29643, +29644, +29677, +29676, +29645, +29646, +29679, +29678, +29647, +29704, +29737, +29736, +29705, +29706, +29739, +29738, +29707, +29708, +29741, +29740, +29709, +29710, +29743, +29742, +29711, +29768, +29801, +29800, +29769, +29770, +29803, +29802, +29771, +29772, +29805, +29804, +29773, +29774, +29807, +29806, +29775, +29832, +29865, +29864, +29833, +29834, +29867, +29866, +29835, +29836, +29869, +29868, +29837, +29838, +29871, +29870, +29839, +29896, +29929, +29928, +29897, +29898, +29931, +29930, +29899, +29900, +29933, +29932, +29901, +29902, +29935, +29934, +29903, +29960, +29993, +29992, +29961, +29962, +29995, +29994, +29963, +29964, +29997, +29996, +29965, +29966, +29999, +29998, +29967, +30024, +30057, +30056, +30025, +30026, +30059, +30058, +30027, +30028, +30061, +30060, +30029, +30030, +30063, +30062, +30031, +30088, +30121, +30120, +30089, +30090, +30123, +30122, +30091, +30092, +30125, +30124, +30093, +30094, +30127, +30126, +30095, +30152, +30185, +30184, +30153, +30154, +30187, +30186, +30155, +30156, +30189, +30188, +30157, +30158, +30191, +30190, +30159, +30216, +30249, +30248, +30217, +30218, +30251, +30250, +30219, +30220, +30253, +30252, +30221, +30222, +30255, +30254, +30223, +30280, +30313, +30312, +30281, +30282, +30315, +30314, +30283, +30284, +30317, +30316, +30285, +30286, +30319, +30318, +30287, +30344, +30377, +30376, +30345, +30346, +30379, +30378, +30347, +30348, +30381, +30380, +30349, +30350, +30383, +30382, +30351, +30408, +30441, +30440, +30409, +30410, +30443, +30442, +30411, +30412, +30445, +30444, +30413, +30414, +30447, +30446, +30415, +30472, +30505, +30504, +30473, +30474, +30507, +30506, +30475, +30476, +30509, +30508, +30477, +30478, +30511, +30510, +30479, +30536, +30569, +30568, +30537, +30538, +30571, +30570, +30539, +30540, +30573, +30572, +30541, +30542, +30575, +30574, +30543, +30600, +30633, +30632, +30601, +30602, +30635, +30634, +30603, +30604, +30637, +30636, +30605, +30606, +30639, +30638, +30607, +30664, +30697, +30696, +30665, +30666, +30699, +30698, +30667, +30668, +30701, +30700, +30669, +30670, +30703, +30702, +30671, +28688, +28721, +28720, +28689, +28690, +28723, +28722, +28691, +28692, +28725, +28724, +28693, +28694, +28727, +28726, +28695, +28752, +28785, +28784, +28753, +28754, +28787, +28786, +28755, +28756, +28789, +28788, +28757, +28758, +28791, +28790, +28759, +28816, +28849, +28848, +28817, +28818, +28851, +28850, +28819, +28820, +28853, +28852, +28821, +28822, +28855, +28854, +28823, +28880, +28913, +28912, +28881, +28882, +28915, +28914, +28883, +28884, +28917, +28916, +28885, +28886, +28919, +28918, +28887, +28944, +28977, +28976, +28945, +28946, +28979, +28978, +28947, +28948, +28981, +28980, +28949, +28950, +28983, +28982, +28951, +29008, +29041, +29040, +29009, +29010, +29043, +29042, +29011, +29012, +29045, +29044, +29013, +29014, +29047, +29046, +29015, +29072, +29105, +29104, +29073, +29074, +29107, +29106, +29075, +29076, +29109, +29108, +29077, +29078, +29111, +29110, +29079, +29136, +29169, +29168, +29137, +29138, +29171, +29170, +29139, +29140, +29173, +29172, +29141, +29142, +29175, +29174, +29143, +29200, +29233, +29232, +29201, +29202, +29235, +29234, +29203, +29204, +29237, +29236, +29205, +29206, +29239, +29238, +29207, +29264, +29297, +29296, +29265, +29266, +29299, +29298, +29267, +29268, +29301, +29300, +29269, +29270, +29303, +29302, +29271, +29328, +29361, +29360, +29329, +29330, +29363, +29362, +29331, +29332, +29365, +29364, +29333, +29334, +29367, +29366, +29335, +29392, +29425, +29424, +29393, +29394, +29427, +29426, +29395, +29396, +29429, +29428, +29397, +29398, +29431, +29430, +29399, +29456, +29489, +29488, +29457, +29458, +29491, +29490, +29459, +29460, +29493, +29492, +29461, +29462, +29495, +29494, +29463, +29520, +29553, +29552, +29521, +29522, +29555, +29554, +29523, +29524, +29557, +29556, +29525, +29526, +29559, +29558, +29527, +29584, +29617, +29616, +29585, +29586, +29619, +29618, +29587, +29588, +29621, +29620, +29589, +29590, +29623, +29622, +29591, +29648, +29681, +29680, +29649, +29650, +29683, +29682, +29651, +29652, +29685, +29684, +29653, +29654, +29687, +29686, +29655, +29712, +29745, +29744, +29713, +29714, +29747, +29746, +29715, +29716, +29749, +29748, +29717, +29718, +29751, +29750, +29719, +29776, +29809, +29808, +29777, +29778, +29811, +29810, +29779, +29780, +29813, +29812, +29781, +29782, +29815, +29814, +29783, +29840, +29873, +29872, +29841, +29842, +29875, +29874, +29843, +29844, +29877, +29876, +29845, +29846, +29879, +29878, +29847, +29904, +29937, +29936, +29905, +29906, +29939, +29938, +29907, +29908, +29941, +29940, +29909, +29910, +29943, +29942, +29911, +29968, +30001, +30000, +29969, +29970, +30003, +30002, +29971, +29972, +30005, +30004, +29973, +29974, +30007, +30006, +29975, +30032, +30065, +30064, +30033, +30034, +30067, +30066, +30035, +30036, +30069, +30068, +30037, +30038, +30071, +30070, +30039, +30096, +30129, +30128, +30097, +30098, +30131, +30130, +30099, +30100, +30133, +30132, +30101, +30102, +30135, +30134, +30103, +30160, +30193, +30192, +30161, +30162, +30195, +30194, +30163, +30164, +30197, +30196, +30165, +30166, +30199, +30198, +30167, +30224, +30257, +30256, +30225, +30226, +30259, +30258, +30227, +30228, +30261, +30260, +30229, +30230, +30263, +30262, +30231, +30288, +30321, +30320, +30289, +30290, +30323, +30322, +30291, +30292, +30325, +30324, +30293, +30294, +30327, +30326, +30295, +30352, +30385, +30384, +30353, +30354, +30387, +30386, +30355, +30356, +30389, +30388, +30357, +30358, +30391, +30390, +30359, +30416, +30449, +30448, +30417, +30418, +30451, +30450, +30419, +30420, +30453, +30452, +30421, +30422, +30455, +30454, +30423, +30480, +30513, +30512, +30481, +30482, +30515, +30514, +30483, +30484, +30517, +30516, +30485, +30486, +30519, +30518, +30487, +30544, +30577, +30576, +30545, +30546, +30579, +30578, +30547, +30548, +30581, +30580, +30549, +30550, +30583, +30582, +30551, +30608, +30641, +30640, +30609, +30610, +30643, +30642, +30611, +30612, +30645, +30644, +30613, +30614, +30647, +30646, +30615, +30672, +30705, +30704, +30673, +30674, +30707, +30706, +30675, +30676, +30709, +30708, +30677, +30678, +30711, +30710, +30679, +28696, +28729, +28728, +28697, +28698, +28731, +28730, +28699, +28700, +28733, +28732, +28701, +28702, +28735, +28734, +28703, +28760, +28793, +28792, +28761, +28762, +28795, +28794, +28763, +28764, +28797, +28796, +28765, +28766, +28799, +28798, +28767, +28824, +28857, +28856, +28825, +28826, +28859, +28858, +28827, +28828, +28861, +28860, +28829, +28830, +28863, +28862, +28831, +28888, +28921, +28920, +28889, +28890, +28923, +28922, +28891, +28892, +28925, +28924, +28893, +28894, +28927, +28926, +28895, +28952, +28985, +28984, +28953, +28954, +28987, +28986, +28955, +28956, +28989, +28988, +28957, +28958, +28991, +28990, +28959, +29016, +29049, +29048, +29017, +29018, +29051, +29050, +29019, +29020, +29053, +29052, +29021, +29022, +29055, +29054, +29023, +29080, +29113, +29112, +29081, +29082, +29115, +29114, +29083, +29084, +29117, +29116, +29085, +29086, +29119, +29118, +29087, +29144, +29177, +29176, +29145, +29146, +29179, +29178, +29147, +29148, +29181, +29180, +29149, +29150, +29183, +29182, +29151, +29208, +29241, +29240, +29209, +29210, +29243, +29242, +29211, +29212, +29245, +29244, +29213, +29214, +29247, +29246, +29215, +29272, +29305, +29304, +29273, +29274, +29307, +29306, +29275, +29276, +29309, +29308, +29277, +29278, +29311, +29310, +29279, +29336, +29369, +29368, +29337, +29338, +29371, +29370, +29339, +29340, +29373, +29372, +29341, +29342, +29375, +29374, +29343, +29400, +29433, +29432, +29401, +29402, +29435, +29434, +29403, +29404, +29437, +29436, +29405, +29406, +29439, +29438, +29407, +29464, +29497, +29496, +29465, +29466, +29499, +29498, +29467, +29468, +29501, +29500, +29469, +29470, +29503, +29502, +29471, +29528, +29561, +29560, +29529, +29530, +29563, +29562, +29531, +29532, +29565, +29564, +29533, +29534, +29567, +29566, +29535, +29592, +29625, +29624, +29593, +29594, +29627, +29626, +29595, +29596, +29629, +29628, +29597, +29598, +29631, +29630, +29599, +29656, +29689, +29688, +29657, +29658, +29691, +29690, +29659, +29660, +29693, +29692, +29661, +29662, +29695, +29694, +29663, +29720, +29753, +29752, +29721, +29722, +29755, +29754, +29723, +29724, +29757, +29756, +29725, +29726, +29759, +29758, +29727, +29784, +29817, +29816, +29785, +29786, +29819, +29818, +29787, +29788, +29821, +29820, +29789, +29790, +29823, +29822, +29791, +29848, +29881, +29880, +29849, +29850, +29883, +29882, +29851, +29852, +29885, +29884, +29853, +29854, +29887, +29886, +29855, +29912, +29945, +29944, +29913, +29914, +29947, +29946, +29915, +29916, +29949, +29948, +29917, +29918, +29951, +29950, +29919, +29976, +30009, +30008, +29977, +29978, +30011, +30010, +29979, +29980, +30013, +30012, +29981, +29982, +30015, +30014, +29983, +30040, +30073, +30072, +30041, +30042, +30075, +30074, +30043, +30044, +30077, +30076, +30045, +30046, +30079, +30078, +30047, +30104, +30137, +30136, +30105, +30106, +30139, +30138, +30107, +30108, +30141, +30140, +30109, +30110, +30143, +30142, +30111, +30168, +30201, +30200, +30169, +30170, +30203, +30202, +30171, +30172, +30205, +30204, +30173, +30174, +30207, +30206, +30175, +30232, +30265, +30264, +30233, +30234, +30267, +30266, +30235, +30236, +30269, +30268, +30237, +30238, +30271, +30270, +30239, +30296, +30329, +30328, +30297, +30298, +30331, +30330, +30299, +30300, +30333, +30332, +30301, +30302, +30335, +30334, +30303, +30360, +30393, +30392, +30361, +30362, +30395, +30394, +30363, +30364, +30397, +30396, +30365, +30366, +30399, +30398, +30367, +30424, +30457, +30456, +30425, +30426, +30459, +30458, +30427, +30428, +30461, +30460, +30429, +30430, +30463, +30462, +30431, +30488, +30521, +30520, +30489, +30490, +30523, +30522, +30491, +30492, +30525, +30524, +30493, +30494, +30527, +30526, +30495, +30552, +30585, +30584, +30553, +30554, +30587, +30586, +30555, +30556, +30589, +30588, +30557, +30558, +30591, +30590, +30559, +30616, +30649, +30648, +30617, +30618, +30651, +30650, +30619, +30620, +30653, +30652, +30621, +30622, +30655, +30654, +30623, +30680, +30713, +30712, +30681, +30682, +30715, +30714, +30683, +30684, +30717, +30716, +30685, +30686, +30719, +30718, +30687, +30720, +30753, +30752, +30721, +30722, +30755, +30754, +30723, +30724, +30757, +30756, +30725, +30726, +30759, +30758, +30727, +30784, +30817, +30816, +30785, +30786, +30819, +30818, +30787, +30788, +30821, +30820, +30789, +30790, +30823, +30822, +30791, +30848, +30881, +30880, +30849, +30850, +30883, +30882, +30851, +30852, +30885, +30884, +30853, +30854, +30887, +30886, +30855, +30912, +30945, +30944, +30913, +30914, +30947, +30946, +30915, +30916, +30949, +30948, +30917, +30918, +30951, +30950, +30919, +30976, +31009, +31008, +30977, +30978, +31011, +31010, +30979, +30980, +31013, +31012, +30981, +30982, +31015, +31014, +30983, +31040, +31073, +31072, +31041, +31042, +31075, +31074, +31043, +31044, +31077, +31076, +31045, +31046, +31079, +31078, +31047, +31104, +31137, +31136, +31105, +31106, +31139, +31138, +31107, +31108, +31141, +31140, +31109, +31110, +31143, +31142, +31111, +31168, +31201, +31200, +31169, +31170, +31203, +31202, +31171, +31172, +31205, +31204, +31173, +31174, +31207, +31206, +31175, +31232, +31265, +31264, +31233, +31234, +31267, +31266, +31235, +31236, +31269, +31268, +31237, +31238, +31271, +31270, +31239, +31296, +31329, +31328, +31297, +31298, +31331, +31330, +31299, +31300, +31333, +31332, +31301, +31302, +31335, +31334, +31303, +31360, +31393, +31392, +31361, +31362, +31395, +31394, +31363, +31364, +31397, +31396, +31365, +31366, +31399, +31398, +31367, +31424, +31457, +31456, +31425, +31426, +31459, +31458, +31427, +31428, +31461, +31460, +31429, +31430, +31463, +31462, +31431, +31488, +31521, +31520, +31489, +31490, +31523, +31522, +31491, +31492, +31525, +31524, +31493, +31494, +31527, +31526, +31495, +31552, +31585, +31584, +31553, +31554, +31587, +31586, +31555, +31556, +31589, +31588, +31557, +31558, +31591, +31590, +31559, +31616, +31649, +31648, +31617, +31618, +31651, +31650, +31619, +31620, +31653, +31652, +31621, +31622, +31655, +31654, +31623, +31680, +31713, +31712, +31681, +31682, +31715, +31714, +31683, +31684, +31717, +31716, +31685, +31686, +31719, +31718, +31687, +31744, +31777, +31776, +31745, +31746, +31779, +31778, +31747, +31748, +31781, +31780, +31749, +31750, +31783, +31782, +31751, +31808, +31841, +31840, +31809, +31810, +31843, +31842, +31811, +31812, +31845, +31844, +31813, +31814, +31847, +31846, +31815, +31872, +31905, +31904, +31873, +31874, +31907, +31906, +31875, +31876, +31909, +31908, +31877, +31878, +31911, +31910, +31879, +31936, +31969, +31968, +31937, +31938, +31971, +31970, +31939, +31940, +31973, +31972, +31941, +31942, +31975, +31974, +31943, +32000, +32033, +32032, +32001, +32002, +32035, +32034, +32003, +32004, +32037, +32036, +32005, +32006, +32039, +32038, +32007, +32064, +32097, +32096, +32065, +32066, +32099, +32098, +32067, +32068, +32101, +32100, +32069, +32070, +32103, +32102, +32071, +32128, +32161, +32160, +32129, +32130, +32163, +32162, +32131, +32132, +32165, +32164, +32133, +32134, +32167, +32166, +32135, +32192, +32225, +32224, +32193, +32194, +32227, +32226, +32195, +32196, +32229, +32228, +32197, +32198, +32231, +32230, +32199, +32256, +32289, +32288, +32257, +32258, +32291, +32290, +32259, +32260, +32293, +32292, +32261, +32262, +32295, +32294, +32263, +32320, +32353, +32352, +32321, +32322, +32355, +32354, +32323, +32324, +32357, +32356, +32325, +32326, +32359, +32358, +32327, +32384, +32417, +32416, +32385, +32386, +32419, +32418, +32387, +32388, +32421, +32420, +32389, +32390, +32423, +32422, +32391, +32448, +32481, +32480, +32449, +32450, +32483, +32482, +32451, +32452, +32485, +32484, +32453, +32454, +32487, +32486, +32455, +32512, +32545, +32544, +32513, +32514, +32547, +32546, +32515, +32516, +32549, +32548, +32517, +32518, +32551, +32550, +32519, +32576, +32609, +32608, +32577, +32578, +32611, +32610, +32579, +32580, +32613, +32612, +32581, +32582, +32615, +32614, +32583, +32640, +32673, +32672, +32641, +32642, +32675, +32674, +32643, +32644, +32677, +32676, +32645, +32646, +32679, +32678, +32647, +32704, +32737, +32736, +32705, +32706, +32739, +32738, +32707, +32708, +32741, +32740, +32709, +32710, +32743, +32742, +32711, +30728, +30761, +30760, +30729, +30730, +30763, +30762, +30731, +30732, +30765, +30764, +30733, +30734, +30767, +30766, +30735, +30792, +30825, +30824, +30793, +30794, +30827, +30826, +30795, +30796, +30829, +30828, +30797, +30798, +30831, +30830, +30799, +30856, +30889, +30888, +30857, +30858, +30891, +30890, +30859, +30860, +30893, +30892, +30861, +30862, +30895, +30894, +30863, +30920, +30953, +30952, +30921, +30922, +30955, +30954, +30923, +30924, +30957, +30956, +30925, +30926, +30959, +30958, +30927, +30984, +31017, +31016, +30985, +30986, +31019, +31018, +30987, +30988, +31021, +31020, +30989, +30990, +31023, +31022, +30991, +31048, +31081, +31080, +31049, +31050, +31083, +31082, +31051, +31052, +31085, +31084, +31053, +31054, +31087, +31086, +31055, +31112, +31145, +31144, +31113, +31114, +31147, +31146, +31115, +31116, +31149, +31148, +31117, +31118, +31151, +31150, +31119, +31176, +31209, +31208, +31177, +31178, +31211, +31210, +31179, +31180, +31213, +31212, +31181, +31182, +31215, +31214, +31183, +31240, +31273, +31272, +31241, +31242, +31275, +31274, +31243, +31244, +31277, +31276, +31245, +31246, +31279, +31278, +31247, +31304, +31337, +31336, +31305, +31306, +31339, +31338, +31307, +31308, +31341, +31340, +31309, +31310, +31343, +31342, +31311, +31368, +31401, +31400, +31369, +31370, +31403, +31402, +31371, +31372, +31405, +31404, +31373, +31374, +31407, +31406, +31375, +31432, +31465, +31464, +31433, +31434, +31467, +31466, +31435, +31436, +31469, +31468, +31437, +31438, +31471, +31470, +31439, +31496, +31529, +31528, +31497, +31498, +31531, +31530, +31499, +31500, +31533, +31532, +31501, +31502, +31535, +31534, +31503, +31560, +31593, +31592, +31561, +31562, +31595, +31594, +31563, +31564, +31597, +31596, +31565, +31566, +31599, +31598, +31567, +31624, +31657, +31656, +31625, +31626, +31659, +31658, +31627, +31628, +31661, +31660, +31629, +31630, +31663, +31662, +31631, +31688, +31721, +31720, +31689, +31690, +31723, +31722, +31691, +31692, +31725, +31724, +31693, +31694, +31727, +31726, +31695, +31752, +31785, +31784, +31753, +31754, +31787, +31786, +31755, +31756, +31789, +31788, +31757, +31758, +31791, +31790, +31759, +31816, +31849, +31848, +31817, +31818, +31851, +31850, +31819, +31820, +31853, +31852, +31821, +31822, +31855, +31854, +31823, +31880, +31913, +31912, +31881, +31882, +31915, +31914, +31883, +31884, +31917, +31916, +31885, +31886, +31919, +31918, +31887, +31944, +31977, +31976, +31945, +31946, +31979, +31978, +31947, +31948, +31981, +31980, +31949, +31950, +31983, +31982, +31951, +32008, +32041, +32040, +32009, +32010, +32043, +32042, +32011, +32012, +32045, +32044, +32013, +32014, +32047, +32046, +32015, +32072, +32105, +32104, +32073, +32074, +32107, +32106, +32075, +32076, +32109, +32108, +32077, +32078, +32111, +32110, +32079, +32136, +32169, +32168, +32137, +32138, +32171, +32170, +32139, +32140, +32173, +32172, +32141, +32142, +32175, +32174, +32143, +32200, +32233, +32232, +32201, +32202, +32235, +32234, +32203, +32204, +32237, +32236, +32205, +32206, +32239, +32238, +32207, +32264, +32297, +32296, +32265, +32266, +32299, +32298, +32267, +32268, +32301, +32300, +32269, +32270, +32303, +32302, +32271, +32328, +32361, +32360, +32329, +32330, +32363, +32362, +32331, +32332, +32365, +32364, +32333, +32334, +32367, +32366, +32335, +32392, +32425, +32424, +32393, +32394, +32427, +32426, +32395, +32396, +32429, +32428, +32397, +32398, +32431, +32430, +32399, +32456, +32489, +32488, +32457, +32458, +32491, +32490, +32459, +32460, +32493, +32492, +32461, +32462, +32495, +32494, +32463, +32520, +32553, +32552, +32521, +32522, +32555, +32554, +32523, +32524, +32557, +32556, +32525, +32526, +32559, +32558, +32527, +32584, +32617, +32616, +32585, +32586, +32619, +32618, +32587, +32588, +32621, +32620, +32589, +32590, +32623, +32622, +32591, +32648, +32681, +32680, +32649, +32650, +32683, +32682, +32651, +32652, +32685, +32684, +32653, +32654, +32687, +32686, +32655, +32712, +32745, +32744, +32713, +32714, +32747, +32746, +32715, +32716, +32749, +32748, +32717, +32718, +32751, +32750, +32719, +30736, +30769, +30768, +30737, +30738, +30771, +30770, +30739, +30740, +30773, +30772, +30741, +30742, +30775, +30774, +30743, +30800, +30833, +30832, +30801, +30802, +30835, +30834, +30803, +30804, +30837, +30836, +30805, +30806, +30839, +30838, +30807, +30864, +30897, +30896, +30865, +30866, +30899, +30898, +30867, +30868, +30901, +30900, +30869, +30870, +30903, +30902, +30871, +30928, +30961, +30960, +30929, +30930, +30963, +30962, +30931, +30932, +30965, +30964, +30933, +30934, +30967, +30966, +30935, +30992, +31025, +31024, +30993, +30994, +31027, +31026, +30995, +30996, +31029, +31028, +30997, +30998, +31031, +31030, +30999, +31056, +31089, +31088, +31057, +31058, +31091, +31090, +31059, +31060, +31093, +31092, +31061, +31062, +31095, +31094, +31063, +31120, +31153, +31152, +31121, +31122, +31155, +31154, +31123, +31124, +31157, +31156, +31125, +31126, +31159, +31158, +31127, +31184, +31217, +31216, +31185, +31186, +31219, +31218, +31187, +31188, +31221, +31220, +31189, +31190, +31223, +31222, +31191, +31248, +31281, +31280, +31249, +31250, +31283, +31282, +31251, +31252, +31285, +31284, +31253, +31254, +31287, +31286, +31255, +31312, +31345, +31344, +31313, +31314, +31347, +31346, +31315, +31316, +31349, +31348, +31317, +31318, +31351, +31350, +31319, +31376, +31409, +31408, +31377, +31378, +31411, +31410, +31379, +31380, +31413, +31412, +31381, +31382, +31415, +31414, +31383, +31440, +31473, +31472, +31441, +31442, +31475, +31474, +31443, +31444, +31477, +31476, +31445, +31446, +31479, +31478, +31447, +31504, +31537, +31536, +31505, +31506, +31539, +31538, +31507, +31508, +31541, +31540, +31509, +31510, +31543, +31542, +31511, +31568, +31601, +31600, +31569, +31570, +31603, +31602, +31571, +31572, +31605, +31604, +31573, +31574, +31607, +31606, +31575, +31632, +31665, +31664, +31633, +31634, +31667, +31666, +31635, +31636, +31669, +31668, +31637, +31638, +31671, +31670, +31639, +31696, +31729, +31728, +31697, +31698, +31731, +31730, +31699, +31700, +31733, +31732, +31701, +31702, +31735, +31734, +31703, +31760, +31793, +31792, +31761, +31762, +31795, +31794, +31763, +31764, +31797, +31796, +31765, +31766, +31799, +31798, +31767, +31824, +31857, +31856, +31825, +31826, +31859, +31858, +31827, +31828, +31861, +31860, +31829, +31830, +31863, +31862, +31831, +31888, +31921, +31920, +31889, +31890, +31923, +31922, +31891, +31892, +31925, +31924, +31893, +31894, +31927, +31926, +31895, +31952, +31985, +31984, +31953, +31954, +31987, +31986, +31955, +31956, +31989, +31988, +31957, +31958, +31991, +31990, +31959, +32016, +32049, +32048, +32017, +32018, +32051, +32050, +32019, +32020, +32053, +32052, +32021, +32022, +32055, +32054, +32023, +32080, +32113, +32112, +32081, +32082, +32115, +32114, +32083, +32084, +32117, +32116, +32085, +32086, +32119, +32118, +32087, +32144, +32177, +32176, +32145, +32146, +32179, +32178, +32147, +32148, +32181, +32180, +32149, +32150, +32183, +32182, +32151, +32208, +32241, +32240, +32209, +32210, +32243, +32242, +32211, +32212, +32245, +32244, +32213, +32214, +32247, +32246, +32215, +32272, +32305, +32304, +32273, +32274, +32307, +32306, +32275, +32276, +32309, +32308, +32277, +32278, +32311, +32310, +32279, +32336, +32369, +32368, +32337, +32338, +32371, +32370, +32339, +32340, +32373, +32372, +32341, +32342, +32375, +32374, +32343, +32400, +32433, +32432, +32401, +32402, +32435, +32434, +32403, +32404, +32437, +32436, +32405, +32406, +32439, +32438, +32407, +32464, +32497, +32496, +32465, +32466, +32499, +32498, +32467, +32468, +32501, +32500, +32469, +32470, +32503, +32502, +32471, +32528, +32561, +32560, +32529, +32530, +32563, +32562, +32531, +32532, +32565, +32564, +32533, +32534, +32567, +32566, +32535, +32592, +32625, +32624, +32593, +32594, +32627, +32626, +32595, +32596, +32629, +32628, +32597, +32598, +32631, +32630, +32599, +32656, +32689, +32688, +32657, +32658, +32691, +32690, +32659, +32660, +32693, +32692, +32661, +32662, +32695, +32694, +32663, +32720, +32753, +32752, +32721, +32722, +32755, +32754, +32723, +32724, +32757, +32756, +32725, +32726, +32759, +32758, +32727, +30744, +30777, +30776, +30745, +30746, +30779, +30778, +30747, +30748, +30781, +30780, +30749, +30750, +30783, +30782, +30751, +30808, +30841, +30840, +30809, +30810, +30843, +30842, +30811, +30812, +30845, +30844, +30813, +30814, +30847, +30846, +30815, +30872, +30905, +30904, +30873, +30874, +30907, +30906, +30875, +30876, +30909, +30908, +30877, +30878, +30911, +30910, +30879, +30936, +30969, +30968, +30937, +30938, +30971, +30970, +30939, +30940, +30973, +30972, +30941, +30942, +30975, +30974, +30943, +31000, +31033, +31032, +31001, +31002, +31035, +31034, +31003, +31004, +31037, +31036, +31005, +31006, +31039, +31038, +31007, +31064, +31097, +31096, +31065, +31066, +31099, +31098, +31067, +31068, +31101, +31100, +31069, +31070, +31103, +31102, +31071, +31128, +31161, +31160, +31129, +31130, +31163, +31162, +31131, +31132, +31165, +31164, +31133, +31134, +31167, +31166, +31135, +31192, +31225, +31224, +31193, +31194, +31227, +31226, +31195, +31196, +31229, +31228, +31197, +31198, +31231, +31230, +31199, +31256, +31289, +31288, +31257, +31258, +31291, +31290, +31259, +31260, +31293, +31292, +31261, +31262, +31295, +31294, +31263, +31320, +31353, +31352, +31321, +31322, +31355, +31354, +31323, +31324, +31357, +31356, +31325, +31326, +31359, +31358, +31327, +31384, +31417, +31416, +31385, +31386, +31419, +31418, +31387, +31388, +31421, +31420, +31389, +31390, +31423, +31422, +31391, +31448, +31481, +31480, +31449, +31450, +31483, +31482, +31451, +31452, +31485, +31484, +31453, +31454, +31487, +31486, +31455, +31512, +31545, +31544, +31513, +31514, +31547, +31546, +31515, +31516, +31549, +31548, +31517, +31518, +31551, +31550, +31519, +31576, +31609, +31608, +31577, +31578, +31611, +31610, +31579, +31580, +31613, +31612, +31581, +31582, +31615, +31614, +31583, +31640, +31673, +31672, +31641, +31642, +31675, +31674, +31643, +31644, +31677, +31676, +31645, +31646, +31679, +31678, +31647, +31704, +31737, +31736, +31705, +31706, +31739, +31738, +31707, +31708, +31741, +31740, +31709, +31710, +31743, +31742, +31711, +31768, +31801, +31800, +31769, +31770, +31803, +31802, +31771, +31772, +31805, +31804, +31773, +31774, +31807, +31806, +31775, +31832, +31865, +31864, +31833, +31834, +31867, +31866, +31835, +31836, +31869, +31868, +31837, +31838, +31871, +31870, +31839, +31896, +31929, +31928, +31897, +31898, +31931, +31930, +31899, +31900, +31933, +31932, +31901, +31902, +31935, +31934, +31903, +31960, +31993, +31992, +31961, +31962, +31995, +31994, +31963, +31964, +31997, +31996, +31965, +31966, +31999, +31998, +31967, +32024, +32057, +32056, +32025, +32026, +32059, +32058, +32027, +32028, +32061, +32060, +32029, +32030, +32063, +32062, +32031, +32088, +32121, +32120, +32089, +32090, +32123, +32122, +32091, +32092, +32125, +32124, +32093, +32094, +32127, +32126, +32095, +32152, +32185, +32184, +32153, +32154, +32187, +32186, +32155, +32156, +32189, +32188, +32157, +32158, +32191, +32190, +32159, +32216, +32249, +32248, +32217, +32218, +32251, +32250, +32219, +32220, +32253, +32252, +32221, +32222, +32255, +32254, +32223, +32280, +32313, +32312, +32281, +32282, +32315, +32314, +32283, +32284, +32317, +32316, +32285, +32286, +32319, +32318, +32287, +32344, +32377, +32376, +32345, +32346, +32379, +32378, +32347, +32348, +32381, +32380, +32349, +32350, +32383, +32382, +32351, +32408, +32441, +32440, +32409, +32410, +32443, +32442, +32411, +32412, +32445, +32444, +32413, +32414, +32447, +32446, +32415, +32472, +32505, +32504, +32473, +32474, +32507, +32506, +32475, +32476, +32509, +32508, +32477, +32478, +32511, +32510, +32479, +32536, +32569, +32568, +32537, +32538, +32571, +32570, +32539, +32540, +32573, +32572, +32541, +32542, +32575, +32574, +32543, +32600, +32633, +32632, +32601, +32602, +32635, +32634, +32603, +32604, +32637, +32636, +32605, +32606, +32639, +32638, +32607, +32664, +32697, +32696, +32665, +32666, +32699, +32698, +32667, +32668, +32701, +32700, +32669, +32670, +32703, +32702, +32671, +32728, +32761, +32760, +32729, +32730, +32763, +32762, +32731, +32732, +32765, +32764, +32733, +32734, +32767, +32766, +32735, +32768, +32801, +32800, +32769, +32770, +32803, +32802, +32771, +32772, +32805, +32804, +32773, +32774, +32807, +32806, +32775, +32832, +32865, +32864, +32833, +32834, +32867, +32866, +32835, +32836, +32869, +32868, +32837, +32838, +32871, +32870, +32839, +32896, +32929, +32928, +32897, +32898, +32931, +32930, +32899, +32900, +32933, +32932, +32901, +32902, +32935, +32934, +32903, +32960, +32993, +32992, +32961, +32962, +32995, +32994, +32963, +32964, +32997, +32996, +32965, +32966, +32999, +32998, +32967, +33024, +33057, +33056, +33025, +33026, +33059, +33058, +33027, +33028, +33061, +33060, +33029, +33030, +33063, +33062, +33031, +33088, +33121, +33120, +33089, +33090, +33123, +33122, +33091, +33092, +33125, +33124, +33093, +33094, +33127, +33126, +33095, +33152, +33185, +33184, +33153, +33154, +33187, +33186, +33155, +33156, +33189, +33188, +33157, +33158, +33191, +33190, +33159, +33216, +33249, +33248, +33217, +33218, +33251, +33250, +33219, +33220, +33253, +33252, +33221, +33222, +33255, +33254, +33223, +33280, +33313, +33312, +33281, +33282, +33315, +33314, +33283, +33284, +33317, +33316, +33285, +33286, +33319, +33318, +33287, +33344, +33377, +33376, +33345, +33346, +33379, +33378, +33347, +33348, +33381, +33380, +33349, +33350, +33383, +33382, +33351, +33408, +33441, +33440, +33409, +33410, +33443, +33442, +33411, +33412, +33445, +33444, +33413, +33414, +33447, +33446, +33415, +33472, +33505, +33504, +33473, +33474, +33507, +33506, +33475, +33476, +33509, +33508, +33477, +33478, +33511, +33510, +33479, +33536, +33569, +33568, +33537, +33538, +33571, +33570, +33539, +33540, +33573, +33572, +33541, +33542, +33575, +33574, +33543, +33600, +33633, +33632, +33601, +33602, +33635, +33634, +33603, +33604, +33637, +33636, +33605, +33606, +33639, +33638, +33607, +33664, +33697, +33696, +33665, +33666, +33699, +33698, +33667, +33668, +33701, +33700, +33669, +33670, +33703, +33702, +33671, +33728, +33761, +33760, +33729, +33730, +33763, +33762, +33731, +33732, +33765, +33764, +33733, +33734, +33767, +33766, +33735, +33792, +33825, +33824, +33793, +33794, +33827, +33826, +33795, +33796, +33829, +33828, +33797, +33798, +33831, +33830, +33799, +33856, +33889, +33888, +33857, +33858, +33891, +33890, +33859, +33860, +33893, +33892, +33861, +33862, +33895, +33894, +33863, +33920, +33953, +33952, +33921, +33922, +33955, +33954, +33923, +33924, +33957, +33956, +33925, +33926, +33959, +33958, +33927, +33984, +34017, +34016, +33985, +33986, +34019, +34018, +33987, +33988, +34021, +34020, +33989, +33990, +34023, +34022, +33991, +34048, +34081, +34080, +34049, +34050, +34083, +34082, +34051, +34052, +34085, +34084, +34053, +34054, +34087, +34086, +34055, +34112, +34145, +34144, +34113, +34114, +34147, +34146, +34115, +34116, +34149, +34148, +34117, +34118, +34151, +34150, +34119, +34176, +34209, +34208, +34177, +34178, +34211, +34210, +34179, +34180, +34213, +34212, +34181, +34182, +34215, +34214, +34183, +34240, +34273, +34272, +34241, +34242, +34275, +34274, +34243, +34244, +34277, +34276, +34245, +34246, +34279, +34278, +34247, +34304, +34337, +34336, +34305, +34306, +34339, +34338, +34307, +34308, +34341, +34340, +34309, +34310, +34343, +34342, +34311, +34368, +34401, +34400, +34369, +34370, +34403, +34402, +34371, +34372, +34405, +34404, +34373, +34374, +34407, +34406, +34375, +34432, +34465, +34464, +34433, +34434, +34467, +34466, +34435, +34436, +34469, +34468, +34437, +34438, +34471, +34470, +34439, +34496, +34529, +34528, +34497, +34498, +34531, +34530, +34499, +34500, +34533, +34532, +34501, +34502, +34535, +34534, +34503, +34560, +34593, +34592, +34561, +34562, +34595, +34594, +34563, +34564, +34597, +34596, +34565, +34566, +34599, +34598, +34567, +34624, +34657, +34656, +34625, +34626, +34659, +34658, +34627, +34628, +34661, +34660, +34629, +34630, +34663, +34662, +34631, +34688, +34721, +34720, +34689, +34690, +34723, +34722, +34691, +34692, +34725, +34724, +34693, +34694, +34727, +34726, +34695, +34752, +34785, +34784, +34753, +34754, +34787, +34786, +34755, +34756, +34789, +34788, +34757, +34758, +34791, +34790, +34759, +32776, +32809, +32808, +32777, +32778, +32811, +32810, +32779, +32780, +32813, +32812, +32781, +32782, +32815, +32814, +32783, +32840, +32873, +32872, +32841, +32842, +32875, +32874, +32843, +32844, +32877, +32876, +32845, +32846, +32879, +32878, +32847, +32904, +32937, +32936, +32905, +32906, +32939, +32938, +32907, +32908, +32941, +32940, +32909, +32910, +32943, +32942, +32911, +32968, +33001, +33000, +32969, +32970, +33003, +33002, +32971, +32972, +33005, +33004, +32973, +32974, +33007, +33006, +32975, +33032, +33065, +33064, +33033, +33034, +33067, +33066, +33035, +33036, +33069, +33068, +33037, +33038, +33071, +33070, +33039, +33096, +33129, +33128, +33097, +33098, +33131, +33130, +33099, +33100, +33133, +33132, +33101, +33102, +33135, +33134, +33103, +33160, +33193, +33192, +33161, +33162, +33195, +33194, +33163, +33164, +33197, +33196, +33165, +33166, +33199, +33198, +33167, +33224, +33257, +33256, +33225, +33226, +33259, +33258, +33227, +33228, +33261, +33260, +33229, +33230, +33263, +33262, +33231, +33288, +33321, +33320, +33289, +33290, +33323, +33322, +33291, +33292, +33325, +33324, +33293, +33294, +33327, +33326, +33295, +33352, +33385, +33384, +33353, +33354, +33387, +33386, +33355, +33356, +33389, +33388, +33357, +33358, +33391, +33390, +33359, +33416, +33449, +33448, +33417, +33418, +33451, +33450, +33419, +33420, +33453, +33452, +33421, +33422, +33455, +33454, +33423, +33480, +33513, +33512, +33481, +33482, +33515, +33514, +33483, +33484, +33517, +33516, +33485, +33486, +33519, +33518, +33487, +33544, +33577, +33576, +33545, +33546, +33579, +33578, +33547, +33548, +33581, +33580, +33549, +33550, +33583, +33582, +33551, +33608, +33641, +33640, +33609, +33610, +33643, +33642, +33611, +33612, +33645, +33644, +33613, +33614, +33647, +33646, +33615, +33672, +33705, +33704, +33673, +33674, +33707, +33706, +33675, +33676, +33709, +33708, +33677, +33678, +33711, +33710, +33679, +33736, +33769, +33768, +33737, +33738, +33771, +33770, +33739, +33740, +33773, +33772, +33741, +33742, +33775, +33774, +33743, +33800, +33833, +33832, +33801, +33802, +33835, +33834, +33803, +33804, +33837, +33836, +33805, +33806, +33839, +33838, +33807, +33864, +33897, +33896, +33865, +33866, +33899, +33898, +33867, +33868, +33901, +33900, +33869, +33870, +33903, +33902, +33871, +33928, +33961, +33960, +33929, +33930, +33963, +33962, +33931, +33932, +33965, +33964, +33933, +33934, +33967, +33966, +33935, +33992, +34025, +34024, +33993, +33994, +34027, +34026, +33995, +33996, +34029, +34028, +33997, +33998, +34031, +34030, +33999, +34056, +34089, +34088, +34057, +34058, +34091, +34090, +34059, +34060, +34093, +34092, +34061, +34062, +34095, +34094, +34063, +34120, +34153, +34152, +34121, +34122, +34155, +34154, +34123, +34124, +34157, +34156, +34125, +34126, +34159, +34158, +34127, +34184, +34217, +34216, +34185, +34186, +34219, +34218, +34187, +34188, +34221, +34220, +34189, +34190, +34223, +34222, +34191, +34248, +34281, +34280, +34249, +34250, +34283, +34282, +34251, +34252, +34285, +34284, +34253, +34254, +34287, +34286, +34255, +34312, +34345, +34344, +34313, +34314, +34347, +34346, +34315, +34316, +34349, +34348, +34317, +34318, +34351, +34350, +34319, +34376, +34409, +34408, +34377, +34378, +34411, +34410, +34379, +34380, +34413, +34412, +34381, +34382, +34415, +34414, +34383, +34440, +34473, +34472, +34441, +34442, +34475, +34474, +34443, +34444, +34477, +34476, +34445, +34446, +34479, +34478, +34447, +34504, +34537, +34536, +34505, +34506, +34539, +34538, +34507, +34508, +34541, +34540, +34509, +34510, +34543, +34542, +34511, +34568, +34601, +34600, +34569, +34570, +34603, +34602, +34571, +34572, +34605, +34604, +34573, +34574, +34607, +34606, +34575, +34632, +34665, +34664, +34633, +34634, +34667, +34666, +34635, +34636, +34669, +34668, +34637, +34638, +34671, +34670, +34639, +34696, +34729, +34728, +34697, +34698, +34731, +34730, +34699, +34700, +34733, +34732, +34701, +34702, +34735, +34734, +34703, +34760, +34793, +34792, +34761, +34762, +34795, +34794, +34763, +34764, +34797, +34796, +34765, +34766, +34799, +34798, +34767, +32784, +32817, +32816, +32785, +32786, +32819, +32818, +32787, +32788, +32821, +32820, +32789, +32790, +32823, +32822, +32791, +32848, +32881, +32880, +32849, +32850, +32883, +32882, +32851, +32852, +32885, +32884, +32853, +32854, +32887, +32886, +32855, +32912, +32945, +32944, +32913, +32914, +32947, +32946, +32915, +32916, +32949, +32948, +32917, +32918, +32951, +32950, +32919, +32976, +33009, +33008, +32977, +32978, +33011, +33010, +32979, +32980, +33013, +33012, +32981, +32982, +33015, +33014, +32983, +33040, +33073, +33072, +33041, +33042, +33075, +33074, +33043, +33044, +33077, +33076, +33045, +33046, +33079, +33078, +33047, +33104, +33137, +33136, +33105, +33106, +33139, +33138, +33107, +33108, +33141, +33140, +33109, +33110, +33143, +33142, +33111, +33168, +33201, +33200, +33169, +33170, +33203, +33202, +33171, +33172, +33205, +33204, +33173, +33174, +33207, +33206, +33175, +33232, +33265, +33264, +33233, +33234, +33267, +33266, +33235, +33236, +33269, +33268, +33237, +33238, +33271, +33270, +33239, +33296, +33329, +33328, +33297, +33298, +33331, +33330, +33299, +33300, +33333, +33332, +33301, +33302, +33335, +33334, +33303, +33360, +33393, +33392, +33361, +33362, +33395, +33394, +33363, +33364, +33397, +33396, +33365, +33366, +33399, +33398, +33367, +33424, +33457, +33456, +33425, +33426, +33459, +33458, +33427, +33428, +33461, +33460, +33429, +33430, +33463, +33462, +33431, +33488, +33521, +33520, +33489, +33490, +33523, +33522, +33491, +33492, +33525, +33524, +33493, +33494, +33527, +33526, +33495, +33552, +33585, +33584, +33553, +33554, +33587, +33586, +33555, +33556, +33589, +33588, +33557, +33558, +33591, +33590, +33559, +33616, +33649, +33648, +33617, +33618, +33651, +33650, +33619, +33620, +33653, +33652, +33621, +33622, +33655, +33654, +33623, +33680, +33713, +33712, +33681, +33682, +33715, +33714, +33683, +33684, +33717, +33716, +33685, +33686, +33719, +33718, +33687, +33744, +33777, +33776, +33745, +33746, +33779, +33778, +33747, +33748, +33781, +33780, +33749, +33750, +33783, +33782, +33751, +33808, +33841, +33840, +33809, +33810, +33843, +33842, +33811, +33812, +33845, +33844, +33813, +33814, +33847, +33846, +33815, +33872, +33905, +33904, +33873, +33874, +33907, +33906, +33875, +33876, +33909, +33908, +33877, +33878, +33911, +33910, +33879, +33936, +33969, +33968, +33937, +33938, +33971, +33970, +33939, +33940, +33973, +33972, +33941, +33942, +33975, +33974, +33943, +34000, +34033, +34032, +34001, +34002, +34035, +34034, +34003, +34004, +34037, +34036, +34005, +34006, +34039, +34038, +34007, +34064, +34097, +34096, +34065, +34066, +34099, +34098, +34067, +34068, +34101, +34100, +34069, +34070, +34103, +34102, +34071, +34128, +34161, +34160, +34129, +34130, +34163, +34162, +34131, +34132, +34165, +34164, +34133, +34134, +34167, +34166, +34135, +34192, +34225, +34224, +34193, +34194, +34227, +34226, +34195, +34196, +34229, +34228, +34197, +34198, +34231, +34230, +34199, +34256, +34289, +34288, +34257, +34258, +34291, +34290, +34259, +34260, +34293, +34292, +34261, +34262, +34295, +34294, +34263, +34320, +34353, +34352, +34321, +34322, +34355, +34354, +34323, +34324, +34357, +34356, +34325, +34326, +34359, +34358, +34327, +34384, +34417, +34416, +34385, +34386, +34419, +34418, +34387, +34388, +34421, +34420, +34389, +34390, +34423, +34422, +34391, +34448, +34481, +34480, +34449, +34450, +34483, +34482, +34451, +34452, +34485, +34484, +34453, +34454, +34487, +34486, +34455, +34512, +34545, +34544, +34513, +34514, +34547, +34546, +34515, +34516, +34549, +34548, +34517, +34518, +34551, +34550, +34519, +34576, +34609, +34608, +34577, +34578, +34611, +34610, +34579, +34580, +34613, +34612, +34581, +34582, +34615, +34614, +34583, +34640, +34673, +34672, +34641, +34642, +34675, +34674, +34643, +34644, +34677, +34676, +34645, +34646, +34679, +34678, +34647, +34704, +34737, +34736, +34705, +34706, +34739, +34738, +34707, +34708, +34741, +34740, +34709, +34710, +34743, +34742, +34711, +34768, +34801, +34800, +34769, +34770, +34803, +34802, +34771, +34772, +34805, +34804, +34773, +34774, +34807, +34806, +34775, +32792, +32825, +32824, +32793, +32794, +32827, +32826, +32795, +32796, +32829, +32828, +32797, +32798, +32831, +32830, +32799, +32856, +32889, +32888, +32857, +32858, +32891, +32890, +32859, +32860, +32893, +32892, +32861, +32862, +32895, +32894, +32863, +32920, +32953, +32952, +32921, +32922, +32955, +32954, +32923, +32924, +32957, +32956, +32925, +32926, +32959, +32958, +32927, +32984, +33017, +33016, +32985, +32986, +33019, +33018, +32987, +32988, +33021, +33020, +32989, +32990, +33023, +33022, +32991, +33048, +33081, +33080, +33049, +33050, +33083, +33082, +33051, +33052, +33085, +33084, +33053, +33054, +33087, +33086, +33055, +33112, +33145, +33144, +33113, +33114, +33147, +33146, +33115, +33116, +33149, +33148, +33117, +33118, +33151, +33150, +33119, +33176, +33209, +33208, +33177, +33178, +33211, +33210, +33179, +33180, +33213, +33212, +33181, +33182, +33215, +33214, +33183, +33240, +33273, +33272, +33241, +33242, +33275, +33274, +33243, +33244, +33277, +33276, +33245, +33246, +33279, +33278, +33247, +33304, +33337, +33336, +33305, +33306, +33339, +33338, +33307, +33308, +33341, +33340, +33309, +33310, +33343, +33342, +33311, +33368, +33401, +33400, +33369, +33370, +33403, +33402, +33371, +33372, +33405, +33404, +33373, +33374, +33407, +33406, +33375, +33432, +33465, +33464, +33433, +33434, +33467, +33466, +33435, +33436, +33469, +33468, +33437, +33438, +33471, +33470, +33439, +33496, +33529, +33528, +33497, +33498, +33531, +33530, +33499, +33500, +33533, +33532, +33501, +33502, +33535, +33534, +33503, +33560, +33593, +33592, +33561, +33562, +33595, +33594, +33563, +33564, +33597, +33596, +33565, +33566, +33599, +33598, +33567, +33624, +33657, +33656, +33625, +33626, +33659, +33658, +33627, +33628, +33661, +33660, +33629, +33630, +33663, +33662, +33631, +33688, +33721, +33720, +33689, +33690, +33723, +33722, +33691, +33692, +33725, +33724, +33693, +33694, +33727, +33726, +33695, +33752, +33785, +33784, +33753, +33754, +33787, +33786, +33755, +33756, +33789, +33788, +33757, +33758, +33791, +33790, +33759, +33816, +33849, +33848, +33817, +33818, +33851, +33850, +33819, +33820, +33853, +33852, +33821, +33822, +33855, +33854, +33823, +33880, +33913, +33912, +33881, +33882, +33915, +33914, +33883, +33884, +33917, +33916, +33885, +33886, +33919, +33918, +33887, +33944, +33977, +33976, +33945, +33946, +33979, +33978, +33947, +33948, +33981, +33980, +33949, +33950, +33983, +33982, +33951, +34008, +34041, +34040, +34009, +34010, +34043, +34042, +34011, +34012, +34045, +34044, +34013, +34014, +34047, +34046, +34015, +34072, +34105, +34104, +34073, +34074, +34107, +34106, +34075, +34076, +34109, +34108, +34077, +34078, +34111, +34110, +34079, +34136, +34169, +34168, +34137, +34138, +34171, +34170, +34139, +34140, +34173, +34172, +34141, +34142, +34175, +34174, +34143, +34200, +34233, +34232, +34201, +34202, +34235, +34234, +34203, +34204, +34237, +34236, +34205, +34206, +34239, +34238, +34207, +34264, +34297, +34296, +34265, +34266, +34299, +34298, +34267, +34268, +34301, +34300, +34269, +34270, +34303, +34302, +34271, +34328, +34361, +34360, +34329, +34330, +34363, +34362, +34331, +34332, +34365, +34364, +34333, +34334, +34367, +34366, +34335, +34392, +34425, +34424, +34393, +34394, +34427, +34426, +34395, +34396, +34429, +34428, +34397, +34398, +34431, +34430, +34399, +34456, +34489, +34488, +34457, +34458, +34491, +34490, +34459, +34460, +34493, +34492, +34461, +34462, +34495, +34494, +34463, +34520, +34553, +34552, +34521, +34522, +34555, +34554, +34523, +34524, +34557, +34556, +34525, +34526, +34559, +34558, +34527, +34584, +34617, +34616, +34585, +34586, +34619, +34618, +34587, +34588, +34621, +34620, +34589, +34590, +34623, +34622, +34591, +34648, +34681, +34680, +34649, +34650, +34683, +34682, +34651, +34652, +34685, +34684, +34653, +34654, +34687, +34686, +34655, +34712, +34745, +34744, +34713, +34714, +34747, +34746, +34715, +34716, +34749, +34748, +34717, +34718, +34751, +34750, +34719, +34776, +34809, +34808, +34777, +34778, +34811, +34810, +34779, +34780, +34813, +34812, +34781, +34782, +34815, +34814, +34783, +34816, +34849, +34848, +34817, +34818, +34851, +34850, +34819, +34820, +34853, +34852, +34821, +34822, +34855, +34854, +34823, +34880, +34913, +34912, +34881, +34882, +34915, +34914, +34883, +34884, +34917, +34916, +34885, +34886, +34919, +34918, +34887, +34944, +34977, +34976, +34945, +34946, +34979, +34978, +34947, +34948, +34981, +34980, +34949, +34950, +34983, +34982, +34951, +35008, +35041, +35040, +35009, +35010, +35043, +35042, +35011, +35012, +35045, +35044, +35013, +35014, +35047, +35046, +35015, +35072, +35105, +35104, +35073, +35074, +35107, +35106, +35075, +35076, +35109, +35108, +35077, +35078, +35111, +35110, +35079, +35136, +35169, +35168, +35137, +35138, +35171, +35170, +35139, +35140, +35173, +35172, +35141, +35142, +35175, +35174, +35143, +35200, +35233, +35232, +35201, +35202, +35235, +35234, +35203, +35204, +35237, +35236, +35205, +35206, +35239, +35238, +35207, +35264, +35297, +35296, +35265, +35266, +35299, +35298, +35267, +35268, +35301, +35300, +35269, +35270, +35303, +35302, +35271, +35328, +35361, +35360, +35329, +35330, +35363, +35362, +35331, +35332, +35365, +35364, +35333, +35334, +35367, +35366, +35335, +35392, +35425, +35424, +35393, +35394, +35427, +35426, +35395, +35396, +35429, +35428, +35397, +35398, +35431, +35430, +35399, +35456, +35489, +35488, +35457, +35458, +35491, +35490, +35459, +35460, +35493, +35492, +35461, +35462, +35495, +35494, +35463, +35520, +35553, +35552, +35521, +35522, +35555, +35554, +35523, +35524, +35557, +35556, +35525, +35526, +35559, +35558, +35527, +35584, +35617, +35616, +35585, +35586, +35619, +35618, +35587, +35588, +35621, +35620, +35589, +35590, +35623, +35622, +35591, +35648, +35681, +35680, +35649, +35650, +35683, +35682, +35651, +35652, +35685, +35684, +35653, +35654, +35687, +35686, +35655, +35712, +35745, +35744, +35713, +35714, +35747, +35746, +35715, +35716, +35749, +35748, +35717, +35718, +35751, +35750, +35719, +35776, +35809, +35808, +35777, +35778, +35811, +35810, +35779, +35780, +35813, +35812, +35781, +35782, +35815, +35814, +35783, +35840, +35873, +35872, +35841, +35842, +35875, +35874, +35843, +35844, +35877, +35876, +35845, +35846, +35879, +35878, +35847, +35904, +35937, +35936, +35905, +35906, +35939, +35938, +35907, +35908, +35941, +35940, +35909, +35910, +35943, +35942, +35911, +35968, +36001, +36000, +35969, +35970, +36003, +36002, +35971, +35972, +36005, +36004, +35973, +35974, +36007, +36006, +35975, +36032, +36065, +36064, +36033, +36034, +36067, +36066, +36035, +36036, +36069, +36068, +36037, +36038, +36071, +36070, +36039, +36096, +36129, +36128, +36097, +36098, +36131, +36130, +36099, +36100, +36133, +36132, +36101, +36102, +36135, +36134, +36103, +36160, +36193, +36192, +36161, +36162, +36195, +36194, +36163, +36164, +36197, +36196, +36165, +36166, +36199, +36198, +36167, +36224, +36257, +36256, +36225, +36226, +36259, +36258, +36227, +36228, +36261, +36260, +36229, +36230, +36263, +36262, +36231, +36288, +36321, +36320, +36289, +36290, +36323, +36322, +36291, +36292, +36325, +36324, +36293, +36294, +36327, +36326, +36295, +36352, +36385, +36384, +36353, +36354, +36387, +36386, +36355, +36356, +36389, +36388, +36357, +36358, +36391, +36390, +36359, +36416, +36449, +36448, +36417, +36418, +36451, +36450, +36419, +36420, +36453, +36452, +36421, +36422, +36455, +36454, +36423, +36480, +36513, +36512, +36481, +36482, +36515, +36514, +36483, +36484, +36517, +36516, +36485, +36486, +36519, +36518, +36487, +36544, +36577, +36576, +36545, +36546, +36579, +36578, +36547, +36548, +36581, +36580, +36549, +36550, +36583, +36582, +36551, +36608, +36641, +36640, +36609, +36610, +36643, +36642, +36611, +36612, +36645, +36644, +36613, +36614, +36647, +36646, +36615, +36672, +36705, +36704, +36673, +36674, +36707, +36706, +36675, +36676, +36709, +36708, +36677, +36678, +36711, +36710, +36679, +36736, +36769, +36768, +36737, +36738, +36771, +36770, +36739, +36740, +36773, +36772, +36741, +36742, +36775, +36774, +36743, +36800, +36833, +36832, +36801, +36802, +36835, +36834, +36803, +36804, +36837, +36836, +36805, +36806, +36839, +36838, +36807, +34824, +34857, +34856, +34825, +34826, +34859, +34858, +34827, +34828, +34861, +34860, +34829, +34830, +34863, +34862, +34831, +34888, +34921, +34920, +34889, +34890, +34923, +34922, +34891, +34892, +34925, +34924, +34893, +34894, +34927, +34926, +34895, +34952, +34985, +34984, +34953, +34954, +34987, +34986, +34955, +34956, +34989, +34988, +34957, +34958, +34991, +34990, +34959, +35016, +35049, +35048, +35017, +35018, +35051, +35050, +35019, +35020, +35053, +35052, +35021, +35022, +35055, +35054, +35023, +35080, +35113, +35112, +35081, +35082, +35115, +35114, +35083, +35084, +35117, +35116, +35085, +35086, +35119, +35118, +35087, +35144, +35177, +35176, +35145, +35146, +35179, +35178, +35147, +35148, +35181, +35180, +35149, +35150, +35183, +35182, +35151, +35208, +35241, +35240, +35209, +35210, +35243, +35242, +35211, +35212, +35245, +35244, +35213, +35214, +35247, +35246, +35215, +35272, +35305, +35304, +35273, +35274, +35307, +35306, +35275, +35276, +35309, +35308, +35277, +35278, +35311, +35310, +35279, +35336, +35369, +35368, +35337, +35338, +35371, +35370, +35339, +35340, +35373, +35372, +35341, +35342, +35375, +35374, +35343, +35400, +35433, +35432, +35401, +35402, +35435, +35434, +35403, +35404, +35437, +35436, +35405, +35406, +35439, +35438, +35407, +35464, +35497, +35496, +35465, +35466, +35499, +35498, +35467, +35468, +35501, +35500, +35469, +35470, +35503, +35502, +35471, +35528, +35561, +35560, +35529, +35530, +35563, +35562, +35531, +35532, +35565, +35564, +35533, +35534, +35567, +35566, +35535, +35592, +35625, +35624, +35593, +35594, +35627, +35626, +35595, +35596, +35629, +35628, +35597, +35598, +35631, +35630, +35599, +35656, +35689, +35688, +35657, +35658, +35691, +35690, +35659, +35660, +35693, +35692, +35661, +35662, +35695, +35694, +35663, +35720, +35753, +35752, +35721, +35722, +35755, +35754, +35723, +35724, +35757, +35756, +35725, +35726, +35759, +35758, +35727, +35784, +35817, +35816, +35785, +35786, +35819, +35818, +35787, +35788, +35821, +35820, +35789, +35790, +35823, +35822, +35791, +35848, +35881, +35880, +35849, +35850, +35883, +35882, +35851, +35852, +35885, +35884, +35853, +35854, +35887, +35886, +35855, +35912, +35945, +35944, +35913, +35914, +35947, +35946, +35915, +35916, +35949, +35948, +35917, +35918, +35951, +35950, +35919, +35976, +36009, +36008, +35977, +35978, +36011, +36010, +35979, +35980, +36013, +36012, +35981, +35982, +36015, +36014, +35983, +36040, +36073, +36072, +36041, +36042, +36075, +36074, +36043, +36044, +36077, +36076, +36045, +36046, +36079, +36078, +36047, +36104, +36137, +36136, +36105, +36106, +36139, +36138, +36107, +36108, +36141, +36140, +36109, +36110, +36143, +36142, +36111, +36168, +36201, +36200, +36169, +36170, +36203, +36202, +36171, +36172, +36205, +36204, +36173, +36174, +36207, +36206, +36175, +36232, +36265, +36264, +36233, +36234, +36267, +36266, +36235, +36236, +36269, +36268, +36237, +36238, +36271, +36270, +36239, +36296, +36329, +36328, +36297, +36298, +36331, +36330, +36299, +36300, +36333, +36332, +36301, +36302, +36335, +36334, +36303, +36360, +36393, +36392, +36361, +36362, +36395, +36394, +36363, +36364, +36397, +36396, +36365, +36366, +36399, +36398, +36367, +36424, +36457, +36456, +36425, +36426, +36459, +36458, +36427, +36428, +36461, +36460, +36429, +36430, +36463, +36462, +36431, +36488, +36521, +36520, +36489, +36490, +36523, +36522, +36491, +36492, +36525, +36524, +36493, +36494, +36527, +36526, +36495, +36552, +36585, +36584, +36553, +36554, +36587, +36586, +36555, +36556, +36589, +36588, +36557, +36558, +36591, +36590, +36559, +36616, +36649, +36648, +36617, +36618, +36651, +36650, +36619, +36620, +36653, +36652, +36621, +36622, +36655, +36654, +36623, +36680, +36713, +36712, +36681, +36682, +36715, +36714, +36683, +36684, +36717, +36716, +36685, +36686, +36719, +36718, +36687, +36744, +36777, +36776, +36745, +36746, +36779, +36778, +36747, +36748, +36781, +36780, +36749, +36750, +36783, +36782, +36751, +36808, +36841, +36840, +36809, +36810, +36843, +36842, +36811, +36812, +36845, +36844, +36813, +36814, +36847, +36846, +36815, +34832, +34865, +34864, +34833, +34834, +34867, +34866, +34835, +34836, +34869, +34868, +34837, +34838, +34871, +34870, +34839, +34896, +34929, +34928, +34897, +34898, +34931, +34930, +34899, +34900, +34933, +34932, +34901, +34902, +34935, +34934, +34903, +34960, +34993, +34992, +34961, +34962, +34995, +34994, +34963, +34964, +34997, +34996, +34965, +34966, +34999, +34998, +34967, +35024, +35057, +35056, +35025, +35026, +35059, +35058, +35027, +35028, +35061, +35060, +35029, +35030, +35063, +35062, +35031, +35088, +35121, +35120, +35089, +35090, +35123, +35122, +35091, +35092, +35125, +35124, +35093, +35094, +35127, +35126, +35095, +35152, +35185, +35184, +35153, +35154, +35187, +35186, +35155, +35156, +35189, +35188, +35157, +35158, +35191, +35190, +35159, +35216, +35249, +35248, +35217, +35218, +35251, +35250, +35219, +35220, +35253, +35252, +35221, +35222, +35255, +35254, +35223, +35280, +35313, +35312, +35281, +35282, +35315, +35314, +35283, +35284, +35317, +35316, +35285, +35286, +35319, +35318, +35287, +35344, +35377, +35376, +35345, +35346, +35379, +35378, +35347, +35348, +35381, +35380, +35349, +35350, +35383, +35382, +35351, +35408, +35441, +35440, +35409, +35410, +35443, +35442, +35411, +35412, +35445, +35444, +35413, +35414, +35447, +35446, +35415, +35472, +35505, +35504, +35473, +35474, +35507, +35506, +35475, +35476, +35509, +35508, +35477, +35478, +35511, +35510, +35479, +35536, +35569, +35568, +35537, +35538, +35571, +35570, +35539, +35540, +35573, +35572, +35541, +35542, +35575, +35574, +35543, +35600, +35633, +35632, +35601, +35602, +35635, +35634, +35603, +35604, +35637, +35636, +35605, +35606, +35639, +35638, +35607, +35664, +35697, +35696, +35665, +35666, +35699, +35698, +35667, +35668, +35701, +35700, +35669, +35670, +35703, +35702, +35671, +35728, +35761, +35760, +35729, +35730, +35763, +35762, +35731, +35732, +35765, +35764, +35733, +35734, +35767, +35766, +35735, +35792, +35825, +35824, +35793, +35794, +35827, +35826, +35795, +35796, +35829, +35828, +35797, +35798, +35831, +35830, +35799, +35856, +35889, +35888, +35857, +35858, +35891, +35890, +35859, +35860, +35893, +35892, +35861, +35862, +35895, +35894, +35863, +35920, +35953, +35952, +35921, +35922, +35955, +35954, +35923, +35924, +35957, +35956, +35925, +35926, +35959, +35958, +35927, +35984, +36017, +36016, +35985, +35986, +36019, +36018, +35987, +35988, +36021, +36020, +35989, +35990, +36023, +36022, +35991, +36048, +36081, +36080, +36049, +36050, +36083, +36082, +36051, +36052, +36085, +36084, +36053, +36054, +36087, +36086, +36055, +36112, +36145, +36144, +36113, +36114, +36147, +36146, +36115, +36116, +36149, +36148, +36117, +36118, +36151, +36150, +36119, +36176, +36209, +36208, +36177, +36178, +36211, +36210, +36179, +36180, +36213, +36212, +36181, +36182, +36215, +36214, +36183, +36240, +36273, +36272, +36241, +36242, +36275, +36274, +36243, +36244, +36277, +36276, +36245, +36246, +36279, +36278, +36247, +36304, +36337, +36336, +36305, +36306, +36339, +36338, +36307, +36308, +36341, +36340, +36309, +36310, +36343, +36342, +36311, +36368, +36401, +36400, +36369, +36370, +36403, +36402, +36371, +36372, +36405, +36404, +36373, +36374, +36407, +36406, +36375, +36432, +36465, +36464, +36433, +36434, +36467, +36466, +36435, +36436, +36469, +36468, +36437, +36438, +36471, +36470, +36439, +36496, +36529, +36528, +36497, +36498, +36531, +36530, +36499, +36500, +36533, +36532, +36501, +36502, +36535, +36534, +36503, +36560, +36593, +36592, +36561, +36562, +36595, +36594, +36563, +36564, +36597, +36596, +36565, +36566, +36599, +36598, +36567, +36624, +36657, +36656, +36625, +36626, +36659, +36658, +36627, +36628, +36661, +36660, +36629, +36630, +36663, +36662, +36631, +36688, +36721, +36720, +36689, +36690, +36723, +36722, +36691, +36692, +36725, +36724, +36693, +36694, +36727, +36726, +36695, +36752, +36785, +36784, +36753, +36754, +36787, +36786, +36755, +36756, +36789, +36788, +36757, +36758, +36791, +36790, +36759, +36816, +36849, +36848, +36817, +36818, +36851, +36850, +36819, +36820, +36853, +36852, +36821, +36822, +36855, +36854, +36823, +34840, +34873, +34872, +34841, +34842, +34875, +34874, +34843, +34844, +34877, +34876, +34845, +34846, +34879, +34878, +34847, +34904, +34937, +34936, +34905, +34906, +34939, +34938, +34907, +34908, +34941, +34940, +34909, +34910, +34943, +34942, +34911, +34968, +35001, +35000, +34969, +34970, +35003, +35002, +34971, +34972, +35005, +35004, +34973, +34974, +35007, +35006, +34975, +35032, +35065, +35064, +35033, +35034, +35067, +35066, +35035, +35036, +35069, +35068, +35037, +35038, +35071, +35070, +35039, +35096, +35129, +35128, +35097, +35098, +35131, +35130, +35099, +35100, +35133, +35132, +35101, +35102, +35135, +35134, +35103, +35160, +35193, +35192, +35161, +35162, +35195, +35194, +35163, +35164, +35197, +35196, +35165, +35166, +35199, +35198, +35167, +35224, +35257, +35256, +35225, +35226, +35259, +35258, +35227, +35228, +35261, +35260, +35229, +35230, +35263, +35262, +35231, +35288, +35321, +35320, +35289, +35290, +35323, +35322, +35291, +35292, +35325, +35324, +35293, +35294, +35327, +35326, +35295, +35352, +35385, +35384, +35353, +35354, +35387, +35386, +35355, +35356, +35389, +35388, +35357, +35358, +35391, +35390, +35359, +35416, +35449, +35448, +35417, +35418, +35451, +35450, +35419, +35420, +35453, +35452, +35421, +35422, +35455, +35454, +35423, +35480, +35513, +35512, +35481, +35482, +35515, +35514, +35483, +35484, +35517, +35516, +35485, +35486, +35519, +35518, +35487, +35544, +35577, +35576, +35545, +35546, +35579, +35578, +35547, +35548, +35581, +35580, +35549, +35550, +35583, +35582, +35551, +35608, +35641, +35640, +35609, +35610, +35643, +35642, +35611, +35612, +35645, +35644, +35613, +35614, +35647, +35646, +35615, +35672, +35705, +35704, +35673, +35674, +35707, +35706, +35675, +35676, +35709, +35708, +35677, +35678, +35711, +35710, +35679, +35736, +35769, +35768, +35737, +35738, +35771, +35770, +35739, +35740, +35773, +35772, +35741, +35742, +35775, +35774, +35743, +35800, +35833, +35832, +35801, +35802, +35835, +35834, +35803, +35804, +35837, +35836, +35805, +35806, +35839, +35838, +35807, +35864, +35897, +35896, +35865, +35866, +35899, +35898, +35867, +35868, +35901, +35900, +35869, +35870, +35903, +35902, +35871, +35928, +35961, +35960, +35929, +35930, +35963, +35962, +35931, +35932, +35965, +35964, +35933, +35934, +35967, +35966, +35935, +35992, +36025, +36024, +35993, +35994, +36027, +36026, +35995, +35996, +36029, +36028, +35997, +35998, +36031, +36030, +35999, +36056, +36089, +36088, +36057, +36058, +36091, +36090, +36059, +36060, +36093, +36092, +36061, +36062, +36095, +36094, +36063, +36120, +36153, +36152, +36121, +36122, +36155, +36154, +36123, +36124, +36157, +36156, +36125, +36126, +36159, +36158, +36127, +36184, +36217, +36216, +36185, +36186, +36219, +36218, +36187, +36188, +36221, +36220, +36189, +36190, +36223, +36222, +36191, +36248, +36281, +36280, +36249, +36250, +36283, +36282, +36251, +36252, +36285, +36284, +36253, +36254, +36287, +36286, +36255, +36312, +36345, +36344, +36313, +36314, +36347, +36346, +36315, +36316, +36349, +36348, +36317, +36318, +36351, +36350, +36319, +36376, +36409, +36408, +36377, +36378, +36411, +36410, +36379, +36380, +36413, +36412, +36381, +36382, +36415, +36414, +36383, +36440, +36473, +36472, +36441, +36442, +36475, +36474, +36443, +36444, +36477, +36476, +36445, +36446, +36479, +36478, +36447, +36504, +36537, +36536, +36505, +36506, +36539, +36538, +36507, +36508, +36541, +36540, +36509, +36510, +36543, +36542, +36511, +36568, +36601, +36600, +36569, +36570, +36603, +36602, +36571, +36572, +36605, +36604, +36573, +36574, +36607, +36606, +36575, +36632, +36665, +36664, +36633, +36634, +36667, +36666, +36635, +36636, +36669, +36668, +36637, +36638, +36671, +36670, +36639, +36696, +36729, +36728, +36697, +36698, +36731, +36730, +36699, +36700, +36733, +36732, +36701, +36702, +36735, +36734, +36703, +36760, +36793, +36792, +36761, +36762, +36795, +36794, +36763, +36764, +36797, +36796, +36765, +36766, +36799, +36798, +36767, +36824, +36857, +36856, +36825, +36826, +36859, +36858, +36827, +36828, +36861, +36860, +36829, +36830, +36863, +36862, +36831, +36864, +36897, +36896, +36865, +36866, +36899, +36898, +36867, +36868, +36901, +36900, +36869, +36870, +36903, +36902, +36871, +36928, +36961, +36960, +36929, +36930, +36963, +36962, +36931, +36932, +36965, +36964, +36933, +36934, +36967, +36966, +36935, +36992, +37025, +37024, +36993, +36994, +37027, +37026, +36995, +36996, +37029, +37028, +36997, +36998, +37031, +37030, +36999, +37056, +37089, +37088, +37057, +37058, +37091, +37090, +37059, +37060, +37093, +37092, +37061, +37062, +37095, +37094, +37063, +37120, +37153, +37152, +37121, +37122, +37155, +37154, +37123, +37124, +37157, +37156, +37125, +37126, +37159, +37158, +37127, +37184, +37217, +37216, +37185, +37186, +37219, +37218, +37187, +37188, +37221, +37220, +37189, +37190, +37223, +37222, +37191, +37248, +37281, +37280, +37249, +37250, +37283, +37282, +37251, +37252, +37285, +37284, +37253, +37254, +37287, +37286, +37255, +37312, +37345, +37344, +37313, +37314, +37347, +37346, +37315, +37316, +37349, +37348, +37317, +37318, +37351, +37350, +37319, +37376, +37409, +37408, +37377, +37378, +37411, +37410, +37379, +37380, +37413, +37412, +37381, +37382, +37415, +37414, +37383, +37440, +37473, +37472, +37441, +37442, +37475, +37474, +37443, +37444, +37477, +37476, +37445, +37446, +37479, +37478, +37447, +37504, +37537, +37536, +37505, +37506, +37539, +37538, +37507, +37508, +37541, +37540, +37509, +37510, +37543, +37542, +37511, +37568, +37601, +37600, +37569, +37570, +37603, +37602, +37571, +37572, +37605, +37604, +37573, +37574, +37607, +37606, +37575, +37632, +37665, +37664, +37633, +37634, +37667, +37666, +37635, +37636, +37669, +37668, +37637, +37638, +37671, +37670, +37639, +37696, +37729, +37728, +37697, +37698, +37731, +37730, +37699, +37700, +37733, +37732, +37701, +37702, +37735, +37734, +37703, +37760, +37793, +37792, +37761, +37762, +37795, +37794, +37763, +37764, +37797, +37796, +37765, +37766, +37799, +37798, +37767, +37824, +37857, +37856, +37825, +37826, +37859, +37858, +37827, +37828, +37861, +37860, +37829, +37830, +37863, +37862, +37831, +37888, +37921, +37920, +37889, +37890, +37923, +37922, +37891, +37892, +37925, +37924, +37893, +37894, +37927, +37926, +37895, +37952, +37985, +37984, +37953, +37954, +37987, +37986, +37955, +37956, +37989, +37988, +37957, +37958, +37991, +37990, +37959, +38016, +38049, +38048, +38017, +38018, +38051, +38050, +38019, +38020, +38053, +38052, +38021, +38022, +38055, +38054, +38023, +38080, +38113, +38112, +38081, +38082, +38115, +38114, +38083, +38084, +38117, +38116, +38085, +38086, +38119, +38118, +38087, +38144, +38177, +38176, +38145, +38146, +38179, +38178, +38147, +38148, +38181, +38180, +38149, +38150, +38183, +38182, +38151, +38208, +38241, +38240, +38209, +38210, +38243, +38242, +38211, +38212, +38245, +38244, +38213, +38214, +38247, +38246, +38215, +38272, +38305, +38304, +38273, +38274, +38307, +38306, +38275, +38276, +38309, +38308, +38277, +38278, +38311, +38310, +38279, +38336, +38369, +38368, +38337, +38338, +38371, +38370, +38339, +38340, +38373, +38372, +38341, +38342, +38375, +38374, +38343, +38400, +38433, +38432, +38401, +38402, +38435, +38434, +38403, +38404, +38437, +38436, +38405, +38406, +38439, +38438, +38407, +38464, +38497, +38496, +38465, +38466, +38499, +38498, +38467, +38468, +38501, +38500, +38469, +38470, +38503, +38502, +38471, +38528, +38561, +38560, +38529, +38530, +38563, +38562, +38531, +38532, +38565, +38564, +38533, +38534, +38567, +38566, +38535, +38592, +38625, +38624, +38593, +38594, +38627, +38626, +38595, +38596, +38629, +38628, +38597, +38598, +38631, +38630, +38599, +38656, +38689, +38688, +38657, +38658, +38691, +38690, +38659, +38660, +38693, +38692, +38661, +38662, +38695, +38694, +38663, +38720, +38753, +38752, +38721, +38722, +38755, +38754, +38723, +38724, +38757, +38756, +38725, +38726, +38759, +38758, +38727, +38784, +38817, +38816, +38785, +38786, +38819, +38818, +38787, +38788, +38821, +38820, +38789, +38790, +38823, +38822, +38791, +38848, +38881, +38880, +38849, +38850, +38883, +38882, +38851, +38852, +38885, +38884, +38853, +38854, +38887, +38886, +38855, +36872, +36905, +36904, +36873, +36874, +36907, +36906, +36875, +36876, +36909, +36908, +36877, +36878, +36911, +36910, +36879, +36936, +36969, +36968, +36937, +36938, +36971, +36970, +36939, +36940, +36973, +36972, +36941, +36942, +36975, +36974, +36943, +37000, +37033, +37032, +37001, +37002, +37035, +37034, +37003, +37004, +37037, +37036, +37005, +37006, +37039, +37038, +37007, +37064, +37097, +37096, +37065, +37066, +37099, +37098, +37067, +37068, +37101, +37100, +37069, +37070, +37103, +37102, +37071, +37128, +37161, +37160, +37129, +37130, +37163, +37162, +37131, +37132, +37165, +37164, +37133, +37134, +37167, +37166, +37135, +37192, +37225, +37224, +37193, +37194, +37227, +37226, +37195, +37196, +37229, +37228, +37197, +37198, +37231, +37230, +37199, +37256, +37289, +37288, +37257, +37258, +37291, +37290, +37259, +37260, +37293, +37292, +37261, +37262, +37295, +37294, +37263, +37320, +37353, +37352, +37321, +37322, +37355, +37354, +37323, +37324, +37357, +37356, +37325, +37326, +37359, +37358, +37327, +37384, +37417, +37416, +37385, +37386, +37419, +37418, +37387, +37388, +37421, +37420, +37389, +37390, +37423, +37422, +37391, +37448, +37481, +37480, +37449, +37450, +37483, +37482, +37451, +37452, +37485, +37484, +37453, +37454, +37487, +37486, +37455, +37512, +37545, +37544, +37513, +37514, +37547, +37546, +37515, +37516, +37549, +37548, +37517, +37518, +37551, +37550, +37519, +37576, +37609, +37608, +37577, +37578, +37611, +37610, +37579, +37580, +37613, +37612, +37581, +37582, +37615, +37614, +37583, +37640, +37673, +37672, +37641, +37642, +37675, +37674, +37643, +37644, +37677, +37676, +37645, +37646, +37679, +37678, +37647, +37704, +37737, +37736, +37705, +37706, +37739, +37738, +37707, +37708, +37741, +37740, +37709, +37710, +37743, +37742, +37711, +37768, +37801, +37800, +37769, +37770, +37803, +37802, +37771, +37772, +37805, +37804, +37773, +37774, +37807, +37806, +37775, +37832, +37865, +37864, +37833, +37834, +37867, +37866, +37835, +37836, +37869, +37868, +37837, +37838, +37871, +37870, +37839, +37896, +37929, +37928, +37897, +37898, +37931, +37930, +37899, +37900, +37933, +37932, +37901, +37902, +37935, +37934, +37903, +37960, +37993, +37992, +37961, +37962, +37995, +37994, +37963, +37964, +37997, +37996, +37965, +37966, +37999, +37998, +37967, +38024, +38057, +38056, +38025, +38026, +38059, +38058, +38027, +38028, +38061, +38060, +38029, +38030, +38063, +38062, +38031, +38088, +38121, +38120, +38089, +38090, +38123, +38122, +38091, +38092, +38125, +38124, +38093, +38094, +38127, +38126, +38095, +38152, +38185, +38184, +38153, +38154, +38187, +38186, +38155, +38156, +38189, +38188, +38157, +38158, +38191, +38190, +38159, +38216, +38249, +38248, +38217, +38218, +38251, +38250, +38219, +38220, +38253, +38252, +38221, +38222, +38255, +38254, +38223, +38280, +38313, +38312, +38281, +38282, +38315, +38314, +38283, +38284, +38317, +38316, +38285, +38286, +38319, +38318, +38287, +38344, +38377, +38376, +38345, +38346, +38379, +38378, +38347, +38348, +38381, +38380, +38349, +38350, +38383, +38382, +38351, +38408, +38441, +38440, +38409, +38410, +38443, +38442, +38411, +38412, +38445, +38444, +38413, +38414, +38447, +38446, +38415, +38472, +38505, +38504, +38473, +38474, +38507, +38506, +38475, +38476, +38509, +38508, +38477, +38478, +38511, +38510, +38479, +38536, +38569, +38568, +38537, +38538, +38571, +38570, +38539, +38540, +38573, +38572, +38541, +38542, +38575, +38574, +38543, +38600, +38633, +38632, +38601, +38602, +38635, +38634, +38603, +38604, +38637, +38636, +38605, +38606, +38639, +38638, +38607, +38664, +38697, +38696, +38665, +38666, +38699, +38698, +38667, +38668, +38701, +38700, +38669, +38670, +38703, +38702, +38671, +38728, +38761, +38760, +38729, +38730, +38763, +38762, +38731, +38732, +38765, +38764, +38733, +38734, +38767, +38766, +38735, +38792, +38825, +38824, +38793, +38794, +38827, +38826, +38795, +38796, +38829, +38828, +38797, +38798, +38831, +38830, +38799, +38856, +38889, +38888, +38857, +38858, +38891, +38890, +38859, +38860, +38893, +38892, +38861, +38862, +38895, +38894, +38863, +36880, +36913, +36912, +36881, +36882, +36915, +36914, +36883, +36884, +36917, +36916, +36885, +36886, +36919, +36918, +36887, +36944, +36977, +36976, +36945, +36946, +36979, +36978, +36947, +36948, +36981, +36980, +36949, +36950, +36983, +36982, +36951, +37008, +37041, +37040, +37009, +37010, +37043, +37042, +37011, +37012, +37045, +37044, +37013, +37014, +37047, +37046, +37015, +37072, +37105, +37104, +37073, +37074, +37107, +37106, +37075, +37076, +37109, +37108, +37077, +37078, +37111, +37110, +37079, +37136, +37169, +37168, +37137, +37138, +37171, +37170, +37139, +37140, +37173, +37172, +37141, +37142, +37175, +37174, +37143, +37200, +37233, +37232, +37201, +37202, +37235, +37234, +37203, +37204, +37237, +37236, +37205, +37206, +37239, +37238, +37207, +37264, +37297, +37296, +37265, +37266, +37299, +37298, +37267, +37268, +37301, +37300, +37269, +37270, +37303, +37302, +37271, +37328, +37361, +37360, +37329, +37330, +37363, +37362, +37331, +37332, +37365, +37364, +37333, +37334, +37367, +37366, +37335, +37392, +37425, +37424, +37393, +37394, +37427, +37426, +37395, +37396, +37429, +37428, +37397, +37398, +37431, +37430, +37399, +37456, +37489, +37488, +37457, +37458, +37491, +37490, +37459, +37460, +37493, +37492, +37461, +37462, +37495, +37494, +37463, +37520, +37553, +37552, +37521, +37522, +37555, +37554, +37523, +37524, +37557, +37556, +37525, +37526, +37559, +37558, +37527, +37584, +37617, +37616, +37585, +37586, +37619, +37618, +37587, +37588, +37621, +37620, +37589, +37590, +37623, +37622, +37591, +37648, +37681, +37680, +37649, +37650, +37683, +37682, +37651, +37652, +37685, +37684, +37653, +37654, +37687, +37686, +37655, +37712, +37745, +37744, +37713, +37714, +37747, +37746, +37715, +37716, +37749, +37748, +37717, +37718, +37751, +37750, +37719, +37776, +37809, +37808, +37777, +37778, +37811, +37810, +37779, +37780, +37813, +37812, +37781, +37782, +37815, +37814, +37783, +37840, +37873, +37872, +37841, +37842, +37875, +37874, +37843, +37844, +37877, +37876, +37845, +37846, +37879, +37878, +37847, +37904, +37937, +37936, +37905, +37906, +37939, +37938, +37907, +37908, +37941, +37940, +37909, +37910, +37943, +37942, +37911, +37968, +38001, +38000, +37969, +37970, +38003, +38002, +37971, +37972, +38005, +38004, +37973, +37974, +38007, +38006, +37975, +38032, +38065, +38064, +38033, +38034, +38067, +38066, +38035, +38036, +38069, +38068, +38037, +38038, +38071, +38070, +38039, +38096, +38129, +38128, +38097, +38098, +38131, +38130, +38099, +38100, +38133, +38132, +38101, +38102, +38135, +38134, +38103, +38160, +38193, +38192, +38161, +38162, +38195, +38194, +38163, +38164, +38197, +38196, +38165, +38166, +38199, +38198, +38167, +38224, +38257, +38256, +38225, +38226, +38259, +38258, +38227, +38228, +38261, +38260, +38229, +38230, +38263, +38262, +38231, +38288, +38321, +38320, +38289, +38290, +38323, +38322, +38291, +38292, +38325, +38324, +38293, +38294, +38327, +38326, +38295, +38352, +38385, +38384, +38353, +38354, +38387, +38386, +38355, +38356, +38389, +38388, +38357, +38358, +38391, +38390, +38359, +38416, +38449, +38448, +38417, +38418, +38451, +38450, +38419, +38420, +38453, +38452, +38421, +38422, +38455, +38454, +38423, +38480, +38513, +38512, +38481, +38482, +38515, +38514, +38483, +38484, +38517, +38516, +38485, +38486, +38519, +38518, +38487, +38544, +38577, +38576, +38545, +38546, +38579, +38578, +38547, +38548, +38581, +38580, +38549, +38550, +38583, +38582, +38551, +38608, +38641, +38640, +38609, +38610, +38643, +38642, +38611, +38612, +38645, +38644, +38613, +38614, +38647, +38646, +38615, +38672, +38705, +38704, +38673, +38674, +38707, +38706, +38675, +38676, +38709, +38708, +38677, +38678, +38711, +38710, +38679, +38736, +38769, +38768, +38737, +38738, +38771, +38770, +38739, +38740, +38773, +38772, +38741, +38742, +38775, +38774, +38743, +38800, +38833, +38832, +38801, +38802, +38835, +38834, +38803, +38804, +38837, +38836, +38805, +38806, +38839, +38838, +38807, +38864, +38897, +38896, +38865, +38866, +38899, +38898, +38867, +38868, +38901, +38900, +38869, +38870, +38903, +38902, +38871, +36888, +36921, +36920, +36889, +36890, +36923, +36922, +36891, +36892, +36925, +36924, +36893, +36894, +36927, +36926, +36895, +36952, +36985, +36984, +36953, +36954, +36987, +36986, +36955, +36956, +36989, +36988, +36957, +36958, +36991, +36990, +36959, +37016, +37049, +37048, +37017, +37018, +37051, +37050, +37019, +37020, +37053, +37052, +37021, +37022, +37055, +37054, +37023, +37080, +37113, +37112, +37081, +37082, +37115, +37114, +37083, +37084, +37117, +37116, +37085, +37086, +37119, +37118, +37087, +37144, +37177, +37176, +37145, +37146, +37179, +37178, +37147, +37148, +37181, +37180, +37149, +37150, +37183, +37182, +37151, +37208, +37241, +37240, +37209, +37210, +37243, +37242, +37211, +37212, +37245, +37244, +37213, +37214, +37247, +37246, +37215, +37272, +37305, +37304, +37273, +37274, +37307, +37306, +37275, +37276, +37309, +37308, +37277, +37278, +37311, +37310, +37279, +37336, +37369, +37368, +37337, +37338, +37371, +37370, +37339, +37340, +37373, +37372, +37341, +37342, +37375, +37374, +37343, +37400, +37433, +37432, +37401, +37402, +37435, +37434, +37403, +37404, +37437, +37436, +37405, +37406, +37439, +37438, +37407, +37464, +37497, +37496, +37465, +37466, +37499, +37498, +37467, +37468, +37501, +37500, +37469, +37470, +37503, +37502, +37471, +37528, +37561, +37560, +37529, +37530, +37563, +37562, +37531, +37532, +37565, +37564, +37533, +37534, +37567, +37566, +37535, +37592, +37625, +37624, +37593, +37594, +37627, +37626, +37595, +37596, +37629, +37628, +37597, +37598, +37631, +37630, +37599, +37656, +37689, +37688, +37657, +37658, +37691, +37690, +37659, +37660, +37693, +37692, +37661, +37662, +37695, +37694, +37663, +37720, +37753, +37752, +37721, +37722, +37755, +37754, +37723, +37724, +37757, +37756, +37725, +37726, +37759, +37758, +37727, +37784, +37817, +37816, +37785, +37786, +37819, +37818, +37787, +37788, +37821, +37820, +37789, +37790, +37823, +37822, +37791, +37848, +37881, +37880, +37849, +37850, +37883, +37882, +37851, +37852, +37885, +37884, +37853, +37854, +37887, +37886, +37855, +37912, +37945, +37944, +37913, +37914, +37947, +37946, +37915, +37916, +37949, +37948, +37917, +37918, +37951, +37950, +37919, +37976, +38009, +38008, +37977, +37978, +38011, +38010, +37979, +37980, +38013, +38012, +37981, +37982, +38015, +38014, +37983, +38040, +38073, +38072, +38041, +38042, +38075, +38074, +38043, +38044, +38077, +38076, +38045, +38046, +38079, +38078, +38047, +38104, +38137, +38136, +38105, +38106, +38139, +38138, +38107, +38108, +38141, +38140, +38109, +38110, +38143, +38142, +38111, +38168, +38201, +38200, +38169, +38170, +38203, +38202, +38171, +38172, +38205, +38204, +38173, +38174, +38207, +38206, +38175, +38232, +38265, +38264, +38233, +38234, +38267, +38266, +38235, +38236, +38269, +38268, +38237, +38238, +38271, +38270, +38239, +38296, +38329, +38328, +38297, +38298, +38331, +38330, +38299, +38300, +38333, +38332, +38301, +38302, +38335, +38334, +38303, +38360, +38393, +38392, +38361, +38362, +38395, +38394, +38363, +38364, +38397, +38396, +38365, +38366, +38399, +38398, +38367, +38424, +38457, +38456, +38425, +38426, +38459, +38458, +38427, +38428, +38461, +38460, +38429, +38430, +38463, +38462, +38431, +38488, +38521, +38520, +38489, +38490, +38523, +38522, +38491, +38492, +38525, +38524, +38493, +38494, +38527, +38526, +38495, +38552, +38585, +38584, +38553, +38554, +38587, +38586, +38555, +38556, +38589, +38588, +38557, +38558, +38591, +38590, +38559, +38616, +38649, +38648, +38617, +38618, +38651, +38650, +38619, +38620, +38653, +38652, +38621, +38622, +38655, +38654, +38623, +38680, +38713, +38712, +38681, +38682, +38715, +38714, +38683, +38684, +38717, +38716, +38685, +38686, +38719, +38718, +38687, +38744, +38777, +38776, +38745, +38746, +38779, +38778, +38747, +38748, +38781, +38780, +38749, +38750, +38783, +38782, +38751, +38808, +38841, +38840, +38809, +38810, +38843, +38842, +38811, +38812, +38845, +38844, +38813, +38814, +38847, +38846, +38815, +38872, +38905, +38904, +38873, +38874, +38907, +38906, +38875, +38876, +38909, +38908, +38877, +38878, +38911, +38910, +38879, +38912, +38945, +38944, +38913, +38914, +38947, +38946, +38915, +38916, +38949, +38948, +38917, +38918, +38951, +38950, +38919, +38976, +39009, +39008, +38977, +38978, +39011, +39010, +38979, +38980, +39013, +39012, +38981, +38982, +39015, +39014, +38983, +39040, +39073, +39072, +39041, +39042, +39075, +39074, +39043, +39044, +39077, +39076, +39045, +39046, +39079, +39078, +39047, +39104, +39137, +39136, +39105, +39106, +39139, +39138, +39107, +39108, +39141, +39140, +39109, +39110, +39143, +39142, +39111, +39168, +39201, +39200, +39169, +39170, +39203, +39202, +39171, +39172, +39205, +39204, +39173, +39174, +39207, +39206, +39175, +39232, +39265, +39264, +39233, +39234, +39267, +39266, +39235, +39236, +39269, +39268, +39237, +39238, +39271, +39270, +39239, +39296, +39329, +39328, +39297, +39298, +39331, +39330, +39299, +39300, +39333, +39332, +39301, +39302, +39335, +39334, +39303, +39360, +39393, +39392, +39361, +39362, +39395, +39394, +39363, +39364, +39397, +39396, +39365, +39366, +39399, +39398, +39367, +39424, +39457, +39456, +39425, +39426, +39459, +39458, +39427, +39428, +39461, +39460, +39429, +39430, +39463, +39462, +39431, +39488, +39521, +39520, +39489, +39490, +39523, +39522, +39491, +39492, +39525, +39524, +39493, +39494, +39527, +39526, +39495, +39552, +39585, +39584, +39553, +39554, +39587, +39586, +39555, +39556, +39589, +39588, +39557, +39558, +39591, +39590, +39559, +39616, +39649, +39648, +39617, +39618, +39651, +39650, +39619, +39620, +39653, +39652, +39621, +39622, +39655, +39654, +39623, +39680, +39713, +39712, +39681, +39682, +39715, +39714, +39683, +39684, +39717, +39716, +39685, +39686, +39719, +39718, +39687, +39744, +39777, +39776, +39745, +39746, +39779, +39778, +39747, +39748, +39781, +39780, +39749, +39750, +39783, +39782, +39751, +39808, +39841, +39840, +39809, +39810, +39843, +39842, +39811, +39812, +39845, +39844, +39813, +39814, +39847, +39846, +39815, +39872, +39905, +39904, +39873, +39874, +39907, +39906, +39875, +39876, +39909, +39908, +39877, +39878, +39911, +39910, +39879, +39936, +39969, +39968, +39937, +39938, +39971, +39970, +39939, +39940, +39973, +39972, +39941, +39942, +39975, +39974, +39943, +40000, +40033, +40032, +40001, +40002, +40035, +40034, +40003, +40004, +40037, +40036, +40005, +40006, +40039, +40038, +40007, +40064, +40097, +40096, +40065, +40066, +40099, +40098, +40067, +40068, +40101, +40100, +40069, +40070, +40103, +40102, +40071, +40128, +40161, +40160, +40129, +40130, +40163, +40162, +40131, +40132, +40165, +40164, +40133, +40134, +40167, +40166, +40135, +40192, +40225, +40224, +40193, +40194, +40227, +40226, +40195, +40196, +40229, +40228, +40197, +40198, +40231, +40230, +40199, +40256, +40289, +40288, +40257, +40258, +40291, +40290, +40259, +40260, +40293, +40292, +40261, +40262, +40295, +40294, +40263, +40320, +40353, +40352, +40321, +40322, +40355, +40354, +40323, +40324, +40357, +40356, +40325, +40326, +40359, +40358, +40327, +40384, +40417, +40416, +40385, +40386, +40419, +40418, +40387, +40388, +40421, +40420, +40389, +40390, +40423, +40422, +40391, +40448, +40481, +40480, +40449, +40450, +40483, +40482, +40451, +40452, +40485, +40484, +40453, +40454, +40487, +40486, +40455, +40512, +40545, +40544, +40513, +40514, +40547, +40546, +40515, +40516, +40549, +40548, +40517, +40518, +40551, +40550, +40519, +40576, +40609, +40608, +40577, +40578, +40611, +40610, +40579, +40580, +40613, +40612, +40581, +40582, +40615, +40614, +40583, +40640, +40673, +40672, +40641, +40642, +40675, +40674, +40643, +40644, +40677, +40676, +40645, +40646, +40679, +40678, +40647, +40704, +40737, +40736, +40705, +40706, +40739, +40738, +40707, +40708, +40741, +40740, +40709, +40710, +40743, +40742, +40711, +40768, +40801, +40800, +40769, +40770, +40803, +40802, +40771, +40772, +40805, +40804, +40773, +40774, +40807, +40806, +40775, +40832, +40865, +40864, +40833, +40834, +40867, +40866, +40835, +40836, +40869, +40868, +40837, +40838, +40871, +40870, +40839, +40896, +40929, +40928, +40897, +40898, +40931, +40930, +40899, +40900, +40933, +40932, +40901, +40902, +40935, +40934, +40903, +38920, +38953, +38952, +38921, +38922, +38955, +38954, +38923, +38924, +38957, +38956, +38925, +38926, +38959, +38958, +38927, +38984, +39017, +39016, +38985, +38986, +39019, +39018, +38987, +38988, +39021, +39020, +38989, +38990, +39023, +39022, +38991, +39048, +39081, +39080, +39049, +39050, +39083, +39082, +39051, +39052, +39085, +39084, +39053, +39054, +39087, +39086, +39055, +39112, +39145, +39144, +39113, +39114, +39147, +39146, +39115, +39116, +39149, +39148, +39117, +39118, +39151, +39150, +39119, +39176, +39209, +39208, +39177, +39178, +39211, +39210, +39179, +39180, +39213, +39212, +39181, +39182, +39215, +39214, +39183, +39240, +39273, +39272, +39241, +39242, +39275, +39274, +39243, +39244, +39277, +39276, +39245, +39246, +39279, +39278, +39247, +39304, +39337, +39336, +39305, +39306, +39339, +39338, +39307, +39308, +39341, +39340, +39309, +39310, +39343, +39342, +39311, +39368, +39401, +39400, +39369, +39370, +39403, +39402, +39371, +39372, +39405, +39404, +39373, +39374, +39407, +39406, +39375, +39432, +39465, +39464, +39433, +39434, +39467, +39466, +39435, +39436, +39469, +39468, +39437, +39438, +39471, +39470, +39439, +39496, +39529, +39528, +39497, +39498, +39531, +39530, +39499, +39500, +39533, +39532, +39501, +39502, +39535, +39534, +39503, +39560, +39593, +39592, +39561, +39562, +39595, +39594, +39563, +39564, +39597, +39596, +39565, +39566, +39599, +39598, +39567, +39624, +39657, +39656, +39625, +39626, +39659, +39658, +39627, +39628, +39661, +39660, +39629, +39630, +39663, +39662, +39631, +39688, +39721, +39720, +39689, +39690, +39723, +39722, +39691, +39692, +39725, +39724, +39693, +39694, +39727, +39726, +39695, +39752, +39785, +39784, +39753, +39754, +39787, +39786, +39755, +39756, +39789, +39788, +39757, +39758, +39791, +39790, +39759, +39816, +39849, +39848, +39817, +39818, +39851, +39850, +39819, +39820, +39853, +39852, +39821, +39822, +39855, +39854, +39823, +39880, +39913, +39912, +39881, +39882, +39915, +39914, +39883, +39884, +39917, +39916, +39885, +39886, +39919, +39918, +39887, +39944, +39977, +39976, +39945, +39946, +39979, +39978, +39947, +39948, +39981, +39980, +39949, +39950, +39983, +39982, +39951, +40008, +40041, +40040, +40009, +40010, +40043, +40042, +40011, +40012, +40045, +40044, +40013, +40014, +40047, +40046, +40015, +40072, +40105, +40104, +40073, +40074, +40107, +40106, +40075, +40076, +40109, +40108, +40077, +40078, +40111, +40110, +40079, +40136, +40169, +40168, +40137, +40138, +40171, +40170, +40139, +40140, +40173, +40172, +40141, +40142, +40175, +40174, +40143, +40200, +40233, +40232, +40201, +40202, +40235, +40234, +40203, +40204, +40237, +40236, +40205, +40206, +40239, +40238, +40207, +40264, +40297, +40296, +40265, +40266, +40299, +40298, +40267, +40268, +40301, +40300, +40269, +40270, +40303, +40302, +40271, +40328, +40361, +40360, +40329, +40330, +40363, +40362, +40331, +40332, +40365, +40364, +40333, +40334, +40367, +40366, +40335, +40392, +40425, +40424, +40393, +40394, +40427, +40426, +40395, +40396, +40429, +40428, +40397, +40398, +40431, +40430, +40399, +40456, +40489, +40488, +40457, +40458, +40491, +40490, +40459, +40460, +40493, +40492, +40461, +40462, +40495, +40494, +40463, +40520, +40553, +40552, +40521, +40522, +40555, +40554, +40523, +40524, +40557, +40556, +40525, +40526, +40559, +40558, +40527, +40584, +40617, +40616, +40585, +40586, +40619, +40618, +40587, +40588, +40621, +40620, +40589, +40590, +40623, +40622, +40591, +40648, +40681, +40680, +40649, +40650, +40683, +40682, +40651, +40652, +40685, +40684, +40653, +40654, +40687, +40686, +40655, +40712, +40745, +40744, +40713, +40714, +40747, +40746, +40715, +40716, +40749, +40748, +40717, +40718, +40751, +40750, +40719, +40776, +40809, +40808, +40777, +40778, +40811, +40810, +40779, +40780, +40813, +40812, +40781, +40782, +40815, +40814, +40783, +40840, +40873, +40872, +40841, +40842, +40875, +40874, +40843, +40844, +40877, +40876, +40845, +40846, +40879, +40878, +40847, +40904, +40937, +40936, +40905, +40906, +40939, +40938, +40907, +40908, +40941, +40940, +40909, +40910, +40943, +40942, +40911, +38928, +38961, +38960, +38929, +38930, +38963, +38962, +38931, +38932, +38965, +38964, +38933, +38934, +38967, +38966, +38935, +38992, +39025, +39024, +38993, +38994, +39027, +39026, +38995, +38996, +39029, +39028, +38997, +38998, +39031, +39030, +38999, +39056, +39089, +39088, +39057, +39058, +39091, +39090, +39059, +39060, +39093, +39092, +39061, +39062, +39095, +39094, +39063, +39120, +39153, +39152, +39121, +39122, +39155, +39154, +39123, +39124, +39157, +39156, +39125, +39126, +39159, +39158, +39127, +39184, +39217, +39216, +39185, +39186, +39219, +39218, +39187, +39188, +39221, +39220, +39189, +39190, +39223, +39222, +39191, +39248, +39281, +39280, +39249, +39250, +39283, +39282, +39251, +39252, +39285, +39284, +39253, +39254, +39287, +39286, +39255, +39312, +39345, +39344, +39313, +39314, +39347, +39346, +39315, +39316, +39349, +39348, +39317, +39318, +39351, +39350, +39319, +39376, +39409, +39408, +39377, +39378, +39411, +39410, +39379, +39380, +39413, +39412, +39381, +39382, +39415, +39414, +39383, +39440, +39473, +39472, +39441, +39442, +39475, +39474, +39443, +39444, +39477, +39476, +39445, +39446, +39479, +39478, +39447, +39504, +39537, +39536, +39505, +39506, +39539, +39538, +39507, +39508, +39541, +39540, +39509, +39510, +39543, +39542, +39511, +39568, +39601, +39600, +39569, +39570, +39603, +39602, +39571, +39572, +39605, +39604, +39573, +39574, +39607, +39606, +39575, +39632, +39665, +39664, +39633, +39634, +39667, +39666, +39635, +39636, +39669, +39668, +39637, +39638, +39671, +39670, +39639, +39696, +39729, +39728, +39697, +39698, +39731, +39730, +39699, +39700, +39733, +39732, +39701, +39702, +39735, +39734, +39703, +39760, +39793, +39792, +39761, +39762, +39795, +39794, +39763, +39764, +39797, +39796, +39765, +39766, +39799, +39798, +39767, +39824, +39857, +39856, +39825, +39826, +39859, +39858, +39827, +39828, +39861, +39860, +39829, +39830, +39863, +39862, +39831, +39888, +39921, +39920, +39889, +39890, +39923, +39922, +39891, +39892, +39925, +39924, +39893, +39894, +39927, +39926, +39895, +39952, +39985, +39984, +39953, +39954, +39987, +39986, +39955, +39956, +39989, +39988, +39957, +39958, +39991, +39990, +39959, +40016, +40049, +40048, +40017, +40018, +40051, +40050, +40019, +40020, +40053, +40052, +40021, +40022, +40055, +40054, +40023, +40080, +40113, +40112, +40081, +40082, +40115, +40114, +40083, +40084, +40117, +40116, +40085, +40086, +40119, +40118, +40087, +40144, +40177, +40176, +40145, +40146, +40179, +40178, +40147, +40148, +40181, +40180, +40149, +40150, +40183, +40182, +40151, +40208, +40241, +40240, +40209, +40210, +40243, +40242, +40211, +40212, +40245, +40244, +40213, +40214, +40247, +40246, +40215, +40272, +40305, +40304, +40273, +40274, +40307, +40306, +40275, +40276, +40309, +40308, +40277, +40278, +40311, +40310, +40279, +40336, +40369, +40368, +40337, +40338, +40371, +40370, +40339, +40340, +40373, +40372, +40341, +40342, +40375, +40374, +40343, +40400, +40433, +40432, +40401, +40402, +40435, +40434, +40403, +40404, +40437, +40436, +40405, +40406, +40439, +40438, +40407, +40464, +40497, +40496, +40465, +40466, +40499, +40498, +40467, +40468, +40501, +40500, +40469, +40470, +40503, +40502, +40471, +40528, +40561, +40560, +40529, +40530, +40563, +40562, +40531, +40532, +40565, +40564, +40533, +40534, +40567, +40566, +40535, +40592, +40625, +40624, +40593, +40594, +40627, +40626, +40595, +40596, +40629, +40628, +40597, +40598, +40631, +40630, +40599, +40656, +40689, +40688, +40657, +40658, +40691, +40690, +40659, +40660, +40693, +40692, +40661, +40662, +40695, +40694, +40663, +40720, +40753, +40752, +40721, +40722, +40755, +40754, +40723, +40724, +40757, +40756, +40725, +40726, +40759, +40758, +40727, +40784, +40817, +40816, +40785, +40786, +40819, +40818, +40787, +40788, +40821, +40820, +40789, +40790, +40823, +40822, +40791, +40848, +40881, +40880, +40849, +40850, +40883, +40882, +40851, +40852, +40885, +40884, +40853, +40854, +40887, +40886, +40855, +40912, +40945, +40944, +40913, +40914, +40947, +40946, +40915, +40916, +40949, +40948, +40917, +40918, +40951, +40950, +40919, +38936, +38969, +38968, +38937, +38938, +38971, +38970, +38939, +38940, +38973, +38972, +38941, +38942, +38975, +38974, +38943, +39000, +39033, +39032, +39001, +39002, +39035, +39034, +39003, +39004, +39037, +39036, +39005, +39006, +39039, +39038, +39007, +39064, +39097, +39096, +39065, +39066, +39099, +39098, +39067, +39068, +39101, +39100, +39069, +39070, +39103, +39102, +39071, +39128, +39161, +39160, +39129, +39130, +39163, +39162, +39131, +39132, +39165, +39164, +39133, +39134, +39167, +39166, +39135, +39192, +39225, +39224, +39193, +39194, +39227, +39226, +39195, +39196, +39229, +39228, +39197, +39198, +39231, +39230, +39199, +39256, +39289, +39288, +39257, +39258, +39291, +39290, +39259, +39260, +39293, +39292, +39261, +39262, +39295, +39294, +39263, +39320, +39353, +39352, +39321, +39322, +39355, +39354, +39323, +39324, +39357, +39356, +39325, +39326, +39359, +39358, +39327, +39384, +39417, +39416, +39385, +39386, +39419, +39418, +39387, +39388, +39421, +39420, +39389, +39390, +39423, +39422, +39391, +39448, +39481, +39480, +39449, +39450, +39483, +39482, +39451, +39452, +39485, +39484, +39453, +39454, +39487, +39486, +39455, +39512, +39545, +39544, +39513, +39514, +39547, +39546, +39515, +39516, +39549, +39548, +39517, +39518, +39551, +39550, +39519, +39576, +39609, +39608, +39577, +39578, +39611, +39610, +39579, +39580, +39613, +39612, +39581, +39582, +39615, +39614, +39583, +39640, +39673, +39672, +39641, +39642, +39675, +39674, +39643, +39644, +39677, +39676, +39645, +39646, +39679, +39678, +39647, +39704, +39737, +39736, +39705, +39706, +39739, +39738, +39707, +39708, +39741, +39740, +39709, +39710, +39743, +39742, +39711, +39768, +39801, +39800, +39769, +39770, +39803, +39802, +39771, +39772, +39805, +39804, +39773, +39774, +39807, +39806, +39775, +39832, +39865, +39864, +39833, +39834, +39867, +39866, +39835, +39836, +39869, +39868, +39837, +39838, +39871, +39870, +39839, +39896, +39929, +39928, +39897, +39898, +39931, +39930, +39899, +39900, +39933, +39932, +39901, +39902, +39935, +39934, +39903, +39960, +39993, +39992, +39961, +39962, +39995, +39994, +39963, +39964, +39997, +39996, +39965, +39966, +39999, +39998, +39967, +40024, +40057, +40056, +40025, +40026, +40059, +40058, +40027, +40028, +40061, +40060, +40029, +40030, +40063, +40062, +40031, +40088, +40121, +40120, +40089, +40090, +40123, +40122, +40091, +40092, +40125, +40124, +40093, +40094, +40127, +40126, +40095, +40152, +40185, +40184, +40153, +40154, +40187, +40186, +40155, +40156, +40189, +40188, +40157, +40158, +40191, +40190, +40159, +40216, +40249, +40248, +40217, +40218, +40251, +40250, +40219, +40220, +40253, +40252, +40221, +40222, +40255, +40254, +40223, +40280, +40313, +40312, +40281, +40282, +40315, +40314, +40283, +40284, +40317, +40316, +40285, +40286, +40319, +40318, +40287, +40344, +40377, +40376, +40345, +40346, +40379, +40378, +40347, +40348, +40381, +40380, +40349, +40350, +40383, +40382, +40351, +40408, +40441, +40440, +40409, +40410, +40443, +40442, +40411, +40412, +40445, +40444, +40413, +40414, +40447, +40446, +40415, +40472, +40505, +40504, +40473, +40474, +40507, +40506, +40475, +40476, +40509, +40508, +40477, +40478, +40511, +40510, +40479, +40536, +40569, +40568, +40537, +40538, +40571, +40570, +40539, +40540, +40573, +40572, +40541, +40542, +40575, +40574, +40543, +40600, +40633, +40632, +40601, +40602, +40635, +40634, +40603, +40604, +40637, +40636, +40605, +40606, +40639, +40638, +40607, +40664, +40697, +40696, +40665, +40666, +40699, +40698, +40667, +40668, +40701, +40700, +40669, +40670, +40703, +40702, +40671, +40728, +40761, +40760, +40729, +40730, +40763, +40762, +40731, +40732, +40765, +40764, +40733, +40734, +40767, +40766, +40735, +40792, +40825, +40824, +40793, +40794, +40827, +40826, +40795, +40796, +40829, +40828, +40797, +40798, +40831, +40830, +40799, +40856, +40889, +40888, +40857, +40858, +40891, +40890, +40859, +40860, +40893, +40892, +40861, +40862, +40895, +40894, +40863, +40920, +40953, +40952, +40921, +40922, +40955, +40954, +40923, +40924, +40957, +40956, +40925, +40926, +40959, +40958, +40927, +40960, +40993, +40992, +40961, +40962, +40995, +40994, +40963, +40964, +40997, +40996, +40965, +40966, +40999, +40998, +40967, +41024, +41057, +41056, +41025, +41026, +41059, +41058, +41027, +41028, +41061, +41060, +41029, +41030, +41063, +41062, +41031, +41088, +41121, +41120, +41089, +41090, +41123, +41122, +41091, +41092, +41125, +41124, +41093, +41094, +41127, +41126, +41095, +41152, +41185, +41184, +41153, +41154, +41187, +41186, +41155, +41156, +41189, +41188, +41157, +41158, +41191, +41190, +41159, +41216, +41249, +41248, +41217, +41218, +41251, +41250, +41219, +41220, +41253, +41252, +41221, +41222, +41255, +41254, +41223, +41280, +41313, +41312, +41281, +41282, +41315, +41314, +41283, +41284, +41317, +41316, +41285, +41286, +41319, +41318, +41287, +41344, +41377, +41376, +41345, +41346, +41379, +41378, +41347, +41348, +41381, +41380, +41349, +41350, +41383, +41382, +41351, +41408, +41441, +41440, +41409, +41410, +41443, +41442, +41411, +41412, +41445, +41444, +41413, +41414, +41447, +41446, +41415, +41472, +41505, +41504, +41473, +41474, +41507, +41506, +41475, +41476, +41509, +41508, +41477, +41478, +41511, +41510, +41479, +41536, +41569, +41568, +41537, +41538, +41571, +41570, +41539, +41540, +41573, +41572, +41541, +41542, +41575, +41574, +41543, +41600, +41633, +41632, +41601, +41602, +41635, +41634, +41603, +41604, +41637, +41636, +41605, +41606, +41639, +41638, +41607, +41664, +41697, +41696, +41665, +41666, +41699, +41698, +41667, +41668, +41701, +41700, +41669, +41670, +41703, +41702, +41671, +41728, +41761, +41760, +41729, +41730, +41763, +41762, +41731, +41732, +41765, +41764, +41733, +41734, +41767, +41766, +41735, +41792, +41825, +41824, +41793, +41794, +41827, +41826, +41795, +41796, +41829, +41828, +41797, +41798, +41831, +41830, +41799, +41856, +41889, +41888, +41857, +41858, +41891, +41890, +41859, +41860, +41893, +41892, +41861, +41862, +41895, +41894, +41863, +41920, +41953, +41952, +41921, +41922, +41955, +41954, +41923, +41924, +41957, +41956, +41925, +41926, +41959, +41958, +41927, +41984, +42017, +42016, +41985, +41986, +42019, +42018, +41987, +41988, +42021, +42020, +41989, +41990, +42023, +42022, +41991, +42048, +42081, +42080, +42049, +42050, +42083, +42082, +42051, +42052, +42085, +42084, +42053, +42054, +42087, +42086, +42055, +42112, +42145, +42144, +42113, +42114, +42147, +42146, +42115, +42116, +42149, +42148, +42117, +42118, +42151, +42150, +42119, +42176, +42209, +42208, +42177, +42178, +42211, +42210, +42179, +42180, +42213, +42212, +42181, +42182, +42215, +42214, +42183, +42240, +42273, +42272, +42241, +42242, +42275, +42274, +42243, +42244, +42277, +42276, +42245, +42246, +42279, +42278, +42247, +42304, +42337, +42336, +42305, +42306, +42339, +42338, +42307, +42308, +42341, +42340, +42309, +42310, +42343, +42342, +42311, +42368, +42401, +42400, +42369, +42370, +42403, +42402, +42371, +42372, +42405, +42404, +42373, +42374, +42407, +42406, +42375, +42432, +42465, +42464, +42433, +42434, +42467, +42466, +42435, +42436, +42469, +42468, +42437, +42438, +42471, +42470, +42439, +42496, +42529, +42528, +42497, +42498, +42531, +42530, +42499, +42500, +42533, +42532, +42501, +42502, +42535, +42534, +42503, +42560, +42593, +42592, +42561, +42562, +42595, +42594, +42563, +42564, +42597, +42596, +42565, +42566, +42599, +42598, +42567, +42624, +42657, +42656, +42625, +42626, +42659, +42658, +42627, +42628, +42661, +42660, +42629, +42630, +42663, +42662, +42631, +42688, +42721, +42720, +42689, +42690, +42723, +42722, +42691, +42692, +42725, +42724, +42693, +42694, +42727, +42726, +42695, +42752, +42785, +42784, +42753, +42754, +42787, +42786, +42755, +42756, +42789, +42788, +42757, +42758, +42791, +42790, +42759, +42816, +42849, +42848, +42817, +42818, +42851, +42850, +42819, +42820, +42853, +42852, +42821, +42822, +42855, +42854, +42823, +42880, +42913, +42912, +42881, +42882, +42915, +42914, +42883, +42884, +42917, +42916, +42885, +42886, +42919, +42918, +42887, +42944, +42977, +42976, +42945, +42946, +42979, +42978, +42947, +42948, +42981, +42980, +42949, +42950, +42983, +42982, +42951, +40968, +41001, +41000, +40969, +40970, +41003, +41002, +40971, +40972, +41005, +41004, +40973, +40974, +41007, +41006, +40975, +41032, +41065, +41064, +41033, +41034, +41067, +41066, +41035, +41036, +41069, +41068, +41037, +41038, +41071, +41070, +41039, +41096, +41129, +41128, +41097, +41098, +41131, +41130, +41099, +41100, +41133, +41132, +41101, +41102, +41135, +41134, +41103, +41160, +41193, +41192, +41161, +41162, +41195, +41194, +41163, +41164, +41197, +41196, +41165, +41166, +41199, +41198, +41167, +41224, +41257, +41256, +41225, +41226, +41259, +41258, +41227, +41228, +41261, +41260, +41229, +41230, +41263, +41262, +41231, +41288, +41321, +41320, +41289, +41290, +41323, +41322, +41291, +41292, +41325, +41324, +41293, +41294, +41327, +41326, +41295, +41352, +41385, +41384, +41353, +41354, +41387, +41386, +41355, +41356, +41389, +41388, +41357, +41358, +41391, +41390, +41359, +41416, +41449, +41448, +41417, +41418, +41451, +41450, +41419, +41420, +41453, +41452, +41421, +41422, +41455, +41454, +41423, +41480, +41513, +41512, +41481, +41482, +41515, +41514, +41483, +41484, +41517, +41516, +41485, +41486, +41519, +41518, +41487, +41544, +41577, +41576, +41545, +41546, +41579, +41578, +41547, +41548, +41581, +41580, +41549, +41550, +41583, +41582, +41551, +41608, +41641, +41640, +41609, +41610, +41643, +41642, +41611, +41612, +41645, +41644, +41613, +41614, +41647, +41646, +41615, +41672, +41705, +41704, +41673, +41674, +41707, +41706, +41675, +41676, +41709, +41708, +41677, +41678, +41711, +41710, +41679, +41736, +41769, +41768, +41737, +41738, +41771, +41770, +41739, +41740, +41773, +41772, +41741, +41742, +41775, +41774, +41743, +41800, +41833, +41832, +41801, +41802, +41835, +41834, +41803, +41804, +41837, +41836, +41805, +41806, +41839, +41838, +41807, +41864, +41897, +41896, +41865, +41866, +41899, +41898, +41867, +41868, +41901, +41900, +41869, +41870, +41903, +41902, +41871, +41928, +41961, +41960, +41929, +41930, +41963, +41962, +41931, +41932, +41965, +41964, +41933, +41934, +41967, +41966, +41935, +41992, +42025, +42024, +41993, +41994, +42027, +42026, +41995, +41996, +42029, +42028, +41997, +41998, +42031, +42030, +41999, +42056, +42089, +42088, +42057, +42058, +42091, +42090, +42059, +42060, +42093, +42092, +42061, +42062, +42095, +42094, +42063, +42120, +42153, +42152, +42121, +42122, +42155, +42154, +42123, +42124, +42157, +42156, +42125, +42126, +42159, +42158, +42127, +42184, +42217, +42216, +42185, +42186, +42219, +42218, +42187, +42188, +42221, +42220, +42189, +42190, +42223, +42222, +42191, +42248, +42281, +42280, +42249, +42250, +42283, +42282, +42251, +42252, +42285, +42284, +42253, +42254, +42287, +42286, +42255, +42312, +42345, +42344, +42313, +42314, +42347, +42346, +42315, +42316, +42349, +42348, +42317, +42318, +42351, +42350, +42319, +42376, +42409, +42408, +42377, +42378, +42411, +42410, +42379, +42380, +42413, +42412, +42381, +42382, +42415, +42414, +42383, +42440, +42473, +42472, +42441, +42442, +42475, +42474, +42443, +42444, +42477, +42476, +42445, +42446, +42479, +42478, +42447, +42504, +42537, +42536, +42505, +42506, +42539, +42538, +42507, +42508, +42541, +42540, +42509, +42510, +42543, +42542, +42511, +42568, +42601, +42600, +42569, +42570, +42603, +42602, +42571, +42572, +42605, +42604, +42573, +42574, +42607, +42606, +42575, +42632, +42665, +42664, +42633, +42634, +42667, +42666, +42635, +42636, +42669, +42668, +42637, +42638, +42671, +42670, +42639, +42696, +42729, +42728, +42697, +42698, +42731, +42730, +42699, +42700, +42733, +42732, +42701, +42702, +42735, +42734, +42703, +42760, +42793, +42792, +42761, +42762, +42795, +42794, +42763, +42764, +42797, +42796, +42765, +42766, +42799, +42798, +42767, +42824, +42857, +42856, +42825, +42826, +42859, +42858, +42827, +42828, +42861, +42860, +42829, +42830, +42863, +42862, +42831, +42888, +42921, +42920, +42889, +42890, +42923, +42922, +42891, +42892, +42925, +42924, +42893, +42894, +42927, +42926, +42895, +42952, +42985, +42984, +42953, +42954, +42987, +42986, +42955, +42956, +42989, +42988, +42957, +42958, +42991, +42990, +42959, +40976, +41009, +41008, +40977, +40978, +41011, +41010, +40979, +40980, +41013, +41012, +40981, +40982, +41015, +41014, +40983, +41040, +41073, +41072, +41041, +41042, +41075, +41074, +41043, +41044, +41077, +41076, +41045, +41046, +41079, +41078, +41047, +41104, +41137, +41136, +41105, +41106, +41139, +41138, +41107, +41108, +41141, +41140, +41109, +41110, +41143, +41142, +41111, +41168, +41201, +41200, +41169, +41170, +41203, +41202, +41171, +41172, +41205, +41204, +41173, +41174, +41207, +41206, +41175, +41232, +41265, +41264, +41233, +41234, +41267, +41266, +41235, +41236, +41269, +41268, +41237, +41238, +41271, +41270, +41239, +41296, +41329, +41328, +41297, +41298, +41331, +41330, +41299, +41300, +41333, +41332, +41301, +41302, +41335, +41334, +41303, +41360, +41393, +41392, +41361, +41362, +41395, +41394, +41363, +41364, +41397, +41396, +41365, +41366, +41399, +41398, +41367, +41424, +41457, +41456, +41425, +41426, +41459, +41458, +41427, +41428, +41461, +41460, +41429, +41430, +41463, +41462, +41431, +41488, +41521, +41520, +41489, +41490, +41523, +41522, +41491, +41492, +41525, +41524, +41493, +41494, +41527, +41526, +41495, +41552, +41585, +41584, +41553, +41554, +41587, +41586, +41555, +41556, +41589, +41588, +41557, +41558, +41591, +41590, +41559, +41616, +41649, +41648, +41617, +41618, +41651, +41650, +41619, +41620, +41653, +41652, +41621, +41622, +41655, +41654, +41623, +41680, +41713, +41712, +41681, +41682, +41715, +41714, +41683, +41684, +41717, +41716, +41685, +41686, +41719, +41718, +41687, +41744, +41777, +41776, +41745, +41746, +41779, +41778, +41747, +41748, +41781, +41780, +41749, +41750, +41783, +41782, +41751, +41808, +41841, +41840, +41809, +41810, +41843, +41842, +41811, +41812, +41845, +41844, +41813, +41814, +41847, +41846, +41815, +41872, +41905, +41904, +41873, +41874, +41907, +41906, +41875, +41876, +41909, +41908, +41877, +41878, +41911, +41910, +41879, +41936, +41969, +41968, +41937, +41938, +41971, +41970, +41939, +41940, +41973, +41972, +41941, +41942, +41975, +41974, +41943, +42000, +42033, +42032, +42001, +42002, +42035, +42034, +42003, +42004, +42037, +42036, +42005, +42006, +42039, +42038, +42007, +42064, +42097, +42096, +42065, +42066, +42099, +42098, +42067, +42068, +42101, +42100, +42069, +42070, +42103, +42102, +42071, +42128, +42161, +42160, +42129, +42130, +42163, +42162, +42131, +42132, +42165, +42164, +42133, +42134, +42167, +42166, +42135, +42192, +42225, +42224, +42193, +42194, +42227, +42226, +42195, +42196, +42229, +42228, +42197, +42198, +42231, +42230, +42199, +42256, +42289, +42288, +42257, +42258, +42291, +42290, +42259, +42260, +42293, +42292, +42261, +42262, +42295, +42294, +42263, +42320, +42353, +42352, +42321, +42322, +42355, +42354, +42323, +42324, +42357, +42356, +42325, +42326, +42359, +42358, +42327, +42384, +42417, +42416, +42385, +42386, +42419, +42418, +42387, +42388, +42421, +42420, +42389, +42390, +42423, +42422, +42391, +42448, +42481, +42480, +42449, +42450, +42483, +42482, +42451, +42452, +42485, +42484, +42453, +42454, +42487, +42486, +42455, +42512, +42545, +42544, +42513, +42514, +42547, +42546, +42515, +42516, +42549, +42548, +42517, +42518, +42551, +42550, +42519, +42576, +42609, +42608, +42577, +42578, +42611, +42610, +42579, +42580, +42613, +42612, +42581, +42582, +42615, +42614, +42583, +42640, +42673, +42672, +42641, +42642, +42675, +42674, +42643, +42644, +42677, +42676, +42645, +42646, +42679, +42678, +42647, +42704, +42737, +42736, +42705, +42706, +42739, +42738, +42707, +42708, +42741, +42740, +42709, +42710, +42743, +42742, +42711, +42768, +42801, +42800, +42769, +42770, +42803, +42802, +42771, +42772, +42805, +42804, +42773, +42774, +42807, +42806, +42775, +42832, +42865, +42864, +42833, +42834, +42867, +42866, +42835, +42836, +42869, +42868, +42837, +42838, +42871, +42870, +42839, +42896, +42929, +42928, +42897, +42898, +42931, +42930, +42899, +42900, +42933, +42932, +42901, +42902, +42935, +42934, +42903, +42960, +42993, +42992, +42961, +42962, +42995, +42994, +42963, +42964, +42997, +42996, +42965, +42966, +42999, +42998, +42967, +40984, +41017, +41016, +40985, +40986, +41019, +41018, +40987, +40988, +41021, +41020, +40989, +40990, +41023, +41022, +40991, +41048, +41081, +41080, +41049, +41050, +41083, +41082, +41051, +41052, +41085, +41084, +41053, +41054, +41087, +41086, +41055, +41112, +41145, +41144, +41113, +41114, +41147, +41146, +41115, +41116, +41149, +41148, +41117, +41118, +41151, +41150, +41119, +41176, +41209, +41208, +41177, +41178, +41211, +41210, +41179, +41180, +41213, +41212, +41181, +41182, +41215, +41214, +41183, +41240, +41273, +41272, +41241, +41242, +41275, +41274, +41243, +41244, +41277, +41276, +41245, +41246, +41279, +41278, +41247, +41304, +41337, +41336, +41305, +41306, +41339, +41338, +41307, +41308, +41341, +41340, +41309, +41310, +41343, +41342, +41311, +41368, +41401, +41400, +41369, +41370, +41403, +41402, +41371, +41372, +41405, +41404, +41373, +41374, +41407, +41406, +41375, +41432, +41465, +41464, +41433, +41434, +41467, +41466, +41435, +41436, +41469, +41468, +41437, +41438, +41471, +41470, +41439, +41496, +41529, +41528, +41497, +41498, +41531, +41530, +41499, +41500, +41533, +41532, +41501, +41502, +41535, +41534, +41503, +41560, +41593, +41592, +41561, +41562, +41595, +41594, +41563, +41564, +41597, +41596, +41565, +41566, +41599, +41598, +41567, +41624, +41657, +41656, +41625, +41626, +41659, +41658, +41627, +41628, +41661, +41660, +41629, +41630, +41663, +41662, +41631, +41688, +41721, +41720, +41689, +41690, +41723, +41722, +41691, +41692, +41725, +41724, +41693, +41694, +41727, +41726, +41695, +41752, +41785, +41784, +41753, +41754, +41787, +41786, +41755, +41756, +41789, +41788, +41757, +41758, +41791, +41790, +41759, +41816, +41849, +41848, +41817, +41818, +41851, +41850, +41819, +41820, +41853, +41852, +41821, +41822, +41855, +41854, +41823, +41880, +41913, +41912, +41881, +41882, +41915, +41914, +41883, +41884, +41917, +41916, +41885, +41886, +41919, +41918, +41887, +41944, +41977, +41976, +41945, +41946, +41979, +41978, +41947, +41948, +41981, +41980, +41949, +41950, +41983, +41982, +41951, +42008, +42041, +42040, +42009, +42010, +42043, +42042, +42011, +42012, +42045, +42044, +42013, +42014, +42047, +42046, +42015, +42072, +42105, +42104, +42073, +42074, +42107, +42106, +42075, +42076, +42109, +42108, +42077, +42078, +42111, +42110, +42079, +42136, +42169, +42168, +42137, +42138, +42171, +42170, +42139, +42140, +42173, +42172, +42141, +42142, +42175, +42174, +42143, +42200, +42233, +42232, +42201, +42202, +42235, +42234, +42203, +42204, +42237, +42236, +42205, +42206, +42239, +42238, +42207, +42264, +42297, +42296, +42265, +42266, +42299, +42298, +42267, +42268, +42301, +42300, +42269, +42270, +42303, +42302, +42271, +42328, +42361, +42360, +42329, +42330, +42363, +42362, +42331, +42332, +42365, +42364, +42333, +42334, +42367, +42366, +42335, +42392, +42425, +42424, +42393, +42394, +42427, +42426, +42395, +42396, +42429, +42428, +42397, +42398, +42431, +42430, +42399, +42456, +42489, +42488, +42457, +42458, +42491, +42490, +42459, +42460, +42493, +42492, +42461, +42462, +42495, +42494, +42463, +42520, +42553, +42552, +42521, +42522, +42555, +42554, +42523, +42524, +42557, +42556, +42525, +42526, +42559, +42558, +42527, +42584, +42617, +42616, +42585, +42586, +42619, +42618, +42587, +42588, +42621, +42620, +42589, +42590, +42623, +42622, +42591, +42648, +42681, +42680, +42649, +42650, +42683, +42682, +42651, +42652, +42685, +42684, +42653, +42654, +42687, +42686, +42655, +42712, +42745, +42744, +42713, +42714, +42747, +42746, +42715, +42716, +42749, +42748, +42717, +42718, +42751, +42750, +42719, +42776, +42809, +42808, +42777, +42778, +42811, +42810, +42779, +42780, +42813, +42812, +42781, +42782, +42815, +42814, +42783, +42840, +42873, +42872, +42841, +42842, +42875, +42874, +42843, +42844, +42877, +42876, +42845, +42846, +42879, +42878, +42847, +42904, +42937, +42936, +42905, +42906, +42939, +42938, +42907, +42908, +42941, +42940, +42909, +42910, +42943, +42942, +42911, +42968, +43001, +43000, +42969, +42970, +43003, +43002, +42971, +42972, +43005, +43004, +42973, +42974, +43007, +43006, +42975, +43008, +43041, +43040, +43009, +43010, +43043, +43042, +43011, +43012, +43045, +43044, +43013, +43014, +43047, +43046, +43015, +43072, +43105, +43104, +43073, +43074, +43107, +43106, +43075, +43076, +43109, +43108, +43077, +43078, +43111, +43110, +43079, +43136, +43169, +43168, +43137, +43138, +43171, +43170, +43139, +43140, +43173, +43172, +43141, +43142, +43175, +43174, +43143, +43200, +43233, +43232, +43201, +43202, +43235, +43234, +43203, +43204, +43237, +43236, +43205, +43206, +43239, +43238, +43207, +43264, +43297, +43296, +43265, +43266, +43299, +43298, +43267, +43268, +43301, +43300, +43269, +43270, +43303, +43302, +43271, +43328, +43361, +43360, +43329, +43330, +43363, +43362, +43331, +43332, +43365, +43364, +43333, +43334, +43367, +43366, +43335, +43392, +43425, +43424, +43393, +43394, +43427, +43426, +43395, +43396, +43429, +43428, +43397, +43398, +43431, +43430, +43399, +43456, +43489, +43488, +43457, +43458, +43491, +43490, +43459, +43460, +43493, +43492, +43461, +43462, +43495, +43494, +43463, +43520, +43553, +43552, +43521, +43522, +43555, +43554, +43523, +43524, +43557, +43556, +43525, +43526, +43559, +43558, +43527, +43584, +43617, +43616, +43585, +43586, +43619, +43618, +43587, +43588, +43621, +43620, +43589, +43590, +43623, +43622, +43591, +43648, +43681, +43680, +43649, +43650, +43683, +43682, +43651, +43652, +43685, +43684, +43653, +43654, +43687, +43686, +43655, +43712, +43745, +43744, +43713, +43714, +43747, +43746, +43715, +43716, +43749, +43748, +43717, +43718, +43751, +43750, +43719, +43776, +43809, +43808, +43777, +43778, +43811, +43810, +43779, +43780, +43813, +43812, +43781, +43782, +43815, +43814, +43783, +43840, +43873, +43872, +43841, +43842, +43875, +43874, +43843, +43844, +43877, +43876, +43845, +43846, +43879, +43878, +43847, +43904, +43937, +43936, +43905, +43906, +43939, +43938, +43907, +43908, +43941, +43940, +43909, +43910, +43943, +43942, +43911, +43968, +44001, +44000, +43969, +43970, +44003, +44002, +43971, +43972, +44005, +44004, +43973, +43974, +44007, +44006, +43975, +44032, +44065, +44064, +44033, +44034, +44067, +44066, +44035, +44036, +44069, +44068, +44037, +44038, +44071, +44070, +44039, +44096, +44129, +44128, +44097, +44098, +44131, +44130, +44099, +44100, +44133, +44132, +44101, +44102, +44135, +44134, +44103, +44160, +44193, +44192, +44161, +44162, +44195, +44194, +44163, +44164, +44197, +44196, +44165, +44166, +44199, +44198, +44167, +44224, +44257, +44256, +44225, +44226, +44259, +44258, +44227, +44228, +44261, +44260, +44229, +44230, +44263, +44262, +44231, +44288, +44321, +44320, +44289, +44290, +44323, +44322, +44291, +44292, +44325, +44324, +44293, +44294, +44327, +44326, +44295, +44352, +44385, +44384, +44353, +44354, +44387, +44386, +44355, +44356, +44389, +44388, +44357, +44358, +44391, +44390, +44359, +44416, +44449, +44448, +44417, +44418, +44451, +44450, +44419, +44420, +44453, +44452, +44421, +44422, +44455, +44454, +44423, +44480, +44513, +44512, +44481, +44482, +44515, +44514, +44483, +44484, +44517, +44516, +44485, +44486, +44519, +44518, +44487, +44544, +44577, +44576, +44545, +44546, +44579, +44578, +44547, +44548, +44581, +44580, +44549, +44550, +44583, +44582, +44551, +44608, +44641, +44640, +44609, +44610, +44643, +44642, +44611, +44612, +44645, +44644, +44613, +44614, +44647, +44646, +44615, +44672, +44705, +44704, +44673, +44674, +44707, +44706, +44675, +44676, +44709, +44708, +44677, +44678, +44711, +44710, +44679, +44736, +44769, +44768, +44737, +44738, +44771, +44770, +44739, +44740, +44773, +44772, +44741, +44742, +44775, +44774, +44743, +44800, +44833, +44832, +44801, +44802, +44835, +44834, +44803, +44804, +44837, +44836, +44805, +44806, +44839, +44838, +44807, +44864, +44897, +44896, +44865, +44866, +44899, +44898, +44867, +44868, +44901, +44900, +44869, +44870, +44903, +44902, +44871, +44928, +44961, +44960, +44929, +44930, +44963, +44962, +44931, +44932, +44965, +44964, +44933, +44934, +44967, +44966, +44935, +44992, +45025, +45024, +44993, +44994, +45027, +45026, +44995, +44996, +45029, +45028, +44997, +44998, +45031, +45030, +44999, +43016, +43049, +43048, +43017, +43018, +43051, +43050, +43019, +43020, +43053, +43052, +43021, +43022, +43055, +43054, +43023, +43080, +43113, +43112, +43081, +43082, +43115, +43114, +43083, +43084, +43117, +43116, +43085, +43086, +43119, +43118, +43087, +43144, +43177, +43176, +43145, +43146, +43179, +43178, +43147, +43148, +43181, +43180, +43149, +43150, +43183, +43182, +43151, +43208, +43241, +43240, +43209, +43210, +43243, +43242, +43211, +43212, +43245, +43244, +43213, +43214, +43247, +43246, +43215, +43272, +43305, +43304, +43273, +43274, +43307, +43306, +43275, +43276, +43309, +43308, +43277, +43278, +43311, +43310, +43279, +43336, +43369, +43368, +43337, +43338, +43371, +43370, +43339, +43340, +43373, +43372, +43341, +43342, +43375, +43374, +43343, +43400, +43433, +43432, +43401, +43402, +43435, +43434, +43403, +43404, +43437, +43436, +43405, +43406, +43439, +43438, +43407, +43464, +43497, +43496, +43465, +43466, +43499, +43498, +43467, +43468, +43501, +43500, +43469, +43470, +43503, +43502, +43471, +43528, +43561, +43560, +43529, +43530, +43563, +43562, +43531, +43532, +43565, +43564, +43533, +43534, +43567, +43566, +43535, +43592, +43625, +43624, +43593, +43594, +43627, +43626, +43595, +43596, +43629, +43628, +43597, +43598, +43631, +43630, +43599, +43656, +43689, +43688, +43657, +43658, +43691, +43690, +43659, +43660, +43693, +43692, +43661, +43662, +43695, +43694, +43663, +43720, +43753, +43752, +43721, +43722, +43755, +43754, +43723, +43724, +43757, +43756, +43725, +43726, +43759, +43758, +43727, +43784, +43817, +43816, +43785, +43786, +43819, +43818, +43787, +43788, +43821, +43820, +43789, +43790, +43823, +43822, +43791, +43848, +43881, +43880, +43849, +43850, +43883, +43882, +43851, +43852, +43885, +43884, +43853, +43854, +43887, +43886, +43855, +43912, +43945, +43944, +43913, +43914, +43947, +43946, +43915, +43916, +43949, +43948, +43917, +43918, +43951, +43950, +43919, +43976, +44009, +44008, +43977, +43978, +44011, +44010, +43979, +43980, +44013, +44012, +43981, +43982, +44015, +44014, +43983, +44040, +44073, +44072, +44041, +44042, +44075, +44074, +44043, +44044, +44077, +44076, +44045, +44046, +44079, +44078, +44047, +44104, +44137, +44136, +44105, +44106, +44139, +44138, +44107, +44108, +44141, +44140, +44109, +44110, +44143, +44142, +44111, +44168, +44201, +44200, +44169, +44170, +44203, +44202, +44171, +44172, +44205, +44204, +44173, +44174, +44207, +44206, +44175, +44232, +44265, +44264, +44233, +44234, +44267, +44266, +44235, +44236, +44269, +44268, +44237, +44238, +44271, +44270, +44239, +44296, +44329, +44328, +44297, +44298, +44331, +44330, +44299, +44300, +44333, +44332, +44301, +44302, +44335, +44334, +44303, +44360, +44393, +44392, +44361, +44362, +44395, +44394, +44363, +44364, +44397, +44396, +44365, +44366, +44399, +44398, +44367, +44424, +44457, +44456, +44425, +44426, +44459, +44458, +44427, +44428, +44461, +44460, +44429, +44430, +44463, +44462, +44431, +44488, +44521, +44520, +44489, +44490, +44523, +44522, +44491, +44492, +44525, +44524, +44493, +44494, +44527, +44526, +44495, +44552, +44585, +44584, +44553, +44554, +44587, +44586, +44555, +44556, +44589, +44588, +44557, +44558, +44591, +44590, +44559, +44616, +44649, +44648, +44617, +44618, +44651, +44650, +44619, +44620, +44653, +44652, +44621, +44622, +44655, +44654, +44623, +44680, +44713, +44712, +44681, +44682, +44715, +44714, +44683, +44684, +44717, +44716, +44685, +44686, +44719, +44718, +44687, +44744, +44777, +44776, +44745, +44746, +44779, +44778, +44747, +44748, +44781, +44780, +44749, +44750, +44783, +44782, +44751, +44808, +44841, +44840, +44809, +44810, +44843, +44842, +44811, +44812, +44845, +44844, +44813, +44814, +44847, +44846, +44815, +44872, +44905, +44904, +44873, +44874, +44907, +44906, +44875, +44876, +44909, +44908, +44877, +44878, +44911, +44910, +44879, +44936, +44969, +44968, +44937, +44938, +44971, +44970, +44939, +44940, +44973, +44972, +44941, +44942, +44975, +44974, +44943, +45000, +45033, +45032, +45001, +45002, +45035, +45034, +45003, +45004, +45037, +45036, +45005, +45006, +45039, +45038, +45007, +43024, +43057, +43056, +43025, +43026, +43059, +43058, +43027, +43028, +43061, +43060, +43029, +43030, +43063, +43062, +43031, +43088, +43121, +43120, +43089, +43090, +43123, +43122, +43091, +43092, +43125, +43124, +43093, +43094, +43127, +43126, +43095, +43152, +43185, +43184, +43153, +43154, +43187, +43186, +43155, +43156, +43189, +43188, +43157, +43158, +43191, +43190, +43159, +43216, +43249, +43248, +43217, +43218, +43251, +43250, +43219, +43220, +43253, +43252, +43221, +43222, +43255, +43254, +43223, +43280, +43313, +43312, +43281, +43282, +43315, +43314, +43283, +43284, +43317, +43316, +43285, +43286, +43319, +43318, +43287, +43344, +43377, +43376, +43345, +43346, +43379, +43378, +43347, +43348, +43381, +43380, +43349, +43350, +43383, +43382, +43351, +43408, +43441, +43440, +43409, +43410, +43443, +43442, +43411, +43412, +43445, +43444, +43413, +43414, +43447, +43446, +43415, +43472, +43505, +43504, +43473, +43474, +43507, +43506, +43475, +43476, +43509, +43508, +43477, +43478, +43511, +43510, +43479, +43536, +43569, +43568, +43537, +43538, +43571, +43570, +43539, +43540, +43573, +43572, +43541, +43542, +43575, +43574, +43543, +43600, +43633, +43632, +43601, +43602, +43635, +43634, +43603, +43604, +43637, +43636, +43605, +43606, +43639, +43638, +43607, +43664, +43697, +43696, +43665, +43666, +43699, +43698, +43667, +43668, +43701, +43700, +43669, +43670, +43703, +43702, +43671, +43728, +43761, +43760, +43729, +43730, +43763, +43762, +43731, +43732, +43765, +43764, +43733, +43734, +43767, +43766, +43735, +43792, +43825, +43824, +43793, +43794, +43827, +43826, +43795, +43796, +43829, +43828, +43797, +43798, +43831, +43830, +43799, +43856, +43889, +43888, +43857, +43858, +43891, +43890, +43859, +43860, +43893, +43892, +43861, +43862, +43895, +43894, +43863, +43920, +43953, +43952, +43921, +43922, +43955, +43954, +43923, +43924, +43957, +43956, +43925, +43926, +43959, +43958, +43927, +43984, +44017, +44016, +43985, +43986, +44019, +44018, +43987, +43988, +44021, +44020, +43989, +43990, +44023, +44022, +43991, +44048, +44081, +44080, +44049, +44050, +44083, +44082, +44051, +44052, +44085, +44084, +44053, +44054, +44087, +44086, +44055, +44112, +44145, +44144, +44113, +44114, +44147, +44146, +44115, +44116, +44149, +44148, +44117, +44118, +44151, +44150, +44119, +44176, +44209, +44208, +44177, +44178, +44211, +44210, +44179, +44180, +44213, +44212, +44181, +44182, +44215, +44214, +44183, +44240, +44273, +44272, +44241, +44242, +44275, +44274, +44243, +44244, +44277, +44276, +44245, +44246, +44279, +44278, +44247, +44304, +44337, +44336, +44305, +44306, +44339, +44338, +44307, +44308, +44341, +44340, +44309, +44310, +44343, +44342, +44311, +44368, +44401, +44400, +44369, +44370, +44403, +44402, +44371, +44372, +44405, +44404, +44373, +44374, +44407, +44406, +44375, +44432, +44465, +44464, +44433, +44434, +44467, +44466, +44435, +44436, +44469, +44468, +44437, +44438, +44471, +44470, +44439, +44496, +44529, +44528, +44497, +44498, +44531, +44530, +44499, +44500, +44533, +44532, +44501, +44502, +44535, +44534, +44503, +44560, +44593, +44592, +44561, +44562, +44595, +44594, +44563, +44564, +44597, +44596, +44565, +44566, +44599, +44598, +44567, +44624, +44657, +44656, +44625, +44626, +44659, +44658, +44627, +44628, +44661, +44660, +44629, +44630, +44663, +44662, +44631, +44688, +44721, +44720, +44689, +44690, +44723, +44722, +44691, +44692, +44725, +44724, +44693, +44694, +44727, +44726, +44695, +44752, +44785, +44784, +44753, +44754, +44787, +44786, +44755, +44756, +44789, +44788, +44757, +44758, +44791, +44790, +44759, +44816, +44849, +44848, +44817, +44818, +44851, +44850, +44819, +44820, +44853, +44852, +44821, +44822, +44855, +44854, +44823, +44880, +44913, +44912, +44881, +44882, +44915, +44914, +44883, +44884, +44917, +44916, +44885, +44886, +44919, +44918, +44887, +44944, +44977, +44976, +44945, +44946, +44979, +44978, +44947, +44948, +44981, +44980, +44949, +44950, +44983, +44982, +44951, +45008, +45041, +45040, +45009, +45010, +45043, +45042, +45011, +45012, +45045, +45044, +45013, +45014, +45047, +45046, +45015, +43032, +43065, +43064, +43033, +43034, +43067, +43066, +43035, +43036, +43069, +43068, +43037, +43038, +43071, +43070, +43039, +43096, +43129, +43128, +43097, +43098, +43131, +43130, +43099, +43100, +43133, +43132, +43101, +43102, +43135, +43134, +43103, +43160, +43193, +43192, +43161, +43162, +43195, +43194, +43163, +43164, +43197, +43196, +43165, +43166, +43199, +43198, +43167, +43224, +43257, +43256, +43225, +43226, +43259, +43258, +43227, +43228, +43261, +43260, +43229, +43230, +43263, +43262, +43231, +43288, +43321, +43320, +43289, +43290, +43323, +43322, +43291, +43292, +43325, +43324, +43293, +43294, +43327, +43326, +43295, +43352, +43385, +43384, +43353, +43354, +43387, +43386, +43355, +43356, +43389, +43388, +43357, +43358, +43391, +43390, +43359, +43416, +43449, +43448, +43417, +43418, +43451, +43450, +43419, +43420, +43453, +43452, +43421, +43422, +43455, +43454, +43423, +43480, +43513, +43512, +43481, +43482, +43515, +43514, +43483, +43484, +43517, +43516, +43485, +43486, +43519, +43518, +43487, +43544, +43577, +43576, +43545, +43546, +43579, +43578, +43547, +43548, +43581, +43580, +43549, +43550, +43583, +43582, +43551, +43608, +43641, +43640, +43609, +43610, +43643, +43642, +43611, +43612, +43645, +43644, +43613, +43614, +43647, +43646, +43615, +43672, +43705, +43704, +43673, +43674, +43707, +43706, +43675, +43676, +43709, +43708, +43677, +43678, +43711, +43710, +43679, +43736, +43769, +43768, +43737, +43738, +43771, +43770, +43739, +43740, +43773, +43772, +43741, +43742, +43775, +43774, +43743, +43800, +43833, +43832, +43801, +43802, +43835, +43834, +43803, +43804, +43837, +43836, +43805, +43806, +43839, +43838, +43807, +43864, +43897, +43896, +43865, +43866, +43899, +43898, +43867, +43868, +43901, +43900, +43869, +43870, +43903, +43902, +43871, +43928, +43961, +43960, +43929, +43930, +43963, +43962, +43931, +43932, +43965, +43964, +43933, +43934, +43967, +43966, +43935, +43992, +44025, +44024, +43993, +43994, +44027, +44026, +43995, +43996, +44029, +44028, +43997, +43998, +44031, +44030, +43999, +44056, +44089, +44088, +44057, +44058, +44091, +44090, +44059, +44060, +44093, +44092, +44061, +44062, +44095, +44094, +44063, +44120, +44153, +44152, +44121, +44122, +44155, +44154, +44123, +44124, +44157, +44156, +44125, +44126, +44159, +44158, +44127, +44184, +44217, +44216, +44185, +44186, +44219, +44218, +44187, +44188, +44221, +44220, +44189, +44190, +44223, +44222, +44191, +44248, +44281, +44280, +44249, +44250, +44283, +44282, +44251, +44252, +44285, +44284, +44253, +44254, +44287, +44286, +44255, +44312, +44345, +44344, +44313, +44314, +44347, +44346, +44315, +44316, +44349, +44348, +44317, +44318, +44351, +44350, +44319, +44376, +44409, +44408, +44377, +44378, +44411, +44410, +44379, +44380, +44413, +44412, +44381, +44382, +44415, +44414, +44383, +44440, +44473, +44472, +44441, +44442, +44475, +44474, +44443, +44444, +44477, +44476, +44445, +44446, +44479, +44478, +44447, +44504, +44537, +44536, +44505, +44506, +44539, +44538, +44507, +44508, +44541, +44540, +44509, +44510, +44543, +44542, +44511, +44568, +44601, +44600, +44569, +44570, +44603, +44602, +44571, +44572, +44605, +44604, +44573, +44574, +44607, +44606, +44575, +44632, +44665, +44664, +44633, +44634, +44667, +44666, +44635, +44636, +44669, +44668, +44637, +44638, +44671, +44670, +44639, +44696, +44729, +44728, +44697, +44698, +44731, +44730, +44699, +44700, +44733, +44732, +44701, +44702, +44735, +44734, +44703, +44760, +44793, +44792, +44761, +44762, +44795, +44794, +44763, +44764, +44797, +44796, +44765, +44766, +44799, +44798, +44767, +44824, +44857, +44856, +44825, +44826, +44859, +44858, +44827, +44828, +44861, +44860, +44829, +44830, +44863, +44862, +44831, +44888, +44921, +44920, +44889, +44890, +44923, +44922, +44891, +44892, +44925, +44924, +44893, +44894, +44927, +44926, +44895, +44952, +44985, +44984, +44953, +44954, +44987, +44986, +44955, +44956, +44989, +44988, +44957, +44958, +44991, +44990, +44959, +45016, +45049, +45048, +45017, +45018, +45051, +45050, +45019, +45020, +45053, +45052, +45021, +45022, +45055, +45054, +45023, +45056, +45089, +45088, +45057, +45058, +45091, +45090, +45059, +45060, +45093, +45092, +45061, +45062, +45095, +45094, +45063, +45120, +45153, +45152, +45121, +45122, +45155, +45154, +45123, +45124, +45157, +45156, +45125, +45126, +45159, +45158, +45127, +45184, +45217, +45216, +45185, +45186, +45219, +45218, +45187, +45188, +45221, +45220, +45189, +45190, +45223, +45222, +45191, +45248, +45281, +45280, +45249, +45250, +45283, +45282, +45251, +45252, +45285, +45284, +45253, +45254, +45287, +45286, +45255, +45312, +45345, +45344, +45313, +45314, +45347, +45346, +45315, +45316, +45349, +45348, +45317, +45318, +45351, +45350, +45319, +45376, +45409, +45408, +45377, +45378, +45411, +45410, +45379, +45380, +45413, +45412, +45381, +45382, +45415, +45414, +45383, +45440, +45473, +45472, +45441, +45442, +45475, +45474, +45443, +45444, +45477, +45476, +45445, +45446, +45479, +45478, +45447, +45504, +45537, +45536, +45505, +45506, +45539, +45538, +45507, +45508, +45541, +45540, +45509, +45510, +45543, +45542, +45511, +45568, +45601, +45600, +45569, +45570, +45603, +45602, +45571, +45572, +45605, +45604, +45573, +45574, +45607, +45606, +45575, +45632, +45665, +45664, +45633, +45634, +45667, +45666, +45635, +45636, +45669, +45668, +45637, +45638, +45671, +45670, +45639, +45696, +45729, +45728, +45697, +45698, +45731, +45730, +45699, +45700, +45733, +45732, +45701, +45702, +45735, +45734, +45703, +45760, +45793, +45792, +45761, +45762, +45795, +45794, +45763, +45764, +45797, +45796, +45765, +45766, +45799, +45798, +45767, +45824, +45857, +45856, +45825, +45826, +45859, +45858, +45827, +45828, +45861, +45860, +45829, +45830, +45863, +45862, +45831, +45888, +45921, +45920, +45889, +45890, +45923, +45922, +45891, +45892, +45925, +45924, +45893, +45894, +45927, +45926, +45895, +45952, +45985, +45984, +45953, +45954, +45987, +45986, +45955, +45956, +45989, +45988, +45957, +45958, +45991, +45990, +45959, +46016, +46049, +46048, +46017, +46018, +46051, +46050, +46019, +46020, +46053, +46052, +46021, +46022, +46055, +46054, +46023, +46080, +46113, +46112, +46081, +46082, +46115, +46114, +46083, +46084, +46117, +46116, +46085, +46086, +46119, +46118, +46087, +46144, +46177, +46176, +46145, +46146, +46179, +46178, +46147, +46148, +46181, +46180, +46149, +46150, +46183, +46182, +46151, +46208, +46241, +46240, +46209, +46210, +46243, +46242, +46211, +46212, +46245, +46244, +46213, +46214, +46247, +46246, +46215, +46272, +46305, +46304, +46273, +46274, +46307, +46306, +46275, +46276, +46309, +46308, +46277, +46278, +46311, +46310, +46279, +46336, +46369, +46368, +46337, +46338, +46371, +46370, +46339, +46340, +46373, +46372, +46341, +46342, +46375, +46374, +46343, +46400, +46433, +46432, +46401, +46402, +46435, +46434, +46403, +46404, +46437, +46436, +46405, +46406, +46439, +46438, +46407, +46464, +46497, +46496, +46465, +46466, +46499, +46498, +46467, +46468, +46501, +46500, +46469, +46470, +46503, +46502, +46471, +46528, +46561, +46560, +46529, +46530, +46563, +46562, +46531, +46532, +46565, +46564, +46533, +46534, +46567, +46566, +46535, +46592, +46625, +46624, +46593, +46594, +46627, +46626, +46595, +46596, +46629, +46628, +46597, +46598, +46631, +46630, +46599, +46656, +46689, +46688, +46657, +46658, +46691, +46690, +46659, +46660, +46693, +46692, +46661, +46662, +46695, +46694, +46663, +46720, +46753, +46752, +46721, +46722, +46755, +46754, +46723, +46724, +46757, +46756, +46725, +46726, +46759, +46758, +46727, +46784, +46817, +46816, +46785, +46786, +46819, +46818, +46787, +46788, +46821, +46820, +46789, +46790, +46823, +46822, +46791, +46848, +46881, +46880, +46849, +46850, +46883, +46882, +46851, +46852, +46885, +46884, +46853, +46854, +46887, +46886, +46855, +46912, +46945, +46944, +46913, +46914, +46947, +46946, +46915, +46916, +46949, +46948, +46917, +46918, +46951, +46950, +46919, +46976, +47009, +47008, +46977, +46978, +47011, +47010, +46979, +46980, +47013, +47012, +46981, +46982, +47015, +47014, +46983, +47040, +47073, +47072, +47041, +47042, +47075, +47074, +47043, +47044, +47077, +47076, +47045, +47046, +47079, +47078, +47047, +45064, +45097, +45096, +45065, +45066, +45099, +45098, +45067, +45068, +45101, +45100, +45069, +45070, +45103, +45102, +45071, +45128, +45161, +45160, +45129, +45130, +45163, +45162, +45131, +45132, +45165, +45164, +45133, +45134, +45167, +45166, +45135, +45192, +45225, +45224, +45193, +45194, +45227, +45226, +45195, +45196, +45229, +45228, +45197, +45198, +45231, +45230, +45199, +45256, +45289, +45288, +45257, +45258, +45291, +45290, +45259, +45260, +45293, +45292, +45261, +45262, +45295, +45294, +45263, +45320, +45353, +45352, +45321, +45322, +45355, +45354, +45323, +45324, +45357, +45356, +45325, +45326, +45359, +45358, +45327, +45384, +45417, +45416, +45385, +45386, +45419, +45418, +45387, +45388, +45421, +45420, +45389, +45390, +45423, +45422, +45391, +45448, +45481, +45480, +45449, +45450, +45483, +45482, +45451, +45452, +45485, +45484, +45453, +45454, +45487, +45486, +45455, +45512, +45545, +45544, +45513, +45514, +45547, +45546, +45515, +45516, +45549, +45548, +45517, +45518, +45551, +45550, +45519, +45576, +45609, +45608, +45577, +45578, +45611, +45610, +45579, +45580, +45613, +45612, +45581, +45582, +45615, +45614, +45583, +45640, +45673, +45672, +45641, +45642, +45675, +45674, +45643, +45644, +45677, +45676, +45645, +45646, +45679, +45678, +45647, +45704, +45737, +45736, +45705, +45706, +45739, +45738, +45707, +45708, +45741, +45740, +45709, +45710, +45743, +45742, +45711, +45768, +45801, +45800, +45769, +45770, +45803, +45802, +45771, +45772, +45805, +45804, +45773, +45774, +45807, +45806, +45775, +45832, +45865, +45864, +45833, +45834, +45867, +45866, +45835, +45836, +45869, +45868, +45837, +45838, +45871, +45870, +45839, +45896, +45929, +45928, +45897, +45898, +45931, +45930, +45899, +45900, +45933, +45932, +45901, +45902, +45935, +45934, +45903, +45960, +45993, +45992, +45961, +45962, +45995, +45994, +45963, +45964, +45997, +45996, +45965, +45966, +45999, +45998, +45967, +46024, +46057, +46056, +46025, +46026, +46059, +46058, +46027, +46028, +46061, +46060, +46029, +46030, +46063, +46062, +46031, +46088, +46121, +46120, +46089, +46090, +46123, +46122, +46091, +46092, +46125, +46124, +46093, +46094, +46127, +46126, +46095, +46152, +46185, +46184, +46153, +46154, +46187, +46186, +46155, +46156, +46189, +46188, +46157, +46158, +46191, +46190, +46159, +46216, +46249, +46248, +46217, +46218, +46251, +46250, +46219, +46220, +46253, +46252, +46221, +46222, +46255, +46254, +46223, +46280, +46313, +46312, +46281, +46282, +46315, +46314, +46283, +46284, +46317, +46316, +46285, +46286, +46319, +46318, +46287, +46344, +46377, +46376, +46345, +46346, +46379, +46378, +46347, +46348, +46381, +46380, +46349, +46350, +46383, +46382, +46351, +46408, +46441, +46440, +46409, +46410, +46443, +46442, +46411, +46412, +46445, +46444, +46413, +46414, +46447, +46446, +46415, +46472, +46505, +46504, +46473, +46474, +46507, +46506, +46475, +46476, +46509, +46508, +46477, +46478, +46511, +46510, +46479, +46536, +46569, +46568, +46537, +46538, +46571, +46570, +46539, +46540, +46573, +46572, +46541, +46542, +46575, +46574, +46543, +46600, +46633, +46632, +46601, +46602, +46635, +46634, +46603, +46604, +46637, +46636, +46605, +46606, +46639, +46638, +46607, +46664, +46697, +46696, +46665, +46666, +46699, +46698, +46667, +46668, +46701, +46700, +46669, +46670, +46703, +46702, +46671, +46728, +46761, +46760, +46729, +46730, +46763, +46762, +46731, +46732, +46765, +46764, +46733, +46734, +46767, +46766, +46735, +46792, +46825, +46824, +46793, +46794, +46827, +46826, +46795, +46796, +46829, +46828, +46797, +46798, +46831, +46830, +46799, +46856, +46889, +46888, +46857, +46858, +46891, +46890, +46859, +46860, +46893, +46892, +46861, +46862, +46895, +46894, +46863, +46920, +46953, +46952, +46921, +46922, +46955, +46954, +46923, +46924, +46957, +46956, +46925, +46926, +46959, +46958, +46927, +46984, +47017, +47016, +46985, +46986, +47019, +47018, +46987, +46988, +47021, +47020, +46989, +46990, +47023, +47022, +46991, +47048, +47081, +47080, +47049, +47050, +47083, +47082, +47051, +47052, +47085, +47084, +47053, +47054, +47087, +47086, +47055, +45072, +45105, +45104, +45073, +45074, +45107, +45106, +45075, +45076, +45109, +45108, +45077, +45078, +45111, +45110, +45079, +45136, +45169, +45168, +45137, +45138, +45171, +45170, +45139, +45140, +45173, +45172, +45141, +45142, +45175, +45174, +45143, +45200, +45233, +45232, +45201, +45202, +45235, +45234, +45203, +45204, +45237, +45236, +45205, +45206, +45239, +45238, +45207, +45264, +45297, +45296, +45265, +45266, +45299, +45298, +45267, +45268, +45301, +45300, +45269, +45270, +45303, +45302, +45271, +45328, +45361, +45360, +45329, +45330, +45363, +45362, +45331, +45332, +45365, +45364, +45333, +45334, +45367, +45366, +45335, +45392, +45425, +45424, +45393, +45394, +45427, +45426, +45395, +45396, +45429, +45428, +45397, +45398, +45431, +45430, +45399, +45456, +45489, +45488, +45457, +45458, +45491, +45490, +45459, +45460, +45493, +45492, +45461, +45462, +45495, +45494, +45463, +45520, +45553, +45552, +45521, +45522, +45555, +45554, +45523, +45524, +45557, +45556, +45525, +45526, +45559, +45558, +45527, +45584, +45617, +45616, +45585, +45586, +45619, +45618, +45587, +45588, +45621, +45620, +45589, +45590, +45623, +45622, +45591, +45648, +45681, +45680, +45649, +45650, +45683, +45682, +45651, +45652, +45685, +45684, +45653, +45654, +45687, +45686, +45655, +45712, +45745, +45744, +45713, +45714, +45747, +45746, +45715, +45716, +45749, +45748, +45717, +45718, +45751, +45750, +45719, +45776, +45809, +45808, +45777, +45778, +45811, +45810, +45779, +45780, +45813, +45812, +45781, +45782, +45815, +45814, +45783, +45840, +45873, +45872, +45841, +45842, +45875, +45874, +45843, +45844, +45877, +45876, +45845, +45846, +45879, +45878, +45847, +45904, +45937, +45936, +45905, +45906, +45939, +45938, +45907, +45908, +45941, +45940, +45909, +45910, +45943, +45942, +45911, +45968, +46001, +46000, +45969, +45970, +46003, +46002, +45971, +45972, +46005, +46004, +45973, +45974, +46007, +46006, +45975, +46032, +46065, +46064, +46033, +46034, +46067, +46066, +46035, +46036, +46069, +46068, +46037, +46038, +46071, +46070, +46039, +46096, +46129, +46128, +46097, +46098, +46131, +46130, +46099, +46100, +46133, +46132, +46101, +46102, +46135, +46134, +46103, +46160, +46193, +46192, +46161, +46162, +46195, +46194, +46163, +46164, +46197, +46196, +46165, +46166, +46199, +46198, +46167, +46224, +46257, +46256, +46225, +46226, +46259, +46258, +46227, +46228, +46261, +46260, +46229, +46230, +46263, +46262, +46231, +46288, +46321, +46320, +46289, +46290, +46323, +46322, +46291, +46292, +46325, +46324, +46293, +46294, +46327, +46326, +46295, +46352, +46385, +46384, +46353, +46354, +46387, +46386, +46355, +46356, +46389, +46388, +46357, +46358, +46391, +46390, +46359, +46416, +46449, +46448, +46417, +46418, +46451, +46450, +46419, +46420, +46453, +46452, +46421, +46422, +46455, +46454, +46423, +46480, +46513, +46512, +46481, +46482, +46515, +46514, +46483, +46484, +46517, +46516, +46485, +46486, +46519, +46518, +46487, +46544, +46577, +46576, +46545, +46546, +46579, +46578, +46547, +46548, +46581, +46580, +46549, +46550, +46583, +46582, +46551, +46608, +46641, +46640, +46609, +46610, +46643, +46642, +46611, +46612, +46645, +46644, +46613, +46614, +46647, +46646, +46615, +46672, +46705, +46704, +46673, +46674, +46707, +46706, +46675, +46676, +46709, +46708, +46677, +46678, +46711, +46710, +46679, +46736, +46769, +46768, +46737, +46738, +46771, +46770, +46739, +46740, +46773, +46772, +46741, +46742, +46775, +46774, +46743, +46800, +46833, +46832, +46801, +46802, +46835, +46834, +46803, +46804, +46837, +46836, +46805, +46806, +46839, +46838, +46807, +46864, +46897, +46896, +46865, +46866, +46899, +46898, +46867, +46868, +46901, +46900, +46869, +46870, +46903, +46902, +46871, +46928, +46961, +46960, +46929, +46930, +46963, +46962, +46931, +46932, +46965, +46964, +46933, +46934, +46967, +46966, +46935, +46992, +47025, +47024, +46993, +46994, +47027, +47026, +46995, +46996, +47029, +47028, +46997, +46998, +47031, +47030, +46999, +47056, +47089, +47088, +47057, +47058, +47091, +47090, +47059, +47060, +47093, +47092, +47061, +47062, +47095, +47094, +47063, +45080, +45113, +45112, +45081, +45082, +45115, +45114, +45083, +45084, +45117, +45116, +45085, +45086, +45119, +45118, +45087, +45144, +45177, +45176, +45145, +45146, +45179, +45178, +45147, +45148, +45181, +45180, +45149, +45150, +45183, +45182, +45151, +45208, +45241, +45240, +45209, +45210, +45243, +45242, +45211, +45212, +45245, +45244, +45213, +45214, +45247, +45246, +45215, +45272, +45305, +45304, +45273, +45274, +45307, +45306, +45275, +45276, +45309, +45308, +45277, +45278, +45311, +45310, +45279, +45336, +45369, +45368, +45337, +45338, +45371, +45370, +45339, +45340, +45373, +45372, +45341, +45342, +45375, +45374, +45343, +45400, +45433, +45432, +45401, +45402, +45435, +45434, +45403, +45404, +45437, +45436, +45405, +45406, +45439, +45438, +45407, +45464, +45497, +45496, +45465, +45466, +45499, +45498, +45467, +45468, +45501, +45500, +45469, +45470, +45503, +45502, +45471, +45528, +45561, +45560, +45529, +45530, +45563, +45562, +45531, +45532, +45565, +45564, +45533, +45534, +45567, +45566, +45535, +45592, +45625, +45624, +45593, +45594, +45627, +45626, +45595, +45596, +45629, +45628, +45597, +45598, +45631, +45630, +45599, +45656, +45689, +45688, +45657, +45658, +45691, +45690, +45659, +45660, +45693, +45692, +45661, +45662, +45695, +45694, +45663, +45720, +45753, +45752, +45721, +45722, +45755, +45754, +45723, +45724, +45757, +45756, +45725, +45726, +45759, +45758, +45727, +45784, +45817, +45816, +45785, +45786, +45819, +45818, +45787, +45788, +45821, +45820, +45789, +45790, +45823, +45822, +45791, +45848, +45881, +45880, +45849, +45850, +45883, +45882, +45851, +45852, +45885, +45884, +45853, +45854, +45887, +45886, +45855, +45912, +45945, +45944, +45913, +45914, +45947, +45946, +45915, +45916, +45949, +45948, +45917, +45918, +45951, +45950, +45919, +45976, +46009, +46008, +45977, +45978, +46011, +46010, +45979, +45980, +46013, +46012, +45981, +45982, +46015, +46014, +45983, +46040, +46073, +46072, +46041, +46042, +46075, +46074, +46043, +46044, +46077, +46076, +46045, +46046, +46079, +46078, +46047, +46104, +46137, +46136, +46105, +46106, +46139, +46138, +46107, +46108, +46141, +46140, +46109, +46110, +46143, +46142, +46111, +46168, +46201, +46200, +46169, +46170, +46203, +46202, +46171, +46172, +46205, +46204, +46173, +46174, +46207, +46206, +46175, +46232, +46265, +46264, +46233, +46234, +46267, +46266, +46235, +46236, +46269, +46268, +46237, +46238, +46271, +46270, +46239, +46296, +46329, +46328, +46297, +46298, +46331, +46330, +46299, +46300, +46333, +46332, +46301, +46302, +46335, +46334, +46303, +46360, +46393, +46392, +46361, +46362, +46395, +46394, +46363, +46364, +46397, +46396, +46365, +46366, +46399, +46398, +46367, +46424, +46457, +46456, +46425, +46426, +46459, +46458, +46427, +46428, +46461, +46460, +46429, +46430, +46463, +46462, +46431, +46488, +46521, +46520, +46489, +46490, +46523, +46522, +46491, +46492, +46525, +46524, +46493, +46494, +46527, +46526, +46495, +46552, +46585, +46584, +46553, +46554, +46587, +46586, +46555, +46556, +46589, +46588, +46557, +46558, +46591, +46590, +46559, +46616, +46649, +46648, +46617, +46618, +46651, +46650, +46619, +46620, +46653, +46652, +46621, +46622, +46655, +46654, +46623, +46680, +46713, +46712, +46681, +46682, +46715, +46714, +46683, +46684, +46717, +46716, +46685, +46686, +46719, +46718, +46687, +46744, +46777, +46776, +46745, +46746, +46779, +46778, +46747, +46748, +46781, +46780, +46749, +46750, +46783, +46782, +46751, +46808, +46841, +46840, +46809, +46810, +46843, +46842, +46811, +46812, +46845, +46844, +46813, +46814, +46847, +46846, +46815, +46872, +46905, +46904, +46873, +46874, +46907, +46906, +46875, +46876, +46909, +46908, +46877, +46878, +46911, +46910, +46879, +46936, +46969, +46968, +46937, +46938, +46971, +46970, +46939, +46940, +46973, +46972, +46941, +46942, +46975, +46974, +46943, +47000, +47033, +47032, +47001, +47002, +47035, +47034, +47003, +47004, +47037, +47036, +47005, +47006, +47039, +47038, +47007, +47064, +47097, +47096, +47065, +47066, +47099, +47098, +47067, +47068, +47101, +47100, +47069, +47070, +47103, +47102, +47071, +47104, +47137, +47136, +47105, +47106, +47139, +47138, +47107, +47108, +47141, +47140, +47109, +47110, +47143, +47142, +47111, +47168, +47201, +47200, +47169, +47170, +47203, +47202, +47171, +47172, +47205, +47204, +47173, +47174, +47207, +47206, +47175, +47232, +47265, +47264, +47233, +47234, +47267, +47266, +47235, +47236, +47269, +47268, +47237, +47238, +47271, +47270, +47239, +47296, +47329, +47328, +47297, +47298, +47331, +47330, +47299, +47300, +47333, +47332, +47301, +47302, +47335, +47334, +47303, +47360, +47393, +47392, +47361, +47362, +47395, +47394, +47363, +47364, +47397, +47396, +47365, +47366, +47399, +47398, +47367, +47424, +47457, +47456, +47425, +47426, +47459, +47458, +47427, +47428, +47461, +47460, +47429, +47430, +47463, +47462, +47431, +47488, +47521, +47520, +47489, +47490, +47523, +47522, +47491, +47492, +47525, +47524, +47493, +47494, +47527, +47526, +47495, +47552, +47585, +47584, +47553, +47554, +47587, +47586, +47555, +47556, +47589, +47588, +47557, +47558, +47591, +47590, +47559, +47616, +47649, +47648, +47617, +47618, +47651, +47650, +47619, +47620, +47653, +47652, +47621, +47622, +47655, +47654, +47623, +47680, +47713, +47712, +47681, +47682, +47715, +47714, +47683, +47684, +47717, +47716, +47685, +47686, +47719, +47718, +47687, +47744, +47777, +47776, +47745, +47746, +47779, +47778, +47747, +47748, +47781, +47780, +47749, +47750, +47783, +47782, +47751, +47808, +47841, +47840, +47809, +47810, +47843, +47842, +47811, +47812, +47845, +47844, +47813, +47814, +47847, +47846, +47815, +47872, +47905, +47904, +47873, +47874, +47907, +47906, +47875, +47876, +47909, +47908, +47877, +47878, +47911, +47910, +47879, +47936, +47969, +47968, +47937, +47938, +47971, +47970, +47939, +47940, +47973, +47972, +47941, +47942, +47975, +47974, +47943, +48000, +48033, +48032, +48001, +48002, +48035, +48034, +48003, +48004, +48037, +48036, +48005, +48006, +48039, +48038, +48007, +48064, +48097, +48096, +48065, +48066, +48099, +48098, +48067, +48068, +48101, +48100, +48069, +48070, +48103, +48102, +48071, +48128, +48161, +48160, +48129, +48130, +48163, +48162, +48131, +48132, +48165, +48164, +48133, +48134, +48167, +48166, +48135, +48192, +48225, +48224, +48193, +48194, +48227, +48226, +48195, +48196, +48229, +48228, +48197, +48198, +48231, +48230, +48199, +48256, +48289, +48288, +48257, +48258, +48291, +48290, +48259, +48260, +48293, +48292, +48261, +48262, +48295, +48294, +48263, +48320, +48353, +48352, +48321, +48322, +48355, +48354, +48323, +48324, +48357, +48356, +48325, +48326, +48359, +48358, +48327, +48384, +48417, +48416, +48385, +48386, +48419, +48418, +48387, +48388, +48421, +48420, +48389, +48390, +48423, +48422, +48391, +48448, +48481, +48480, +48449, +48450, +48483, +48482, +48451, +48452, +48485, +48484, +48453, +48454, +48487, +48486, +48455, +48512, +48545, +48544, +48513, +48514, +48547, +48546, +48515, +48516, +48549, +48548, +48517, +48518, +48551, +48550, +48519, +48576, +48609, +48608, +48577, +48578, +48611, +48610, +48579, +48580, +48613, +48612, +48581, +48582, +48615, +48614, +48583, +48640, +48673, +48672, +48641, +48642, +48675, +48674, +48643, +48644, +48677, +48676, +48645, +48646, +48679, +48678, +48647, +48704, +48737, +48736, +48705, +48706, +48739, +48738, +48707, +48708, +48741, +48740, +48709, +48710, +48743, +48742, +48711, +48768, +48801, +48800, +48769, +48770, +48803, +48802, +48771, +48772, +48805, +48804, +48773, +48774, +48807, +48806, +48775, +48832, +48865, +48864, +48833, +48834, +48867, +48866, +48835, +48836, +48869, +48868, +48837, +48838, +48871, +48870, +48839, +48896, +48929, +48928, +48897, +48898, +48931, +48930, +48899, +48900, +48933, +48932, +48901, +48902, +48935, +48934, +48903, +48960, +48993, +48992, +48961, +48962, +48995, +48994, +48963, +48964, +48997, +48996, +48965, +48966, +48999, +48998, +48967, +49024, +49057, +49056, +49025, +49026, +49059, +49058, +49027, +49028, +49061, +49060, +49029, +49030, +49063, +49062, +49031, +49088, +49121, +49120, +49089, +49090, +49123, +49122, +49091, +49092, +49125, +49124, +49093, +49094, +49127, +49126, +49095, +47112, +47145, +47144, +47113, +47114, +47147, +47146, +47115, +47116, +47149, +47148, +47117, +47118, +47151, +47150, +47119, +47176, +47209, +47208, +47177, +47178, +47211, +47210, +47179, +47180, +47213, +47212, +47181, +47182, +47215, +47214, +47183, +47240, +47273, +47272, +47241, +47242, +47275, +47274, +47243, +47244, +47277, +47276, +47245, +47246, +47279, +47278, +47247, +47304, +47337, +47336, +47305, +47306, +47339, +47338, +47307, +47308, +47341, +47340, +47309, +47310, +47343, +47342, +47311, +47368, +47401, +47400, +47369, +47370, +47403, +47402, +47371, +47372, +47405, +47404, +47373, +47374, +47407, +47406, +47375, +47432, +47465, +47464, +47433, +47434, +47467, +47466, +47435, +47436, +47469, +47468, +47437, +47438, +47471, +47470, +47439, +47496, +47529, +47528, +47497, +47498, +47531, +47530, +47499, +47500, +47533, +47532, +47501, +47502, +47535, +47534, +47503, +47560, +47593, +47592, +47561, +47562, +47595, +47594, +47563, +47564, +47597, +47596, +47565, +47566, +47599, +47598, +47567, +47624, +47657, +47656, +47625, +47626, +47659, +47658, +47627, +47628, +47661, +47660, +47629, +47630, +47663, +47662, +47631, +47688, +47721, +47720, +47689, +47690, +47723, +47722, +47691, +47692, +47725, +47724, +47693, +47694, +47727, +47726, +47695, +47752, +47785, +47784, +47753, +47754, +47787, +47786, +47755, +47756, +47789, +47788, +47757, +47758, +47791, +47790, +47759, +47816, +47849, +47848, +47817, +47818, +47851, +47850, +47819, +47820, +47853, +47852, +47821, +47822, +47855, +47854, +47823, +47880, +47913, +47912, +47881, +47882, +47915, +47914, +47883, +47884, +47917, +47916, +47885, +47886, +47919, +47918, +47887, +47944, +47977, +47976, +47945, +47946, +47979, +47978, +47947, +47948, +47981, +47980, +47949, +47950, +47983, +47982, +47951, +48008, +48041, +48040, +48009, +48010, +48043, +48042, +48011, +48012, +48045, +48044, +48013, +48014, +48047, +48046, +48015, +48072, +48105, +48104, +48073, +48074, +48107, +48106, +48075, +48076, +48109, +48108, +48077, +48078, +48111, +48110, +48079, +48136, +48169, +48168, +48137, +48138, +48171, +48170, +48139, +48140, +48173, +48172, +48141, +48142, +48175, +48174, +48143, +48200, +48233, +48232, +48201, +48202, +48235, +48234, +48203, +48204, +48237, +48236, +48205, +48206, +48239, +48238, +48207, +48264, +48297, +48296, +48265, +48266, +48299, +48298, +48267, +48268, +48301, +48300, +48269, +48270, +48303, +48302, +48271, +48328, +48361, +48360, +48329, +48330, +48363, +48362, +48331, +48332, +48365, +48364, +48333, +48334, +48367, +48366, +48335, +48392, +48425, +48424, +48393, +48394, +48427, +48426, +48395, +48396, +48429, +48428, +48397, +48398, +48431, +48430, +48399, +48456, +48489, +48488, +48457, +48458, +48491, +48490, +48459, +48460, +48493, +48492, +48461, +48462, +48495, +48494, +48463, +48520, +48553, +48552, +48521, +48522, +48555, +48554, +48523, +48524, +48557, +48556, +48525, +48526, +48559, +48558, +48527, +48584, +48617, +48616, +48585, +48586, +48619, +48618, +48587, +48588, +48621, +48620, +48589, +48590, +48623, +48622, +48591, +48648, +48681, +48680, +48649, +48650, +48683, +48682, +48651, +48652, +48685, +48684, +48653, +48654, +48687, +48686, +48655, +48712, +48745, +48744, +48713, +48714, +48747, +48746, +48715, +48716, +48749, +48748, +48717, +48718, +48751, +48750, +48719, +48776, +48809, +48808, +48777, +48778, +48811, +48810, +48779, +48780, +48813, +48812, +48781, +48782, +48815, +48814, +48783, +48840, +48873, +48872, +48841, +48842, +48875, +48874, +48843, +48844, +48877, +48876, +48845, +48846, +48879, +48878, +48847, +48904, +48937, +48936, +48905, +48906, +48939, +48938, +48907, +48908, +48941, +48940, +48909, +48910, +48943, +48942, +48911, +48968, +49001, +49000, +48969, +48970, +49003, +49002, +48971, +48972, +49005, +49004, +48973, +48974, +49007, +49006, +48975, +49032, +49065, +49064, +49033, +49034, +49067, +49066, +49035, +49036, +49069, +49068, +49037, +49038, +49071, +49070, +49039, +49096, +49129, +49128, +49097, +49098, +49131, +49130, +49099, +49100, +49133, +49132, +49101, +49102, +49135, +49134, +49103, +47120, +47153, +47152, +47121, +47122, +47155, +47154, +47123, +47124, +47157, +47156, +47125, +47126, +47159, +47158, +47127, +47184, +47217, +47216, +47185, +47186, +47219, +47218, +47187, +47188, +47221, +47220, +47189, +47190, +47223, +47222, +47191, +47248, +47281, +47280, +47249, +47250, +47283, +47282, +47251, +47252, +47285, +47284, +47253, +47254, +47287, +47286, +47255, +47312, +47345, +47344, +47313, +47314, +47347, +47346, +47315, +47316, +47349, +47348, +47317, +47318, +47351, +47350, +47319, +47376, +47409, +47408, +47377, +47378, +47411, +47410, +47379, +47380, +47413, +47412, +47381, +47382, +47415, +47414, +47383, +47440, +47473, +47472, +47441, +47442, +47475, +47474, +47443, +47444, +47477, +47476, +47445, +47446, +47479, +47478, +47447, +47504, +47537, +47536, +47505, +47506, +47539, +47538, +47507, +47508, +47541, +47540, +47509, +47510, +47543, +47542, +47511, +47568, +47601, +47600, +47569, +47570, +47603, +47602, +47571, +47572, +47605, +47604, +47573, +47574, +47607, +47606, +47575, +47632, +47665, +47664, +47633, +47634, +47667, +47666, +47635, +47636, +47669, +47668, +47637, +47638, +47671, +47670, +47639, +47696, +47729, +47728, +47697, +47698, +47731, +47730, +47699, +47700, +47733, +47732, +47701, +47702, +47735, +47734, +47703, +47760, +47793, +47792, +47761, +47762, +47795, +47794, +47763, +47764, +47797, +47796, +47765, +47766, +47799, +47798, +47767, +47824, +47857, +47856, +47825, +47826, +47859, +47858, +47827, +47828, +47861, +47860, +47829, +47830, +47863, +47862, +47831, +47888, +47921, +47920, +47889, +47890, +47923, +47922, +47891, +47892, +47925, +47924, +47893, +47894, +47927, +47926, +47895, +47952, +47985, +47984, +47953, +47954, +47987, +47986, +47955, +47956, +47989, +47988, +47957, +47958, +47991, +47990, +47959, +48016, +48049, +48048, +48017, +48018, +48051, +48050, +48019, +48020, +48053, +48052, +48021, +48022, +48055, +48054, +48023, +48080, +48113, +48112, +48081, +48082, +48115, +48114, +48083, +48084, +48117, +48116, +48085, +48086, +48119, +48118, +48087, +48144, +48177, +48176, +48145, +48146, +48179, +48178, +48147, +48148, +48181, +48180, +48149, +48150, +48183, +48182, +48151, +48208, +48241, +48240, +48209, +48210, +48243, +48242, +48211, +48212, +48245, +48244, +48213, +48214, +48247, +48246, +48215, +48272, +48305, +48304, +48273, +48274, +48307, +48306, +48275, +48276, +48309, +48308, +48277, +48278, +48311, +48310, +48279, +48336, +48369, +48368, +48337, +48338, +48371, +48370, +48339, +48340, +48373, +48372, +48341, +48342, +48375, +48374, +48343, +48400, +48433, +48432, +48401, +48402, +48435, +48434, +48403, +48404, +48437, +48436, +48405, +48406, +48439, +48438, +48407, +48464, +48497, +48496, +48465, +48466, +48499, +48498, +48467, +48468, +48501, +48500, +48469, +48470, +48503, +48502, +48471, +48528, +48561, +48560, +48529, +48530, +48563, +48562, +48531, +48532, +48565, +48564, +48533, +48534, +48567, +48566, +48535, +48592, +48625, +48624, +48593, +48594, +48627, +48626, +48595, +48596, +48629, +48628, +48597, +48598, +48631, +48630, +48599, +48656, +48689, +48688, +48657, +48658, +48691, +48690, +48659, +48660, +48693, +48692, +48661, +48662, +48695, +48694, +48663, +48720, +48753, +48752, +48721, +48722, +48755, +48754, +48723, +48724, +48757, +48756, +48725, +48726, +48759, +48758, +48727, +48784, +48817, +48816, +48785, +48786, +48819, +48818, +48787, +48788, +48821, +48820, +48789, +48790, +48823, +48822, +48791, +48848, +48881, +48880, +48849, +48850, +48883, +48882, +48851, +48852, +48885, +48884, +48853, +48854, +48887, +48886, +48855, +48912, +48945, +48944, +48913, +48914, +48947, +48946, +48915, +48916, +48949, +48948, +48917, +48918, +48951, +48950, +48919, +48976, +49009, +49008, +48977, +48978, +49011, +49010, +48979, +48980, +49013, +49012, +48981, +48982, +49015, +49014, +48983, +49040, +49073, +49072, +49041, +49042, +49075, +49074, +49043, +49044, +49077, +49076, +49045, +49046, +49079, +49078, +49047, +49104, +49137, +49136, +49105, +49106, +49139, +49138, +49107, +49108, +49141, +49140, +49109, +49110, +49143, +49142, +49111, +47128, +47161, +47160, +47129, +47130, +47163, +47162, +47131, +47132, +47165, +47164, +47133, +47134, +47167, +47166, +47135, +47192, +47225, +47224, +47193, +47194, +47227, +47226, +47195, +47196, +47229, +47228, +47197, +47198, +47231, +47230, +47199, +47256, +47289, +47288, +47257, +47258, +47291, +47290, +47259, +47260, +47293, +47292, +47261, +47262, +47295, +47294, +47263, +47320, +47353, +47352, +47321, +47322, +47355, +47354, +47323, +47324, +47357, +47356, +47325, +47326, +47359, +47358, +47327, +47384, +47417, +47416, +47385, +47386, +47419, +47418, +47387, +47388, +47421, +47420, +47389, +47390, +47423, +47422, +47391, +47448, +47481, +47480, +47449, +47450, +47483, +47482, +47451, +47452, +47485, +47484, +47453, +47454, +47487, +47486, +47455, +47512, +47545, +47544, +47513, +47514, +47547, +47546, +47515, +47516, +47549, +47548, +47517, +47518, +47551, +47550, +47519, +47576, +47609, +47608, +47577, +47578, +47611, +47610, +47579, +47580, +47613, +47612, +47581, +47582, +47615, +47614, +47583, +47640, +47673, +47672, +47641, +47642, +47675, +47674, +47643, +47644, +47677, +47676, +47645, +47646, +47679, +47678, +47647, +47704, +47737, +47736, +47705, +47706, +47739, +47738, +47707, +47708, +47741, +47740, +47709, +47710, +47743, +47742, +47711, +47768, +47801, +47800, +47769, +47770, +47803, +47802, +47771, +47772, +47805, +47804, +47773, +47774, +47807, +47806, +47775, +47832, +47865, +47864, +47833, +47834, +47867, +47866, +47835, +47836, +47869, +47868, +47837, +47838, +47871, +47870, +47839, +47896, +47929, +47928, +47897, +47898, +47931, +47930, +47899, +47900, +47933, +47932, +47901, +47902, +47935, +47934, +47903, +47960, +47993, +47992, +47961, +47962, +47995, +47994, +47963, +47964, +47997, +47996, +47965, +47966, +47999, +47998, +47967, +48024, +48057, +48056, +48025, +48026, +48059, +48058, +48027, +48028, +48061, +48060, +48029, +48030, +48063, +48062, +48031, +48088, +48121, +48120, +48089, +48090, +48123, +48122, +48091, +48092, +48125, +48124, +48093, +48094, +48127, +48126, +48095, +48152, +48185, +48184, +48153, +48154, +48187, +48186, +48155, +48156, +48189, +48188, +48157, +48158, +48191, +48190, +48159, +48216, +48249, +48248, +48217, +48218, +48251, +48250, +48219, +48220, +48253, +48252, +48221, +48222, +48255, +48254, +48223, +48280, +48313, +48312, +48281, +48282, +48315, +48314, +48283, +48284, +48317, +48316, +48285, +48286, +48319, +48318, +48287, +48344, +48377, +48376, +48345, +48346, +48379, +48378, +48347, +48348, +48381, +48380, +48349, +48350, +48383, +48382, +48351, +48408, +48441, +48440, +48409, +48410, +48443, +48442, +48411, +48412, +48445, +48444, +48413, +48414, +48447, +48446, +48415, +48472, +48505, +48504, +48473, +48474, +48507, +48506, +48475, +48476, +48509, +48508, +48477, +48478, +48511, +48510, +48479, +48536, +48569, +48568, +48537, +48538, +48571, +48570, +48539, +48540, +48573, +48572, +48541, +48542, +48575, +48574, +48543, +48600, +48633, +48632, +48601, +48602, +48635, +48634, +48603, +48604, +48637, +48636, +48605, +48606, +48639, +48638, +48607, +48664, +48697, +48696, +48665, +48666, +48699, +48698, +48667, +48668, +48701, +48700, +48669, +48670, +48703, +48702, +48671, +48728, +48761, +48760, +48729, +48730, +48763, +48762, +48731, +48732, +48765, +48764, +48733, +48734, +48767, +48766, +48735, +48792, +48825, +48824, +48793, +48794, +48827, +48826, +48795, +48796, +48829, +48828, +48797, +48798, +48831, +48830, +48799, +48856, +48889, +48888, +48857, +48858, +48891, +48890, +48859, +48860, +48893, +48892, +48861, +48862, +48895, +48894, +48863, +48920, +48953, +48952, +48921, +48922, +48955, +48954, +48923, +48924, +48957, +48956, +48925, +48926, +48959, +48958, +48927, +48984, +49017, +49016, +48985, +48986, +49019, +49018, +48987, +48988, +49021, +49020, +48989, +48990, +49023, +49022, +48991, +49048, +49081, +49080, +49049, +49050, +49083, +49082, +49051, +49052, +49085, +49084, +49053, +49054, +49087, +49086, +49055, +49112, +49145, +49144, +49113, +49114, +49147, +49146, +49115, +49116, +49149, +49148, +49117, +49118, +49151, +49150, +49119, +49152, +49185, +49184, +49153, +49154, +49187, +49186, +49155, +49156, +49189, +49188, +49157, +49158, +49191, +49190, +49159, +49216, +49249, +49248, +49217, +49218, +49251, +49250, +49219, +49220, +49253, +49252, +49221, +49222, +49255, +49254, +49223, +49280, +49313, +49312, +49281, +49282, +49315, +49314, +49283, +49284, +49317, +49316, +49285, +49286, +49319, +49318, +49287, +49344, +49377, +49376, +49345, +49346, +49379, +49378, +49347, +49348, +49381, +49380, +49349, +49350, +49383, +49382, +49351, +49408, +49441, +49440, +49409, +49410, +49443, +49442, +49411, +49412, +49445, +49444, +49413, +49414, +49447, +49446, +49415, +49472, +49505, +49504, +49473, +49474, +49507, +49506, +49475, +49476, +49509, +49508, +49477, +49478, +49511, +49510, +49479, +49536, +49569, +49568, +49537, +49538, +49571, +49570, +49539, +49540, +49573, +49572, +49541, +49542, +49575, +49574, +49543, +49600, +49633, +49632, +49601, +49602, +49635, +49634, +49603, +49604, +49637, +49636, +49605, +49606, +49639, +49638, +49607, +49664, +49697, +49696, +49665, +49666, +49699, +49698, +49667, +49668, +49701, +49700, +49669, +49670, +49703, +49702, +49671, +49728, +49761, +49760, +49729, +49730, +49763, +49762, +49731, +49732, +49765, +49764, +49733, +49734, +49767, +49766, +49735, +49792, +49825, +49824, +49793, +49794, +49827, +49826, +49795, +49796, +49829, +49828, +49797, +49798, +49831, +49830, +49799, +49856, +49889, +49888, +49857, +49858, +49891, +49890, +49859, +49860, +49893, +49892, +49861, +49862, +49895, +49894, +49863, +49920, +49953, +49952, +49921, +49922, +49955, +49954, +49923, +49924, +49957, +49956, +49925, +49926, +49959, +49958, +49927, +49984, +50017, +50016, +49985, +49986, +50019, +50018, +49987, +49988, +50021, +50020, +49989, +49990, +50023, +50022, +49991, +50048, +50081, +50080, +50049, +50050, +50083, +50082, +50051, +50052, +50085, +50084, +50053, +50054, +50087, +50086, +50055, +50112, +50145, +50144, +50113, +50114, +50147, +50146, +50115, +50116, +50149, +50148, +50117, +50118, +50151, +50150, +50119, +50176, +50209, +50208, +50177, +50178, +50211, +50210, +50179, +50180, +50213, +50212, +50181, +50182, +50215, +50214, +50183, +50240, +50273, +50272, +50241, +50242, +50275, +50274, +50243, +50244, +50277, +50276, +50245, +50246, +50279, +50278, +50247, +50304, +50337, +50336, +50305, +50306, +50339, +50338, +50307, +50308, +50341, +50340, +50309, +50310, +50343, +50342, +50311, +50368, +50401, +50400, +50369, +50370, +50403, +50402, +50371, +50372, +50405, +50404, +50373, +50374, +50407, +50406, +50375, +50432, +50465, +50464, +50433, +50434, +50467, +50466, +50435, +50436, +50469, +50468, +50437, +50438, +50471, +50470, +50439, +50496, +50529, +50528, +50497, +50498, +50531, +50530, +50499, +50500, +50533, +50532, +50501, +50502, +50535, +50534, +50503, +50560, +50593, +50592, +50561, +50562, +50595, +50594, +50563, +50564, +50597, +50596, +50565, +50566, +50599, +50598, +50567, +50624, +50657, +50656, +50625, +50626, +50659, +50658, +50627, +50628, +50661, +50660, +50629, +50630, +50663, +50662, +50631, +50688, +50721, +50720, +50689, +50690, +50723, +50722, +50691, +50692, +50725, +50724, +50693, +50694, +50727, +50726, +50695, +50752, +50785, +50784, +50753, +50754, +50787, +50786, +50755, +50756, +50789, +50788, +50757, +50758, +50791, +50790, +50759, +50816, +50849, +50848, +50817, +50818, +50851, +50850, +50819, +50820, +50853, +50852, +50821, +50822, +50855, +50854, +50823, +50880, +50913, +50912, +50881, +50882, +50915, +50914, +50883, +50884, +50917, +50916, +50885, +50886, +50919, +50918, +50887, +50944, +50977, +50976, +50945, +50946, +50979, +50978, +50947, +50948, +50981, +50980, +50949, +50950, +50983, +50982, +50951, +51008, +51041, +51040, +51009, +51010, +51043, +51042, +51011, +51012, +51045, +51044, +51013, +51014, +51047, +51046, +51015, +51072, +51105, +51104, +51073, +51074, +51107, +51106, +51075, +51076, +51109, +51108, +51077, +51078, +51111, +51110, +51079, +51136, +51169, +51168, +51137, +51138, +51171, +51170, +51139, +51140, +51173, +51172, +51141, +51142, +51175, +51174, +51143, +49160, +49193, +49192, +49161, +49162, +49195, +49194, +49163, +49164, +49197, +49196, +49165, +49166, +49199, +49198, +49167, +49224, +49257, +49256, +49225, +49226, +49259, +49258, +49227, +49228, +49261, +49260, +49229, +49230, +49263, +49262, +49231, +49288, +49321, +49320, +49289, +49290, +49323, +49322, +49291, +49292, +49325, +49324, +49293, +49294, +49327, +49326, +49295, +49352, +49385, +49384, +49353, +49354, +49387, +49386, +49355, +49356, +49389, +49388, +49357, +49358, +49391, +49390, +49359, +49416, +49449, +49448, +49417, +49418, +49451, +49450, +49419, +49420, +49453, +49452, +49421, +49422, +49455, +49454, +49423, +49480, +49513, +49512, +49481, +49482, +49515, +49514, +49483, +49484, +49517, +49516, +49485, +49486, +49519, +49518, +49487, +49544, +49577, +49576, +49545, +49546, +49579, +49578, +49547, +49548, +49581, +49580, +49549, +49550, +49583, +49582, +49551, +49608, +49641, +49640, +49609, +49610, +49643, +49642, +49611, +49612, +49645, +49644, +49613, +49614, +49647, +49646, +49615, +49672, +49705, +49704, +49673, +49674, +49707, +49706, +49675, +49676, +49709, +49708, +49677, +49678, +49711, +49710, +49679, +49736, +49769, +49768, +49737, +49738, +49771, +49770, +49739, +49740, +49773, +49772, +49741, +49742, +49775, +49774, +49743, +49800, +49833, +49832, +49801, +49802, +49835, +49834, +49803, +49804, +49837, +49836, +49805, +49806, +49839, +49838, +49807, +49864, +49897, +49896, +49865, +49866, +49899, +49898, +49867, +49868, +49901, +49900, +49869, +49870, +49903, +49902, +49871, +49928, +49961, +49960, +49929, +49930, +49963, +49962, +49931, +49932, +49965, +49964, +49933, +49934, +49967, +49966, +49935, +49992, +50025, +50024, +49993, +49994, +50027, +50026, +49995, +49996, +50029, +50028, +49997, +49998, +50031, +50030, +49999, +50056, +50089, +50088, +50057, +50058, +50091, +50090, +50059, +50060, +50093, +50092, +50061, +50062, +50095, +50094, +50063, +50120, +50153, +50152, +50121, +50122, +50155, +50154, +50123, +50124, +50157, +50156, +50125, +50126, +50159, +50158, +50127, +50184, +50217, +50216, +50185, +50186, +50219, +50218, +50187, +50188, +50221, +50220, +50189, +50190, +50223, +50222, +50191, +50248, +50281, +50280, +50249, +50250, +50283, +50282, +50251, +50252, +50285, +50284, +50253, +50254, +50287, +50286, +50255, +50312, +50345, +50344, +50313, +50314, +50347, +50346, +50315, +50316, +50349, +50348, +50317, +50318, +50351, +50350, +50319, +50376, +50409, +50408, +50377, +50378, +50411, +50410, +50379, +50380, +50413, +50412, +50381, +50382, +50415, +50414, +50383, +50440, +50473, +50472, +50441, +50442, +50475, +50474, +50443, +50444, +50477, +50476, +50445, +50446, +50479, +50478, +50447, +50504, +50537, +50536, +50505, +50506, +50539, +50538, +50507, +50508, +50541, +50540, +50509, +50510, +50543, +50542, +50511, +50568, +50601, +50600, +50569, +50570, +50603, +50602, +50571, +50572, +50605, +50604, +50573, +50574, +50607, +50606, +50575, +50632, +50665, +50664, +50633, +50634, +50667, +50666, +50635, +50636, +50669, +50668, +50637, +50638, +50671, +50670, +50639, +50696, +50729, +50728, +50697, +50698, +50731, +50730, +50699, +50700, +50733, +50732, +50701, +50702, +50735, +50734, +50703, +50760, +50793, +50792, +50761, +50762, +50795, +50794, +50763, +50764, +50797, +50796, +50765, +50766, +50799, +50798, +50767, +50824, +50857, +50856, +50825, +50826, +50859, +50858, +50827, +50828, +50861, +50860, +50829, +50830, +50863, +50862, +50831, +50888, +50921, +50920, +50889, +50890, +50923, +50922, +50891, +50892, +50925, +50924, +50893, +50894, +50927, +50926, +50895, +50952, +50985, +50984, +50953, +50954, +50987, +50986, +50955, +50956, +50989, +50988, +50957, +50958, +50991, +50990, +50959, +51016, +51049, +51048, +51017, +51018, +51051, +51050, +51019, +51020, +51053, +51052, +51021, +51022, +51055, +51054, +51023, +51080, +51113, +51112, +51081, +51082, +51115, +51114, +51083, +51084, +51117, +51116, +51085, +51086, +51119, +51118, +51087, +51144, +51177, +51176, +51145, +51146, +51179, +51178, +51147, +51148, +51181, +51180, +51149, +51150, +51183, +51182, +51151, +49168, +49201, +49200, +49169, +49170, +49203, +49202, +49171, +49172, +49205, +49204, +49173, +49174, +49207, +49206, +49175, +49232, +49265, +49264, +49233, +49234, +49267, +49266, +49235, +49236, +49269, +49268, +49237, +49238, +49271, +49270, +49239, +49296, +49329, +49328, +49297, +49298, +49331, +49330, +49299, +49300, +49333, +49332, +49301, +49302, +49335, +49334, +49303, +49360, +49393, +49392, +49361, +49362, +49395, +49394, +49363, +49364, +49397, +49396, +49365, +49366, +49399, +49398, +49367, +49424, +49457, +49456, +49425, +49426, +49459, +49458, +49427, +49428, +49461, +49460, +49429, +49430, +49463, +49462, +49431, +49488, +49521, +49520, +49489, +49490, +49523, +49522, +49491, +49492, +49525, +49524, +49493, +49494, +49527, +49526, +49495, +49552, +49585, +49584, +49553, +49554, +49587, +49586, +49555, +49556, +49589, +49588, +49557, +49558, +49591, +49590, +49559, +49616, +49649, +49648, +49617, +49618, +49651, +49650, +49619, +49620, +49653, +49652, +49621, +49622, +49655, +49654, +49623, +49680, +49713, +49712, +49681, +49682, +49715, +49714, +49683, +49684, +49717, +49716, +49685, +49686, +49719, +49718, +49687, +49744, +49777, +49776, +49745, +49746, +49779, +49778, +49747, +49748, +49781, +49780, +49749, +49750, +49783, +49782, +49751, +49808, +49841, +49840, +49809, +49810, +49843, +49842, +49811, +49812, +49845, +49844, +49813, +49814, +49847, +49846, +49815, +49872, +49905, +49904, +49873, +49874, +49907, +49906, +49875, +49876, +49909, +49908, +49877, +49878, +49911, +49910, +49879, +49936, +49969, +49968, +49937, +49938, +49971, +49970, +49939, +49940, +49973, +49972, +49941, +49942, +49975, +49974, +49943, +50000, +50033, +50032, +50001, +50002, +50035, +50034, +50003, +50004, +50037, +50036, +50005, +50006, +50039, +50038, +50007, +50064, +50097, +50096, +50065, +50066, +50099, +50098, +50067, +50068, +50101, +50100, +50069, +50070, +50103, +50102, +50071, +50128, +50161, +50160, +50129, +50130, +50163, +50162, +50131, +50132, +50165, +50164, +50133, +50134, +50167, +50166, +50135, +50192, +50225, +50224, +50193, +50194, +50227, +50226, +50195, +50196, +50229, +50228, +50197, +50198, +50231, +50230, +50199, +50256, +50289, +50288, +50257, +50258, +50291, +50290, +50259, +50260, +50293, +50292, +50261, +50262, +50295, +50294, +50263, +50320, +50353, +50352, +50321, +50322, +50355, +50354, +50323, +50324, +50357, +50356, +50325, +50326, +50359, +50358, +50327, +50384, +50417, +50416, +50385, +50386, +50419, +50418, +50387, +50388, +50421, +50420, +50389, +50390, +50423, +50422, +50391, +50448, +50481, +50480, +50449, +50450, +50483, +50482, +50451, +50452, +50485, +50484, +50453, +50454, +50487, +50486, +50455, +50512, +50545, +50544, +50513, +50514, +50547, +50546, +50515, +50516, +50549, +50548, +50517, +50518, +50551, +50550, +50519, +50576, +50609, +50608, +50577, +50578, +50611, +50610, +50579, +50580, +50613, +50612, +50581, +50582, +50615, +50614, +50583, +50640, +50673, +50672, +50641, +50642, +50675, +50674, +50643, +50644, +50677, +50676, +50645, +50646, +50679, +50678, +50647, +50704, +50737, +50736, +50705, +50706, +50739, +50738, +50707, +50708, +50741, +50740, +50709, +50710, +50743, +50742, +50711, +50768, +50801, +50800, +50769, +50770, +50803, +50802, +50771, +50772, +50805, +50804, +50773, +50774, +50807, +50806, +50775, +50832, +50865, +50864, +50833, +50834, +50867, +50866, +50835, +50836, +50869, +50868, +50837, +50838, +50871, +50870, +50839, +50896, +50929, +50928, +50897, +50898, +50931, +50930, +50899, +50900, +50933, +50932, +50901, +50902, +50935, +50934, +50903, +50960, +50993, +50992, +50961, +50962, +50995, +50994, +50963, +50964, +50997, +50996, +50965, +50966, +50999, +50998, +50967, +51024, +51057, +51056, +51025, +51026, +51059, +51058, +51027, +51028, +51061, +51060, +51029, +51030, +51063, +51062, +51031, +51088, +51121, +51120, +51089, +51090, +51123, +51122, +51091, +51092, +51125, +51124, +51093, +51094, +51127, +51126, +51095, +51152, +51185, +51184, +51153, +51154, +51187, +51186, +51155, +51156, +51189, +51188, +51157, +51158, +51191, +51190, +51159, +49176, +49209, +49208, +49177, +49178, +49211, +49210, +49179, +49180, +49213, +49212, +49181, +49182, +49215, +49214, +49183, +49240, +49273, +49272, +49241, +49242, +49275, +49274, +49243, +49244, +49277, +49276, +49245, +49246, +49279, +49278, +49247, +49304, +49337, +49336, +49305, +49306, +49339, +49338, +49307, +49308, +49341, +49340, +49309, +49310, +49343, +49342, +49311, +49368, +49401, +49400, +49369, +49370, +49403, +49402, +49371, +49372, +49405, +49404, +49373, +49374, +49407, +49406, +49375, +49432, +49465, +49464, +49433, +49434, +49467, +49466, +49435, +49436, +49469, +49468, +49437, +49438, +49471, +49470, +49439, +49496, +49529, +49528, +49497, +49498, +49531, +49530, +49499, +49500, +49533, +49532, +49501, +49502, +49535, +49534, +49503, +49560, +49593, +49592, +49561, +49562, +49595, +49594, +49563, +49564, +49597, +49596, +49565, +49566, +49599, +49598, +49567, +49624, +49657, +49656, +49625, +49626, +49659, +49658, +49627, +49628, +49661, +49660, +49629, +49630, +49663, +49662, +49631, +49688, +49721, +49720, +49689, +49690, +49723, +49722, +49691, +49692, +49725, +49724, +49693, +49694, +49727, +49726, +49695, +49752, +49785, +49784, +49753, +49754, +49787, +49786, +49755, +49756, +49789, +49788, +49757, +49758, +49791, +49790, +49759, +49816, +49849, +49848, +49817, +49818, +49851, +49850, +49819, +49820, +49853, +49852, +49821, +49822, +49855, +49854, +49823, +49880, +49913, +49912, +49881, +49882, +49915, +49914, +49883, +49884, +49917, +49916, +49885, +49886, +49919, +49918, +49887, +49944, +49977, +49976, +49945, +49946, +49979, +49978, +49947, +49948, +49981, +49980, +49949, +49950, +49983, +49982, +49951, +50008, +50041, +50040, +50009, +50010, +50043, +50042, +50011, +50012, +50045, +50044, +50013, +50014, +50047, +50046, +50015, +50072, +50105, +50104, +50073, +50074, +50107, +50106, +50075, +50076, +50109, +50108, +50077, +50078, +50111, +50110, +50079, +50136, +50169, +50168, +50137, +50138, +50171, +50170, +50139, +50140, +50173, +50172, +50141, +50142, +50175, +50174, +50143, +50200, +50233, +50232, +50201, +50202, +50235, +50234, +50203, +50204, +50237, +50236, +50205, +50206, +50239, +50238, +50207, +50264, +50297, +50296, +50265, +50266, +50299, +50298, +50267, +50268, +50301, +50300, +50269, +50270, +50303, +50302, +50271, +50328, +50361, +50360, +50329, +50330, +50363, +50362, +50331, +50332, +50365, +50364, +50333, +50334, +50367, +50366, +50335, +50392, +50425, +50424, +50393, +50394, +50427, +50426, +50395, +50396, +50429, +50428, +50397, +50398, +50431, +50430, +50399, +50456, +50489, +50488, +50457, +50458, +50491, +50490, +50459, +50460, +50493, +50492, +50461, +50462, +50495, +50494, +50463, +50520, +50553, +50552, +50521, +50522, +50555, +50554, +50523, +50524, +50557, +50556, +50525, +50526, +50559, +50558, +50527, +50584, +50617, +50616, +50585, +50586, +50619, +50618, +50587, +50588, +50621, +50620, +50589, +50590, +50623, +50622, +50591, +50648, +50681, +50680, +50649, +50650, +50683, +50682, +50651, +50652, +50685, +50684, +50653, +50654, +50687, +50686, +50655, +50712, +50745, +50744, +50713, +50714, +50747, +50746, +50715, +50716, +50749, +50748, +50717, +50718, +50751, +50750, +50719, +50776, +50809, +50808, +50777, +50778, +50811, +50810, +50779, +50780, +50813, +50812, +50781, +50782, +50815, +50814, +50783, +50840, +50873, +50872, +50841, +50842, +50875, +50874, +50843, +50844, +50877, +50876, +50845, +50846, +50879, +50878, +50847, +50904, +50937, +50936, +50905, +50906, +50939, +50938, +50907, +50908, +50941, +50940, +50909, +50910, +50943, +50942, +50911, +50968, +51001, +51000, +50969, +50970, +51003, +51002, +50971, +50972, +51005, +51004, +50973, +50974, +51007, +51006, +50975, +51032, +51065, +51064, +51033, +51034, +51067, +51066, +51035, +51036, +51069, +51068, +51037, +51038, +51071, +51070, +51039, +51096, +51129, +51128, +51097, +51098, +51131, +51130, +51099, +51100, +51133, +51132, +51101, +51102, +51135, +51134, +51103, +51160, +51193, +51192, +51161, +51162, +51195, +51194, +51163, +51164, +51197, +51196, +51165, +51166, +51199, +51198, +51167, +51200, +51233, +51232, +51201, +51202, +51235, +51234, +51203, +51204, +51237, +51236, +51205, +51206, +51239, +51238, +51207, +51264, +51297, +51296, +51265, +51266, +51299, +51298, +51267, +51268, +51301, +51300, +51269, +51270, +51303, +51302, +51271, +51328, +51361, +51360, +51329, +51330, +51363, +51362, +51331, +51332, +51365, +51364, +51333, +51334, +51367, +51366, +51335, +51392, +51425, +51424, +51393, +51394, +51427, +51426, +51395, +51396, +51429, +51428, +51397, +51398, +51431, +51430, +51399, +51456, +51489, +51488, +51457, +51458, +51491, +51490, +51459, +51460, +51493, +51492, +51461, +51462, +51495, +51494, +51463, +51520, +51553, +51552, +51521, +51522, +51555, +51554, +51523, +51524, +51557, +51556, +51525, +51526, +51559, +51558, +51527, +51584, +51617, +51616, +51585, +51586, +51619, +51618, +51587, +51588, +51621, +51620, +51589, +51590, +51623, +51622, +51591, +51648, +51681, +51680, +51649, +51650, +51683, +51682, +51651, +51652, +51685, +51684, +51653, +51654, +51687, +51686, +51655, +51712, +51745, +51744, +51713, +51714, +51747, +51746, +51715, +51716, +51749, +51748, +51717, +51718, +51751, +51750, +51719, +51776, +51809, +51808, +51777, +51778, +51811, +51810, +51779, +51780, +51813, +51812, +51781, +51782, +51815, +51814, +51783, +51840, +51873, +51872, +51841, +51842, +51875, +51874, +51843, +51844, +51877, +51876, +51845, +51846, +51879, +51878, +51847, +51904, +51937, +51936, +51905, +51906, +51939, +51938, +51907, +51908, +51941, +51940, +51909, +51910, +51943, +51942, +51911, +51968, +52001, +52000, +51969, +51970, +52003, +52002, +51971, +51972, +52005, +52004, +51973, +51974, +52007, +52006, +51975, +52032, +52065, +52064, +52033, +52034, +52067, +52066, +52035, +52036, +52069, +52068, +52037, +52038, +52071, +52070, +52039, +52096, +52129, +52128, +52097, +52098, +52131, +52130, +52099, +52100, +52133, +52132, +52101, +52102, +52135, +52134, +52103, +52160, +52193, +52192, +52161, +52162, +52195, +52194, +52163, +52164, +52197, +52196, +52165, +52166, +52199, +52198, +52167, +52224, +52257, +52256, +52225, +52226, +52259, +52258, +52227, +52228, +52261, +52260, +52229, +52230, +52263, +52262, +52231, +52288, +52321, +52320, +52289, +52290, +52323, +52322, +52291, +52292, +52325, +52324, +52293, +52294, +52327, +52326, +52295, +52352, +52385, +52384, +52353, +52354, +52387, +52386, +52355, +52356, +52389, +52388, +52357, +52358, +52391, +52390, +52359, +52416, +52449, +52448, +52417, +52418, +52451, +52450, +52419, +52420, +52453, +52452, +52421, +52422, +52455, +52454, +52423, +52480, +52513, +52512, +52481, +52482, +52515, +52514, +52483, +52484, +52517, +52516, +52485, +52486, +52519, +52518, +52487, +52544, +52577, +52576, +52545, +52546, +52579, +52578, +52547, +52548, +52581, +52580, +52549, +52550, +52583, +52582, +52551, +52608, +52641, +52640, +52609, +52610, +52643, +52642, +52611, +52612, +52645, +52644, +52613, +52614, +52647, +52646, +52615, +52672, +52705, +52704, +52673, +52674, +52707, +52706, +52675, +52676, +52709, +52708, +52677, +52678, +52711, +52710, +52679, +52736, +52769, +52768, +52737, +52738, +52771, +52770, +52739, +52740, +52773, +52772, +52741, +52742, +52775, +52774, +52743, +52800, +52833, +52832, +52801, +52802, +52835, +52834, +52803, +52804, +52837, +52836, +52805, +52806, +52839, +52838, +52807, +52864, +52897, +52896, +52865, +52866, +52899, +52898, +52867, +52868, +52901, +52900, +52869, +52870, +52903, +52902, +52871, +52928, +52961, +52960, +52929, +52930, +52963, +52962, +52931, +52932, +52965, +52964, +52933, +52934, +52967, +52966, +52935, +52992, +53025, +53024, +52993, +52994, +53027, +53026, +52995, +52996, +53029, +53028, +52997, +52998, +53031, +53030, +52999, +53056, +53089, +53088, +53057, +53058, +53091, +53090, +53059, +53060, +53093, +53092, +53061, +53062, +53095, +53094, +53063, +53120, +53153, +53152, +53121, +53122, +53155, +53154, +53123, +53124, +53157, +53156, +53125, +53126, +53159, +53158, +53127, +53184, +53217, +53216, +53185, +53186, +53219, +53218, +53187, +53188, +53221, +53220, +53189, +53190, +53223, +53222, +53191, +51208, +51241, +51240, +51209, +51210, +51243, +51242, +51211, +51212, +51245, +51244, +51213, +51214, +51247, +51246, +51215, +51272, +51305, +51304, +51273, +51274, +51307, +51306, +51275, +51276, +51309, +51308, +51277, +51278, +51311, +51310, +51279, +51336, +51369, +51368, +51337, +51338, +51371, +51370, +51339, +51340, +51373, +51372, +51341, +51342, +51375, +51374, +51343, +51400, +51433, +51432, +51401, +51402, +51435, +51434, +51403, +51404, +51437, +51436, +51405, +51406, +51439, +51438, +51407, +51464, +51497, +51496, +51465, +51466, +51499, +51498, +51467, +51468, +51501, +51500, +51469, +51470, +51503, +51502, +51471, +51528, +51561, +51560, +51529, +51530, +51563, +51562, +51531, +51532, +51565, +51564, +51533, +51534, +51567, +51566, +51535, +51592, +51625, +51624, +51593, +51594, +51627, +51626, +51595, +51596, +51629, +51628, +51597, +51598, +51631, +51630, +51599, +51656, +51689, +51688, +51657, +51658, +51691, +51690, +51659, +51660, +51693, +51692, +51661, +51662, +51695, +51694, +51663, +51720, +51753, +51752, +51721, +51722, +51755, +51754, +51723, +51724, +51757, +51756, +51725, +51726, +51759, +51758, +51727, +51784, +51817, +51816, +51785, +51786, +51819, +51818, +51787, +51788, +51821, +51820, +51789, +51790, +51823, +51822, +51791, +51848, +51881, +51880, +51849, +51850, +51883, +51882, +51851, +51852, +51885, +51884, +51853, +51854, +51887, +51886, +51855, +51912, +51945, +51944, +51913, +51914, +51947, +51946, +51915, +51916, +51949, +51948, +51917, +51918, +51951, +51950, +51919, +51976, +52009, +52008, +51977, +51978, +52011, +52010, +51979, +51980, +52013, +52012, +51981, +51982, +52015, +52014, +51983, +52040, +52073, +52072, +52041, +52042, +52075, +52074, +52043, +52044, +52077, +52076, +52045, +52046, +52079, +52078, +52047, +52104, +52137, +52136, +52105, +52106, +52139, +52138, +52107, +52108, +52141, +52140, +52109, +52110, +52143, +52142, +52111, +52168, +52201, +52200, +52169, +52170, +52203, +52202, +52171, +52172, +52205, +52204, +52173, +52174, +52207, +52206, +52175, +52232, +52265, +52264, +52233, +52234, +52267, +52266, +52235, +52236, +52269, +52268, +52237, +52238, +52271, +52270, +52239, +52296, +52329, +52328, +52297, +52298, +52331, +52330, +52299, +52300, +52333, +52332, +52301, +52302, +52335, +52334, +52303, +52360, +52393, +52392, +52361, +52362, +52395, +52394, +52363, +52364, +52397, +52396, +52365, +52366, +52399, +52398, +52367, +52424, +52457, +52456, +52425, +52426, +52459, +52458, +52427, +52428, +52461, +52460, +52429, +52430, +52463, +52462, +52431, +52488, +52521, +52520, +52489, +52490, +52523, +52522, +52491, +52492, +52525, +52524, +52493, +52494, +52527, +52526, +52495, +52552, +52585, +52584, +52553, +52554, +52587, +52586, +52555, +52556, +52589, +52588, +52557, +52558, +52591, +52590, +52559, +52616, +52649, +52648, +52617, +52618, +52651, +52650, +52619, +52620, +52653, +52652, +52621, +52622, +52655, +52654, +52623, +52680, +52713, +52712, +52681, +52682, +52715, +52714, +52683, +52684, +52717, +52716, +52685, +52686, +52719, +52718, +52687, +52744, +52777, +52776, +52745, +52746, +52779, +52778, +52747, +52748, +52781, +52780, +52749, +52750, +52783, +52782, +52751, +52808, +52841, +52840, +52809, +52810, +52843, +52842, +52811, +52812, +52845, +52844, +52813, +52814, +52847, +52846, +52815, +52872, +52905, +52904, +52873, +52874, +52907, +52906, +52875, +52876, +52909, +52908, +52877, +52878, +52911, +52910, +52879, +52936, +52969, +52968, +52937, +52938, +52971, +52970, +52939, +52940, +52973, +52972, +52941, +52942, +52975, +52974, +52943, +53000, +53033, +53032, +53001, +53002, +53035, +53034, +53003, +53004, +53037, +53036, +53005, +53006, +53039, +53038, +53007, +53064, +53097, +53096, +53065, +53066, +53099, +53098, +53067, +53068, +53101, +53100, +53069, +53070, +53103, +53102, +53071, +53128, +53161, +53160, +53129, +53130, +53163, +53162, +53131, +53132, +53165, +53164, +53133, +53134, +53167, +53166, +53135, +53192, +53225, +53224, +53193, +53194, +53227, +53226, +53195, +53196, +53229, +53228, +53197, +53198, +53231, +53230, +53199, +51216, +51249, +51248, +51217, +51218, +51251, +51250, +51219, +51220, +51253, +51252, +51221, +51222, +51255, +51254, +51223, +51280, +51313, +51312, +51281, +51282, +51315, +51314, +51283, +51284, +51317, +51316, +51285, +51286, +51319, +51318, +51287, +51344, +51377, +51376, +51345, +51346, +51379, +51378, +51347, +51348, +51381, +51380, +51349, +51350, +51383, +51382, +51351, +51408, +51441, +51440, +51409, +51410, +51443, +51442, +51411, +51412, +51445, +51444, +51413, +51414, +51447, +51446, +51415, +51472, +51505, +51504, +51473, +51474, +51507, +51506, +51475, +51476, +51509, +51508, +51477, +51478, +51511, +51510, +51479, +51536, +51569, +51568, +51537, +51538, +51571, +51570, +51539, +51540, +51573, +51572, +51541, +51542, +51575, +51574, +51543, +51600, +51633, +51632, +51601, +51602, +51635, +51634, +51603, +51604, +51637, +51636, +51605, +51606, +51639, +51638, +51607, +51664, +51697, +51696, +51665, +51666, +51699, +51698, +51667, +51668, +51701, +51700, +51669, +51670, +51703, +51702, +51671, +51728, +51761, +51760, +51729, +51730, +51763, +51762, +51731, +51732, +51765, +51764, +51733, +51734, +51767, +51766, +51735, +51792, +51825, +51824, +51793, +51794, +51827, +51826, +51795, +51796, +51829, +51828, +51797, +51798, +51831, +51830, +51799, +51856, +51889, +51888, +51857, +51858, +51891, +51890, +51859, +51860, +51893, +51892, +51861, +51862, +51895, +51894, +51863, +51920, +51953, +51952, +51921, +51922, +51955, +51954, +51923, +51924, +51957, +51956, +51925, +51926, +51959, +51958, +51927, +51984, +52017, +52016, +51985, +51986, +52019, +52018, +51987, +51988, +52021, +52020, +51989, +51990, +52023, +52022, +51991, +52048, +52081, +52080, +52049, +52050, +52083, +52082, +52051, +52052, +52085, +52084, +52053, +52054, +52087, +52086, +52055, +52112, +52145, +52144, +52113, +52114, +52147, +52146, +52115, +52116, +52149, +52148, +52117, +52118, +52151, +52150, +52119, +52176, +52209, +52208, +52177, +52178, +52211, +52210, +52179, +52180, +52213, +52212, +52181, +52182, +52215, +52214, +52183, +52240, +52273, +52272, +52241, +52242, +52275, +52274, +52243, +52244, +52277, +52276, +52245, +52246, +52279, +52278, +52247, +52304, +52337, +52336, +52305, +52306, +52339, +52338, +52307, +52308, +52341, +52340, +52309, +52310, +52343, +52342, +52311, +52368, +52401, +52400, +52369, +52370, +52403, +52402, +52371, +52372, +52405, +52404, +52373, +52374, +52407, +52406, +52375, +52432, +52465, +52464, +52433, +52434, +52467, +52466, +52435, +52436, +52469, +52468, +52437, +52438, +52471, +52470, +52439, +52496, +52529, +52528, +52497, +52498, +52531, +52530, +52499, +52500, +52533, +52532, +52501, +52502, +52535, +52534, +52503, +52560, +52593, +52592, +52561, +52562, +52595, +52594, +52563, +52564, +52597, +52596, +52565, +52566, +52599, +52598, +52567, +52624, +52657, +52656, +52625, +52626, +52659, +52658, +52627, +52628, +52661, +52660, +52629, +52630, +52663, +52662, +52631, +52688, +52721, +52720, +52689, +52690, +52723, +52722, +52691, +52692, +52725, +52724, +52693, +52694, +52727, +52726, +52695, +52752, +52785, +52784, +52753, +52754, +52787, +52786, +52755, +52756, +52789, +52788, +52757, +52758, +52791, +52790, +52759, +52816, +52849, +52848, +52817, +52818, +52851, +52850, +52819, +52820, +52853, +52852, +52821, +52822, +52855, +52854, +52823, +52880, +52913, +52912, +52881, +52882, +52915, +52914, +52883, +52884, +52917, +52916, +52885, +52886, +52919, +52918, +52887, +52944, +52977, +52976, +52945, +52946, +52979, +52978, +52947, +52948, +52981, +52980, +52949, +52950, +52983, +52982, +52951, +53008, +53041, +53040, +53009, +53010, +53043, +53042, +53011, +53012, +53045, +53044, +53013, +53014, +53047, +53046, +53015, +53072, +53105, +53104, +53073, +53074, +53107, +53106, +53075, +53076, +53109, +53108, +53077, +53078, +53111, +53110, +53079, +53136, +53169, +53168, +53137, +53138, +53171, +53170, +53139, +53140, +53173, +53172, +53141, +53142, +53175, +53174, +53143, +53200, +53233, +53232, +53201, +53202, +53235, +53234, +53203, +53204, +53237, +53236, +53205, +53206, +53239, +53238, +53207, +51224, +51257, +51256, +51225, +51226, +51259, +51258, +51227, +51228, +51261, +51260, +51229, +51230, +51263, +51262, +51231, +51288, +51321, +51320, +51289, +51290, +51323, +51322, +51291, +51292, +51325, +51324, +51293, +51294, +51327, +51326, +51295, +51352, +51385, +51384, +51353, +51354, +51387, +51386, +51355, +51356, +51389, +51388, +51357, +51358, +51391, +51390, +51359, +51416, +51449, +51448, +51417, +51418, +51451, +51450, +51419, +51420, +51453, +51452, +51421, +51422, +51455, +51454, +51423, +51480, +51513, +51512, +51481, +51482, +51515, +51514, +51483, +51484, +51517, +51516, +51485, +51486, +51519, +51518, +51487, +51544, +51577, +51576, +51545, +51546, +51579, +51578, +51547, +51548, +51581, +51580, +51549, +51550, +51583, +51582, +51551, +51608, +51641, +51640, +51609, +51610, +51643, +51642, +51611, +51612, +51645, +51644, +51613, +51614, +51647, +51646, +51615, +51672, +51705, +51704, +51673, +51674, +51707, +51706, +51675, +51676, +51709, +51708, +51677, +51678, +51711, +51710, +51679, +51736, +51769, +51768, +51737, +51738, +51771, +51770, +51739, +51740, +51773, +51772, +51741, +51742, +51775, +51774, +51743, +51800, +51833, +51832, +51801, +51802, +51835, +51834, +51803, +51804, +51837, +51836, +51805, +51806, +51839, +51838, +51807, +51864, +51897, +51896, +51865, +51866, +51899, +51898, +51867, +51868, +51901, +51900, +51869, +51870, +51903, +51902, +51871, +51928, +51961, +51960, +51929, +51930, +51963, +51962, +51931, +51932, +51965, +51964, +51933, +51934, +51967, +51966, +51935, +51992, +52025, +52024, +51993, +51994, +52027, +52026, +51995, +51996, +52029, +52028, +51997, +51998, +52031, +52030, +51999, +52056, +52089, +52088, +52057, +52058, +52091, +52090, +52059, +52060, +52093, +52092, +52061, +52062, +52095, +52094, +52063, +52120, +52153, +52152, +52121, +52122, +52155, +52154, +52123, +52124, +52157, +52156, +52125, +52126, +52159, +52158, +52127, +52184, +52217, +52216, +52185, +52186, +52219, +52218, +52187, +52188, +52221, +52220, +52189, +52190, +52223, +52222, +52191, +52248, +52281, +52280, +52249, +52250, +52283, +52282, +52251, +52252, +52285, +52284, +52253, +52254, +52287, +52286, +52255, +52312, +52345, +52344, +52313, +52314, +52347, +52346, +52315, +52316, +52349, +52348, +52317, +52318, +52351, +52350, +52319, +52376, +52409, +52408, +52377, +52378, +52411, +52410, +52379, +52380, +52413, +52412, +52381, +52382, +52415, +52414, +52383, +52440, +52473, +52472, +52441, +52442, +52475, +52474, +52443, +52444, +52477, +52476, +52445, +52446, +52479, +52478, +52447, +52504, +52537, +52536, +52505, +52506, +52539, +52538, +52507, +52508, +52541, +52540, +52509, +52510, +52543, +52542, +52511, +52568, +52601, +52600, +52569, +52570, +52603, +52602, +52571, +52572, +52605, +52604, +52573, +52574, +52607, +52606, +52575, +52632, +52665, +52664, +52633, +52634, +52667, +52666, +52635, +52636, +52669, +52668, +52637, +52638, +52671, +52670, +52639, +52696, +52729, +52728, +52697, +52698, +52731, +52730, +52699, +52700, +52733, +52732, +52701, +52702, +52735, +52734, +52703, +52760, +52793, +52792, +52761, +52762, +52795, +52794, +52763, +52764, +52797, +52796, +52765, +52766, +52799, +52798, +52767, +52824, +52857, +52856, +52825, +52826, +52859, +52858, +52827, +52828, +52861, +52860, +52829, +52830, +52863, +52862, +52831, +52888, +52921, +52920, +52889, +52890, +52923, +52922, +52891, +52892, +52925, +52924, +52893, +52894, +52927, +52926, +52895, +52952, +52985, +52984, +52953, +52954, +52987, +52986, +52955, +52956, +52989, +52988, +52957, +52958, +52991, +52990, +52959, +53016, +53049, +53048, +53017, +53018, +53051, +53050, +53019, +53020, +53053, +53052, +53021, +53022, +53055, +53054, +53023, +53080, +53113, +53112, +53081, +53082, +53115, +53114, +53083, +53084, +53117, +53116, +53085, +53086, +53119, +53118, +53087, +53144, +53177, +53176, +53145, +53146, +53179, +53178, +53147, +53148, +53181, +53180, +53149, +53150, +53183, +53182, +53151, +53208, +53241, +53240, +53209, +53210, +53243, +53242, +53211, +53212, +53245, +53244, +53213, +53214, +53247, +53246, +53215, +53248, +53281, +53280, +53249, +53250, +53283, +53282, +53251, +53252, +53285, +53284, +53253, +53254, +53287, +53286, +53255, +53312, +53345, +53344, +53313, +53314, +53347, +53346, +53315, +53316, +53349, +53348, +53317, +53318, +53351, +53350, +53319, +53376, +53409, +53408, +53377, +53378, +53411, +53410, +53379, +53380, +53413, +53412, +53381, +53382, +53415, +53414, +53383, +53440, +53473, +53472, +53441, +53442, +53475, +53474, +53443, +53444, +53477, +53476, +53445, +53446, +53479, +53478, +53447, +53504, +53537, +53536, +53505, +53506, +53539, +53538, +53507, +53508, +53541, +53540, +53509, +53510, +53543, +53542, +53511, +53568, +53601, +53600, +53569, +53570, +53603, +53602, +53571, +53572, +53605, +53604, +53573, +53574, +53607, +53606, +53575, +53632, +53665, +53664, +53633, +53634, +53667, +53666, +53635, +53636, +53669, +53668, +53637, +53638, +53671, +53670, +53639, +53696, +53729, +53728, +53697, +53698, +53731, +53730, +53699, +53700, +53733, +53732, +53701, +53702, +53735, +53734, +53703, +53760, +53793, +53792, +53761, +53762, +53795, +53794, +53763, +53764, +53797, +53796, +53765, +53766, +53799, +53798, +53767, +53824, +53857, +53856, +53825, +53826, +53859, +53858, +53827, +53828, +53861, +53860, +53829, +53830, +53863, +53862, +53831, +53888, +53921, +53920, +53889, +53890, +53923, +53922, +53891, +53892, +53925, +53924, +53893, +53894, +53927, +53926, +53895, +53952, +53985, +53984, +53953, +53954, +53987, +53986, +53955, +53956, +53989, +53988, +53957, +53958, +53991, +53990, +53959, +54016, +54049, +54048, +54017, +54018, +54051, +54050, +54019, +54020, +54053, +54052, +54021, +54022, +54055, +54054, +54023, +54080, +54113, +54112, +54081, +54082, +54115, +54114, +54083, +54084, +54117, +54116, +54085, +54086, +54119, +54118, +54087, +54144, +54177, +54176, +54145, +54146, +54179, +54178, +54147, +54148, +54181, +54180, +54149, +54150, +54183, +54182, +54151, +54208, +54241, +54240, +54209, +54210, +54243, +54242, +54211, +54212, +54245, +54244, +54213, +54214, +54247, +54246, +54215, +54272, +54305, +54304, +54273, +54274, +54307, +54306, +54275, +54276, +54309, +54308, +54277, +54278, +54311, +54310, +54279, +54336, +54369, +54368, +54337, +54338, +54371, +54370, +54339, +54340, +54373, +54372, +54341, +54342, +54375, +54374, +54343, +54400, +54433, +54432, +54401, +54402, +54435, +54434, +54403, +54404, +54437, +54436, +54405, +54406, +54439, +54438, +54407, +54464, +54497, +54496, +54465, +54466, +54499, +54498, +54467, +54468, +54501, +54500, +54469, +54470, +54503, +54502, +54471, +54528, +54561, +54560, +54529, +54530, +54563, +54562, +54531, +54532, +54565, +54564, +54533, +54534, +54567, +54566, +54535, +54592, +54625, +54624, +54593, +54594, +54627, +54626, +54595, +54596, +54629, +54628, +54597, +54598, +54631, +54630, +54599, +54656, +54689, +54688, +54657, +54658, +54691, +54690, +54659, +54660, +54693, +54692, +54661, +54662, +54695, +54694, +54663, +54720, +54753, +54752, +54721, +54722, +54755, +54754, +54723, +54724, +54757, +54756, +54725, +54726, +54759, +54758, +54727, +54784, +54817, +54816, +54785, +54786, +54819, +54818, +54787, +54788, +54821, +54820, +54789, +54790, +54823, +54822, +54791, +54848, +54881, +54880, +54849, +54850, +54883, +54882, +54851, +54852, +54885, +54884, +54853, +54854, +54887, +54886, +54855, +54912, +54945, +54944, +54913, +54914, +54947, +54946, +54915, +54916, +54949, +54948, +54917, +54918, +54951, +54950, +54919, +54976, +55009, +55008, +54977, +54978, +55011, +55010, +54979, +54980, +55013, +55012, +54981, +54982, +55015, +55014, +54983, +55040, +55073, +55072, +55041, +55042, +55075, +55074, +55043, +55044, +55077, +55076, +55045, +55046, +55079, +55078, +55047, +55104, +55137, +55136, +55105, +55106, +55139, +55138, +55107, +55108, +55141, +55140, +55109, +55110, +55143, +55142, +55111, +55168, +55201, +55200, +55169, +55170, +55203, +55202, +55171, +55172, +55205, +55204, +55173, +55174, +55207, +55206, +55175, +55232, +55265, +55264, +55233, +55234, +55267, +55266, +55235, +55236, +55269, +55268, +55237, +55238, +55271, +55270, +55239, +53256, +53289, +53288, +53257, +53258, +53291, +53290, +53259, +53260, +53293, +53292, +53261, +53262, +53295, +53294, +53263, +53320, +53353, +53352, +53321, +53322, +53355, +53354, +53323, +53324, +53357, +53356, +53325, +53326, +53359, +53358, +53327, +53384, +53417, +53416, +53385, +53386, +53419, +53418, +53387, +53388, +53421, +53420, +53389, +53390, +53423, +53422, +53391, +53448, +53481, +53480, +53449, +53450, +53483, +53482, +53451, +53452, +53485, +53484, +53453, +53454, +53487, +53486, +53455, +53512, +53545, +53544, +53513, +53514, +53547, +53546, +53515, +53516, +53549, +53548, +53517, +53518, +53551, +53550, +53519, +53576, +53609, +53608, +53577, +53578, +53611, +53610, +53579, +53580, +53613, +53612, +53581, +53582, +53615, +53614, +53583, +53640, +53673, +53672, +53641, +53642, +53675, +53674, +53643, +53644, +53677, +53676, +53645, +53646, +53679, +53678, +53647, +53704, +53737, +53736, +53705, +53706, +53739, +53738, +53707, +53708, +53741, +53740, +53709, +53710, +53743, +53742, +53711, +53768, +53801, +53800, +53769, +53770, +53803, +53802, +53771, +53772, +53805, +53804, +53773, +53774, +53807, +53806, +53775, +53832, +53865, +53864, +53833, +53834, +53867, +53866, +53835, +53836, +53869, +53868, +53837, +53838, +53871, +53870, +53839, +53896, +53929, +53928, +53897, +53898, +53931, +53930, +53899, +53900, +53933, +53932, +53901, +53902, +53935, +53934, +53903, +53960, +53993, +53992, +53961, +53962, +53995, +53994, +53963, +53964, +53997, +53996, +53965, +53966, +53999, +53998, +53967, +54024, +54057, +54056, +54025, +54026, +54059, +54058, +54027, +54028, +54061, +54060, +54029, +54030, +54063, +54062, +54031, +54088, +54121, +54120, +54089, +54090, +54123, +54122, +54091, +54092, +54125, +54124, +54093, +54094, +54127, +54126, +54095, +54152, +54185, +54184, +54153, +54154, +54187, +54186, +54155, +54156, +54189, +54188, +54157, +54158, +54191, +54190, +54159, +54216, +54249, +54248, +54217, +54218, +54251, +54250, +54219, +54220, +54253, +54252, +54221, +54222, +54255, +54254, +54223, +54280, +54313, +54312, +54281, +54282, +54315, +54314, +54283, +54284, +54317, +54316, +54285, +54286, +54319, +54318, +54287, +54344, +54377, +54376, +54345, +54346, +54379, +54378, +54347, +54348, +54381, +54380, +54349, +54350, +54383, +54382, +54351, +54408, +54441, +54440, +54409, +54410, +54443, +54442, +54411, +54412, +54445, +54444, +54413, +54414, +54447, +54446, +54415, +54472, +54505, +54504, +54473, +54474, +54507, +54506, +54475, +54476, +54509, +54508, +54477, +54478, +54511, +54510, +54479, +54536, +54569, +54568, +54537, +54538, +54571, +54570, +54539, +54540, +54573, +54572, +54541, +54542, +54575, +54574, +54543, +54600, +54633, +54632, +54601, +54602, +54635, +54634, +54603, +54604, +54637, +54636, +54605, +54606, +54639, +54638, +54607, +54664, +54697, +54696, +54665, +54666, +54699, +54698, +54667, +54668, +54701, +54700, +54669, +54670, +54703, +54702, +54671, +54728, +54761, +54760, +54729, +54730, +54763, +54762, +54731, +54732, +54765, +54764, +54733, +54734, +54767, +54766, +54735, +54792, +54825, +54824, +54793, +54794, +54827, +54826, +54795, +54796, +54829, +54828, +54797, +54798, +54831, +54830, +54799, +54856, +54889, +54888, +54857, +54858, +54891, +54890, +54859, +54860, +54893, +54892, +54861, +54862, +54895, +54894, +54863, +54920, +54953, +54952, +54921, +54922, +54955, +54954, +54923, +54924, +54957, +54956, +54925, +54926, +54959, +54958, +54927, +54984, +55017, +55016, +54985, +54986, +55019, +55018, +54987, +54988, +55021, +55020, +54989, +54990, +55023, +55022, +54991, +55048, +55081, +55080, +55049, +55050, +55083, +55082, +55051, +55052, +55085, +55084, +55053, +55054, +55087, +55086, +55055, +55112, +55145, +55144, +55113, +55114, +55147, +55146, +55115, +55116, +55149, +55148, +55117, +55118, +55151, +55150, +55119, +55176, +55209, +55208, +55177, +55178, +55211, +55210, +55179, +55180, +55213, +55212, +55181, +55182, +55215, +55214, +55183, +55240, +55273, +55272, +55241, +55242, +55275, +55274, +55243, +55244, +55277, +55276, +55245, +55246, +55279, +55278, +55247, +53264, +53297, +53296, +53265, +53266, +53299, +53298, +53267, +53268, +53301, +53300, +53269, +53270, +53303, +53302, +53271, +53328, +53361, +53360, +53329, +53330, +53363, +53362, +53331, +53332, +53365, +53364, +53333, +53334, +53367, +53366, +53335, +53392, +53425, +53424, +53393, +53394, +53427, +53426, +53395, +53396, +53429, +53428, +53397, +53398, +53431, +53430, +53399, +53456, +53489, +53488, +53457, +53458, +53491, +53490, +53459, +53460, +53493, +53492, +53461, +53462, +53495, +53494, +53463, +53520, +53553, +53552, +53521, +53522, +53555, +53554, +53523, +53524, +53557, +53556, +53525, +53526, +53559, +53558, +53527, +53584, +53617, +53616, +53585, +53586, +53619, +53618, +53587, +53588, +53621, +53620, +53589, +53590, +53623, +53622, +53591, +53648, +53681, +53680, +53649, +53650, +53683, +53682, +53651, +53652, +53685, +53684, +53653, +53654, +53687, +53686, +53655, +53712, +53745, +53744, +53713, +53714, +53747, +53746, +53715, +53716, +53749, +53748, +53717, +53718, +53751, +53750, +53719, +53776, +53809, +53808, +53777, +53778, +53811, +53810, +53779, +53780, +53813, +53812, +53781, +53782, +53815, +53814, +53783, +53840, +53873, +53872, +53841, +53842, +53875, +53874, +53843, +53844, +53877, +53876, +53845, +53846, +53879, +53878, +53847, +53904, +53937, +53936, +53905, +53906, +53939, +53938, +53907, +53908, +53941, +53940, +53909, +53910, +53943, +53942, +53911, +53968, +54001, +54000, +53969, +53970, +54003, +54002, +53971, +53972, +54005, +54004, +53973, +53974, +54007, +54006, +53975, +54032, +54065, +54064, +54033, +54034, +54067, +54066, +54035, +54036, +54069, +54068, +54037, +54038, +54071, +54070, +54039, +54096, +54129, +54128, +54097, +54098, +54131, +54130, +54099, +54100, +54133, +54132, +54101, +54102, +54135, +54134, +54103, +54160, +54193, +54192, +54161, +54162, +54195, +54194, +54163, +54164, +54197, +54196, +54165, +54166, +54199, +54198, +54167, +54224, +54257, +54256, +54225, +54226, +54259, +54258, +54227, +54228, +54261, +54260, +54229, +54230, +54263, +54262, +54231, +54288, +54321, +54320, +54289, +54290, +54323, +54322, +54291, +54292, +54325, +54324, +54293, +54294, +54327, +54326, +54295, +54352, +54385, +54384, +54353, +54354, +54387, +54386, +54355, +54356, +54389, +54388, +54357, +54358, +54391, +54390, +54359, +54416, +54449, +54448, +54417, +54418, +54451, +54450, +54419, +54420, +54453, +54452, +54421, +54422, +54455, +54454, +54423, +54480, +54513, +54512, +54481, +54482, +54515, +54514, +54483, +54484, +54517, +54516, +54485, +54486, +54519, +54518, +54487, +54544, +54577, +54576, +54545, +54546, +54579, +54578, +54547, +54548, +54581, +54580, +54549, +54550, +54583, +54582, +54551, +54608, +54641, +54640, +54609, +54610, +54643, +54642, +54611, +54612, +54645, +54644, +54613, +54614, +54647, +54646, +54615, +54672, +54705, +54704, +54673, +54674, +54707, +54706, +54675, +54676, +54709, +54708, +54677, +54678, +54711, +54710, +54679, +54736, +54769, +54768, +54737, +54738, +54771, +54770, +54739, +54740, +54773, +54772, +54741, +54742, +54775, +54774, +54743, +54800, +54833, +54832, +54801, +54802, +54835, +54834, +54803, +54804, +54837, +54836, +54805, +54806, +54839, +54838, +54807, +54864, +54897, +54896, +54865, +54866, +54899, +54898, +54867, +54868, +54901, +54900, +54869, +54870, +54903, +54902, +54871, +54928, +54961, +54960, +54929, +54930, +54963, +54962, +54931, +54932, +54965, +54964, +54933, +54934, +54967, +54966, +54935, +54992, +55025, +55024, +54993, +54994, +55027, +55026, +54995, +54996, +55029, +55028, +54997, +54998, +55031, +55030, +54999, +55056, +55089, +55088, +55057, +55058, +55091, +55090, +55059, +55060, +55093, +55092, +55061, +55062, +55095, +55094, +55063, +55120, +55153, +55152, +55121, +55122, +55155, +55154, +55123, +55124, +55157, +55156, +55125, +55126, +55159, +55158, +55127, +55184, +55217, +55216, +55185, +55186, +55219, +55218, +55187, +55188, +55221, +55220, +55189, +55190, +55223, +55222, +55191, +55248, +55281, +55280, +55249, +55250, +55283, +55282, +55251, +55252, +55285, +55284, +55253, +55254, +55287, +55286, +55255, +53272, +53305, +53304, +53273, +53274, +53307, +53306, +53275, +53276, +53309, +53308, +53277, +53278, +53311, +53310, +53279, +53336, +53369, +53368, +53337, +53338, +53371, +53370, +53339, +53340, +53373, +53372, +53341, +53342, +53375, +53374, +53343, +53400, +53433, +53432, +53401, +53402, +53435, +53434, +53403, +53404, +53437, +53436, +53405, +53406, +53439, +53438, +53407, +53464, +53497, +53496, +53465, +53466, +53499, +53498, +53467, +53468, +53501, +53500, +53469, +53470, +53503, +53502, +53471, +53528, +53561, +53560, +53529, +53530, +53563, +53562, +53531, +53532, +53565, +53564, +53533, +53534, +53567, +53566, +53535, +53592, +53625, +53624, +53593, +53594, +53627, +53626, +53595, +53596, +53629, +53628, +53597, +53598, +53631, +53630, +53599, +53656, +53689, +53688, +53657, +53658, +53691, +53690, +53659, +53660, +53693, +53692, +53661, +53662, +53695, +53694, +53663, +53720, +53753, +53752, +53721, +53722, +53755, +53754, +53723, +53724, +53757, +53756, +53725, +53726, +53759, +53758, +53727, +53784, +53817, +53816, +53785, +53786, +53819, +53818, +53787, +53788, +53821, +53820, +53789, +53790, +53823, +53822, +53791, +53848, +53881, +53880, +53849, +53850, +53883, +53882, +53851, +53852, +53885, +53884, +53853, +53854, +53887, +53886, +53855, +53912, +53945, +53944, +53913, +53914, +53947, +53946, +53915, +53916, +53949, +53948, +53917, +53918, +53951, +53950, +53919, +53976, +54009, +54008, +53977, +53978, +54011, +54010, +53979, +53980, +54013, +54012, +53981, +53982, +54015, +54014, +53983, +54040, +54073, +54072, +54041, +54042, +54075, +54074, +54043, +54044, +54077, +54076, +54045, +54046, +54079, +54078, +54047, +54104, +54137, +54136, +54105, +54106, +54139, +54138, +54107, +54108, +54141, +54140, +54109, +54110, +54143, +54142, +54111, +54168, +54201, +54200, +54169, +54170, +54203, +54202, +54171, +54172, +54205, +54204, +54173, +54174, +54207, +54206, +54175, +54232, +54265, +54264, +54233, +54234, +54267, +54266, +54235, +54236, +54269, +54268, +54237, +54238, +54271, +54270, +54239, +54296, +54329, +54328, +54297, +54298, +54331, +54330, +54299, +54300, +54333, +54332, +54301, +54302, +54335, +54334, +54303, +54360, +54393, +54392, +54361, +54362, +54395, +54394, +54363, +54364, +54397, +54396, +54365, +54366, +54399, +54398, +54367, +54424, +54457, +54456, +54425, +54426, +54459, +54458, +54427, +54428, +54461, +54460, +54429, +54430, +54463, +54462, +54431, +54488, +54521, +54520, +54489, +54490, +54523, +54522, +54491, +54492, +54525, +54524, +54493, +54494, +54527, +54526, +54495, +54552, +54585, +54584, +54553, +54554, +54587, +54586, +54555, +54556, +54589, +54588, +54557, +54558, +54591, +54590, +54559, +54616, +54649, +54648, +54617, +54618, +54651, +54650, +54619, +54620, +54653, +54652, +54621, +54622, +54655, +54654, +54623, +54680, +54713, +54712, +54681, +54682, +54715, +54714, +54683, +54684, +54717, +54716, +54685, +54686, +54719, +54718, +54687, +54744, +54777, +54776, +54745, +54746, +54779, +54778, +54747, +54748, +54781, +54780, +54749, +54750, +54783, +54782, +54751, +54808, +54841, +54840, +54809, +54810, +54843, +54842, +54811, +54812, +54845, +54844, +54813, +54814, +54847, +54846, +54815, +54872, +54905, +54904, +54873, +54874, +54907, +54906, +54875, +54876, +54909, +54908, +54877, +54878, +54911, +54910, +54879, +54936, +54969, +54968, +54937, +54938, +54971, +54970, +54939, +54940, +54973, +54972, +54941, +54942, +54975, +54974, +54943, +55000, +55033, +55032, +55001, +55002, +55035, +55034, +55003, +55004, +55037, +55036, +55005, +55006, +55039, +55038, +55007, +55064, +55097, +55096, +55065, +55066, +55099, +55098, +55067, +55068, +55101, +55100, +55069, +55070, +55103, +55102, +55071, +55128, +55161, +55160, +55129, +55130, +55163, +55162, +55131, +55132, +55165, +55164, +55133, +55134, +55167, +55166, +55135, +55192, +55225, +55224, +55193, +55194, +55227, +55226, +55195, +55196, +55229, +55228, +55197, +55198, +55231, +55230, +55199, +55256, +55289, +55288, +55257, +55258, +55291, +55290, +55259, +55260, +55293, +55292, +55261, +55262, +55295, +55294, +55263, +55296, +55329, +55328, +55297, +55298, +55331, +55330, +55299, +55300, +55333, +55332, +55301, +55302, +55335, +55334, +55303, +55360, +55393, +55392, +55361, +55362, +55395, +55394, +55363, +55364, +55397, +55396, +55365, +55366, +55399, +55398, +55367, +55424, +55457, +55456, +55425, +55426, +55459, +55458, +55427, +55428, +55461, +55460, +55429, +55430, +55463, +55462, +55431, +55488, +55521, +55520, +55489, +55490, +55523, +55522, +55491, +55492, +55525, +55524, +55493, +55494, +55527, +55526, +55495, +55552, +55585, +55584, +55553, +55554, +55587, +55586, +55555, +55556, +55589, +55588, +55557, +55558, +55591, +55590, +55559, +55616, +55649, +55648, +55617, +55618, +55651, +55650, +55619, +55620, +55653, +55652, +55621, +55622, +55655, +55654, +55623, +55680, +55713, +55712, +55681, +55682, +55715, +55714, +55683, +55684, +55717, +55716, +55685, +55686, +55719, +55718, +55687, +55744, +55777, +55776, +55745, +55746, +55779, +55778, +55747, +55748, +55781, +55780, +55749, +55750, +55783, +55782, +55751, +55808, +55841, +55840, +55809, +55810, +55843, +55842, +55811, +55812, +55845, +55844, +55813, +55814, +55847, +55846, +55815, +55872, +55905, +55904, +55873, +55874, +55907, +55906, +55875, +55876, +55909, +55908, +55877, +55878, +55911, +55910, +55879, +55936, +55969, +55968, +55937, +55938, +55971, +55970, +55939, +55940, +55973, +55972, +55941, +55942, +55975, +55974, +55943, +56000, +56033, +56032, +56001, +56002, +56035, +56034, +56003, +56004, +56037, +56036, +56005, +56006, +56039, +56038, +56007, +56064, +56097, +56096, +56065, +56066, +56099, +56098, +56067, +56068, +56101, +56100, +56069, +56070, +56103, +56102, +56071, +56128, +56161, +56160, +56129, +56130, +56163, +56162, +56131, +56132, +56165, +56164, +56133, +56134, +56167, +56166, +56135, +56192, +56225, +56224, +56193, +56194, +56227, +56226, +56195, +56196, +56229, +56228, +56197, +56198, +56231, +56230, +56199, +56256, +56289, +56288, +56257, +56258, +56291, +56290, +56259, +56260, +56293, +56292, +56261, +56262, +56295, +56294, +56263, +56320, +56353, +56352, +56321, +56322, +56355, +56354, +56323, +56324, +56357, +56356, +56325, +56326, +56359, +56358, +56327, +56384, +56417, +56416, +56385, +56386, +56419, +56418, +56387, +56388, +56421, +56420, +56389, +56390, +56423, +56422, +56391, +56448, +56481, +56480, +56449, +56450, +56483, +56482, +56451, +56452, +56485, +56484, +56453, +56454, +56487, +56486, +56455, +56512, +56545, +56544, +56513, +56514, +56547, +56546, +56515, +56516, +56549, +56548, +56517, +56518, +56551, +56550, +56519, +56576, +56609, +56608, +56577, +56578, +56611, +56610, +56579, +56580, +56613, +56612, +56581, +56582, +56615, +56614, +56583, +56640, +56673, +56672, +56641, +56642, +56675, +56674, +56643, +56644, +56677, +56676, +56645, +56646, +56679, +56678, +56647, +56704, +56737, +56736, +56705, +56706, +56739, +56738, +56707, +56708, +56741, +56740, +56709, +56710, +56743, +56742, +56711, +56768, +56801, +56800, +56769, +56770, +56803, +56802, +56771, +56772, +56805, +56804, +56773, +56774, +56807, +56806, +56775, +56832, +56865, +56864, +56833, +56834, +56867, +56866, +56835, +56836, +56869, +56868, +56837, +56838, +56871, +56870, +56839, +56896, +56929, +56928, +56897, +56898, +56931, +56930, +56899, +56900, +56933, +56932, +56901, +56902, +56935, +56934, +56903, +56960, +56993, +56992, +56961, +56962, +56995, +56994, +56963, +56964, +56997, +56996, +56965, +56966, +56999, +56998, +56967, +57024, +57057, +57056, +57025, +57026, +57059, +57058, +57027, +57028, +57061, +57060, +57029, +57030, +57063, +57062, +57031, +57088, +57121, +57120, +57089, +57090, +57123, +57122, +57091, +57092, +57125, +57124, +57093, +57094, +57127, +57126, +57095, +57152, +57185, +57184, +57153, +57154, +57187, +57186, +57155, +57156, +57189, +57188, +57157, +57158, +57191, +57190, +57159, +57216, +57249, +57248, +57217, +57218, +57251, +57250, +57219, +57220, +57253, +57252, +57221, +57222, +57255, +57254, +57223, +57280, +57313, +57312, +57281, +57282, +57315, +57314, +57283, +57284, +57317, +57316, +57285, +57286, +57319, +57318, +57287, +55304, +55337, +55336, +55305, +55306, +55339, +55338, +55307, +55308, +55341, +55340, +55309, +55310, +55343, +55342, +55311, +55368, +55401, +55400, +55369, +55370, +55403, +55402, +55371, +55372, +55405, +55404, +55373, +55374, +55407, +55406, +55375, +55432, +55465, +55464, +55433, +55434, +55467, +55466, +55435, +55436, +55469, +55468, +55437, +55438, +55471, +55470, +55439, +55496, +55529, +55528, +55497, +55498, +55531, +55530, +55499, +55500, +55533, +55532, +55501, +55502, +55535, +55534, +55503, +55560, +55593, +55592, +55561, +55562, +55595, +55594, +55563, +55564, +55597, +55596, +55565, +55566, +55599, +55598, +55567, +55624, +55657, +55656, +55625, +55626, +55659, +55658, +55627, +55628, +55661, +55660, +55629, +55630, +55663, +55662, +55631, +55688, +55721, +55720, +55689, +55690, +55723, +55722, +55691, +55692, +55725, +55724, +55693, +55694, +55727, +55726, +55695, +55752, +55785, +55784, +55753, +55754, +55787, +55786, +55755, +55756, +55789, +55788, +55757, +55758, +55791, +55790, +55759, +55816, +55849, +55848, +55817, +55818, +55851, +55850, +55819, +55820, +55853, +55852, +55821, +55822, +55855, +55854, +55823, +55880, +55913, +55912, +55881, +55882, +55915, +55914, +55883, +55884, +55917, +55916, +55885, +55886, +55919, +55918, +55887, +55944, +55977, +55976, +55945, +55946, +55979, +55978, +55947, +55948, +55981, +55980, +55949, +55950, +55983, +55982, +55951, +56008, +56041, +56040, +56009, +56010, +56043, +56042, +56011, +56012, +56045, +56044, +56013, +56014, +56047, +56046, +56015, +56072, +56105, +56104, +56073, +56074, +56107, +56106, +56075, +56076, +56109, +56108, +56077, +56078, +56111, +56110, +56079, +56136, +56169, +56168, +56137, +56138, +56171, +56170, +56139, +56140, +56173, +56172, +56141, +56142, +56175, +56174, +56143, +56200, +56233, +56232, +56201, +56202, +56235, +56234, +56203, +56204, +56237, +56236, +56205, +56206, +56239, +56238, +56207, +56264, +56297, +56296, +56265, +56266, +56299, +56298, +56267, +56268, +56301, +56300, +56269, +56270, +56303, +56302, +56271, +56328, +56361, +56360, +56329, +56330, +56363, +56362, +56331, +56332, +56365, +56364, +56333, +56334, +56367, +56366, +56335, +56392, +56425, +56424, +56393, +56394, +56427, +56426, +56395, +56396, +56429, +56428, +56397, +56398, +56431, +56430, +56399, +56456, +56489, +56488, +56457, +56458, +56491, +56490, +56459, +56460, +56493, +56492, +56461, +56462, +56495, +56494, +56463, +56520, +56553, +56552, +56521, +56522, +56555, +56554, +56523, +56524, +56557, +56556, +56525, +56526, +56559, +56558, +56527, +56584, +56617, +56616, +56585, +56586, +56619, +56618, +56587, +56588, +56621, +56620, +56589, +56590, +56623, +56622, +56591, +56648, +56681, +56680, +56649, +56650, +56683, +56682, +56651, +56652, +56685, +56684, +56653, +56654, +56687, +56686, +56655, +56712, +56745, +56744, +56713, +56714, +56747, +56746, +56715, +56716, +56749, +56748, +56717, +56718, +56751, +56750, +56719, +56776, +56809, +56808, +56777, +56778, +56811, +56810, +56779, +56780, +56813, +56812, +56781, +56782, +56815, +56814, +56783, +56840, +56873, +56872, +56841, +56842, +56875, +56874, +56843, +56844, +56877, +56876, +56845, +56846, +56879, +56878, +56847, +56904, +56937, +56936, +56905, +56906, +56939, +56938, +56907, +56908, +56941, +56940, +56909, +56910, +56943, +56942, +56911, +56968, +57001, +57000, +56969, +56970, +57003, +57002, +56971, +56972, +57005, +57004, +56973, +56974, +57007, +57006, +56975, +57032, +57065, +57064, +57033, +57034, +57067, +57066, +57035, +57036, +57069, +57068, +57037, +57038, +57071, +57070, +57039, +57096, +57129, +57128, +57097, +57098, +57131, +57130, +57099, +57100, +57133, +57132, +57101, +57102, +57135, +57134, +57103, +57160, +57193, +57192, +57161, +57162, +57195, +57194, +57163, +57164, +57197, +57196, +57165, +57166, +57199, +57198, +57167, +57224, +57257, +57256, +57225, +57226, +57259, +57258, +57227, +57228, +57261, +57260, +57229, +57230, +57263, +57262, +57231, +57288, +57321, +57320, +57289, +57290, +57323, +57322, +57291, +57292, +57325, +57324, +57293, +57294, +57327, +57326, +57295, +55312, +55345, +55344, +55313, +55314, +55347, +55346, +55315, +55316, +55349, +55348, +55317, +55318, +55351, +55350, +55319, +55376, +55409, +55408, +55377, +55378, +55411, +55410, +55379, +55380, +55413, +55412, +55381, +55382, +55415, +55414, +55383, +55440, +55473, +55472, +55441, +55442, +55475, +55474, +55443, +55444, +55477, +55476, +55445, +55446, +55479, +55478, +55447, +55504, +55537, +55536, +55505, +55506, +55539, +55538, +55507, +55508, +55541, +55540, +55509, +55510, +55543, +55542, +55511, +55568, +55601, +55600, +55569, +55570, +55603, +55602, +55571, +55572, +55605, +55604, +55573, +55574, +55607, +55606, +55575, +55632, +55665, +55664, +55633, +55634, +55667, +55666, +55635, +55636, +55669, +55668, +55637, +55638, +55671, +55670, +55639, +55696, +55729, +55728, +55697, +55698, +55731, +55730, +55699, +55700, +55733, +55732, +55701, +55702, +55735, +55734, +55703, +55760, +55793, +55792, +55761, +55762, +55795, +55794, +55763, +55764, +55797, +55796, +55765, +55766, +55799, +55798, +55767, +55824, +55857, +55856, +55825, +55826, +55859, +55858, +55827, +55828, +55861, +55860, +55829, +55830, +55863, +55862, +55831, +55888, +55921, +55920, +55889, +55890, +55923, +55922, +55891, +55892, +55925, +55924, +55893, +55894, +55927, +55926, +55895, +55952, +55985, +55984, +55953, +55954, +55987, +55986, +55955, +55956, +55989, +55988, +55957, +55958, +55991, +55990, +55959, +56016, +56049, +56048, +56017, +56018, +56051, +56050, +56019, +56020, +56053, +56052, +56021, +56022, +56055, +56054, +56023, +56080, +56113, +56112, +56081, +56082, +56115, +56114, +56083, +56084, +56117, +56116, +56085, +56086, +56119, +56118, +56087, +56144, +56177, +56176, +56145, +56146, +56179, +56178, +56147, +56148, +56181, +56180, +56149, +56150, +56183, +56182, +56151, +56208, +56241, +56240, +56209, +56210, +56243, +56242, +56211, +56212, +56245, +56244, +56213, +56214, +56247, +56246, +56215, +56272, +56305, +56304, +56273, +56274, +56307, +56306, +56275, +56276, +56309, +56308, +56277, +56278, +56311, +56310, +56279, +56336, +56369, +56368, +56337, +56338, +56371, +56370, +56339, +56340, +56373, +56372, +56341, +56342, +56375, +56374, +56343, +56400, +56433, +56432, +56401, +56402, +56435, +56434, +56403, +56404, +56437, +56436, +56405, +56406, +56439, +56438, +56407, +56464, +56497, +56496, +56465, +56466, +56499, +56498, +56467, +56468, +56501, +56500, +56469, +56470, +56503, +56502, +56471, +56528, +56561, +56560, +56529, +56530, +56563, +56562, +56531, +56532, +56565, +56564, +56533, +56534, +56567, +56566, +56535, +56592, +56625, +56624, +56593, +56594, +56627, +56626, +56595, +56596, +56629, +56628, +56597, +56598, +56631, +56630, +56599, +56656, +56689, +56688, +56657, +56658, +56691, +56690, +56659, +56660, +56693, +56692, +56661, +56662, +56695, +56694, +56663, +56720, +56753, +56752, +56721, +56722, +56755, +56754, +56723, +56724, +56757, +56756, +56725, +56726, +56759, +56758, +56727, +56784, +56817, +56816, +56785, +56786, +56819, +56818, +56787, +56788, +56821, +56820, +56789, +56790, +56823, +56822, +56791, +56848, +56881, +56880, +56849, +56850, +56883, +56882, +56851, +56852, +56885, +56884, +56853, +56854, +56887, +56886, +56855, +56912, +56945, +56944, +56913, +56914, +56947, +56946, +56915, +56916, +56949, +56948, +56917, +56918, +56951, +56950, +56919, +56976, +57009, +57008, +56977, +56978, +57011, +57010, +56979, +56980, +57013, +57012, +56981, +56982, +57015, +57014, +56983, +57040, +57073, +57072, +57041, +57042, +57075, +57074, +57043, +57044, +57077, +57076, +57045, +57046, +57079, +57078, +57047, +57104, +57137, +57136, +57105, +57106, +57139, +57138, +57107, +57108, +57141, +57140, +57109, +57110, +57143, +57142, +57111, +57168, +57201, +57200, +57169, +57170, +57203, +57202, +57171, +57172, +57205, +57204, +57173, +57174, +57207, +57206, +57175, +57232, +57265, +57264, +57233, +57234, +57267, +57266, +57235, +57236, +57269, +57268, +57237, +57238, +57271, +57270, +57239, +57296, +57329, +57328, +57297, +57298, +57331, +57330, +57299, +57300, +57333, +57332, +57301, +57302, +57335, +57334, +57303, +55320, +55353, +55352, +55321, +55322, +55355, +55354, +55323, +55324, +55357, +55356, +55325, +55326, +55359, +55358, +55327, +55384, +55417, +55416, +55385, +55386, +55419, +55418, +55387, +55388, +55421, +55420, +55389, +55390, +55423, +55422, +55391, +55448, +55481, +55480, +55449, +55450, +55483, +55482, +55451, +55452, +55485, +55484, +55453, +55454, +55487, +55486, +55455, +55512, +55545, +55544, +55513, +55514, +55547, +55546, +55515, +55516, +55549, +55548, +55517, +55518, +55551, +55550, +55519, +55576, +55609, +55608, +55577, +55578, +55611, +55610, +55579, +55580, +55613, +55612, +55581, +55582, +55615, +55614, +55583, +55640, +55673, +55672, +55641, +55642, +55675, +55674, +55643, +55644, +55677, +55676, +55645, +55646, +55679, +55678, +55647, +55704, +55737, +55736, +55705, +55706, +55739, +55738, +55707, +55708, +55741, +55740, +55709, +55710, +55743, +55742, +55711, +55768, +55801, +55800, +55769, +55770, +55803, +55802, +55771, +55772, +55805, +55804, +55773, +55774, +55807, +55806, +55775, +55832, +55865, +55864, +55833, +55834, +55867, +55866, +55835, +55836, +55869, +55868, +55837, +55838, +55871, +55870, +55839, +55896, +55929, +55928, +55897, +55898, +55931, +55930, +55899, +55900, +55933, +55932, +55901, +55902, +55935, +55934, +55903, +55960, +55993, +55992, +55961, +55962, +55995, +55994, +55963, +55964, +55997, +55996, +55965, +55966, +55999, +55998, +55967, +56024, +56057, +56056, +56025, +56026, +56059, +56058, +56027, +56028, +56061, +56060, +56029, +56030, +56063, +56062, +56031, +56088, +56121, +56120, +56089, +56090, +56123, +56122, +56091, +56092, +56125, +56124, +56093, +56094, +56127, +56126, +56095, +56152, +56185, +56184, +56153, +56154, +56187, +56186, +56155, +56156, +56189, +56188, +56157, +56158, +56191, +56190, +56159, +56216, +56249, +56248, +56217, +56218, +56251, +56250, +56219, +56220, +56253, +56252, +56221, +56222, +56255, +56254, +56223, +56280, +56313, +56312, +56281, +56282, +56315, +56314, +56283, +56284, +56317, +56316, +56285, +56286, +56319, +56318, +56287, +56344, +56377, +56376, +56345, +56346, +56379, +56378, +56347, +56348, +56381, +56380, +56349, +56350, +56383, +56382, +56351, +56408, +56441, +56440, +56409, +56410, +56443, +56442, +56411, +56412, +56445, +56444, +56413, +56414, +56447, +56446, +56415, +56472, +56505, +56504, +56473, +56474, +56507, +56506, +56475, +56476, +56509, +56508, +56477, +56478, +56511, +56510, +56479, +56536, +56569, +56568, +56537, +56538, +56571, +56570, +56539, +56540, +56573, +56572, +56541, +56542, +56575, +56574, +56543, +56600, +56633, +56632, +56601, +56602, +56635, +56634, +56603, +56604, +56637, +56636, +56605, +56606, +56639, +56638, +56607, +56664, +56697, +56696, +56665, +56666, +56699, +56698, +56667, +56668, +56701, +56700, +56669, +56670, +56703, +56702, +56671, +56728, +56761, +56760, +56729, +56730, +56763, +56762, +56731, +56732, +56765, +56764, +56733, +56734, +56767, +56766, +56735, +56792, +56825, +56824, +56793, +56794, +56827, +56826, +56795, +56796, +56829, +56828, +56797, +56798, +56831, +56830, +56799, +56856, +56889, +56888, +56857, +56858, +56891, +56890, +56859, +56860, +56893, +56892, +56861, +56862, +56895, +56894, +56863, +56920, +56953, +56952, +56921, +56922, +56955, +56954, +56923, +56924, +56957, +56956, +56925, +56926, +56959, +56958, +56927, +56984, +57017, +57016, +56985, +56986, +57019, +57018, +56987, +56988, +57021, +57020, +56989, +56990, +57023, +57022, +56991, +57048, +57081, +57080, +57049, +57050, +57083, +57082, +57051, +57052, +57085, +57084, +57053, +57054, +57087, +57086, +57055, +57112, +57145, +57144, +57113, +57114, +57147, +57146, +57115, +57116, +57149, +57148, +57117, +57118, +57151, +57150, +57119, +57176, +57209, +57208, +57177, +57178, +57211, +57210, +57179, +57180, +57213, +57212, +57181, +57182, +57215, +57214, +57183, +57240, +57273, +57272, +57241, +57242, +57275, +57274, +57243, +57244, +57277, +57276, +57245, +57246, +57279, +57278, +57247, +57304, +57337, +57336, +57305, +57306, +57339, +57338, +57307, +57308, +57341, +57340, +57309, +57310, +57343, +57342, +57311, +57344, +57377, +57376, +57345, +57346, +57379, +57378, +57347, +57348, +57381, +57380, +57349, +57350, +57383, +57382, +57351, +57408, +57441, +57440, +57409, +57410, +57443, +57442, +57411, +57412, +57445, +57444, +57413, +57414, +57447, +57446, +57415, +57472, +57505, +57504, +57473, +57474, +57507, +57506, +57475, +57476, +57509, +57508, +57477, +57478, +57511, +57510, +57479, +57536, +57569, +57568, +57537, +57538, +57571, +57570, +57539, +57540, +57573, +57572, +57541, +57542, +57575, +57574, +57543, +57600, +57633, +57632, +57601, +57602, +57635, +57634, +57603, +57604, +57637, +57636, +57605, +57606, +57639, +57638, +57607, +57664, +57697, +57696, +57665, +57666, +57699, +57698, +57667, +57668, +57701, +57700, +57669, +57670, +57703, +57702, +57671, +57728, +57761, +57760, +57729, +57730, +57763, +57762, +57731, +57732, +57765, +57764, +57733, +57734, +57767, +57766, +57735, +57792, +57825, +57824, +57793, +57794, +57827, +57826, +57795, +57796, +57829, +57828, +57797, +57798, +57831, +57830, +57799, +57856, +57889, +57888, +57857, +57858, +57891, +57890, +57859, +57860, +57893, +57892, +57861, +57862, +57895, +57894, +57863, +57920, +57953, +57952, +57921, +57922, +57955, +57954, +57923, +57924, +57957, +57956, +57925, +57926, +57959, +57958, +57927, +57984, +58017, +58016, +57985, +57986, +58019, +58018, +57987, +57988, +58021, +58020, +57989, +57990, +58023, +58022, +57991, +58048, +58081, +58080, +58049, +58050, +58083, +58082, +58051, +58052, +58085, +58084, +58053, +58054, +58087, +58086, +58055, +58112, +58145, +58144, +58113, +58114, +58147, +58146, +58115, +58116, +58149, +58148, +58117, +58118, +58151, +58150, +58119, +58176, +58209, +58208, +58177, +58178, +58211, +58210, +58179, +58180, +58213, +58212, +58181, +58182, +58215, +58214, +58183, +58240, +58273, +58272, +58241, +58242, +58275, +58274, +58243, +58244, +58277, +58276, +58245, +58246, +58279, +58278, +58247, +58304, +58337, +58336, +58305, +58306, +58339, +58338, +58307, +58308, +58341, +58340, +58309, +58310, +58343, +58342, +58311, +58368, +58401, +58400, +58369, +58370, +58403, +58402, +58371, +58372, +58405, +58404, +58373, +58374, +58407, +58406, +58375, +58432, +58465, +58464, +58433, +58434, +58467, +58466, +58435, +58436, +58469, +58468, +58437, +58438, +58471, +58470, +58439, +58496, +58529, +58528, +58497, +58498, +58531, +58530, +58499, +58500, +58533, +58532, +58501, +58502, +58535, +58534, +58503, +58560, +58593, +58592, +58561, +58562, +58595, +58594, +58563, +58564, +58597, +58596, +58565, +58566, +58599, +58598, +58567, +58624, +58657, +58656, +58625, +58626, +58659, +58658, +58627, +58628, +58661, +58660, +58629, +58630, +58663, +58662, +58631, +58688, +58721, +58720, +58689, +58690, +58723, +58722, +58691, +58692, +58725, +58724, +58693, +58694, +58727, +58726, +58695, +58752, +58785, +58784, +58753, +58754, +58787, +58786, +58755, +58756, +58789, +58788, +58757, +58758, +58791, +58790, +58759, +58816, +58849, +58848, +58817, +58818, +58851, +58850, +58819, +58820, +58853, +58852, +58821, +58822, +58855, +58854, +58823, +58880, +58913, +58912, +58881, +58882, +58915, +58914, +58883, +58884, +58917, +58916, +58885, +58886, +58919, +58918, +58887, +58944, +58977, +58976, +58945, +58946, +58979, +58978, +58947, +58948, +58981, +58980, +58949, +58950, +58983, +58982, +58951, +59008, +59041, +59040, +59009, +59010, +59043, +59042, +59011, +59012, +59045, +59044, +59013, +59014, +59047, +59046, +59015, +59072, +59105, +59104, +59073, +59074, +59107, +59106, +59075, +59076, +59109, +59108, +59077, +59078, +59111, +59110, +59079, +59136, +59169, +59168, +59137, +59138, +59171, +59170, +59139, +59140, +59173, +59172, +59141, +59142, +59175, +59174, +59143, +59200, +59233, +59232, +59201, +59202, +59235, +59234, +59203, +59204, +59237, +59236, +59205, +59206, +59239, +59238, +59207, +59264, +59297, +59296, +59265, +59266, +59299, +59298, +59267, +59268, +59301, +59300, +59269, +59270, +59303, +59302, +59271, +59328, +59361, +59360, +59329, +59330, +59363, +59362, +59331, +59332, +59365, +59364, +59333, +59334, +59367, +59366, +59335, +57352, +57385, +57384, +57353, +57354, +57387, +57386, +57355, +57356, +57389, +57388, +57357, +57358, +57391, +57390, +57359, +57416, +57449, +57448, +57417, +57418, +57451, +57450, +57419, +57420, +57453, +57452, +57421, +57422, +57455, +57454, +57423, +57480, +57513, +57512, +57481, +57482, +57515, +57514, +57483, +57484, +57517, +57516, +57485, +57486, +57519, +57518, +57487, +57544, +57577, +57576, +57545, +57546, +57579, +57578, +57547, +57548, +57581, +57580, +57549, +57550, +57583, +57582, +57551, +57608, +57641, +57640, +57609, +57610, +57643, +57642, +57611, +57612, +57645, +57644, +57613, +57614, +57647, +57646, +57615, +57672, +57705, +57704, +57673, +57674, +57707, +57706, +57675, +57676, +57709, +57708, +57677, +57678, +57711, +57710, +57679, +57736, +57769, +57768, +57737, +57738, +57771, +57770, +57739, +57740, +57773, +57772, +57741, +57742, +57775, +57774, +57743, +57800, +57833, +57832, +57801, +57802, +57835, +57834, +57803, +57804, +57837, +57836, +57805, +57806, +57839, +57838, +57807, +57864, +57897, +57896, +57865, +57866, +57899, +57898, +57867, +57868, +57901, +57900, +57869, +57870, +57903, +57902, +57871, +57928, +57961, +57960, +57929, +57930, +57963, +57962, +57931, +57932, +57965, +57964, +57933, +57934, +57967, +57966, +57935, +57992, +58025, +58024, +57993, +57994, +58027, +58026, +57995, +57996, +58029, +58028, +57997, +57998, +58031, +58030, +57999, +58056, +58089, +58088, +58057, +58058, +58091, +58090, +58059, +58060, +58093, +58092, +58061, +58062, +58095, +58094, +58063, +58120, +58153, +58152, +58121, +58122, +58155, +58154, +58123, +58124, +58157, +58156, +58125, +58126, +58159, +58158, +58127, +58184, +58217, +58216, +58185, +58186, +58219, +58218, +58187, +58188, +58221, +58220, +58189, +58190, +58223, +58222, +58191, +58248, +58281, +58280, +58249, +58250, +58283, +58282, +58251, +58252, +58285, +58284, +58253, +58254, +58287, +58286, +58255, +58312, +58345, +58344, +58313, +58314, +58347, +58346, +58315, +58316, +58349, +58348, +58317, +58318, +58351, +58350, +58319, +58376, +58409, +58408, +58377, +58378, +58411, +58410, +58379, +58380, +58413, +58412, +58381, +58382, +58415, +58414, +58383, +58440, +58473, +58472, +58441, +58442, +58475, +58474, +58443, +58444, +58477, +58476, +58445, +58446, +58479, +58478, +58447, +58504, +58537, +58536, +58505, +58506, +58539, +58538, +58507, +58508, +58541, +58540, +58509, +58510, +58543, +58542, +58511, +58568, +58601, +58600, +58569, +58570, +58603, +58602, +58571, +58572, +58605, +58604, +58573, +58574, +58607, +58606, +58575, +58632, +58665, +58664, +58633, +58634, +58667, +58666, +58635, +58636, +58669, +58668, +58637, +58638, +58671, +58670, +58639, +58696, +58729, +58728, +58697, +58698, +58731, +58730, +58699, +58700, +58733, +58732, +58701, +58702, +58735, +58734, +58703, +58760, +58793, +58792, +58761, +58762, +58795, +58794, +58763, +58764, +58797, +58796, +58765, +58766, +58799, +58798, +58767, +58824, +58857, +58856, +58825, +58826, +58859, +58858, +58827, +58828, +58861, +58860, +58829, +58830, +58863, +58862, +58831, +58888, +58921, +58920, +58889, +58890, +58923, +58922, +58891, +58892, +58925, +58924, +58893, +58894, +58927, +58926, +58895, +58952, +58985, +58984, +58953, +58954, +58987, +58986, +58955, +58956, +58989, +58988, +58957, +58958, +58991, +58990, +58959, +59016, +59049, +59048, +59017, +59018, +59051, +59050, +59019, +59020, +59053, +59052, +59021, +59022, +59055, +59054, +59023, +59080, +59113, +59112, +59081, +59082, +59115, +59114, +59083, +59084, +59117, +59116, +59085, +59086, +59119, +59118, +59087, +59144, +59177, +59176, +59145, +59146, +59179, +59178, +59147, +59148, +59181, +59180, +59149, +59150, +59183, +59182, +59151, +59208, +59241, +59240, +59209, +59210, +59243, +59242, +59211, +59212, +59245, +59244, +59213, +59214, +59247, +59246, +59215, +59272, +59305, +59304, +59273, +59274, +59307, +59306, +59275, +59276, +59309, +59308, +59277, +59278, +59311, +59310, +59279, +59336, +59369, +59368, +59337, +59338, +59371, +59370, +59339, +59340, +59373, +59372, +59341, +59342, +59375, +59374, +59343, +57360, +57393, +57392, +57361, +57362, +57395, +57394, +57363, +57364, +57397, +57396, +57365, +57366, +57399, +57398, +57367, +57424, +57457, +57456, +57425, +57426, +57459, +57458, +57427, +57428, +57461, +57460, +57429, +57430, +57463, +57462, +57431, +57488, +57521, +57520, +57489, +57490, +57523, +57522, +57491, +57492, +57525, +57524, +57493, +57494, +57527, +57526, +57495, +57552, +57585, +57584, +57553, +57554, +57587, +57586, +57555, +57556, +57589, +57588, +57557, +57558, +57591, +57590, +57559, +57616, +57649, +57648, +57617, +57618, +57651, +57650, +57619, +57620, +57653, +57652, +57621, +57622, +57655, +57654, +57623, +57680, +57713, +57712, +57681, +57682, +57715, +57714, +57683, +57684, +57717, +57716, +57685, +57686, +57719, +57718, +57687, +57744, +57777, +57776, +57745, +57746, +57779, +57778, +57747, +57748, +57781, +57780, +57749, +57750, +57783, +57782, +57751, +57808, +57841, +57840, +57809, +57810, +57843, +57842, +57811, +57812, +57845, +57844, +57813, +57814, +57847, +57846, +57815, +57872, +57905, +57904, +57873, +57874, +57907, +57906, +57875, +57876, +57909, +57908, +57877, +57878, +57911, +57910, +57879, +57936, +57969, +57968, +57937, +57938, +57971, +57970, +57939, +57940, +57973, +57972, +57941, +57942, +57975, +57974, +57943, +58000, +58033, +58032, +58001, +58002, +58035, +58034, +58003, +58004, +58037, +58036, +58005, +58006, +58039, +58038, +58007, +58064, +58097, +58096, +58065, +58066, +58099, +58098, +58067, +58068, +58101, +58100, +58069, +58070, +58103, +58102, +58071, +58128, +58161, +58160, +58129, +58130, +58163, +58162, +58131, +58132, +58165, +58164, +58133, +58134, +58167, +58166, +58135, +58192, +58225, +58224, +58193, +58194, +58227, +58226, +58195, +58196, +58229, +58228, +58197, +58198, +58231, +58230, +58199, +58256, +58289, +58288, +58257, +58258, +58291, +58290, +58259, +58260, +58293, +58292, +58261, +58262, +58295, +58294, +58263, +58320, +58353, +58352, +58321, +58322, +58355, +58354, +58323, +58324, +58357, +58356, +58325, +58326, +58359, +58358, +58327, +58384, +58417, +58416, +58385, +58386, +58419, +58418, +58387, +58388, +58421, +58420, +58389, +58390, +58423, +58422, +58391, +58448, +58481, +58480, +58449, +58450, +58483, +58482, +58451, +58452, +58485, +58484, +58453, +58454, +58487, +58486, +58455, +58512, +58545, +58544, +58513, +58514, +58547, +58546, +58515, +58516, +58549, +58548, +58517, +58518, +58551, +58550, +58519, +58576, +58609, +58608, +58577, +58578, +58611, +58610, +58579, +58580, +58613, +58612, +58581, +58582, +58615, +58614, +58583, +58640, +58673, +58672, +58641, +58642, +58675, +58674, +58643, +58644, +58677, +58676, +58645, +58646, +58679, +58678, +58647, +58704, +58737, +58736, +58705, +58706, +58739, +58738, +58707, +58708, +58741, +58740, +58709, +58710, +58743, +58742, +58711, +58768, +58801, +58800, +58769, +58770, +58803, +58802, +58771, +58772, +58805, +58804, +58773, +58774, +58807, +58806, +58775, +58832, +58865, +58864, +58833, +58834, +58867, +58866, +58835, +58836, +58869, +58868, +58837, +58838, +58871, +58870, +58839, +58896, +58929, +58928, +58897, +58898, +58931, +58930, +58899, +58900, +58933, +58932, +58901, +58902, +58935, +58934, +58903, +58960, +58993, +58992, +58961, +58962, +58995, +58994, +58963, +58964, +58997, +58996, +58965, +58966, +58999, +58998, +58967, +59024, +59057, +59056, +59025, +59026, +59059, +59058, +59027, +59028, +59061, +59060, +59029, +59030, +59063, +59062, +59031, +59088, +59121, +59120, +59089, +59090, +59123, +59122, +59091, +59092, +59125, +59124, +59093, +59094, +59127, +59126, +59095, +59152, +59185, +59184, +59153, +59154, +59187, +59186, +59155, +59156, +59189, +59188, +59157, +59158, +59191, +59190, +59159, +59216, +59249, +59248, +59217, +59218, +59251, +59250, +59219, +59220, +59253, +59252, +59221, +59222, +59255, +59254, +59223, +59280, +59313, +59312, +59281, +59282, +59315, +59314, +59283, +59284, +59317, +59316, +59285, +59286, +59319, +59318, +59287, +59344, +59377, +59376, +59345, +59346, +59379, +59378, +59347, +59348, +59381, +59380, +59349, +59350, +59383, +59382, +59351, +57368, +57401, +57400, +57369, +57370, +57403, +57402, +57371, +57372, +57405, +57404, +57373, +57374, +57407, +57406, +57375, +57432, +57465, +57464, +57433, +57434, +57467, +57466, +57435, +57436, +57469, +57468, +57437, +57438, +57471, +57470, +57439, +57496, +57529, +57528, +57497, +57498, +57531, +57530, +57499, +57500, +57533, +57532, +57501, +57502, +57535, +57534, +57503, +57560, +57593, +57592, +57561, +57562, +57595, +57594, +57563, +57564, +57597, +57596, +57565, +57566, +57599, +57598, +57567, +57624, +57657, +57656, +57625, +57626, +57659, +57658, +57627, +57628, +57661, +57660, +57629, +57630, +57663, +57662, +57631, +57688, +57721, +57720, +57689, +57690, +57723, +57722, +57691, +57692, +57725, +57724, +57693, +57694, +57727, +57726, +57695, +57752, +57785, +57784, +57753, +57754, +57787, +57786, +57755, +57756, +57789, +57788, +57757, +57758, +57791, +57790, +57759, +57816, +57849, +57848, +57817, +57818, +57851, +57850, +57819, +57820, +57853, +57852, +57821, +57822, +57855, +57854, +57823, +57880, +57913, +57912, +57881, +57882, +57915, +57914, +57883, +57884, +57917, +57916, +57885, +57886, +57919, +57918, +57887, +57944, +57977, +57976, +57945, +57946, +57979, +57978, +57947, +57948, +57981, +57980, +57949, +57950, +57983, +57982, +57951, +58008, +58041, +58040, +58009, +58010, +58043, +58042, +58011, +58012, +58045, +58044, +58013, +58014, +58047, +58046, +58015, +58072, +58105, +58104, +58073, +58074, +58107, +58106, +58075, +58076, +58109, +58108, +58077, +58078, +58111, +58110, +58079, +58136, +58169, +58168, +58137, +58138, +58171, +58170, +58139, +58140, +58173, +58172, +58141, +58142, +58175, +58174, +58143, +58200, +58233, +58232, +58201, +58202, +58235, +58234, +58203, +58204, +58237, +58236, +58205, +58206, +58239, +58238, +58207, +58264, +58297, +58296, +58265, +58266, +58299, +58298, +58267, +58268, +58301, +58300, +58269, +58270, +58303, +58302, +58271, +58328, +58361, +58360, +58329, +58330, +58363, +58362, +58331, +58332, +58365, +58364, +58333, +58334, +58367, +58366, +58335, +58392, +58425, +58424, +58393, +58394, +58427, +58426, +58395, +58396, +58429, +58428, +58397, +58398, +58431, +58430, +58399, +58456, +58489, +58488, +58457, +58458, +58491, +58490, +58459, +58460, +58493, +58492, +58461, +58462, +58495, +58494, +58463, +58520, +58553, +58552, +58521, +58522, +58555, +58554, +58523, +58524, +58557, +58556, +58525, +58526, +58559, +58558, +58527, +58584, +58617, +58616, +58585, +58586, +58619, +58618, +58587, +58588, +58621, +58620, +58589, +58590, +58623, +58622, +58591, +58648, +58681, +58680, +58649, +58650, +58683, +58682, +58651, +58652, +58685, +58684, +58653, +58654, +58687, +58686, +58655, +58712, +58745, +58744, +58713, +58714, +58747, +58746, +58715, +58716, +58749, +58748, +58717, +58718, +58751, +58750, +58719, +58776, +58809, +58808, +58777, +58778, +58811, +58810, +58779, +58780, +58813, +58812, +58781, +58782, +58815, +58814, +58783, +58840, +58873, +58872, +58841, +58842, +58875, +58874, +58843, +58844, +58877, +58876, +58845, +58846, +58879, +58878, +58847, +58904, +58937, +58936, +58905, +58906, +58939, +58938, +58907, +58908, +58941, +58940, +58909, +58910, +58943, +58942, +58911, +58968, +59001, +59000, +58969, +58970, +59003, +59002, +58971, +58972, +59005, +59004, +58973, +58974, +59007, +59006, +58975, +59032, +59065, +59064, +59033, +59034, +59067, +59066, +59035, +59036, +59069, +59068, +59037, +59038, +59071, +59070, +59039, +59096, +59129, +59128, +59097, +59098, +59131, +59130, +59099, +59100, +59133, +59132, +59101, +59102, +59135, +59134, +59103, +59160, +59193, +59192, +59161, +59162, +59195, +59194, +59163, +59164, +59197, +59196, +59165, +59166, +59199, +59198, +59167, +59224, +59257, +59256, +59225, +59226, +59259, +59258, +59227, +59228, +59261, +59260, +59229, +59230, +59263, +59262, +59231, +59288, +59321, +59320, +59289, +59290, +59323, +59322, +59291, +59292, +59325, +59324, +59293, +59294, +59327, +59326, +59295, +59352, +59385, +59384, +59353, +59354, +59387, +59386, +59355, +59356, +59389, +59388, +59357, +59358, +59391, +59390, +59359, +59392, +59425, +59424, +59393, +59394, +59427, +59426, +59395, +59396, +59429, +59428, +59397, +59398, +59431, +59430, +59399, +59456, +59489, +59488, +59457, +59458, +59491, +59490, +59459, +59460, +59493, +59492, +59461, +59462, +59495, +59494, +59463, +59520, +59553, +59552, +59521, +59522, +59555, +59554, +59523, +59524, +59557, +59556, +59525, +59526, +59559, +59558, +59527, +59584, +59617, +59616, +59585, +59586, +59619, +59618, +59587, +59588, +59621, +59620, +59589, +59590, +59623, +59622, +59591, +59648, +59681, +59680, +59649, +59650, +59683, +59682, +59651, +59652, +59685, +59684, +59653, +59654, +59687, +59686, +59655, +59712, +59745, +59744, +59713, +59714, +59747, +59746, +59715, +59716, +59749, +59748, +59717, +59718, +59751, +59750, +59719, +59776, +59809, +59808, +59777, +59778, +59811, +59810, +59779, +59780, +59813, +59812, +59781, +59782, +59815, +59814, +59783, +59840, +59873, +59872, +59841, +59842, +59875, +59874, +59843, +59844, +59877, +59876, +59845, +59846, +59879, +59878, +59847, +59904, +59937, +59936, +59905, +59906, +59939, +59938, +59907, +59908, +59941, +59940, +59909, +59910, +59943, +59942, +59911, +59968, +60001, +60000, +59969, +59970, +60003, +60002, +59971, +59972, +60005, +60004, +59973, +59974, +60007, +60006, +59975, +60032, +60065, +60064, +60033, +60034, +60067, +60066, +60035, +60036, +60069, +60068, +60037, +60038, +60071, +60070, +60039, +60096, +60129, +60128, +60097, +60098, +60131, +60130, +60099, +60100, +60133, +60132, +60101, +60102, +60135, +60134, +60103, +60160, +60193, +60192, +60161, +60162, +60195, +60194, +60163, +60164, +60197, +60196, +60165, +60166, +60199, +60198, +60167, +60224, +60257, +60256, +60225, +60226, +60259, +60258, +60227, +60228, +60261, +60260, +60229, +60230, +60263, +60262, +60231, +60288, +60321, +60320, +60289, +60290, +60323, +60322, +60291, +60292, +60325, +60324, +60293, +60294, +60327, +60326, +60295, +60352, +60385, +60384, +60353, +60354, +60387, +60386, +60355, +60356, +60389, +60388, +60357, +60358, +60391, +60390, +60359, +60416, +60449, +60448, +60417, +60418, +60451, +60450, +60419, +60420, +60453, +60452, +60421, +60422, +60455, +60454, +60423, +60480, +60513, +60512, +60481, +60482, +60515, +60514, +60483, +60484, +60517, +60516, +60485, +60486, +60519, +60518, +60487, +60544, +60577, +60576, +60545, +60546, +60579, +60578, +60547, +60548, +60581, +60580, +60549, +60550, +60583, +60582, +60551, +60608, +60641, +60640, +60609, +60610, +60643, +60642, +60611, +60612, +60645, +60644, +60613, +60614, +60647, +60646, +60615, +60672, +60705, +60704, +60673, +60674, +60707, +60706, +60675, +60676, +60709, +60708, +60677, +60678, +60711, +60710, +60679, +60736, +60769, +60768, +60737, +60738, +60771, +60770, +60739, +60740, +60773, +60772, +60741, +60742, +60775, +60774, +60743, +60800, +60833, +60832, +60801, +60802, +60835, +60834, +60803, +60804, +60837, +60836, +60805, +60806, +60839, +60838, +60807, +60864, +60897, +60896, +60865, +60866, +60899, +60898, +60867, +60868, +60901, +60900, +60869, +60870, +60903, +60902, +60871, +60928, +60961, +60960, +60929, +60930, +60963, +60962, +60931, +60932, +60965, +60964, +60933, +60934, +60967, +60966, +60935, +60992, +61025, +61024, +60993, +60994, +61027, +61026, +60995, +60996, +61029, +61028, +60997, +60998, +61031, +61030, +60999, +61056, +61089, +61088, +61057, +61058, +61091, +61090, +61059, +61060, +61093, +61092, +61061, +61062, +61095, +61094, +61063, +61120, +61153, +61152, +61121, +61122, +61155, +61154, +61123, +61124, +61157, +61156, +61125, +61126, +61159, +61158, +61127, +61184, +61217, +61216, +61185, +61186, +61219, +61218, +61187, +61188, +61221, +61220, +61189, +61190, +61223, +61222, +61191, +61248, +61281, +61280, +61249, +61250, +61283, +61282, +61251, +61252, +61285, +61284, +61253, +61254, +61287, +61286, +61255, +61312, +61345, +61344, +61313, +61314, +61347, +61346, +61315, +61316, +61349, +61348, +61317, +61318, +61351, +61350, +61319, +61376, +61409, +61408, +61377, +61378, +61411, +61410, +61379, +61380, +61413, +61412, +61381, +61382, +61415, +61414, +61383, +59400, +59433, +59432, +59401, +59402, +59435, +59434, +59403, +59404, +59437, +59436, +59405, +59406, +59439, +59438, +59407, +59464, +59497, +59496, +59465, +59466, +59499, +59498, +59467, +59468, +59501, +59500, +59469, +59470, +59503, +59502, +59471, +59528, +59561, +59560, +59529, +59530, +59563, +59562, +59531, +59532, +59565, +59564, +59533, +59534, +59567, +59566, +59535, +59592, +59625, +59624, +59593, +59594, +59627, +59626, +59595, +59596, +59629, +59628, +59597, +59598, +59631, +59630, +59599, +59656, +59689, +59688, +59657, +59658, +59691, +59690, +59659, +59660, +59693, +59692, +59661, +59662, +59695, +59694, +59663, +59720, +59753, +59752, +59721, +59722, +59755, +59754, +59723, +59724, +59757, +59756, +59725, +59726, +59759, +59758, +59727, +59784, +59817, +59816, +59785, +59786, +59819, +59818, +59787, +59788, +59821, +59820, +59789, +59790, +59823, +59822, +59791, +59848, +59881, +59880, +59849, +59850, +59883, +59882, +59851, +59852, +59885, +59884, +59853, +59854, +59887, +59886, +59855, +59912, +59945, +59944, +59913, +59914, +59947, +59946, +59915, +59916, +59949, +59948, +59917, +59918, +59951, +59950, +59919, +59976, +60009, +60008, +59977, +59978, +60011, +60010, +59979, +59980, +60013, +60012, +59981, +59982, +60015, +60014, +59983, +60040, +60073, +60072, +60041, +60042, +60075, +60074, +60043, +60044, +60077, +60076, +60045, +60046, +60079, +60078, +60047, +60104, +60137, +60136, +60105, +60106, +60139, +60138, +60107, +60108, +60141, +60140, +60109, +60110, +60143, +60142, +60111, +60168, +60201, +60200, +60169, +60170, +60203, +60202, +60171, +60172, +60205, +60204, +60173, +60174, +60207, +60206, +60175, +60232, +60265, +60264, +60233, +60234, +60267, +60266, +60235, +60236, +60269, +60268, +60237, +60238, +60271, +60270, +60239, +60296, +60329, +60328, +60297, +60298, +60331, +60330, +60299, +60300, +60333, +60332, +60301, +60302, +60335, +60334, +60303, +60360, +60393, +60392, +60361, +60362, +60395, +60394, +60363, +60364, +60397, +60396, +60365, +60366, +60399, +60398, +60367, +60424, +60457, +60456, +60425, +60426, +60459, +60458, +60427, +60428, +60461, +60460, +60429, +60430, +60463, +60462, +60431, +60488, +60521, +60520, +60489, +60490, +60523, +60522, +60491, +60492, +60525, +60524, +60493, +60494, +60527, +60526, +60495, +60552, +60585, +60584, +60553, +60554, +60587, +60586, +60555, +60556, +60589, +60588, +60557, +60558, +60591, +60590, +60559, +60616, +60649, +60648, +60617, +60618, +60651, +60650, +60619, +60620, +60653, +60652, +60621, +60622, +60655, +60654, +60623, +60680, +60713, +60712, +60681, +60682, +60715, +60714, +60683, +60684, +60717, +60716, +60685, +60686, +60719, +60718, +60687, +60744, +60777, +60776, +60745, +60746, +60779, +60778, +60747, +60748, +60781, +60780, +60749, +60750, +60783, +60782, +60751, +60808, +60841, +60840, +60809, +60810, +60843, +60842, +60811, +60812, +60845, +60844, +60813, +60814, +60847, +60846, +60815, +60872, +60905, +60904, +60873, +60874, +60907, +60906, +60875, +60876, +60909, +60908, +60877, +60878, +60911, +60910, +60879, +60936, +60969, +60968, +60937, +60938, +60971, +60970, +60939, +60940, +60973, +60972, +60941, +60942, +60975, +60974, +60943, +61000, +61033, +61032, +61001, +61002, +61035, +61034, +61003, +61004, +61037, +61036, +61005, +61006, +61039, +61038, +61007, +61064, +61097, +61096, +61065, +61066, +61099, +61098, +61067, +61068, +61101, +61100, +61069, +61070, +61103, +61102, +61071, +61128, +61161, +61160, +61129, +61130, +61163, +61162, +61131, +61132, +61165, +61164, +61133, +61134, +61167, +61166, +61135, +61192, +61225, +61224, +61193, +61194, +61227, +61226, +61195, +61196, +61229, +61228, +61197, +61198, +61231, +61230, +61199, +61256, +61289, +61288, +61257, +61258, +61291, +61290, +61259, +61260, +61293, +61292, +61261, +61262, +61295, +61294, +61263, +61320, +61353, +61352, +61321, +61322, +61355, +61354, +61323, +61324, +61357, +61356, +61325, +61326, +61359, +61358, +61327, +61384, +61417, +61416, +61385, +61386, +61419, +61418, +61387, +61388, +61421, +61420, +61389, +61390, +61423, +61422, +61391, +59408, +59441, +59440, +59409, +59410, +59443, +59442, +59411, +59412, +59445, +59444, +59413, +59414, +59447, +59446, +59415, +59472, +59505, +59504, +59473, +59474, +59507, +59506, +59475, +59476, +59509, +59508, +59477, +59478, +59511, +59510, +59479, +59536, +59569, +59568, +59537, +59538, +59571, +59570, +59539, +59540, +59573, +59572, +59541, +59542, +59575, +59574, +59543, +59600, +59633, +59632, +59601, +59602, +59635, +59634, +59603, +59604, +59637, +59636, +59605, +59606, +59639, +59638, +59607, +59664, +59697, +59696, +59665, +59666, +59699, +59698, +59667, +59668, +59701, +59700, +59669, +59670, +59703, +59702, +59671, +59728, +59761, +59760, +59729, +59730, +59763, +59762, +59731, +59732, +59765, +59764, +59733, +59734, +59767, +59766, +59735, +59792, +59825, +59824, +59793, +59794, +59827, +59826, +59795, +59796, +59829, +59828, +59797, +59798, +59831, +59830, +59799, +59856, +59889, +59888, +59857, +59858, +59891, +59890, +59859, +59860, +59893, +59892, +59861, +59862, +59895, +59894, +59863, +59920, +59953, +59952, +59921, +59922, +59955, +59954, +59923, +59924, +59957, +59956, +59925, +59926, +59959, +59958, +59927, +59984, +60017, +60016, +59985, +59986, +60019, +60018, +59987, +59988, +60021, +60020, +59989, +59990, +60023, +60022, +59991, +60048, +60081, +60080, +60049, +60050, +60083, +60082, +60051, +60052, +60085, +60084, +60053, +60054, +60087, +60086, +60055, +60112, +60145, +60144, +60113, +60114, +60147, +60146, +60115, +60116, +60149, +60148, +60117, +60118, +60151, +60150, +60119, +60176, +60209, +60208, +60177, +60178, +60211, +60210, +60179, +60180, +60213, +60212, +60181, +60182, +60215, +60214, +60183, +60240, +60273, +60272, +60241, +60242, +60275, +60274, +60243, +60244, +60277, +60276, +60245, +60246, +60279, +60278, +60247, +60304, +60337, +60336, +60305, +60306, +60339, +60338, +60307, +60308, +60341, +60340, +60309, +60310, +60343, +60342, +60311, +60368, +60401, +60400, +60369, +60370, +60403, +60402, +60371, +60372, +60405, +60404, +60373, +60374, +60407, +60406, +60375, +60432, +60465, +60464, +60433, +60434, +60467, +60466, +60435, +60436, +60469, +60468, +60437, +60438, +60471, +60470, +60439, +60496, +60529, +60528, +60497, +60498, +60531, +60530, +60499, +60500, +60533, +60532, +60501, +60502, +60535, +60534, +60503, +60560, +60593, +60592, +60561, +60562, +60595, +60594, +60563, +60564, +60597, +60596, +60565, +60566, +60599, +60598, +60567, +60624, +60657, +60656, +60625, +60626, +60659, +60658, +60627, +60628, +60661, +60660, +60629, +60630, +60663, +60662, +60631, +60688, +60721, +60720, +60689, +60690, +60723, +60722, +60691, +60692, +60725, +60724, +60693, +60694, +60727, +60726, +60695, +60752, +60785, +60784, +60753, +60754, +60787, +60786, +60755, +60756, +60789, +60788, +60757, +60758, +60791, +60790, +60759, +60816, +60849, +60848, +60817, +60818, +60851, +60850, +60819, +60820, +60853, +60852, +60821, +60822, +60855, +60854, +60823, +60880, +60913, +60912, +60881, +60882, +60915, +60914, +60883, +60884, +60917, +60916, +60885, +60886, +60919, +60918, +60887, +60944, +60977, +60976, +60945, +60946, +60979, +60978, +60947, +60948, +60981, +60980, +60949, +60950, +60983, +60982, +60951, +61008, +61041, +61040, +61009, +61010, +61043, +61042, +61011, +61012, +61045, +61044, +61013, +61014, +61047, +61046, +61015, +61072, +61105, +61104, +61073, +61074, +61107, +61106, +61075, +61076, +61109, +61108, +61077, +61078, +61111, +61110, +61079, +61136, +61169, +61168, +61137, +61138, +61171, +61170, +61139, +61140, +61173, +61172, +61141, +61142, +61175, +61174, +61143, +61200, +61233, +61232, +61201, +61202, +61235, +61234, +61203, +61204, +61237, +61236, +61205, +61206, +61239, +61238, +61207, +61264, +61297, +61296, +61265, +61266, +61299, +61298, +61267, +61268, +61301, +61300, +61269, +61270, +61303, +61302, +61271, +61328, +61361, +61360, +61329, +61330, +61363, +61362, +61331, +61332, +61365, +61364, +61333, +61334, +61367, +61366, +61335, +61392, +61425, +61424, +61393, +61394, +61427, +61426, +61395, +61396, +61429, +61428, +61397, +61398, +61431, +61430, +61399, +59416, +59449, +59448, +59417, +59418, +59451, +59450, +59419, +59420, +59453, +59452, +59421, +59422, +59455, +59454, +59423, +59480, +59513, +59512, +59481, +59482, +59515, +59514, +59483, +59484, +59517, +59516, +59485, +59486, +59519, +59518, +59487, +59544, +59577, +59576, +59545, +59546, +59579, +59578, +59547, +59548, +59581, +59580, +59549, +59550, +59583, +59582, +59551, +59608, +59641, +59640, +59609, +59610, +59643, +59642, +59611, +59612, +59645, +59644, +59613, +59614, +59647, +59646, +59615, +59672, +59705, +59704, +59673, +59674, +59707, +59706, +59675, +59676, +59709, +59708, +59677, +59678, +59711, +59710, +59679, +59736, +59769, +59768, +59737, +59738, +59771, +59770, +59739, +59740, +59773, +59772, +59741, +59742, +59775, +59774, +59743, +59800, +59833, +59832, +59801, +59802, +59835, +59834, +59803, +59804, +59837, +59836, +59805, +59806, +59839, +59838, +59807, +59864, +59897, +59896, +59865, +59866, +59899, +59898, +59867, +59868, +59901, +59900, +59869, +59870, +59903, +59902, +59871, +59928, +59961, +59960, +59929, +59930, +59963, +59962, +59931, +59932, +59965, +59964, +59933, +59934, +59967, +59966, +59935, +59992, +60025, +60024, +59993, +59994, +60027, +60026, +59995, +59996, +60029, +60028, +59997, +59998, +60031, +60030, +59999, +60056, +60089, +60088, +60057, +60058, +60091, +60090, +60059, +60060, +60093, +60092, +60061, +60062, +60095, +60094, +60063, +60120, +60153, +60152, +60121, +60122, +60155, +60154, +60123, +60124, +60157, +60156, +60125, +60126, +60159, +60158, +60127, +60184, +60217, +60216, +60185, +60186, +60219, +60218, +60187, +60188, +60221, +60220, +60189, +60190, +60223, +60222, +60191, +60248, +60281, +60280, +60249, +60250, +60283, +60282, +60251, +60252, +60285, +60284, +60253, +60254, +60287, +60286, +60255, +60312, +60345, +60344, +60313, +60314, +60347, +60346, +60315, +60316, +60349, +60348, +60317, +60318, +60351, +60350, +60319, +60376, +60409, +60408, +60377, +60378, +60411, +60410, +60379, +60380, +60413, +60412, +60381, +60382, +60415, +60414, +60383, +60440, +60473, +60472, +60441, +60442, +60475, +60474, +60443, +60444, +60477, +60476, +60445, +60446, +60479, +60478, +60447, +60504, +60537, +60536, +60505, +60506, +60539, +60538, +60507, +60508, +60541, +60540, +60509, +60510, +60543, +60542, +60511, +60568, +60601, +60600, +60569, +60570, +60603, +60602, +60571, +60572, +60605, +60604, +60573, +60574, +60607, +60606, +60575, +60632, +60665, +60664, +60633, +60634, +60667, +60666, +60635, +60636, +60669, +60668, +60637, +60638, +60671, +60670, +60639, +60696, +60729, +60728, +60697, +60698, +60731, +60730, +60699, +60700, +60733, +60732, +60701, +60702, +60735, +60734, +60703, +60760, +60793, +60792, +60761, +60762, +60795, +60794, +60763, +60764, +60797, +60796, +60765, +60766, +60799, +60798, +60767, +60824, +60857, +60856, +60825, +60826, +60859, +60858, +60827, +60828, +60861, +60860, +60829, +60830, +60863, +60862, +60831, +60888, +60921, +60920, +60889, +60890, +60923, +60922, +60891, +60892, +60925, +60924, +60893, +60894, +60927, +60926, +60895, +60952, +60985, +60984, +60953, +60954, +60987, +60986, +60955, +60956, +60989, +60988, +60957, +60958, +60991, +60990, +60959, +61016, +61049, +61048, +61017, +61018, +61051, +61050, +61019, +61020, +61053, +61052, +61021, +61022, +61055, +61054, +61023, +61080, +61113, +61112, +61081, +61082, +61115, +61114, +61083, +61084, +61117, +61116, +61085, +61086, +61119, +61118, +61087, +61144, +61177, +61176, +61145, +61146, +61179, +61178, +61147, +61148, +61181, +61180, +61149, +61150, +61183, +61182, +61151, +61208, +61241, +61240, +61209, +61210, +61243, +61242, +61211, +61212, +61245, +61244, +61213, +61214, +61247, +61246, +61215, +61272, +61305, +61304, +61273, +61274, +61307, +61306, +61275, +61276, +61309, +61308, +61277, +61278, +61311, +61310, +61279, +61336, +61369, +61368, +61337, +61338, +61371, +61370, +61339, +61340, +61373, +61372, +61341, +61342, +61375, +61374, +61343, +61400, +61433, +61432, +61401, +61402, +61435, +61434, +61403, +61404, +61437, +61436, +61405, +61406, +61439, +61438, +61407, +61440, +61473, +61472, +61441, +61442, +61475, +61474, +61443, +61444, +61477, +61476, +61445, +61446, +61479, +61478, +61447, +61504, +61537, +61536, +61505, +61506, +61539, +61538, +61507, +61508, +61541, +61540, +61509, +61510, +61543, +61542, +61511, +61568, +61601, +61600, +61569, +61570, +61603, +61602, +61571, +61572, +61605, +61604, +61573, +61574, +61607, +61606, +61575, +61632, +61665, +61664, +61633, +61634, +61667, +61666, +61635, +61636, +61669, +61668, +61637, +61638, +61671, +61670, +61639, +61696, +61729, +61728, +61697, +61698, +61731, +61730, +61699, +61700, +61733, +61732, +61701, +61702, +61735, +61734, +61703, +61760, +61793, +61792, +61761, +61762, +61795, +61794, +61763, +61764, +61797, +61796, +61765, +61766, +61799, +61798, +61767, +61824, +61857, +61856, +61825, +61826, +61859, +61858, +61827, +61828, +61861, +61860, +61829, +61830, +61863, +61862, +61831, +61888, +61921, +61920, +61889, +61890, +61923, +61922, +61891, +61892, +61925, +61924, +61893, +61894, +61927, +61926, +61895, +61952, +61985, +61984, +61953, +61954, +61987, +61986, +61955, +61956, +61989, +61988, +61957, +61958, +61991, +61990, +61959, +62016, +62049, +62048, +62017, +62018, +62051, +62050, +62019, +62020, +62053, +62052, +62021, +62022, +62055, +62054, +62023, +62080, +62113, +62112, +62081, +62082, +62115, +62114, +62083, +62084, +62117, +62116, +62085, +62086, +62119, +62118, +62087, +62144, +62177, +62176, +62145, +62146, +62179, +62178, +62147, +62148, +62181, +62180, +62149, +62150, +62183, +62182, +62151, +62208, +62241, +62240, +62209, +62210, +62243, +62242, +62211, +62212, +62245, +62244, +62213, +62214, +62247, +62246, +62215, +62272, +62305, +62304, +62273, +62274, +62307, +62306, +62275, +62276, +62309, +62308, +62277, +62278, +62311, +62310, +62279, +62336, +62369, +62368, +62337, +62338, +62371, +62370, +62339, +62340, +62373, +62372, +62341, +62342, +62375, +62374, +62343, +62400, +62433, +62432, +62401, +62402, +62435, +62434, +62403, +62404, +62437, +62436, +62405, +62406, +62439, +62438, +62407, +62464, +62497, +62496, +62465, +62466, +62499, +62498, +62467, +62468, +62501, +62500, +62469, +62470, +62503, +62502, +62471, +62528, +62561, +62560, +62529, +62530, +62563, +62562, +62531, +62532, +62565, +62564, +62533, +62534, +62567, +62566, +62535, +62592, +62625, +62624, +62593, +62594, +62627, +62626, +62595, +62596, +62629, +62628, +62597, +62598, +62631, +62630, +62599, +62656, +62689, +62688, +62657, +62658, +62691, +62690, +62659, +62660, +62693, +62692, +62661, +62662, +62695, +62694, +62663, +62720, +62753, +62752, +62721, +62722, +62755, +62754, +62723, +62724, +62757, +62756, +62725, +62726, +62759, +62758, +62727, +62784, +62817, +62816, +62785, +62786, +62819, +62818, +62787, +62788, +62821, +62820, +62789, +62790, +62823, +62822, +62791, +62848, +62881, +62880, +62849, +62850, +62883, +62882, +62851, +62852, +62885, +62884, +62853, +62854, +62887, +62886, +62855, +62912, +62945, +62944, +62913, +62914, +62947, +62946, +62915, +62916, +62949, +62948, +62917, +62918, +62951, +62950, +62919, +62976, +63009, +63008, +62977, +62978, +63011, +63010, +62979, +62980, +63013, +63012, +62981, +62982, +63015, +63014, +62983, +63040, +63073, +63072, +63041, +63042, +63075, +63074, +63043, +63044, +63077, +63076, +63045, +63046, +63079, +63078, +63047, +63104, +63137, +63136, +63105, +63106, +63139, +63138, +63107, +63108, +63141, +63140, +63109, +63110, +63143, +63142, +63111, +63168, +63201, +63200, +63169, +63170, +63203, +63202, +63171, +63172, +63205, +63204, +63173, +63174, +63207, +63206, +63175, +63232, +63265, +63264, +63233, +63234, +63267, +63266, +63235, +63236, +63269, +63268, +63237, +63238, +63271, +63270, +63239, +63296, +63329, +63328, +63297, +63298, +63331, +63330, +63299, +63300, +63333, +63332, +63301, +63302, +63335, +63334, +63303, +63360, +63393, +63392, +63361, +63362, +63395, +63394, +63363, +63364, +63397, +63396, +63365, +63366, +63399, +63398, +63367, +63424, +63457, +63456, +63425, +63426, +63459, +63458, +63427, +63428, +63461, +63460, +63429, +63430, +63463, +63462, +63431, +61448, +61481, +61480, +61449, +61450, +61483, +61482, +61451, +61452, +61485, +61484, +61453, +61454, +61487, +61486, +61455, +61512, +61545, +61544, +61513, +61514, +61547, +61546, +61515, +61516, +61549, +61548, +61517, +61518, +61551, +61550, +61519, +61576, +61609, +61608, +61577, +61578, +61611, +61610, +61579, +61580, +61613, +61612, +61581, +61582, +61615, +61614, +61583, +61640, +61673, +61672, +61641, +61642, +61675, +61674, +61643, +61644, +61677, +61676, +61645, +61646, +61679, +61678, +61647, +61704, +61737, +61736, +61705, +61706, +61739, +61738, +61707, +61708, +61741, +61740, +61709, +61710, +61743, +61742, +61711, +61768, +61801, +61800, +61769, +61770, +61803, +61802, +61771, +61772, +61805, +61804, +61773, +61774, +61807, +61806, +61775, +61832, +61865, +61864, +61833, +61834, +61867, +61866, +61835, +61836, +61869, +61868, +61837, +61838, +61871, +61870, +61839, +61896, +61929, +61928, +61897, +61898, +61931, +61930, +61899, +61900, +61933, +61932, +61901, +61902, +61935, +61934, +61903, +61960, +61993, +61992, +61961, +61962, +61995, +61994, +61963, +61964, +61997, +61996, +61965, +61966, +61999, +61998, +61967, +62024, +62057, +62056, +62025, +62026, +62059, +62058, +62027, +62028, +62061, +62060, +62029, +62030, +62063, +62062, +62031, +62088, +62121, +62120, +62089, +62090, +62123, +62122, +62091, +62092, +62125, +62124, +62093, +62094, +62127, +62126, +62095, +62152, +62185, +62184, +62153, +62154, +62187, +62186, +62155, +62156, +62189, +62188, +62157, +62158, +62191, +62190, +62159, +62216, +62249, +62248, +62217, +62218, +62251, +62250, +62219, +62220, +62253, +62252, +62221, +62222, +62255, +62254, +62223, +62280, +62313, +62312, +62281, +62282, +62315, +62314, +62283, +62284, +62317, +62316, +62285, +62286, +62319, +62318, +62287, +62344, +62377, +62376, +62345, +62346, +62379, +62378, +62347, +62348, +62381, +62380, +62349, +62350, +62383, +62382, +62351, +62408, +62441, +62440, +62409, +62410, +62443, +62442, +62411, +62412, +62445, +62444, +62413, +62414, +62447, +62446, +62415, +62472, +62505, +62504, +62473, +62474, +62507, +62506, +62475, +62476, +62509, +62508, +62477, +62478, +62511, +62510, +62479, +62536, +62569, +62568, +62537, +62538, +62571, +62570, +62539, +62540, +62573, +62572, +62541, +62542, +62575, +62574, +62543, +62600, +62633, +62632, +62601, +62602, +62635, +62634, +62603, +62604, +62637, +62636, +62605, +62606, +62639, +62638, +62607, +62664, +62697, +62696, +62665, +62666, +62699, +62698, +62667, +62668, +62701, +62700, +62669, +62670, +62703, +62702, +62671, +62728, +62761, +62760, +62729, +62730, +62763, +62762, +62731, +62732, +62765, +62764, +62733, +62734, +62767, +62766, +62735, +62792, +62825, +62824, +62793, +62794, +62827, +62826, +62795, +62796, +62829, +62828, +62797, +62798, +62831, +62830, +62799, +62856, +62889, +62888, +62857, +62858, +62891, +62890, +62859, +62860, +62893, +62892, +62861, +62862, +62895, +62894, +62863, +62920, +62953, +62952, +62921, +62922, +62955, +62954, +62923, +62924, +62957, +62956, +62925, +62926, +62959, +62958, +62927, +62984, +63017, +63016, +62985, +62986, +63019, +63018, +62987, +62988, +63021, +63020, +62989, +62990, +63023, +63022, +62991, +63048, +63081, +63080, +63049, +63050, +63083, +63082, +63051, +63052, +63085, +63084, +63053, +63054, +63087, +63086, +63055, +63112, +63145, +63144, +63113, +63114, +63147, +63146, +63115, +63116, +63149, +63148, +63117, +63118, +63151, +63150, +63119, +63176, +63209, +63208, +63177, +63178, +63211, +63210, +63179, +63180, +63213, +63212, +63181, +63182, +63215, +63214, +63183, +63240, +63273, +63272, +63241, +63242, +63275, +63274, +63243, +63244, +63277, +63276, +63245, +63246, +63279, +63278, +63247, +63304, +63337, +63336, +63305, +63306, +63339, +63338, +63307, +63308, +63341, +63340, +63309, +63310, +63343, +63342, +63311, +63368, +63401, +63400, +63369, +63370, +63403, +63402, +63371, +63372, +63405, +63404, +63373, +63374, +63407, +63406, +63375, +63432, +63465, +63464, +63433, +63434, +63467, +63466, +63435, +63436, +63469, +63468, +63437, +63438, +63471, +63470, +63439, +61456, +61489, +61488, +61457, +61458, +61491, +61490, +61459, +61460, +61493, +61492, +61461, +61462, +61495, +61494, +61463, +61520, +61553, +61552, +61521, +61522, +61555, +61554, +61523, +61524, +61557, +61556, +61525, +61526, +61559, +61558, +61527, +61584, +61617, +61616, +61585, +61586, +61619, +61618, +61587, +61588, +61621, +61620, +61589, +61590, +61623, +61622, +61591, +61648, +61681, +61680, +61649, +61650, +61683, +61682, +61651, +61652, +61685, +61684, +61653, +61654, +61687, +61686, +61655, +61712, +61745, +61744, +61713, +61714, +61747, +61746, +61715, +61716, +61749, +61748, +61717, +61718, +61751, +61750, +61719, +61776, +61809, +61808, +61777, +61778, +61811, +61810, +61779, +61780, +61813, +61812, +61781, +61782, +61815, +61814, +61783, +61840, +61873, +61872, +61841, +61842, +61875, +61874, +61843, +61844, +61877, +61876, +61845, +61846, +61879, +61878, +61847, +61904, +61937, +61936, +61905, +61906, +61939, +61938, +61907, +61908, +61941, +61940, +61909, +61910, +61943, +61942, +61911, +61968, +62001, +62000, +61969, +61970, +62003, +62002, +61971, +61972, +62005, +62004, +61973, +61974, +62007, +62006, +61975, +62032, +62065, +62064, +62033, +62034, +62067, +62066, +62035, +62036, +62069, +62068, +62037, +62038, +62071, +62070, +62039, +62096, +62129, +62128, +62097, +62098, +62131, +62130, +62099, +62100, +62133, +62132, +62101, +62102, +62135, +62134, +62103, +62160, +62193, +62192, +62161, +62162, +62195, +62194, +62163, +62164, +62197, +62196, +62165, +62166, +62199, +62198, +62167, +62224, +62257, +62256, +62225, +62226, +62259, +62258, +62227, +62228, +62261, +62260, +62229, +62230, +62263, +62262, +62231, +62288, +62321, +62320, +62289, +62290, +62323, +62322, +62291, +62292, +62325, +62324, +62293, +62294, +62327, +62326, +62295, +62352, +62385, +62384, +62353, +62354, +62387, +62386, +62355, +62356, +62389, +62388, +62357, +62358, +62391, +62390, +62359, +62416, +62449, +62448, +62417, +62418, +62451, +62450, +62419, +62420, +62453, +62452, +62421, +62422, +62455, +62454, +62423, +62480, +62513, +62512, +62481, +62482, +62515, +62514, +62483, +62484, +62517, +62516, +62485, +62486, +62519, +62518, +62487, +62544, +62577, +62576, +62545, +62546, +62579, +62578, +62547, +62548, +62581, +62580, +62549, +62550, +62583, +62582, +62551, +62608, +62641, +62640, +62609, +62610, +62643, +62642, +62611, +62612, +62645, +62644, +62613, +62614, +62647, +62646, +62615, +62672, +62705, +62704, +62673, +62674, +62707, +62706, +62675, +62676, +62709, +62708, +62677, +62678, +62711, +62710, +62679, +62736, +62769, +62768, +62737, +62738, +62771, +62770, +62739, +62740, +62773, +62772, +62741, +62742, +62775, +62774, +62743, +62800, +62833, +62832, +62801, +62802, +62835, +62834, +62803, +62804, +62837, +62836, +62805, +62806, +62839, +62838, +62807, +62864, +62897, +62896, +62865, +62866, +62899, +62898, +62867, +62868, +62901, +62900, +62869, +62870, +62903, +62902, +62871, +62928, +62961, +62960, +62929, +62930, +62963, +62962, +62931, +62932, +62965, +62964, +62933, +62934, +62967, +62966, +62935, +62992, +63025, +63024, +62993, +62994, +63027, +63026, +62995, +62996, +63029, +63028, +62997, +62998, +63031, +63030, +62999, +63056, +63089, +63088, +63057, +63058, +63091, +63090, +63059, +63060, +63093, +63092, +63061, +63062, +63095, +63094, +63063, +63120, +63153, +63152, +63121, +63122, +63155, +63154, +63123, +63124, +63157, +63156, +63125, +63126, +63159, +63158, +63127, +63184, +63217, +63216, +63185, +63186, +63219, +63218, +63187, +63188, +63221, +63220, +63189, +63190, +63223, +63222, +63191, +63248, +63281, +63280, +63249, +63250, +63283, +63282, +63251, +63252, +63285, +63284, +63253, +63254, +63287, +63286, +63255, +63312, +63345, +63344, +63313, +63314, +63347, +63346, +63315, +63316, +63349, +63348, +63317, +63318, +63351, +63350, +63319, +63376, +63409, +63408, +63377, +63378, +63411, +63410, +63379, +63380, +63413, +63412, +63381, +63382, +63415, +63414, +63383, +63440, +63473, +63472, +63441, +63442, +63475, +63474, +63443, +63444, +63477, +63476, +63445, +63446, +63479, +63478, +63447, +61464, +61497, +61496, +61465, +61466, +61499, +61498, +61467, +61468, +61501, +61500, +61469, +61470, +61503, +61502, +61471, +61528, +61561, +61560, +61529, +61530, +61563, +61562, +61531, +61532, +61565, +61564, +61533, +61534, +61567, +61566, +61535, +61592, +61625, +61624, +61593, +61594, +61627, +61626, +61595, +61596, +61629, +61628, +61597, +61598, +61631, +61630, +61599, +61656, +61689, +61688, +61657, +61658, +61691, +61690, +61659, +61660, +61693, +61692, +61661, +61662, +61695, +61694, +61663, +61720, +61753, +61752, +61721, +61722, +61755, +61754, +61723, +61724, +61757, +61756, +61725, +61726, +61759, +61758, +61727, +61784, +61817, +61816, +61785, +61786, +61819, +61818, +61787, +61788, +61821, +61820, +61789, +61790, +61823, +61822, +61791, +61848, +61881, +61880, +61849, +61850, +61883, +61882, +61851, +61852, +61885, +61884, +61853, +61854, +61887, +61886, +61855, +61912, +61945, +61944, +61913, +61914, +61947, +61946, +61915, +61916, +61949, +61948, +61917, +61918, +61951, +61950, +61919, +61976, +62009, +62008, +61977, +61978, +62011, +62010, +61979, +61980, +62013, +62012, +61981, +61982, +62015, +62014, +61983, +62040, +62073, +62072, +62041, +62042, +62075, +62074, +62043, +62044, +62077, +62076, +62045, +62046, +62079, +62078, +62047, +62104, +62137, +62136, +62105, +62106, +62139, +62138, +62107, +62108, +62141, +62140, +62109, +62110, +62143, +62142, +62111, +62168, +62201, +62200, +62169, +62170, +62203, +62202, +62171, +62172, +62205, +62204, +62173, +62174, +62207, +62206, +62175, +62232, +62265, +62264, +62233, +62234, +62267, +62266, +62235, +62236, +62269, +62268, +62237, +62238, +62271, +62270, +62239, +62296, +62329, +62328, +62297, +62298, +62331, +62330, +62299, +62300, +62333, +62332, +62301, +62302, +62335, +62334, +62303, +62360, +62393, +62392, +62361, +62362, +62395, +62394, +62363, +62364, +62397, +62396, +62365, +62366, +62399, +62398, +62367, +62424, +62457, +62456, +62425, +62426, +62459, +62458, +62427, +62428, +62461, +62460, +62429, +62430, +62463, +62462, +62431, +62488, +62521, +62520, +62489, +62490, +62523, +62522, +62491, +62492, +62525, +62524, +62493, +62494, +62527, +62526, +62495, +62552, +62585, +62584, +62553, +62554, +62587, +62586, +62555, +62556, +62589, +62588, +62557, +62558, +62591, +62590, +62559, +62616, +62649, +62648, +62617, +62618, +62651, +62650, +62619, +62620, +62653, +62652, +62621, +62622, +62655, +62654, +62623, +62680, +62713, +62712, +62681, +62682, +62715, +62714, +62683, +62684, +62717, +62716, +62685, +62686, +62719, +62718, +62687, +62744, +62777, +62776, +62745, +62746, +62779, +62778, +62747, +62748, +62781, +62780, +62749, +62750, +62783, +62782, +62751, +62808, +62841, +62840, +62809, +62810, +62843, +62842, +62811, +62812, +62845, +62844, +62813, +62814, +62847, +62846, +62815, +62872, +62905, +62904, +62873, +62874, +62907, +62906, +62875, +62876, +62909, +62908, +62877, +62878, +62911, +62910, +62879, +62936, +62969, +62968, +62937, +62938, +62971, +62970, +62939, +62940, +62973, +62972, +62941, +62942, +62975, +62974, +62943, +63000, +63033, +63032, +63001, +63002, +63035, +63034, +63003, +63004, +63037, +63036, +63005, +63006, +63039, +63038, +63007, +63064, +63097, +63096, +63065, +63066, +63099, +63098, +63067, +63068, +63101, +63100, +63069, +63070, +63103, +63102, +63071, +63128, +63161, +63160, +63129, +63130, +63163, +63162, +63131, +63132, +63165, +63164, +63133, +63134, +63167, +63166, +63135, +63192, +63225, +63224, +63193, +63194, +63227, +63226, +63195, +63196, +63229, +63228, +63197, +63198, +63231, +63230, +63199, +63256, +63289, +63288, +63257, +63258, +63291, +63290, +63259, +63260, +63293, +63292, +63261, +63262, +63295, +63294, +63263, +63320, +63353, +63352, +63321, +63322, +63355, +63354, +63323, +63324, +63357, +63356, +63325, +63326, +63359, +63358, +63327, +63384, +63417, +63416, +63385, +63386, +63419, +63418, +63387, +63388, +63421, +63420, +63389, +63390, +63423, +63422, +63391, +63448, +63481, +63480, +63449, +63450, +63483, +63482, +63451, +63452, +63485, +63484, +63453, +63454, +63487, +63486, +63455, +63488, +63521, +63520, +63489, +63490, +63523, +63522, +63491, +63492, +63525, +63524, +63493, +63494, +63527, +63526, +63495, +63552, +63585, +63584, +63553, +63554, +63587, +63586, +63555, +63556, +63589, +63588, +63557, +63558, +63591, +63590, +63559, +63616, +63649, +63648, +63617, +63618, +63651, +63650, +63619, +63620, +63653, +63652, +63621, +63622, +63655, +63654, +63623, +63680, +63713, +63712, +63681, +63682, +63715, +63714, +63683, +63684, +63717, +63716, +63685, +63686, +63719, +63718, +63687, +63744, +63777, +63776, +63745, +63746, +63779, +63778, +63747, +63748, +63781, +63780, +63749, +63750, +63783, +63782, +63751, +63808, +63841, +63840, +63809, +63810, +63843, +63842, +63811, +63812, +63845, +63844, +63813, +63814, +63847, +63846, +63815, +63872, +63905, +63904, +63873, +63874, +63907, +63906, +63875, +63876, +63909, +63908, +63877, +63878, +63911, +63910, +63879, +63936, +63969, +63968, +63937, +63938, +63971, +63970, +63939, +63940, +63973, +63972, +63941, +63942, +63975, +63974, +63943, +64000, +64033, +64032, +64001, +64002, +64035, +64034, +64003, +64004, +64037, +64036, +64005, +64006, +64039, +64038, +64007, +64064, +64097, +64096, +64065, +64066, +64099, +64098, +64067, +64068, +64101, +64100, +64069, +64070, +64103, +64102, +64071, +64128, +64161, +64160, +64129, +64130, +64163, +64162, +64131, +64132, +64165, +64164, +64133, +64134, +64167, +64166, +64135, +64192, +64225, +64224, +64193, +64194, +64227, +64226, +64195, +64196, +64229, +64228, +64197, +64198, +64231, +64230, +64199, +64256, +64289, +64288, +64257, +64258, +64291, +64290, +64259, +64260, +64293, +64292, +64261, +64262, +64295, +64294, +64263, +64320, +64353, +64352, +64321, +64322, +64355, +64354, +64323, +64324, +64357, +64356, +64325, +64326, +64359, +64358, +64327, +64384, +64417, +64416, +64385, +64386, +64419, +64418, +64387, +64388, +64421, +64420, +64389, +64390, +64423, +64422, +64391, +64448, +64481, +64480, +64449, +64450, +64483, +64482, +64451, +64452, +64485, +64484, +64453, +64454, +64487, +64486, +64455, +64512, +64545, +64544, +64513, +64514, +64547, +64546, +64515, +64516, +64549, +64548, +64517, +64518, +64551, +64550, +64519, +64576, +64609, +64608, +64577, +64578, +64611, +64610, +64579, +64580, +64613, +64612, +64581, +64582, +64615, +64614, +64583, +64640, +64673, +64672, +64641, +64642, +64675, +64674, +64643, +64644, +64677, +64676, +64645, +64646, +64679, +64678, +64647, +64704, +64737, +64736, +64705, +64706, +64739, +64738, +64707, +64708, +64741, +64740, +64709, +64710, +64743, +64742, +64711, +64768, +64801, +64800, +64769, +64770, +64803, +64802, +64771, +64772, +64805, +64804, +64773, +64774, +64807, +64806, +64775, +64832, +64865, +64864, +64833, +64834, +64867, +64866, +64835, +64836, +64869, +64868, +64837, +64838, +64871, +64870, +64839, +64896, +64929, +64928, +64897, +64898, +64931, +64930, +64899, +64900, +64933, +64932, +64901, +64902, +64935, +64934, +64903, +64960, +64993, +64992, +64961, +64962, +64995, +64994, +64963, +64964, +64997, +64996, +64965, +64966, +64999, +64998, +64967, +65024, +65057, +65056, +65025, +65026, +65059, +65058, +65027, +65028, +65061, +65060, +65029, +65030, +65063, +65062, +65031, +65088, +65121, +65120, +65089, +65090, +65123, +65122, +65091, +65092, +65125, +65124, +65093, +65094, +65127, +65126, +65095, +65152, +65185, +65184, +65153, +65154, +65187, +65186, +65155, +65156, +65189, +65188, +65157, +65158, +65191, +65190, +65159, +65216, +65249, +65248, +65217, +65218, +65251, +65250, +65219, +65220, +65253, +65252, +65221, +65222, +65255, +65254, +65223, +65280, +65313, +65312, +65281, +65282, +65315, +65314, +65283, +65284, +65317, +65316, +65285, +65286, +65319, +65318, +65287, +65344, +65377, +65376, +65345, +65346, +65379, +65378, +65347, +65348, +65381, +65380, +65349, +65350, +65383, +65382, +65351, +65408, +65441, +65440, +65409, +65410, +65443, +65442, +65411, +65412, +65445, +65444, +65413, +65414, +65447, +65446, +65415, +65472, +65505, +65504, +65473, +65474, +65507, +65506, +65475, +65476, +65509, +65508, +65477, +65478, +65511, +65510, +65479, +63496, +63529, +63528, +63497, +63498, +63531, +63530, +63499, +63500, +63533, +63532, +63501, +63502, +63535, +63534, +63503, +63560, +63593, +63592, +63561, +63562, +63595, +63594, +63563, +63564, +63597, +63596, +63565, +63566, +63599, +63598, +63567, +63624, +63657, +63656, +63625, +63626, +63659, +63658, +63627, +63628, +63661, +63660, +63629, +63630, +63663, +63662, +63631, +63688, +63721, +63720, +63689, +63690, +63723, +63722, +63691, +63692, +63725, +63724, +63693, +63694, +63727, +63726, +63695, +63752, +63785, +63784, +63753, +63754, +63787, +63786, +63755, +63756, +63789, +63788, +63757, +63758, +63791, +63790, +63759, +63816, +63849, +63848, +63817, +63818, +63851, +63850, +63819, +63820, +63853, +63852, +63821, +63822, +63855, +63854, +63823, +63880, +63913, +63912, +63881, +63882, +63915, +63914, +63883, +63884, +63917, +63916, +63885, +63886, +63919, +63918, +63887, +63944, +63977, +63976, +63945, +63946, +63979, +63978, +63947, +63948, +63981, +63980, +63949, +63950, +63983, +63982, +63951, +64008, +64041, +64040, +64009, +64010, +64043, +64042, +64011, +64012, +64045, +64044, +64013, +64014, +64047, +64046, +64015, +64072, +64105, +64104, +64073, +64074, +64107, +64106, +64075, +64076, +64109, +64108, +64077, +64078, +64111, +64110, +64079, +64136, +64169, +64168, +64137, +64138, +64171, +64170, +64139, +64140, +64173, +64172, +64141, +64142, +64175, +64174, +64143, +64200, +64233, +64232, +64201, +64202, +64235, +64234, +64203, +64204, +64237, +64236, +64205, +64206, +64239, +64238, +64207, +64264, +64297, +64296, +64265, +64266, +64299, +64298, +64267, +64268, +64301, +64300, +64269, +64270, +64303, +64302, +64271, +64328, +64361, +64360, +64329, +64330, +64363, +64362, +64331, +64332, +64365, +64364, +64333, +64334, +64367, +64366, +64335, +64392, +64425, +64424, +64393, +64394, +64427, +64426, +64395, +64396, +64429, +64428, +64397, +64398, +64431, +64430, +64399, +64456, +64489, +64488, +64457, +64458, +64491, +64490, +64459, +64460, +64493, +64492, +64461, +64462, +64495, +64494, +64463, +64520, +64553, +64552, +64521, +64522, +64555, +64554, +64523, +64524, +64557, +64556, +64525, +64526, +64559, +64558, +64527, +64584, +64617, +64616, +64585, +64586, +64619, +64618, +64587, +64588, +64621, +64620, +64589, +64590, +64623, +64622, +64591, +64648, +64681, +64680, +64649, +64650, +64683, +64682, +64651, +64652, +64685, +64684, +64653, +64654, +64687, +64686, +64655, +64712, +64745, +64744, +64713, +64714, +64747, +64746, +64715, +64716, +64749, +64748, +64717, +64718, +64751, +64750, +64719, +64776, +64809, +64808, +64777, +64778, +64811, +64810, +64779, +64780, +64813, +64812, +64781, +64782, +64815, +64814, +64783, +64840, +64873, +64872, +64841, +64842, +64875, +64874, +64843, +64844, +64877, +64876, +64845, +64846, +64879, +64878, +64847, +64904, +64937, +64936, +64905, +64906, +64939, +64938, +64907, +64908, +64941, +64940, +64909, +64910, +64943, +64942, +64911, +64968, +65001, +65000, +64969, +64970, +65003, +65002, +64971, +64972, +65005, +65004, +64973, +64974, +65007, +65006, +64975, +65032, +65065, +65064, +65033, +65034, +65067, +65066, +65035, +65036, +65069, +65068, +65037, +65038, +65071, +65070, +65039, +65096, +65129, +65128, +65097, +65098, +65131, +65130, +65099, +65100, +65133, +65132, +65101, +65102, +65135, +65134, +65103, +65160, +65193, +65192, +65161, +65162, +65195, +65194, +65163, +65164, +65197, +65196, +65165, +65166, +65199, +65198, +65167, +65224, +65257, +65256, +65225, +65226, +65259, +65258, +65227, +65228, +65261, +65260, +65229, +65230, +65263, +65262, +65231, +65288, +65321, +65320, +65289, +65290, +65323, +65322, +65291, +65292, +65325, +65324, +65293, +65294, +65327, +65326, +65295, +65352, +65385, +65384, +65353, +65354, +65387, +65386, +65355, +65356, +65389, +65388, +65357, +65358, +65391, +65390, +65359, +65416, +65449, +65448, +65417, +65418, +65451, +65450, +65419, +65420, +65453, +65452, +65421, +65422, +65455, +65454, +65423, +65480, +65513, +65512, +65481, +65482, +65515, +65514, +65483, +65484, +65517, +65516, +65485, +65486, +65519, +65518, +65487, +63504, +63537, +63536, +63505, +63506, +63539, +63538, +63507, +63508, +63541, +63540, +63509, +63510, +63543, +63542, +63511, +63568, +63601, +63600, +63569, +63570, +63603, +63602, +63571, +63572, +63605, +63604, +63573, +63574, +63607, +63606, +63575, +63632, +63665, +63664, +63633, +63634, +63667, +63666, +63635, +63636, +63669, +63668, +63637, +63638, +63671, +63670, +63639, +63696, +63729, +63728, +63697, +63698, +63731, +63730, +63699, +63700, +63733, +63732, +63701, +63702, +63735, +63734, +63703, +63760, +63793, +63792, +63761, +63762, +63795, +63794, +63763, +63764, +63797, +63796, +63765, +63766, +63799, +63798, +63767, +63824, +63857, +63856, +63825, +63826, +63859, +63858, +63827, +63828, +63861, +63860, +63829, +63830, +63863, +63862, +63831, +63888, +63921, +63920, +63889, +63890, +63923, +63922, +63891, +63892, +63925, +63924, +63893, +63894, +63927, +63926, +63895, +63952, +63985, +63984, +63953, +63954, +63987, +63986, +63955, +63956, +63989, +63988, +63957, +63958, +63991, +63990, +63959, +64016, +64049, +64048, +64017, +64018, +64051, +64050, +64019, +64020, +64053, +64052, +64021, +64022, +64055, +64054, +64023, +64080, +64113, +64112, +64081, +64082, +64115, +64114, +64083, +64084, +64117, +64116, +64085, +64086, +64119, +64118, +64087, +64144, +64177, +64176, +64145, +64146, +64179, +64178, +64147, +64148, +64181, +64180, +64149, +64150, +64183, +64182, +64151, +64208, +64241, +64240, +64209, +64210, +64243, +64242, +64211, +64212, +64245, +64244, +64213, +64214, +64247, +64246, +64215, +64272, +64305, +64304, +64273, +64274, +64307, +64306, +64275, +64276, +64309, +64308, +64277, +64278, +64311, +64310, +64279, +64336, +64369, +64368, +64337, +64338, +64371, +64370, +64339, +64340, +64373, +64372, +64341, +64342, +64375, +64374, +64343, +64400, +64433, +64432, +64401, +64402, +64435, +64434, +64403, +64404, +64437, +64436, +64405, +64406, +64439, +64438, +64407, +64464, +64497, +64496, +64465, +64466, +64499, +64498, +64467, +64468, +64501, +64500, +64469, +64470, +64503, +64502, +64471, +64528, +64561, +64560, +64529, +64530, +64563, +64562, +64531, +64532, +64565, +64564, +64533, +64534, +64567, +64566, +64535, +64592, +64625, +64624, +64593, +64594, +64627, +64626, +64595, +64596, +64629, +64628, +64597, +64598, +64631, +64630, +64599, +64656, +64689, +64688, +64657, +64658, +64691, +64690, +64659, +64660, +64693, +64692, +64661, +64662, +64695, +64694, +64663, +64720, +64753, +64752, +64721, +64722, +64755, +64754, +64723, +64724, +64757, +64756, +64725, +64726, +64759, +64758, +64727, +64784, +64817, +64816, +64785, +64786, +64819, +64818, +64787, +64788, +64821, +64820, +64789, +64790, +64823, +64822, +64791, +64848, +64881, +64880, +64849, +64850, +64883, +64882, +64851, +64852, +64885, +64884, +64853, +64854, +64887, +64886, +64855, +64912, +64945, +64944, +64913, +64914, +64947, +64946, +64915, +64916, +64949, +64948, +64917, +64918, +64951, +64950, +64919, +64976, +65009, +65008, +64977, +64978, +65011, +65010, +64979, +64980, +65013, +65012, +64981, +64982, +65015, +65014, +64983, +65040, +65073, +65072, +65041, +65042, +65075, +65074, +65043, +65044, +65077, +65076, +65045, +65046, +65079, +65078, +65047, +65104, +65137, +65136, +65105, +65106, +65139, +65138, +65107, +65108, +65141, +65140, +65109, +65110, +65143, +65142, +65111, +65168, +65201, +65200, +65169, +65170, +65203, +65202, +65171, +65172, +65205, +65204, +65173, +65174, +65207, +65206, +65175, +65232, +65265, +65264, +65233, +65234, +65267, +65266, +65235, +65236, +65269, +65268, +65237, +65238, +65271, +65270, +65239, +65296, +65329, +65328, +65297, +65298, +65331, +65330, +65299, +65300, +65333, +65332, +65301, +65302, +65335, +65334, +65303, +65360, +65393, +65392, +65361, +65362, +65395, +65394, +65363, +65364, +65397, +65396, +65365, +65366, +65399, +65398, +65367, +65424, +65457, +65456, +65425, +65426, +65459, +65458, +65427, +65428, +65461, +65460, +65429, +65430, +65463, +65462, +65431, +65488, +65521, +65520, +65489, +65490, +65523, +65522, +65491, +65492, +65525, +65524, +65493, +65494, +65527, +65526, +65495, +63512, +63545, +63544, +63513, +63514, +63547, +63546, +63515, +63516, +63549, +63548, +63517, +63518, +63551, +63550, +63519, +63576, +63609, +63608, +63577, +63578, +63611, +63610, +63579, +63580, +63613, +63612, +63581, +63582, +63615, +63614, +63583, +63640, +63673, +63672, +63641, +63642, +63675, +63674, +63643, +63644, +63677, +63676, +63645, +63646, +63679, +63678, +63647, +63704, +63737, +63736, +63705, +63706, +63739, +63738, +63707, +63708, +63741, +63740, +63709, +63710, +63743, +63742, +63711, +63768, +63801, +63800, +63769, +63770, +63803, +63802, +63771, +63772, +63805, +63804, +63773, +63774, +63807, +63806, +63775, +63832, +63865, +63864, +63833, +63834, +63867, +63866, +63835, +63836, +63869, +63868, +63837, +63838, +63871, +63870, +63839, +63896, +63929, +63928, +63897, +63898, +63931, +63930, +63899, +63900, +63933, +63932, +63901, +63902, +63935, +63934, +63903, +63960, +63993, +63992, +63961, +63962, +63995, +63994, +63963, +63964, +63997, +63996, +63965, +63966, +63999, +63998, +63967, +64024, +64057, +64056, +64025, +64026, +64059, +64058, +64027, +64028, +64061, +64060, +64029, +64030, +64063, +64062, +64031, +64088, +64121, +64120, +64089, +64090, +64123, +64122, +64091, +64092, +64125, +64124, +64093, +64094, +64127, +64126, +64095, +64152, +64185, +64184, +64153, +64154, +64187, +64186, +64155, +64156, +64189, +64188, +64157, +64158, +64191, +64190, +64159, +64216, +64249, +64248, +64217, +64218, +64251, +64250, +64219, +64220, +64253, +64252, +64221, +64222, +64255, +64254, +64223, +64280, +64313, +64312, +64281, +64282, +64315, +64314, +64283, +64284, +64317, +64316, +64285, +64286, +64319, +64318, +64287, +64344, +64377, +64376, +64345, +64346, +64379, +64378, +64347, +64348, +64381, +64380, +64349, +64350, +64383, +64382, +64351, +64408, +64441, +64440, +64409, +64410, +64443, +64442, +64411, +64412, +64445, +64444, +64413, +64414, +64447, +64446, +64415, +64472, +64505, +64504, +64473, +64474, +64507, +64506, +64475, +64476, +64509, +64508, +64477, +64478, +64511, +64510, +64479, +64536, +64569, +64568, +64537, +64538, +64571, +64570, +64539, +64540, +64573, +64572, +64541, +64542, +64575, +64574, +64543, +64600, +64633, +64632, +64601, +64602, +64635, +64634, +64603, +64604, +64637, +64636, +64605, +64606, +64639, +64638, +64607, +64664, +64697, +64696, +64665, +64666, +64699, +64698, +64667, +64668, +64701, +64700, +64669, +64670, +64703, +64702, +64671, +64728, +64761, +64760, +64729, +64730, +64763, +64762, +64731, +64732, +64765, +64764, +64733, +64734, +64767, +64766, +64735, +64792, +64825, +64824, +64793, +64794, +64827, +64826, +64795, +64796, +64829, +64828, +64797, +64798, +64831, +64830, +64799, +64856, +64889, +64888, +64857, +64858, +64891, +64890, +64859, +64860, +64893, +64892, +64861, +64862, +64895, +64894, +64863, +64920, +64953, +64952, +64921, +64922, +64955, +64954, +64923, +64924, +64957, +64956, +64925, +64926, +64959, +64958, +64927, +64984, +65017, +65016, +64985, +64986, +65019, +65018, +64987, +64988, +65021, +65020, +64989, +64990, +65023, +65022, +64991, +65048, +65081, +65080, +65049, +65050, +65083, +65082, +65051, +65052, +65085, +65084, +65053, +65054, +65087, +65086, +65055, +65112, +65145, +65144, +65113, +65114, +65147, +65146, +65115, +65116, +65149, +65148, +65117, +65118, +65151, +65150, +65119, +65176, +65209, +65208, +65177, +65178, +65211, +65210, +65179, +65180, +65213, +65212, +65181, +65182, +65215, +65214, +65183, +65240, +65273, +65272, +65241, +65242, +65275, +65274, +65243, +65244, +65277, +65276, +65245, +65246, +65279, +65278, +65247, +65304, +65337, +65336, +65305, +65306, +65339, +65338, +65307, +65308, +65341, +65340, +65309, +65310, +65343, +65342, +65311, +65368, +65401, +65400, +65369, +65370, +65403, +65402, +65371, +65372, +65405, +65404, +65373, +65374, +65407, +65406, +65375, +65432, +65465, +65464, +65433, +65434, +65467, +65466, +65435, +65436, +65469, +65468, +65437, +65438, +65471, +65470, +65439, +65496, +65529, +65528, +65497, +65498, +65531, +65530, +65499, +65500, +65533, +65532, +65501, +65502, +65535, +65534, +65503, diff --git a/source/wii/gx/anorm_dots.h b/source/wii/gx/anorm_dots.h new file mode 100644 index 0000000..2845fa2 --- /dev/null +++ b/source/wii/gx/anorm_dots.h @@ -0,0 +1,37 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +{ +{1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.34,1.27,1.53,1.17,1.46,1.71,0.98,1.05,1.20,1.34,1.48,1.86,1.82,1.71,1.62,1.09,0.94,0.99,0.79,0.85,0.82,0.90,0.87,0.93,0.96,0.76,0.74,0.79,0.76,0.74,0.79,0.78,0.85,0.92,0.85,1.00,0.93,1.06,0.81,0.86,0.89,1.16,1.12,0.97,0.95,1.28,1.38,1.35,1.60,1.77,1.57,1.33,1.50,1.58,1.69,1.63,1.82,1.74,1.91,1.92,1.80,1.04,0.97,1.21,0.90,0.93,0.97,1.05,1.21,1.48,1.37,0.77,0.80,0.84,0.85,0.88,0.92,0.73,0.71,0.74,0.74,0.71,0.75,0.73,0.79,0.84,0.78,0.79,0.86,0.81,1.05,0.94,0.99,0.90,0.95,0.92,0.86,1.24,1.44,1.14,1.59,1.34,1.02,1.27,1.50,1.49,1.80,1.69,1.86,1.72,1.87,1.80,1.69,1.00,0.98,1.23,0.95,0.96,1.09,1.16,1.37,1.63,1.46,0.99,1.10,1.25,1.24,1.51,1.41,1.67,1.77,1.55,1.72,1.95,1.89,1.98,1.91,1.86,1.97,1.99,1.94,0.81,0.89,0.85,0.98,0.90,0.94,0.75,0.78,0.73,0.89,0.83,0.82,0.72,0.77,0.76,0.72,0.70,0.71,0.91,0.83,0.89,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.46,1.34,1.60,1.16,1.46,1.71,0.94,0.99,1.05,1.26,1.33,1.74,1.76,1.57,1.54,1.23,0.98,1.05,0.83,0.89,0.84,0.92,0.87,0.91,0.96,0.78,0.74,0.79,0.72,0.72,0.75,0.76,0.80,0.88,0.83,0.94,0.87,0.95,0.76,0.80,0.82,0.97,0.96,0.89,0.88,1.08,1.11,1.10,1.37,1.59,1.37,1.07,1.27,1.34,1.57,1.45,1.69,1.55,1.77,1.79,1.60,0.93,0.90,0.99,0.86,0.87,0.93,0.96,1.07,1.35,1.18,0.73,0.76,0.77,0.81,0.82,0.85,0.70,0.71,0.72,0.78,0.73,0.77,0.73,0.79,0.82,0.76,0.83,0.90,0.84,1.18,0.98,1.03,0.92,0.95,0.90,0.86,1.32,1.45,1.15,1.53,1.27,0.99,1.42,1.65,1.58,1.93,1.83,1.94,1.81,1.88,1.74,1.70,1.19,1.17,1.44,1.11,1.15,1.36,1.41,1.61,1.81,1.67,1.22,1.34,1.50,1.42,1.65,1.61,1.82,1.91,1.75,1.80,1.89,1.89,1.98,1.99,1.94,1.98,1.92,1.87,0.86,0.95,0.92,1.14,0.98,1.03,0.79,0.84,0.77,0.97,0.90,0.89,0.76,0.82,0.82,0.74,0.72,0.71,0.98,0.89,0.97,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.60,1.44,1.68,1.22,1.49,1.71,0.93,0.99,0.99,1.23,1.22,1.60,1.68,1.44,1.49,1.40,1.14,1.19,0.89,0.96,0.89,0.97,0.89,0.91,0.98,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.91,0.83,0.89,0.72,0.76,0.76,0.89,0.89,0.82,0.82,0.98,0.96,0.97,1.14,1.40,1.19,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.70,0.72,0.73,0.77,0.76,0.79,0.70,0.72,0.71,0.82,0.77,0.80,0.74,0.79,0.80,0.74,0.87,0.93,0.85,1.23,1.02,1.02,0.93,0.93,0.87,0.85,1.30,1.35,1.07,1.38,1.11,0.94,1.47,1.71,1.56,1.97,1.88,1.92,1.79,1.79,1.59,1.60,1.30,1.35,1.56,1.37,1.38,1.59,1.60,1.79,1.92,1.79,1.48,1.57,1.72,1.61,1.78,1.79,1.93,1.99,1.90,1.86,1.78,1.86,1.93,1.99,1.97,1.90,1.79,1.72,0.94,1.07,1.00,1.37,1.21,1.30,0.86,0.91,0.83,1.14,0.98,0.96,0.82,0.88,0.89,0.79,0.76,0.73,1.07,0.94,1.11,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.74,1.57,1.76,1.33,1.54,1.71,0.94,1.05,0.99,1.26,1.16,1.46,1.60,1.34,1.46,1.59,1.37,1.37,0.97,1.11,0.96,1.10,0.95,0.94,1.08,0.89,0.82,0.88,0.72,0.76,0.75,0.80,0.80,0.88,0.87,0.91,0.83,0.87,0.72,0.76,0.74,0.83,0.84,0.78,0.79,0.96,0.89,0.92,0.98,1.23,1.05,0.86,0.92,0.95,1.11,0.98,1.22,1.03,1.34,1.42,1.14,0.79,0.77,0.84,0.78,0.76,0.82,0.82,0.89,0.97,0.90,0.70,0.71,0.71,0.73,0.72,0.74,0.73,0.76,0.72,0.86,0.81,0.82,0.76,0.79,0.77,0.73,0.90,0.95,0.86,1.18,1.03,0.98,0.92,0.90,0.83,0.84,1.19,1.17,0.98,1.15,0.97,0.89,1.42,1.65,1.44,1.93,1.83,1.81,1.67,1.61,1.36,1.41,1.32,1.45,1.58,1.57,1.53,1.74,1.70,1.88,1.94,1.81,1.69,1.77,1.87,1.79,1.89,1.92,1.98,1.99,1.98,1.89,1.65,1.80,1.82,1.91,1.94,1.75,1.61,1.50,1.07,1.34,1.27,1.60,1.45,1.55,0.93,0.99,0.90,1.35,1.18,1.07,0.87,0.93,0.96,0.85,0.82,0.77,1.15,0.99,1.27,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.86,1.71,1.82,1.48,1.62,1.71,0.98,1.20,1.05,1.34,1.17,1.34,1.53,1.27,1.46,1.77,1.60,1.57,1.16,1.38,1.12,1.35,1.06,1.00,1.28,0.97,0.89,0.95,0.76,0.81,0.79,0.86,0.85,0.92,0.93,0.93,0.85,0.87,0.74,0.78,0.74,0.79,0.82,0.76,0.79,0.96,0.85,0.90,0.94,1.09,0.99,0.81,0.85,0.89,0.95,0.90,0.99,0.94,1.10,1.24,0.98,0.75,0.73,0.78,0.74,0.72,0.77,0.76,0.82,0.89,0.83,0.73,0.71,0.71,0.71,0.70,0.72,0.77,0.80,0.74,0.90,0.85,0.84,0.78,0.79,0.75,0.73,0.92,0.95,0.86,1.05,0.99,0.94,0.90,0.86,0.79,0.81,1.00,0.98,0.91,0.96,0.89,0.83,1.27,1.50,1.23,1.80,1.69,1.63,1.46,1.37,1.09,1.16,1.24,1.44,1.49,1.69,1.59,1.80,1.69,1.87,1.86,1.72,1.82,1.91,1.94,1.92,1.95,1.99,1.98,1.91,1.97,1.89,1.51,1.72,1.67,1.77,1.86,1.55,1.41,1.25,1.33,1.58,1.50,1.80,1.63,1.74,1.04,1.21,0.97,1.48,1.37,1.21,0.93,0.97,1.05,0.92,0.88,0.84,1.14,1.02,1.34,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.94,1.84,1.87,1.64,1.71,1.71,1.14,1.38,1.19,1.46,1.23,1.26,1.48,1.26,1.50,1.91,1.80,1.76,1.41,1.61,1.39,1.59,1.33,1.24,1.51,1.18,0.97,1.11,0.82,0.88,0.86,0.94,0.92,0.99,1.03,0.98,0.91,0.90,0.79,0.84,0.77,0.79,0.84,0.77,0.83,0.99,0.85,0.91,0.92,1.02,1.00,0.79,0.80,0.86,0.88,0.84,0.92,0.88,0.97,1.10,0.94,0.74,0.71,0.74,0.72,0.70,0.73,0.72,0.76,0.82,0.77,0.77,0.73,0.74,0.71,0.70,0.73,0.83,0.85,0.78,0.92,0.88,0.86,0.81,0.79,0.74,0.75,0.92,0.93,0.85,0.96,0.94,0.88,0.86,0.81,0.75,0.79,0.93,0.90,0.85,0.88,0.82,0.77,1.05,1.27,0.99,1.60,1.47,1.39,1.20,1.11,0.95,0.97,1.08,1.33,1.31,1.70,1.55,1.76,1.57,1.76,1.70,1.54,1.85,1.97,1.91,1.99,1.97,1.99,1.91,1.77,1.88,1.85,1.39,1.64,1.51,1.58,1.74,1.32,1.22,1.01,1.54,1.76,1.65,1.93,1.70,1.85,1.28,1.39,1.09,1.52,1.48,1.26,0.97,0.99,1.18,1.00,0.93,0.90,1.05,1.01,1.31,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.97,1.92,1.88,1.79,1.79,1.71,1.37,1.59,1.38,1.60,1.35,1.23,1.47,1.30,1.56,1.99,1.93,1.90,1.60,1.78,1.61,1.79,1.57,1.48,1.72,1.40,1.14,1.37,0.89,0.96,0.94,1.07,1.00,1.21,1.30,1.14,0.98,0.96,0.86,0.91,0.83,0.82,0.88,0.82,0.89,1.11,0.87,0.94,0.93,1.02,1.07,0.80,0.79,0.85,0.82,0.80,0.87,0.85,0.93,1.02,0.93,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.82,0.76,0.79,0.72,0.73,0.76,0.89,0.89,0.82,0.93,0.91,0.86,0.83,0.79,0.73,0.76,0.91,0.89,0.83,0.89,0.89,0.82,0.82,0.76,0.72,0.76,0.86,0.83,0.79,0.82,0.76,0.73,0.94,1.00,0.91,1.37,1.21,1.14,0.98,0.96,0.88,0.89,0.96,1.14,1.07,1.60,1.40,1.61,1.37,1.57,1.48,1.30,1.78,1.93,1.79,1.99,1.92,1.90,1.79,1.59,1.72,1.79,1.30,1.56,1.35,1.38,1.60,1.11,1.07,0.94,1.68,1.86,1.71,1.97,1.68,1.86,1.44,1.49,1.22,1.44,1.49,1.22,0.99,0.99,1.23,1.19,0.98,0.97,0.97,0.98,1.19,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.94,1.97,1.87,1.91,1.85,1.71,1.60,1.77,1.58,1.74,1.51,1.26,1.48,1.39,1.64,1.99,1.97,1.99,1.70,1.85,1.76,1.91,1.76,1.70,1.88,1.55,1.33,1.57,0.96,1.08,1.05,1.31,1.27,1.47,1.54,1.39,1.20,1.11,0.93,0.99,0.90,0.88,0.95,0.88,0.97,1.32,0.92,1.01,0.97,1.10,1.22,0.84,0.80,0.88,0.79,0.79,0.85,0.86,0.92,1.02,0.94,0.82,0.76,0.77,0.72,0.73,0.70,0.72,0.71,0.74,0.74,0.88,0.81,0.85,0.75,0.77,0.82,0.94,0.93,0.86,0.92,0.92,0.86,0.85,0.79,0.74,0.79,0.88,0.85,0.81,0.82,0.83,0.77,0.78,0.73,0.71,0.75,0.79,0.77,0.74,0.77,0.73,0.70,0.86,0.92,0.84,1.14,0.99,0.98,0.91,0.90,0.84,0.83,0.88,0.97,0.94,1.41,1.18,1.39,1.11,1.33,1.24,1.03,1.61,1.80,1.59,1.91,1.84,1.76,1.64,1.38,1.51,1.71,1.26,1.50,1.23,1.19,1.46,0.99,1.00,0.91,1.70,1.85,1.65,1.93,1.54,1.76,1.52,1.48,1.26,1.28,1.39,1.09,0.99,0.97,1.18,1.31,1.01,1.05,0.90,0.93,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.86,1.95,1.82,1.98,1.89,1.71,1.80,1.91,1.77,1.86,1.67,1.34,1.53,1.51,1.72,1.92,1.91,1.99,1.69,1.82,1.80,1.94,1.87,1.86,1.97,1.59,1.44,1.69,1.05,1.24,1.27,1.49,1.50,1.69,1.72,1.63,1.46,1.37,1.00,1.23,0.98,0.95,1.09,0.96,1.16,1.55,0.99,1.25,1.10,1.24,1.41,0.90,0.85,0.94,0.79,0.81,0.85,0.89,0.94,1.09,0.98,0.89,0.82,0.83,0.74,0.77,0.72,0.76,0.73,0.75,0.78,0.94,0.86,0.91,0.79,0.83,0.89,0.99,0.95,0.90,0.90,0.92,0.84,0.86,0.79,0.75,0.81,0.85,0.80,0.78,0.76,0.77,0.73,0.74,0.71,0.71,0.73,0.74,0.74,0.71,0.76,0.72,0.70,0.79,0.85,0.78,0.98,0.92,0.93,0.85,0.87,0.82,0.79,0.81,0.89,0.86,1.16,0.97,1.12,0.95,1.06,1.00,0.93,1.38,1.60,1.35,1.77,1.71,1.57,1.48,1.20,1.28,1.62,1.27,1.46,1.17,1.05,1.34,0.96,0.99,0.90,1.63,1.74,1.50,1.80,1.33,1.58,1.48,1.37,1.21,1.04,1.21,0.97,0.97,0.93,1.05,1.34,1.02,1.14,0.84,0.88,0.92,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.74,1.89,1.76,1.98,1.89,1.71,1.93,1.99,1.91,1.94,1.82,1.46,1.60,1.65,1.80,1.79,1.77,1.92,1.57,1.69,1.74,1.87,1.88,1.94,1.98,1.53,1.45,1.70,1.18,1.32,1.42,1.58,1.65,1.83,1.81,1.81,1.67,1.61,1.19,1.44,1.17,1.11,1.36,1.15,1.41,1.75,1.22,1.50,1.34,1.42,1.61,0.98,0.92,1.03,0.83,0.86,0.89,0.95,0.98,1.23,1.14,0.97,0.89,0.90,0.78,0.82,0.76,0.82,0.77,0.79,0.84,0.98,0.90,0.98,0.83,0.89,0.97,1.03,0.95,0.92,0.86,0.90,0.82,0.86,0.79,0.77,0.84,0.81,0.76,0.76,0.72,0.73,0.70,0.72,0.71,0.73,0.73,0.72,0.74,0.71,0.78,0.74,0.72,0.75,0.80,0.76,0.94,0.88,0.91,0.83,0.87,0.84,0.79,0.76,0.82,0.80,0.97,0.89,0.96,0.88,0.95,0.94,0.87,1.11,1.37,1.10,1.59,1.57,1.37,1.33,1.05,1.08,1.54,1.34,1.46,1.16,0.99,1.26,0.96,1.05,0.92,1.45,1.55,1.27,1.60,1.07,1.34,1.35,1.18,1.07,0.93,0.99,0.90,0.93,0.87,0.96,1.27,0.99,1.15,0.77,0.82,0.85,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.60,1.78,1.68,1.93,1.86,1.71,1.97,1.99,1.99,1.97,1.93,1.60,1.68,1.78,1.86,1.61,1.57,1.79,1.37,1.48,1.59,1.72,1.79,1.92,1.90,1.38,1.35,1.60,1.23,1.30,1.47,1.56,1.71,1.88,1.79,1.92,1.79,1.79,1.30,1.56,1.35,1.37,1.59,1.38,1.60,1.90,1.48,1.72,1.57,1.61,1.79,1.21,1.00,1.30,0.89,0.94,0.96,1.07,1.14,1.40,1.37,1.14,0.96,0.98,0.82,0.88,0.82,0.89,0.83,0.86,0.91,1.02,0.93,1.07,0.87,0.94,1.11,1.02,0.93,0.93,0.82,0.87,0.80,0.85,0.79,0.80,0.85,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.72,0.76,0.73,0.82,0.79,0.76,0.73,0.79,0.76,0.93,0.86,0.91,0.83,0.89,0.89,0.82,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.44,1.19,1.22,0.99,0.98,1.49,1.44,1.49,1.22,0.99,1.23,0.98,1.19,0.97,1.21,1.30,1.00,1.37,0.94,1.07,1.14,0.98,0.96,0.86,0.91,0.83,0.88,0.82,0.89,1.11,0.94,1.07,0.73,0.76,0.79,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.46,1.65,1.60,1.82,1.80,1.71,1.93,1.91,1.99,1.94,1.98,1.74,1.76,1.89,1.89,1.42,1.34,1.61,1.11,1.22,1.36,1.50,1.61,1.81,1.75,1.15,1.17,1.41,1.18,1.19,1.42,1.44,1.65,1.83,1.67,1.94,1.81,1.88,1.32,1.58,1.45,1.57,1.74,1.53,1.70,1.98,1.69,1.87,1.77,1.79,1.92,1.45,1.27,1.55,0.97,1.07,1.11,1.34,1.37,1.59,1.60,1.35,1.07,1.18,0.86,0.93,0.87,0.96,0.90,0.93,0.99,1.03,0.95,1.15,0.90,0.99,1.27,0.98,0.90,0.92,0.78,0.83,0.77,0.84,0.79,0.82,0.86,0.73,0.71,0.73,0.72,0.70,0.73,0.72,0.76,0.81,0.76,0.76,0.82,0.77,0.89,0.85,0.82,0.75,0.80,0.80,0.94,0.88,0.94,0.87,0.95,0.96,0.88,0.72,0.74,0.76,0.83,0.78,0.84,0.79,0.87,0.91,0.83,0.89,0.98,0.92,1.23,1.34,1.05,1.16,0.99,0.96,1.46,1.57,1.54,1.33,1.05,1.26,1.08,1.37,1.10,0.98,1.03,0.92,1.14,0.86,0.95,0.97,0.90,0.89,0.79,0.84,0.77,0.82,0.76,0.82,0.97,0.89,0.98,0.71,0.72,0.74,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.34,1.51,1.53,1.67,1.72,1.71,1.80,1.77,1.91,1.86,1.98,1.86,1.82,1.95,1.89,1.24,1.10,1.41,0.95,0.99,1.09,1.25,1.37,1.63,1.55,0.96,0.98,1.16,1.05,1.00,1.27,1.23,1.50,1.69,1.46,1.86,1.72,1.87,1.24,1.49,1.44,1.69,1.80,1.59,1.69,1.97,1.82,1.94,1.91,1.92,1.99,1.63,1.50,1.74,1.16,1.33,1.38,1.58,1.60,1.77,1.80,1.48,1.21,1.37,0.90,0.97,0.93,1.05,0.97,1.04,1.21,0.99,0.95,1.14,0.92,1.02,1.34,0.94,0.86,0.90,0.74,0.79,0.75,0.81,0.79,0.84,0.86,0.71,0.71,0.73,0.76,0.73,0.77,0.74,0.80,0.85,0.78,0.81,0.89,0.84,0.97,0.92,0.88,0.79,0.85,0.86,0.98,0.92,1.00,0.93,1.06,1.12,0.95,0.74,0.74,0.78,0.79,0.76,0.82,0.79,0.87,0.93,0.85,0.85,0.94,0.90,1.09,1.27,0.99,1.17,1.05,0.96,1.46,1.71,1.62,1.48,1.20,1.34,1.28,1.57,1.35,0.90,0.94,0.85,0.98,0.81,0.89,0.89,0.83,0.82,0.75,0.78,0.73,0.77,0.72,0.76,0.89,0.83,0.91,0.71,0.70,0.72,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, +{1.26,1.39,1.48,1.51,1.64,1.71,1.60,1.58,1.77,1.74,1.91,1.94,1.87,1.97,1.85,1.10,0.97,1.22,0.88,0.92,0.95,1.01,1.11,1.39,1.32,0.88,0.90,0.97,0.96,0.93,1.05,0.99,1.27,1.47,1.20,1.70,1.54,1.76,1.08,1.31,1.33,1.70,1.76,1.55,1.57,1.88,1.85,1.91,1.97,1.99,1.99,1.70,1.65,1.85,1.41,1.54,1.61,1.76,1.80,1.91,1.93,1.52,1.26,1.48,0.92,0.99,0.97,1.18,1.09,1.28,1.39,0.94,0.93,1.05,0.92,1.01,1.31,0.88,0.81,0.86,0.72,0.75,0.74,0.79,0.79,0.86,0.85,0.71,0.73,0.75,0.82,0.77,0.83,0.78,0.85,0.88,0.81,0.88,0.97,0.90,1.18,1.00,0.93,0.86,0.92,0.94,1.14,0.99,1.24,1.03,1.33,1.39,1.11,0.79,0.77,0.84,0.79,0.77,0.84,0.83,0.90,0.98,0.91,0.85,0.92,0.91,1.02,1.26,1.00,1.23,1.19,0.99,1.50,1.84,1.71,1.64,1.38,1.46,1.51,1.76,1.59,0.84,0.88,0.80,0.94,0.79,0.86,0.82,0.77,0.76,0.74,0.74,0.71,0.73,0.70,0.72,0.82,0.77,0.85,0.74,0.70,0.73,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00} +} diff --git a/source/wii/gx/gx_decal.c b/source/wii/gx/gx_decal.c new file mode 100644 index 0000000..4a6863a --- /dev/null +++ b/source/wii/gx/gx_decal.c @@ -0,0 +1,658 @@ +#include "../../quakedef.h" + +#define DEFAULT_NUM_DECALS 1024 //*4 +#define ABSOLUTE_MIN_DECALS 256 +#define ABSOLUTE_MAX_DECALS 32768 +#define MAX_DECAL_VERTICES 128 +#define MAX_DECAL_TRIANGLES 64 + +typedef struct decal_s +{ + vec3_t origin; + vec3_t normal; + vec3_t tangent; + float radius; + int bspdecal; + + struct decal_s *next; + double die; + double starttime; + + int srcblend; + int dstblend; + + int texture; + + // geometry of decal + int vertexCount, triangleCount; + vec3_t vertexArray[MAX_DECAL_VERTICES]; + float texcoordArray[MAX_DECAL_VERTICES][2]; + int triangleArray[MAX_DECAL_TRIANGLES][3]; +} decal_t; + +static decal_t *decals, *active_decals, *free_decals; +static plane_t leftPlane, rightPlane, bottomPlane, topPlane, backPlane, frontPlane; +int DecalClipPolygonAgainstPlane (plane_t *plane, int vertexCount, vec3_t *vertex, vec3_t *newVertex); + +extern cvar_t r_decaltime; +extern cvar_t r_decal_viewdistance; + +static int r_numdecals; + +float RandomMinMax (float min, float max) +{ + return min + ((rand() % 10000) / 10000.0) * (max - min); +} + +int DecalClipPolygon (int vertexCount, vec3_t *vertices, vec3_t *newVertex) +{ + vec3_t tempVertex[64]; + + // Clip against all six planes + int count = DecalClipPolygonAgainstPlane (&leftPlane, vertexCount, vertices, tempVertex); + if (count != 0) + { + count = DecalClipPolygonAgainstPlane (&rightPlane, count, tempVertex, newVertex); + if (count != 0) + { + count = DecalClipPolygonAgainstPlane (&bottomPlane, count, newVertex, tempVertex); + if (count != 0) + { + count = DecalClipPolygonAgainstPlane (&topPlane, count, tempVertex, newVertex); + if (count != 0) + { + count = DecalClipPolygonAgainstPlane (&backPlane, count, newVertex, tempVertex); + if (count != 0) + { + count = DecalClipPolygonAgainstPlane (&frontPlane, count, tempVertex, newVertex); + } + } + } + } + } + + return count; +} + +int DecalClipPolygonAgainstPlane (plane_t *plane, int vertexCount, vec3_t *vertex, vec3_t *newVertex) +{ + int a, b, c, count, negativeCount = 0; + float t; + qboolean negative[65]; + vec3_t v1, v2; + + // Classify vertices + for (a = 0 ; a < vertexCount ; a++) + { + qboolean neg = ((DotProduct(plane->normal, vertex[a]) - plane->dist) < 0.0); + negative[a] = neg; + negativeCount += neg; + } + + // Discard this polygon if it's completely culled + if (negativeCount == vertexCount) + return 0; + + count = 0; + for (b = 0 ; b < vertexCount ; b++) + { + // c is the index of the previous vertex + c = (b != 0) ? b - 1 : vertexCount - 1; + + if (negative[b]) + { + if (!negative[c]) + { + // Current vertex is on negative side of plane, but previous vertex is on positive side. + VectorCopy (vertex[c], v1); + VectorCopy (vertex[b], v2); + + t = (DotProduct(plane->normal, v1) - plane->dist) / + (plane->normal[0] * (v1[0] - v2[0]) + + plane->normal[1] * (v1[1] - v2[1]) + + plane->normal[2] * (v1[2] - v2[2])); + + VectorScale (v1, (1.0 - t), newVertex[count]); + VectorMA (newVertex[count], t, v2, newVertex[count]); + + count++; + } + } + else + { + if (negative[c]) + { + // Current vertex is on positive side of plane, but previous vertex is on negative side. + VectorCopy (vertex[b], v1); + VectorCopy (vertex[c], v2); + + t = (DotProduct(plane->normal, v1) - plane->dist) / + (plane->normal[0] * (v1[0] - v2[0]) + + plane->normal[1] * (v1[1] - v2[1]) + + plane->normal[2] * (v1[2] - v2[2])); + + VectorScale (v1, (1.0 - t), newVertex[count]); + VectorMA (newVertex[count], t, v2, newVertex[count]); + + count++; + } + + // Include current vertex + VectorCopy (vertex[b], newVertex[count]); + count++; + } + } + + // Return number of vertices in clipped polygon + return count; +} + + +qboolean DecalAddPolygon (decal_t *dec, int vertcount, vec3_t *vertices) +{ + int a, b, count/*, *triangle*/; + + count = dec->vertexCount; + if (count + vertcount >= MAX_DECAL_VERTICES) + return false; + + if (dec->triangleCount + vertcount - 2 >= MAX_DECAL_TRIANGLES) + return false; + + // Add polygon as a triangle fan + //triangle = &dec->triangleArray[dec->triangleCount][0]; + for (a = 2 ; a < vertcount ; a++) + { + dec->triangleArray[dec->triangleCount][0] = count; + dec->triangleArray[dec->triangleCount][1] = (count + a - 1); + dec->triangleArray[dec->triangleCount][2] = (count + a ); + //Con_Printf ("DecalAddPolygon: %i\n", count); + dec->triangleCount++; + } + + // Assign vertex colors + for (b = 0 ; b < vertcount ; b++) + { + VectorCopy(vertices[b], dec->vertexArray[count]); + count++; + } + + dec->vertexCount = count; + return true; +} + + + +const double decalEpsilon = 0.001; + +void DecalClipLeaf (decal_t *dec, mleaf_t *leaf) +{ + int c; + vec3_t newVertex[64], t3; + msurface_t **surf; + + c = leaf->nummarksurfaces; + surf = leaf->firstmarksurface; + + // for all surfaces in the leaf + for (c = 0 ; c < leaf->nummarksurfaces ; c++, surf++) + { + int i, count; + glpoly_t *poly; + + poly = (*surf)->polys; + for (i = 0 ; i < poly->numverts ; i++) + { + newVertex[i][0] = poly->verts[i][0]; + newVertex[i][1] = poly->verts[i][1]; + newVertex[i][2] = poly->verts[i][2]; + } + + VectorCopy ((*surf)->plane->normal, t3); + + if ((*surf)->flags & SURF_PLANEBACK) + VectorNegate (t3, t3); + + // avoid backfacing and ortogonal facing faces to recieve decal parts + if (DotProduct(dec->normal, t3) > decalEpsilon) + { + count = DecalClipPolygon (poly->numverts, newVertex, newVertex); + if (count != 0 && !DecalAddPolygon(dec, count, newVertex)) + break; + } + } +} + + +void DecalWalkBsp_R (decal_t *dec, mnode_t *node) +{ + float dist; + mplane_t *plane; + mleaf_t *leaf; + + if (node->contents < 0) + { //we are in a leaf + leaf = (mleaf_t *)node; + DecalClipLeaf (dec, leaf); + return; + } + + plane = node->plane; + dist = DotProduct (dec->origin, plane->normal) - plane->dist; + + if (dist > dec->radius) + { + DecalWalkBsp_R (dec, node->children[0]); + return; + } + if (dist < -dec->radius) + { + DecalWalkBsp_R (dec, node->children[1]); + return; + } + + DecalWalkBsp_R (dec, node->children[0]); + DecalWalkBsp_R (dec, node->children[1]); +} + +/* +=============== +=============== +=============== +=============== +=============== +=============== +=============== +=============== +=============== +*/ + +/* +=============== +R_InitDecals +=============== +*/ +void R_InitDecals (void) +{ + int i; + + Cvar_RegisterVariable (&r_decaltime); + Cvar_RegisterVariable (&r_decal_viewdistance); + + if (!qmb_initialized) + return; + + if ((i = COM_CheckParm("-decals")) && i + 1 < com_argc) + { + r_numdecals = atoi(com_argv[i+1]); + r_numdecals = bound(ABSOLUTE_MIN_DECALS, r_numdecals, ABSOLUTE_MAX_DECALS); + } + else + { + r_numdecals = DEFAULT_NUM_DECALS; + } + + decals = (decal_t*)Hunk_AllocName (r_numdecals * sizeof(decal_t), "decals"); +} + +/* +=============== +R_ClearDecals +=============== +*/ +void R_ClearDecals (void) +{ + int i; + + if (!qmb_initialized) + return; + + memset (decals, 0, r_numdecals * sizeof(decal_t)); + free_decals = &decals[0]; + active_decals = NULL; + + for (i = 0 ; i < r_numdecals ; i++) + decals[i].next = &decals[i+1]; + + decals[r_numdecals-1].next = NULL; +} + +void R_SpawnDecal (vec3_t center, vec3_t normal, vec3_t tangent, int tex, int size, int isbsp) +{ +// naievil -- fixme + + int a; + float width, height, depth, d, one_over_w, one_over_h; + vec3_t binormal, test = {0.5, 0.5, 0.5}; + decal_t *dec; + + if (!qmb_initialized) + return; + + // allocate decal + if (!free_decals) + return; + + dec = free_decals; + free_decals = dec->next; + dec->next = active_decals; + active_decals = dec; + + VectorNormalize (test); + CrossProduct (normal, test, tangent); + + VectorCopy (center, dec->origin); + VectorCopy (tangent, dec->tangent); + VectorCopy (normal, dec->normal); + VectorNormalize (tangent); + VectorNormalize (normal); + CrossProduct (normal, tangent, binormal); + VectorNormalize (binormal); + + width = RandomMinMax (size * 0.5, size); + height = width; + depth = width * 0.5; + dec->radius = fmax(fmax(width, height), depth); + dec->starttime = cl.time; + dec->bspdecal = isbsp; + dec->die = (isbsp ? 0 : cl.time + r_decaltime.value); + dec->texture = tex; + + // Calculate boundary planes + d = DotProduct (center, tangent); + VectorCopy (tangent, leftPlane.normal); + leftPlane.dist = -(width * 0.5 - d); + VectorNegate (tangent, tangent); + VectorCopy (tangent, rightPlane.normal); + VectorNegate (tangent, tangent); + rightPlane.dist = -(width * 0.5 + d); + + d = DotProduct (center, binormal); + VectorCopy (binormal, bottomPlane.normal); + bottomPlane.dist = -(height * 0.5 - d); + VectorNegate (binormal, binormal); + VectorCopy (binormal, topPlane.normal); + VectorNegate (binormal, binormal); + topPlane.dist = -(height * 0.5 + d); + + d = DotProduct (center, normal); + VectorCopy (normal, backPlane.normal); + backPlane.dist = -(depth - d); + VectorNegate (normal, normal); + VectorCopy (normal, frontPlane.normal); + VectorNegate (normal, normal); + frontPlane.dist = -(depth + d); + + // Begin with empty mesh + dec->vertexCount = 0; + dec->triangleCount = 0; + + // Clip decal to bsp + DecalWalkBsp_R (dec, cl.worldmodel->nodes); + + // This happens when a decal is to far from any surface or the surface is to steeply sloped + if (dec->triangleCount == 0) + { // deallocate decal + active_decals = dec->next; + dec->next = free_decals; + free_decals = dec; + return; + } + + // Assign texture mapping coordinates + one_over_w = 1.0F / width; + one_over_h = 1.0F / height; + for (a = 0 ; a < dec->vertexCount ; a++) + { + float s, t; + vec3_t v; + + VectorSubtract (dec->vertexArray[a], center, v); + s = DotProduct (v, tangent) * one_over_w + 0.5F; + t = DotProduct (v, binormal) * one_over_h + 0.5F; + // sBTODO + // fix texture mapping coords for decals + //Con_Printf ("s:%f t:%f\n", s, t); + dec->texcoordArray[a][0] = s; + dec->texcoordArray[a][1] = t; + } + +} + +//Revamped by blubs +void R_SpawnDecalStatic (vec3_t org, int tex, int size) +{ + + int i; + float frac, bestfrac; + vec3_t tangent, v, bestorg, normal, bestnormal, org2; + vec3_t tempVec; + + if (!qmb_initialized) + return; + + VectorClear (bestorg); + VectorClear (bestnormal); + VectorClear(tempVec); + + bestfrac = 10; + for (i = 0 ; i < 26 ; i++) + { + //Reference: i = 0: check straight up, i = 1: check straight down + //1 < i < 10: Check sideways in increments of 45 degrees + //9 < i < 18: Check angled 45 degrees down in increments of 45 degrees + //17 < i : Check angled 45 degrees up in increments of 45 degrees + org2[0] = (((((i - 2) % 8) < 2) || (((i - 2) % 8) == 7)) ? 1 : 0 ) + ((((i - 2) % 8) > 2 && ((i - 2) % 8) < 6) ? -1 : 0 ); + org2[1] = ((((i - 2) % 8) > 0 && ((i - 2) % 8) < 4) ? 1 : 0 ) + ((((i - 2) % 8) > 4 && ((i - 2) % 8) < 7) ? -1 : 0 ); + org2[2] = ((i == 0) ? 1 : 0) + ((i == 1) ? -1 : 0) + (((i > 9) && (i < 18)) ? 1 : 0) + ((i > 17) ? -1 : 0); + + VectorCopy(org,tempVec); + VectorMA(tempVec, -0.1,org2,tempVec); + + VectorMA (org, 20, org2, org2); + TraceLineN (tempVec, org2, v, normal); + + VectorSubtract(org2,tempVec,org2);//goal + VectorSubtract(v,tempVec,tempVec);//collision + + if(VectorLength(org2) == 0) + return; + + frac = VectorLength(tempVec) / VectorLength(org2); + + if(frac < 1 && frac < bestfrac) + { + bestfrac = frac; + VectorCopy(v,bestorg); + VectorCopy(normal, bestnormal); + CrossProduct(normal,bestnormal,tangent); + } + } + + if (bestfrac < 1) { + R_SpawnDecal (bestorg, bestnormal, tangent, tex, size, 0); + } +} + +// sBTODO needs translated + +/* +=============== +R_DrawDecals +=============== +*/ +void R_DrawDecals (void) +{ + int i; + //float dcolor; + vec3_t decaldist; + decal_t *p, *kill; + float *point_tex, *point_xyz; + + if (!qmb_initialized) + return; + + /* + sceGuEnable (GU_BLEND); + sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); + sceGuDepthMask (GU_TRUE); + sceGuShadeModel (GU_SMOOTH); + sceGuDepthOffset(-256); + */ + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + QGX_Blend (true); + + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + for ( ; ; ) + { + kill = active_decals; + + if (kill && (kill->die < cl.time) && (!kill->bspdecal)) + { + active_decals = kill->next; + kill->next = free_decals; + free_decals = kill; + continue; + } + break; + } + + for (p = active_decals ; p ; p = p->next) + { + + for ( ; ; ) + { + kill = p->next; + + if (kill && (kill->die < cl.time) && (!kill->bspdecal)) + { + p->next = kill->next; + kill->next = free_decals; + free_decals = kill; + continue; + } + break; + } + VectorSubtract (r_refdef.vieworg, p->origin, decaldist); + + if (VectorLength(decaldist) > r_decal_viewdistance.value) + continue; + + /* ?? lol + if (p->texture == decal_q3blood) + sceGuBlendFunc (GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); + else + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); + */ + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + + GL_Bind0 (p->texture); + /* + dcolor = 1; + if (((p->die - cl.time) < 0.5) && (!p->bspdecal)) + { + float scale = 2 * (p->die - cl.time); + //sceGuColor(GU_COLOR(dcolor * scale, dcolor * scale, dcolor * scale, scale)); + GX_Color4u8(dcolor * scale, dcolor * scale, dcolor * scale, scale); + } + else + { + dcolor = (1 - (VectorLength(decaldist) / r_decal_viewdistance.value)); + //sceGuColor(GU_COLOR(dcolor, dcolor, dcolor, dcolor)); + GX_Color4u8(dcolor, dcolor, dcolor, dcolor); + } + */ + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, p->triangleCount); + for (i = 0 ; i < p->triangleCount ; i++) + { + // Allocate memory for this polygon. + + const int unclipped_vertex_count = 3; + //glvert_t* const unclipped_vertices = static_cast(sizeof(glvert_t) * unclipped_vertex_count); + for(int v = 0; v < unclipped_vertex_count ; v++) + { + point_tex = &p->texcoordArray[p->triangleArray[i][v]][0]; + point_xyz = &p->vertexArray [p->triangleArray[i][v]][0]; + /* + unclipped_vertices[v].st[0] = point_tex[0]; + unclipped_vertices[v].st[1] = point_tex[1]; + unclipped_vertices[v].xyz[0] = point_xyz[0]; + unclipped_vertices[v].xyz[1] = point_xyz[1]; + unclipped_vertices[v].xyz[2] = point_xyz[2]; + */ + } + + //point_tex = &p->texcoordArray[p->triangleArray[i][v]][0]; + //point_xyz = &p->vertexArray [p->triangleArray[i][v]][0]; + + GX_Position3f32(point_xyz[0], point_xyz[1], point_xyz[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (point_tex[0], point_tex[1]); + + + /* + if (clipping::is_clipping_required( + unclipped_vertices, + unclipped_vertex_count)) + { + // Clip the polygon. + const glvert_t* clipped_vertices; + size_t clipped_vertex_count; + clipping::clip( + unclipped_vertices, + unclipped_vertex_count, + &clipped_vertices, + &clipped_vertex_count); + + // Did we have any vertices left? + if (clipped_vertex_count) + { + // Copy the vertices to the display list. + const size_t buffer_size = clipped_vertex_count * sizeof(glvert_t); + glvert_t* const display_list_vertices = malloc(sizeof(buffer_size)); + memcpy(display_list_vertices, clipped_vertices, buffer_size); + + // Draw the clipped vertices. + + sceGuDrawArray( + GU_TRIANGLE_FAN, + GU_TEXTURE_32BITF | GU_VERTEX_32BITF, + clipped_vertex_count, 0, display_list_vertices); + + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, clipped_vertex_count); + + + } + } + else + {*/ + // Draw the poly directly. + /* + sceGuDrawArray( + GU_TRIANGLE_FAN, + GU_TEXTURE_32BITF | GU_VERTEX_32BITF, + unclipped_vertex_count, 0, unclipped_vertices); + */ + //} + } + GX_End (); + } + + //sceGuDepthOffset(0); + /* + sceGuDisable (GU_BLEND); + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); + sceGuDepthMask (GU_FALSE); + + sceGuColor(GU_COLOR(1,1,1,1)); + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); + sceGuShadeModel (GU_FLAT); + */ + + QGX_ZMode (true); + QGX_Blend (false); + + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); +} + diff --git a/source/wii/gx/gx_decal.h b/source/wii/gx/gx_decal.h new file mode 100644 index 0000000..e711e44 --- /dev/null +++ b/source/wii/gx/gx_decal.h @@ -0,0 +1,2 @@ +void R_SpawnDecal (vec3_t center, vec3_t normal, vec3_t tangent, int tex, int size, int isbsp); +void R_SpawnDecalStatic (vec3_t org, int tex, int size); \ No newline at end of file diff --git a/source/wii/gx/gx_draw.c b/source/wii/gx/gx_draw.c new file mode 100644 index 0000000..fa8c6ee --- /dev/null +++ b/source/wii/gx/gx_draw.c @@ -0,0 +1,1432 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// draw.c -- this is the only file outside the refresh that touches the +// vid buffer + +// ELUTODO: MANY assumptions about the pictures sizes + +#include +#include + +#include "../../quakedef.h" +#include + +byte *draw_chars; // 8*8 graphic characters +qpic_t *draw_backtile; + +qpic_t *sniper_scope; +qpic_t *sniper_scope_nb; + +int translate_texture; +int char_texture; + +int white_texturenum; + +//Loading Fill by Crow_bar +float loading_cur_step; +char loading_name[32]; +float loading_num_step; +int loading_step; +float loading_cur_step_bk; + +typedef struct +{ + int texnum; + float sl, tl, sh, th; +} glpic_t; + +//byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)]; +//qpic_t *conback = (qpic_t *)&conback_buffer; + +//============================================================================= +/* Support Routines */ + +typedef struct cachepic_s +{ + char name[MAX_QPATH]; + qpic_t pic; + byte padding[32]; // for appended glpic +} cachepic_t; + +#define MAX_CACHED_PICS 128 +cachepic_t cachepics[MAX_CACHED_PICS]; +cachepic_t menu_cachepics[MAX_CACHED_PICS]; +int menu_numcachepics; +int numcachepics; + +int pic_texels; +int pic_count; + +int GL_LoadPicTexture (qpic_t *pic, char *name); + +/* +================ +Draw_CachePic +================ +*/ +qpic_t *Draw_CachePic (char *path) +{ + cachepic_t *pic; + int i; + //qpic_t *dat; + glpic_t *gl; + char str[128]; + int index = 0; + + strcpy (str, path); + for (pic=cachepics, i=0 ; iname)) + return &pic->pic; + + if (numcachepics == MAX_CACHED_PICS) + Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); + + numcachepics++; + strcpy (pic->name, str); +// +// load the pic from disk +// + //Con_Printf ("Attempting to load: %s\n", str); + index = loadtextureimage (str, 0, 0, true, false, true); + if(index > 0) + { + pic->pic.width = gltextures[index].width; + pic->pic.height = gltextures[index].height; + + gltextures[index].islmp = false; + gl = (glpic_t *)pic->pic.data; + gl->texnum = index; + gl->sl = 0; + gl->sh = 1; + gl->tl = 0; + gl->th = 1; + + return &pic->pic; + } + + // sB NZ:P only uses lmps for console. + // seperated logic. + return NULL; +} + +/* +================ +Draw_CachePic +================ +*/ +qpic_t *Draw_LMP (char *path) +{ + cachepic_t *pic; + int i; + qpic_t *dat; + glpic_t *gl; + + for (pic=menu_cachepics, i=0 ; iname)) + return &pic->pic; + + if (menu_numcachepics == MAX_CACHED_PICS) + Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); + menu_numcachepics++; + strcpy (pic->name, path); + +// +// load the pic from disk +// + dat = (qpic_t *)COM_LoadTempFile (path); + if (!dat) + Sys_Error ("Draw_CachePic: failed to load %s", path); + SwapPic (dat); + + pic->pic.width = dat->width; + pic->pic.height = dat->height; + + gl = (glpic_t *)pic->pic.data; + gl->texnum = GL_LoadPicTexture (dat, pic->name); + gl->sl = 0; + gl->sh = 1; + gl->tl = 0; + gl->th = 1; + + return &pic->pic; +} + +/* +void Draw_CharToConback (int num, byte *dest) +{ + int row, col; + byte *source; + int drawline; + int x; + + row = num>>4; + col = num&15; + source = draw_chars + (row<<10) + (col<<3); + + drawline = 8; + + while (drawline--) + { + for (x=0 ; x<8 ; x++) + if (source[x] != 255) + dest[x] = 0x60 + source[x]; + source += 128; + dest += 320; + } + +} +*/ + +// ! " # $ % & ' ( ) * _ , - . / 0 +// 1 2 3 4 5 6 7 8 9 : ; < = > ? @ +// A B C D E F G H I J K L M N O P +// Q R S T U V W X Y Z [ \ ] ^ _ ` +// a b c d e f g h i j k l m n o p +// q r s t u v w x y z { | } ~ +int font_kerningamount[96]; + +void InitKerningMap(void) +{ + // Initialize the kerning amount as 8px for each + // char in the event we cant load the file. + for(int i = 0; i < 96; i++) { + font_kerningamount[i] = 8; + } + + FILE *kerning_map = fopen(va("%s/gfx/kerning_map.txt", com_gamedir), "r"); + if (kerning_map == NULL) { + return; + } + + char buffer[1024]; + if (fgets(buffer, sizeof(buffer), kerning_map) != NULL) { + char *token = strtok(buffer, ","); + int i = 0; + while (token != NULL && i < 96) { + font_kerningamount[i++] = atoi(token); + token = strtok(NULL, ","); + } + } + + fclose(kerning_map); +} + +/* +=============== +Draw_Init +=============== +*/ +void Draw_Init (void) +{ + /* + int i; + qpic_t *cb; + qpic_t *player_pic; + byte *dest; + int x, y; + char ver[40]; + glpic_t *gl; + int start; + byte *ncdata; + */ + byte white_texture[64] = { // ELUTODO assumes 0xfe is white + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe + }; // ELUTODO no necessity to be this big? + + // load the console background and the charset + // by hand, because we need to write the version + // string into the background before turning + // it into a texture + draw_chars = loadimagepixels ("gfx/charset.tga", false, 0, 0, 4); + + // now turn them into textures + char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, true, 4); +/* + start = Hunk_LowMark(); + + cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp"); + if (!cb) + Sys_Error ("Couldn't load gfx/conback.lmp"); + SwapPic (cb); + + // hack the version number directly into the pic + sprintf (ver, "(WiiGX %4.2f) Quake %4.2f", (float)WIIGX_VERSION, (float)VERSION); + + dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver); + y = strlen(ver); + for (x=0 ; xwidth = cb->width; + conback->height = cb->height; + ncdata = cb->data; + + gl = (glpic_t *)conback->data; + gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false, true, 1); + gl->sl = 0; + gl->sh = 1; + gl->tl = 0; + gl->th = 1; + + // This is done in video_gx.c now too + conback->width = vid.width; + conback->height = vid.height; + + // free loaded console + Hunk_FreeToLowMark(start); +*/ + white_texturenum = GL_LoadTexture("white_texturenum", 8, 8, white_texture, false, false, true, 1); + sniper_scope = Draw_CachePic ("gfx/hud/scope"); + sniper_scope_nb = Draw_CachePic ("gfx/hud/scope_256"); + + //Clear_LoadingFill (); + + InitKerningMap(); +} + +/* +================ +Draw_CharacterRGBA + +This is the same as Draw_Character, but with RGBA color codes. +- Cypress +================ +*/ +extern cvar_t scr_coloredtext; +void Draw_CharacterRGBA(int x, int y, int num, float r, float g, float b, float a, float scale) +{ + int row, col; + float frow, fcol, size; + + if (num == 32) + return; // space + + num &= 255; + + if (y <= -8) + return; // totally off screen + + row = num>>4; + col = num&15; + + frow = row*0.0625; + fcol = col*0.0625; + size = 0.0625*(float)scale; + + GL_Bind0 (char_texture); + + GX_SetMinMag (GX_LINEAR, GX_NEAR); + + //glEnable(GL_BLEND); + QGX_Blend(true); + //glColor4f(r/255, g/255, b/255, a/255); + //glDisable (GL_ALPHA_TEST); + QGX_Alpha(false); + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + //GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + //glBegin (GL_QUADS); + /* + glTexCoord2f (fcol, frow); + glVertex2f (x, y); + + glTexCoord2f (fcol + (float)(size/(float)scale), frow); + glVertex2f (x+(8*(scale)), y); + + glTexCoord2f (fcol + (float)(size/(float)scale), frow + (float)(size/(float)scale)); + glVertex2f (x+(8*(scale)), y+(8*(scale))); + + glTexCoord2f (fcol, frow + (float)(size/(float)scale)); + glVertex2f (x, y+(8*(scale))); + + */ + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(fcol, frow); + + GX_Position3f32(x+(8*(scale)), y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(fcol + (size/scale), frow); + + GX_Position3f32(x+(8*(scale)), y+(8*(scale)), 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(fcol + (size/scale), frow + (size/scale)); + + GX_Position3f32(x, y+(8*(scale)), 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(fcol, frow + (size/scale)); + //glEnd (); + GX_End (); + //glColor4f(1,1,1,1); + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + //GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + //glEnable(GL_ALPHA_TEST); + QGX_Alpha(true); + //glDisable (GL_BLEND); + QGX_Blend(false); +} + + +/* +================ +Draw_Character + +Draws one 8*8 graphics character with 0 being transparent. +It can be clipped to the top of the screen to allow the console to be +smoothly scrolled off. +================ +*/ +void Draw_Character (int x, int y, int num) +{ + /* + int row, col; + float frow, fcol, size; + + if (num == 32) + return; // space + + num &= 255; + + if (y <= -8) + return; // totally off screen + + row = num>>4; + col = num&15; + + frow = row*0.0625; + fcol = col*0.0625; + size = 0.0625; + + GL_Bind0 (char_texture); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(fcol, frow); + + GX_Position3f32(x + 8, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(fcol + size, frow); + + GX_Position3f32(x + 8, y + 8, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(fcol + size, frow + size); + + GX_Position3f32(x, y + 8, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(fcol, frow + size); + GX_End(); + */ + + Draw_CharacterRGBA(x, y, num, 255, 255, 255, 255, 1); +} + +void Draw_ColoredString(int x, int y, char *str, float r, float g, float b, float a, float scale) +{ + while (*str) + { + Draw_CharacterRGBA (x, y, *str, r, g, b, a, scale); + + // Hooray for variable-spacing! + if (*str == ' ') + if (scale == 1.5) { + x += 6 * scale; + } else { + x += 4 * scale; + } + else if ((int)*str < 33 || (int)*str > 126) + if (scale == 1.5) { + x += 12 * scale; + } else { + x += 8 * scale; + } + else + x += (font_kerningamount[(int)(*str - 33)] + 1) * scale; + + str++; + //x += 8*scale; + } +} + +/* +================ +Draw_String +================ +*/ +void Draw_String (int x, int y, char *str) +{ + Draw_ColoredString(x, y, str, 255, 255, 255, 255, 1); +} + +int getTextWidth(char *str, float scale) +{ + float width = 0; + + for (int i = 0; i < strlen(str); i++) { + // Hooray for variable-spacing! + if (str[i] == ' ') + if (scale == 1.5) { + width += 6 * scale; + } else { + width += 4 * scale; + } + else if ((int)str[i] < 33 || (int)str[i] > 126) + if (scale == 1.5) { + width += 12 * scale; + } else { + width += 8 * scale; + } + else + width += (font_kerningamount[(int)(str[i] - 33)] + 1) * scale; + } + + return (int)width; +} + + +void Draw_ColoredStringCentered(int y, char *str, float r, float g, float b, float a, float scale) +{ + Draw_ColoredString((vid.width - getTextWidth(str, scale))/2, y, str, r, g, b, a, scale); +} + +/* +================ +Draw_DebugChar + +Draws a single character directly to the upper right corner of the screen. +This is for debugging lockups by drawing different chars in different parts +of the code. +================ +*/ +void Draw_DebugChar (char num) +{ +} + +/* +============= +Draw_ColoredStretchPic +============= +*/ +void Draw_ColoredStretchPic (int x, int y, qpic_t *pic, int x_value, int y_value, int r, int g , int b, int a) +{ + /* + glpic_t *gl; + + if (scrap_dirty) + Scrap_Upload (); + gl = (glpic_t *)pic->data; + + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glColor4f(r/255.0,g/255.0,b/255.0,a/255.0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + GL_Bind (gl->texnum); + glBegin (GL_QUADS); + glTexCoord2f (0, 0); + glVertex2f (x, y); + glTexCoord2f (1, 0); + glVertex2f (x+x_value, y); + glTexCoord2f (1, 1); + glVertex2f (x+x_value, y+y_value); + glTexCoord2f (0, 1); + glVertex2f (x, y+y_value); + glEnd (); + + glColor4f(1,1,1,1); + */ + ///////////////////////////////////////////////////// + glpic_t *gl; + + gl = (glpic_t *)pic->data; + + QGX_Alpha(false); + QGX_Blend(true); + + //GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + GL_Bind0 (gl->texnum); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + //GX_SetMinMag (GX_NEAR, GX_NEAR); + //GX_SetMaxAniso(GX_MAX_ANISOTROPY); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(x+x_value, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(x+x_value, y+y_value, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(x, y+y_value, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(0, 1); + + GX_End(); + + QGX_Blend(false); + QGX_Alpha(true); +} + +/* +============= +Draw_StretchPic +============= +*/ +void Draw_StretchPic (int x, int y, qpic_t *pic, int x_value, int y_value) +{ + Draw_ColoredStretchPic (x, y, pic, x_value, y_value, 255, 255, 255, 255); +} + +/* +============= +Draw_ColorPic +============= +*/ +void Draw_ColorPic (int x, int y, qpic_t *pic, float r, float g , float b, float a) +{ + glpic_t *gl; + + gl = (glpic_t *)pic->data; + + QGX_Alpha(false); + QGX_Blend(true); + + GL_Bind0 (gl->texnum); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(gl->sl, gl->tl); + + GX_Position3f32(x + pic->width, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(gl->sh, gl->tl); + + GX_Position3f32(x + pic->width, y + pic->height, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(gl->sh, gl->th); + + GX_Position3f32(x, y + pic->height, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(gl->sl, gl->th); + + GX_End(); + + QGX_Blend(false); + QGX_Alpha(true); +} + +/* +============= +Draw_AlphaPic +============= +*/ +void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha) +{ + /* + glpic_t *gl; + + gl = (glpic_t *)pic->data; + + QGX_Alpha(false); + QGX_Blend(true); + + GL_Bind0 (gl->texnum); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, (u8)(0xff * alpha)); + GX_TexCoord2f32(gl->sl, gl->tl); + + GX_Position3f32(x + pic->width, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, (u8)(0xff * alpha)); + GX_TexCoord2f32(gl->sh, gl->tl); + + GX_Position3f32(x + pic->width, y + pic->height, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, (u8)(0xff * alpha)); + GX_TexCoord2f32(gl->sh, gl->th); + + GX_Position3f32(x, y + pic->height, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, (u8)(0xff * alpha)); + GX_TexCoord2f32(gl->sl, gl->th); + GX_End(); + + QGX_Blend(false); + QGX_Alpha(true); + */ + Draw_ColorPic(x, y, pic, 255, 255, 255, alpha); +} + + +/* +============= +Draw_Pic +============= +*/ +void Draw_Pic (int x, int y, qpic_t *pic) +{ + /* + glpic_t *gl; + + gl = (glpic_t *)pic->data; + + GL_Bind0 (gl->texnum); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(gl->sl, gl->tl); + + GX_Position3f32(x + pic->width, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(gl->sh, gl->tl); + + GX_Position3f32(x + pic->width, y + pic->height, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(gl->sh, gl->th); + + GX_Position3f32(x, y + pic->height, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(gl->sl, gl->th); + GX_End(); + */ + + Draw_ColorPic(x, y, pic, 255, 255, 255, 255); +} + + +/* +============= +Draw_TransPic +============= +*/ +void Draw_TransPic (int x, int y, qpic_t *pic) +{ + if (x < 0 || (unsigned)(x + pic->width) > vid.conwidth || y < 0 || + (unsigned)(y + pic->height) > vid.conheight) + { + Sys_Error ("Draw_TransPic: bad coordinates"); + } + + Draw_Pic (x, y, pic); +} + +/* +================== +Draw_TransAlphaPic +================== +*/ +void Draw_TransAlphaPic (int x, int y, qpic_t *pic, float alpha) +{ + if (x < 0 || (unsigned)(x + pic->width) > vid.conwidth || y < 0 || + (unsigned)(y + pic->height) > vid.conheight) + { + Sys_Error ("Draw_TransPic: bad coordinates"); + } + + Draw_AlphaPic (x, y, pic, alpha); +} + +/* +================ +Draw_LoadingFill +By Crow_bar +================ +*/ +void Draw_LoadingFill(void) +{ + if(!loading_num_step) + return; + + int size = 16; + int max_step = 350; + int x = (vid.width / 2) - (max_step / 2); + int y = vid.height - (size/ 2) - 35; + //int l; + //char str[64]; + char* text; + + + if(loading_cur_step > loading_num_step) + loading_cur_step = loading_num_step; + + if (loading_cur_step < loading_cur_step_bk) + loading_cur_step = loading_cur_step_bk; + + if (loading_cur_step == loading_num_step && loading_cur_step_bk != loading_num_step) + loading_cur_step = loading_cur_step_bk; + + float loadsize = loading_cur_step * (max_step / loading_num_step); + Draw_FillByColor (x - 2, y - 2, max_step + 4, size + 4, 69, 69, 69, 255); + Draw_FillByColor (x, y, (int)loadsize, size, 0, 0, 0, 200); + + switch(loading_step) { + case 1: text = "Loading Models.."; break; + case 2: text = "Loading World.."; break; + case 3: text = "Running Test Frame.."; break; + case 4: text = "Loading Sounds.."; break; + default: text = "Initializing.."; break; + } + + //l = strlen (text); + //Draw_String((vid.width - l*12)/2, y+2, text); + Draw_ColoredStringCentered(y, text, 255, 255, 255, 255, 2); + + loading_cur_step_bk = loading_cur_step; +} + +void Clear_LoadingFill (void) +{ + //it is end loading + loading_cur_step = 0; + loading_cur_step_bk = 0; + loading_num_step = 0; + loading_step = -1; + memset(loading_name, 0, sizeof(loading_name)); +} + +/* +============= +Draw_AlphaTileClear + +This repeats a 64*64 alpha blended tile graphic to fill the screen around a sized down +refresh window. +============= +*/ +void Draw_AlphaTileClear (int x, int y, int w, int h, float alpha) +{ + GL_Bind0 (*(int *)draw_backtile->data); + //GX_SetMinMag (GX_NEAR, GX_NEAR); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, alpha); + GX_TexCoord2f32(x / 64.0, y / 64.0); + + GX_Position3f32(x + w, y, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, alpha); + GX_TexCoord2f32((x + w) / 64.0, y / 64.0); + + GX_Position3f32(x + w, y + h, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, alpha); + GX_TexCoord2f32((x + w) / 64.0, (y + h) / 64.0); + + GX_Position3f32(x, y + h, 0.0f); + GX_Color4u8(0xff, 0xff, 0xff, alpha); + GX_TexCoord2f32(x / 64.0, (y + h) / 64.0); + GX_End(); +} + + +/* +============= +Draw_Fill + +Fills a box of pixels with a single color +============= +*/ +void Draw_Fill (int x, int y, int w, int h, float r, float g, float b, float a) +{ + //glDisable (GL_TEXTURE_2D); + + QGX_Alpha(false); + QGX_Blend(true); + + GL_Bind0 (white_texturenum); + //GX_SetMinMag (GX_NEAR, GX_NEAR); + //glEnable (GL_BLEND); //johnfitz -- for alpha + //glDisable (GL_ALPHA_TEST); //johnfitz -- for alpha + //glColor4f (r/255, g/255, b/255, a/255); + //GX_Color4u8(r, g, b, a); + //GL_DisableMultitexture(); + + //GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + //GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0); + //GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + //glBegin (GL_QUADS); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + + /* + glVertex2f (x,y); + glVertex2f (x+w, y); + glVertex2f (x+w, y+h); + glVertex2f (x, y+h); + */ + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(x + w, y, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(x + w, y + h, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(x, y + h, 0.0f); + GX_Color4u8(r, g, b, a); + GX_TexCoord2f32(0, 1); + + //glEnd (); + GX_End (); + + //glColor4f (1,1,1,1); + //glDisable (GL_BLEND); //johnfitz -- for alpha + QGX_Blend(false); + QGX_Alpha(true); + //glEnable(GL_ALPHA_TEST); //johnfitz -- for alpha + //QGX_Alpha(true); + //glEnable (GL_TEXTURE_2D); + + //GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + //GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + //GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + +} + +/* +================ +Draw_ConsoleBackground + +================ +*/ +void Draw_ConsoleBackground (int lines) +{ + /* + int y = (vid.conheight * 3) >> 2; + + if (lines > y) + Draw_Pic(0, lines - vid.conheight, conback); + else + Draw_AlphaPic (0, lines - vid.conheight, conback, (float)(1.2 * lines)/y); + */ + + Draw_Fill(0, 0, vid.width, lines, 0, 0, 0, 85); +} + +/* +============= +Draw_FillByColor + +Fills a box of pixels with a single color +============= +*/ +void Draw_FillByColor (int x, int y, int w, int h, int r, int g, int b, int a) +{ + Draw_Fill(x, y, w, h, r, g, b, a); +} + + +/* +============= +Draw_Fill + +Fills a box of pixels with a single color +============= + +void Draw_Fill (int x, int y, int w, int h, int c) +{ + // ELUTODO: do not use a texture + GL_Bind0 (white_texturenum); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(x, y, 0.0f); + GX_Color4u8(host_basepal[c*3], host_basepal[c*3+1], host_basepal[c*3+2], 0xff); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(x + w, y, 0.0f); + GX_Color4u8(host_basepal[c*3], host_basepal[c*3+1], host_basepal[c*3+2], 0xff); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(x + w, y + h, 0.0f); + GX_Color4u8(host_basepal[c*3], host_basepal[c*3+1], host_basepal[c*3+2], 0xff); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(x, y + h, 0.0f); + GX_Color4u8(host_basepal[c*3], host_basepal[c*3+1], host_basepal[c*3+2], 0xff); + GX_TexCoord2f32(0, 1); + GX_End(); +} +*/ +//============================================================================= + +extern cvar_t crosshair; +extern qboolean croshhairmoving; +//extern cvar_t cl_zoom; +extern qpic_t *hitmark; +double Hitmark_Time, crosshair_spread_time; +float cur_spread; +float crosshair_offset_step; + +int CrossHairWeapon (void) +{ + int i; + switch(cl.stats[STAT_ACTIVEWEAPON]) + { + case W_COLT: + case W_BIATCH: + case W_357: + case W_KILLU: + i = 22; + break; + case W_PTRS: + case W_PENETRATOR: + case W_KAR_SCOPE: + case W_HEADCRACKER: + case W_KAR: + case W_ARMAGEDDON: + case W_SPRING: + case W_PULVERIZER: + i = 65; + break; + case W_MP40: + case W_AFTERBURNER: + case W_STG: + case W_SPATZ: + case W_THOMPSON: + case W_GIBS: + case W_BAR: + case W_WIDOW: + case W_PPSH: + case W_REAPER: + case W_RAY: + case W_PORTER: + case W_TYPE: + case W_SAMURAI: + case W_FG: + case W_IMPELLER: + case W_MP5: + case W_KOLLIDER: + i = 10; + break; + case W_BROWNING: + case W_ACCELERATOR: + case W_MG: + case W_BARRACUDA: + i = 30; + break; + case W_SAWNOFF: + case W_SNUFF: + i = 50; + break; + case W_TRENCH: + case W_GUT: + case W_DB: + case W_BORE: + i = 35; + break; + case W_GEWEHR: + case W_COMPRESSOR: + case W_M1: + case W_M1000: + case W_M1A1: + case W_WIDDER: + i = 5; + break; + case W_PANZER: + case W_LONGINUS: + case W_TESLA: + i = 0; + break; + default: + i = 0; + break; + } + + i *= 0.68; + i += 6; + + if (cl.perks & 64) + i *= 0.75; + + return i; +} +int CrossHairMaxSpread (void) +{ + int i; + switch(cl.stats[STAT_ACTIVEWEAPON]) + { + case W_COLT: + case W_BIATCH: + case W_STG: + case W_SPATZ: + case W_MP40: + case W_AFTERBURNER: + case W_THOMPSON: + case W_GIBS: + case W_BAR: + case W_WIDOW: + case W_357: + case W_KILLU: + case W_BROWNING: + case W_ACCELERATOR: + case W_FG: + case W_IMPELLER: + case W_MP5: + case W_KOLLIDER: + case W_MG: + case W_BARRACUDA: + case W_PPSH: + case W_REAPER: + case W_RAY: + case W_PORTER: + case W_TYPE: + case W_SAMURAI: + i = 48; + break; + case W_PTRS: + case W_PENETRATOR: + case W_KAR_SCOPE: + case W_HEADCRACKER: + case W_KAR: + case W_ARMAGEDDON: + case W_SPRING: + case W_PULVERIZER: + i = 75; + break; + case W_SAWNOFF: + case W_SNUFF: + i = 50; + break; + case W_DB: + case W_BORE: + case W_TRENCH: + case W_GUT: + case W_GEWEHR: + case W_COMPRESSOR: + case W_M1: + case W_M1000: + case W_M1A1: + case W_WIDDER: + i = 35; + break; + case W_PANZER: + case W_LONGINUS: + case W_TESLA: + i = 0; + break; + default: + i = 0; + break; + } + + i *= 0.68; + i += 6; + + if (cl.perks & 64) + i *= 0.75; + + return i; +} + +/* +================ +Draw_Crosshair +================ +*/ + +extern float crosshair_opacity; +extern cvar_t cl_crosshair_debug; +extern qboolean crosshair_pulse_grenade; +extern cvar_t cl_crossx, cl_crossy; +extern qboolean aimsnap; +extern cvar_t sniper_center; +void Draw_Crosshair (void) +{ + int scopex, scopey; + + if (cl_crosshair_debug.value) { + Draw_FillByColor(vid.width/2, 0, 1, 240, 255, 0, 0, 255); + Draw_FillByColor(0, vid.height/2, 400, 1, 0, 255, 0, 255); + } + + if (key_dest != key_game) { + return; + } + + // We only want the crosshair to show in-game and while player is alive. + if (cl.stats[STAT_HEALTH] < 1) { + return; + } + + if (cl.stats[STAT_ZOOM] == 2) { + scopex = ((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value)/* * vid.conwidth/vid.width*/) - 156; + scopey = ((scr_vrect.y + scr_vrect.height/2 + cl_crossy.value)/* * vid.conheight/vid.height*/) - 156; + + if (sniper_center.value) { + Draw_StretchPic (0, 0, sniper_scope, vid.width, vid.height); + } else { + Draw_StretchPic (scopex, scopey, sniper_scope_nb, 312, 312); + //left screen + Draw_FillByColor (0, 0, scopex, scr_vrect.height, 0, 0, 0, 255); + //right screen + Draw_FillByColor (scopex + 312, 0, scr_vrect.width - scopex, scr_vrect.height, 0, 0, 0, 255); + //top screen + Draw_FillByColor (0, 0, scr_vrect.width, scopey, 0, 0, 0, 255); + //bottom screen + Draw_FillByColor (0, scopey + 312, scr_vrect.width, scr_vrect.height - scopey, 0, 0, 0, 255); + } + } + + if (Hitmark_Time > sv.time) { + + if ((cl.stats[STAT_ZOOM] == 1 && ads_center.value) || (cl.stats[STAT_ZOOM] == 2 && sniper_center.value)) { + Draw_ColoredStretchPic ((vid.width - 12)/2, (vid.height - 12)/2, hitmark, 24, 24, 255, 255, 255, 225); + } + else { + Draw_ColoredStretchPic (((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width) - 12/* - hitmark->width*/, + ((scr_vrect.y + scr_vrect.height/2 + cl_crossy.value) * vid.conheight/vid.height) - 12/* - hitmark->height*/, hitmark, 24, 24, 255, 255, 255, 225); + } + } + + /* + Draw_Character ((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width, + (scr_vrect.y + scr_vrect.height/2 + cl_crossy.value - hitmark->height) * vid.conheight/vid.height, '+'); + */ + + float col; + + if (sv_player->v.facingenemy == 1) { + col = 0; + } else { + col = 255; + } + + // crosshair moving + if ((crosshair_spread_time > sv.time && crosshair_spread_time) || croshhairmoving == true) + { + cur_spread = cur_spread + 4; + if (cur_spread >= CrossHairMaxSpread()) + cur_spread = CrossHairMaxSpread()*1.5f; + + crosshair_opacity -= 8; + if (crosshair_opacity <= 155) + crosshair_opacity = 155; + } + // crosshair not moving + else if ((crosshair_spread_time < sv.time && crosshair_spread_time) || croshhairmoving == false) + { + cur_spread = cur_spread - 2; + if (cur_spread <= 0) { + cur_spread = 0; + crosshair_spread_time = 0; + } + + crosshair_opacity += 20; + if (crosshair_opacity >= 255) + crosshair_opacity = 255; + } + + int x_value, y_value; + int crosshair_offset; + + //Draw_CharacterRGBA((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width - 4, (scr_vrect.y + scr_vrect.height/2 + cl_crossy.value) * vid.conheight/vid.height - 8, '.', 255, (int)col, (int)col, 255, 1.4); + if (aimsnap == true) + Draw_FillByColor(vid.width/2 - 4, vid.height/2 - 4, 4, 4, 255, (int)col, (int)col, (int)crosshair_opacity); + else + Draw_FillByColor(((scr_vrect.x + scr_vrect.width - 4)/2 + cl_crossx.value) * vid.conwidth/vid.width, ((scr_vrect.y + scr_vrect.height - 4)/2 + cl_crossy.value) * vid.conheight/vid.height, 4, 4, 255, (int)col, (int)col, (int)crosshair_opacity); + + // Make sure to do this after hitmark drawing. + if (cl.stats[STAT_ZOOM] == 1 || cl.stats[STAT_ZOOM] == 2 || cl.stats[STAT_ZOOM] == 3) + return; + + // Standard crosshair (+) + if (crosshair.value == 1) { + crosshair_offset = CrossHairWeapon() + cur_spread; + if (CrossHairMaxSpread() < crosshair_offset) + crosshair_offset = CrossHairMaxSpread()*1.5f; + + if (sv_player->v.view_ofs[2] == 8) { + crosshair_offset *= 0.80; + } else if (sv_player->v.view_ofs[2] == -10) { + crosshair_offset *= 0.65; + } + + /* + Draw_Character ((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width, + (scr_vrect.y + scr_vrect.height/2 + cl_crossy.value - hitmark->height) * vid.conheight/vid.height, '+'); + */ + + crosshair_offset_step += (crosshair_offset - crosshair_offset_step)/* * 0.5*/; //0.5 place + + //x_value = (vid.width - 3)/2 - crosshair_offset_step; + //y_value = (vid.height - 1)/2; + x_value = ((scr_vrect.x + scr_vrect.width - 12)/2 + cl_crossx.value) * vid.conwidth/vid.width - crosshair_offset_step; + y_value = ((scr_vrect.y + scr_vrect.height - 3)/2 + cl_crossy.value) * vid.conheight/vid.height; + Draw_FillByColor(x_value - 20, y_value, 13, 2, 255, (int)col, (int)col, (int)crosshair_opacity); + + //x_value = (vid.width - 3)/2 + crosshair_offset_step; + //y_value = (vid.height - 1)/2; + x_value = ((scr_vrect.x + scr_vrect.width - 12)/2 + cl_crossx.value) * vid.conwidth/vid.width + crosshair_offset_step; + y_value = ((scr_vrect.y + scr_vrect.height - 3)/2 + cl_crossy.value) * vid.conheight/vid.height; + Draw_FillByColor(x_value + 20, y_value, 13, 2, 255, (int)col, (int)col, (int)crosshair_opacity); + + //x_value = (vid.width - 1)/2; + //y_value = (vid.height - 3)/2 - crosshair_offset_step; + x_value = ((scr_vrect.x + scr_vrect.width - 3)/2 + cl_crossx.value) * vid.conwidth/vid.width; + y_value = ((scr_vrect.y + scr_vrect.height - 12)/2 + cl_crossy.value) * vid.conheight/vid.height - crosshair_offset_step; + Draw_FillByColor(x_value, y_value - 20, 2, 13, 255, (int)col, (int)col, (int)crosshair_opacity); + + //x_value = (vid.width - 1)/2; + //y_value = (vid.height - 3)/2 + crosshair_offset_step; + x_value = ((scr_vrect.x + scr_vrect.width - 3)/2 + cl_crossx.value) * vid.conwidth/vid.width; + y_value = ((scr_vrect.y + scr_vrect.height - 12)/2 + cl_crossy.value) * vid.conheight/vid.height + crosshair_offset_step; + Draw_FillByColor(x_value, y_value + 20, 2, 13, 255, (int)col, (int)col, (int)crosshair_opacity); + } + // Area of Effect (o) + else if (crosshair.value == 2) { + Draw_CharacterRGBA((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width - 5, (scr_vrect.y + scr_vrect.height/2 + cl_crossy.value) * vid.conheight/vid.height - 5, 'O', 255, (int)col, (int)col, (int)crosshair_opacity, 2.0); + } + // Dot crosshair (.) + else if (crosshair.value == 3) { + Draw_CharacterRGBA((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width - 5, (scr_vrect.y + scr_vrect.height/2 + cl_crossy.value) * vid.conheight/vid.height - 5, '.', 255, (int)col, (int)col, (int)crosshair_opacity, 2.0); + } + // Grenade crosshair + else if (crosshair.value == 4) { + if (crosshair_pulse_grenade) { + crosshair_offset_step = 0; + cur_spread = 2; + } + + crosshair_pulse_grenade = false; + + crosshair_offset = 12 + cur_spread; + crosshair_offset_step += (crosshair_offset - crosshair_offset_step) * 0.5; + + //x_value = (vid.width - 3)/2 - crosshair_offset_step; + //y_value = (vid.height - 1)/2; + x_value = ((scr_vrect.x + scr_vrect.width - 10)/2 + cl_crossx.value) * vid.conwidth/vid.width - crosshair_offset_step; + y_value = ((scr_vrect.y + scr_vrect.height - 2)/2 + cl_crossy.value) * vid.conheight/vid.height; + Draw_FillByColor(x_value - 20, y_value, 10, 2, 255, 255, 255, 255); + + //x_value = (vid.width - 3)/2 + crosshair_offset_step; + //y_value = (vid.height - 1)/2; + x_value = ((scr_vrect.x + scr_vrect.width - 10)/2 + cl_crossx.value) * vid.conwidth/vid.width + crosshair_offset_step; + y_value = ((scr_vrect.y + scr_vrect.height - 2)/2 + cl_crossy.value) * vid.conheight/vid.height; + Draw_FillByColor(x_value + 20, y_value, 10, 2, 255, 255, 255, 255); + + //x_value = (vid.width - 1)/2; + //y_value = (vid.height - 3)/2 - crosshair_offset_step; + x_value = ((scr_vrect.x + scr_vrect.width - 2)/2 + cl_crossx.value) * vid.conwidth/vid.width; + y_value = ((scr_vrect.y + scr_vrect.height - 10)/2 + cl_crossy.value) * vid.conheight/vid.height - crosshair_offset_step; + Draw_FillByColor(x_value, y_value - 20, 2, 10, 255, 255, 255, 255); + + //x_value = (vid.width - 1)/2; + //y_value = (vid.height - 3)/2 + crosshair_offset_step; + x_value = ((scr_vrect.x + scr_vrect.width - 2)/2 + cl_crossx.value) * vid.conwidth/vid.width; + y_value = ((scr_vrect.y + scr_vrect.height - 10)/2 + cl_crossy.value) * vid.conheight/vid.height + crosshair_offset_step; + Draw_FillByColor(x_value, y_value + 20, 2, 10, 255, 255, 255, 255); + } + +} + + +/* +================ +Draw_FadeScreen + +================ +*/ +void Draw_FadeScreen (void) +{ + // ELUTODO: do not use a texture + QGX_Alpha(false); + QGX_Blend(true); + + GL_Bind0 (white_texturenum); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(0, 0, 0.0f); + GX_Color4u8(0x00, 0x00, 0x00, 0xcc); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(vid.conwidth, 0, 0.0f); + GX_Color4u8(0x00, 0x00, 0x00, 0xcc); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(vid.conwidth, vid.conheight, 0.0f); + GX_Color4u8(0x00, 0x00, 0x00, 0xcc); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(0, vid.conheight, 0.0f); + GX_Color4u8(0x00, 0x00, 0x00, 0xcc); + GX_TexCoord2f32(0, 1); + GX_End(); + + QGX_Blend(false); + QGX_Alpha(true); +} + +//============================================================================= + +/* +================ +GL_Set2D + +Setup as if the screen was 320*200 +================ +*/ +void GL_Set2D (void) +{ + GX_SetViewport(glx, gly, glwidth, glheight, 0.0f, 1.0f); + + guOrtho(perspective,0, vid.height, 0, vid.width, ZMIN2D, ZMAX2D); + GX_LoadProjectionMtx(perspective, GX_ORTHOGRAPHIC); + + guMtxIdentity(modelview); + GX_LoadPosMtxImm(modelview, GX_PNMTX0); + + // ELUODO: filtering is making some borders + QGX_ZMode(false); + QGX_Blend(true); + GX_SetCullMode(GX_CULL_NONE); + QGX_Alpha(true); + + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GL_DisableMultitexture(); +} \ No newline at end of file diff --git a/source/wii/gx/gx_fog.c b/source/wii/gx/gx_fog.c new file mode 100644 index 0000000..78736bf --- /dev/null +++ b/source/wii/gx/gx_fog.c @@ -0,0 +1,357 @@ +/* + +Fogging system based on FitzQuake's implementation +Now with Quakespasm bits thrown into it! +Modified for Wii :) + +*/ + +#include "../../quakedef.h" + +//============================================================================== +// +// GLOBAL FOG +// +//============================================================================== +#define DEFAULT_GRAY 0.3 + +float fog_start; +float fog_end; +float fog_red; +float fog_green; +float fog_blue; + +float old_start; +float old_end; +float old_red; +float old_green; +float old_blue; + +float fade_time; //duration of fade +float fade_done; //time when fade will be done + +extern Mtx44 perspective; +GXColor BLACK = {0, 0, 0, 255}; + +/* +============= +Fog_Update + +update internal variables +============= +*/ +void Fog_Update (float start, float end, float red, float green, float blue, float time) +{ + //save previous settings for fade + if (time > 0) + { + //check for a fade in progress + if (fade_done > cl.time) + { + float f; + + f = (fade_done - cl.time) / fade_time; + old_start = f * old_start + (85.0 - f) * fog_start; + old_end = f * old_end + (85.0 - f) * fog_end; + old_red = f * old_red + (85.0 - f) * fog_red; + old_green = f * old_green + (85.0 - f) * fog_green; + old_blue = f * old_blue + (85.0 - f) * fog_blue; + } + else + { + old_start = fog_start; + old_end = fog_end; + old_red = fog_red; + old_green = fog_green; + old_blue = fog_blue; + } + } + + fog_start = start; + fog_end = end; + fog_red = red; + fog_green = green; + fog_blue = blue; + fade_time = time; + fade_done = cl.time + time; +} + +/* +============= +Fog_ParseServerMessage + +handle an SVC_FOG message from server +============= +*/ +void Fog_ParseServerMessage (void) +{ + float start, end, red, green, blue, time; + + start = MSG_ReadByte(); + end = MSG_ReadByte(); + red = MSG_ReadByte(); + green = MSG_ReadByte(); + blue = MSG_ReadByte(); + time = MSG_ReadShort(); + + //Con_Printf("updating fog values"); + + Fog_Update (start, end, red, green, blue, time); +} + +/* +============= +Fog_FogCommand_f + +handle the 'fog' console command +============= +*/ +void Fog_FogCommand_f (void) +{ + switch (Cmd_Argc()) + { + default: + case 1: + Con_Printf("usage:\n"); + Con_Printf(" fog \n"); + Con_Printf(" fog \n"); + Con_Printf(" fog \n"); + Con_Printf(" fog \n"); + Con_Printf(" fog \n"); + Con_Printf(" fog \n"); + Con_Printf("current values:\n"); + Con_Printf(" \"start\" is \"%f\"\n", fog_start); + Con_Printf(" \"end\" is \"%f\"\n", fog_end); + Con_Printf(" \"red\" is \"%f\"\n", fog_red); + Con_Printf(" \"green\" is \"%f\"\n", fog_green); + Con_Printf(" \"blue\" is \"%f\"\n", fog_blue); + Con_Printf(" \"fade\" is \"%f\"\n", fade_time); + break; + case 2: //TEST + Fog_Update(fog_start, + fog_end, + fog_red, + fog_green, + fog_blue, + atof(Cmd_Argv(1))); + break; + case 3: + Fog_Update(atof(Cmd_Argv(1)), + atof(Cmd_Argv(2)), + fog_red, + fog_green, + fog_blue, + 0.0); + break; + case 4: + Fog_Update(fog_start, + fog_end, + CLAMP(0.0, atof(Cmd_Argv(1)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(2)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(3)), 85.0), + 0.0); + break; + case 5: //TEST + Fog_Update(fog_start, + fog_end, + CLAMP(0.0, atof(Cmd_Argv(1)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(2)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(3)), 85.0), + atof(Cmd_Argv(4))); + break; + case 6: + Fog_Update(atof(Cmd_Argv(1)), + atof(Cmd_Argv(2)), + CLAMP(0.0, atof(Cmd_Argv(3)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(4)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(5)), 85.0), + 0.0); + break; + case 7: + Fog_Update(atof(Cmd_Argv(1)), + atof(Cmd_Argv(2)), + CLAMP(0.0, atof(Cmd_Argv(3)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(4)), 85.0), + CLAMP(0.0, atof(Cmd_Argv(5)), 85.0), + atof(Cmd_Argv(6))); + break; + } +} + +/* +============= +Fog_ParseWorldspawn + +called at map load +============= +*/ +void Fog_ParseWorldspawn (void) +{ + char key[128], value[4096]; + char *data; + + //initially no fog + fog_start = 0; + old_start = 0; + + fog_end = 4000; + old_end = 4000; + + fog_red = 0.0; + old_red = 0.0; + + fog_green = 0.0; + old_green = 0.0; + + fog_blue = 0.0; + old_blue = 0.0; + + fade_time = 0.0; + fade_done = 0.0; + + data = COM_Parse(cl.worldmodel->entities); + if (!data) + return; // error + if (com_token[0] != '{') + return; // error + while (1) + { + data = COM_Parse(data); + if (!data) + return; // error + if (com_token[0] == '}') + break; // end of worldspawn + if (com_token[0] == '_') + strcpy(key, com_token + 1); + else + strcpy(key, com_token); + while (key[strlen(key)-1] == ' ') // remove trailing spaces + key[strlen(key)-1] = 0; + data = COM_Parse(data); + if (!data) + return; // error + strcpy(value, com_token); + + if (!strcmp("fog", key)) + { + sscanf(value, "%f %f %f %f %f", &fog_start, &fog_end, &fog_red, &fog_green, &fog_blue); + } + } +} + +/* Deduce the projection type (perspective vs orthogonal) and the values of the + * near and far clipping plane from the projection matrix. + * Note that the formulas for computing "near" and "far" are only valid for + * matrices created by opengx or by the gu* family of GX functions. OpenGL + * books use different formulas. + */ +static void get_projection_info(float *near, float *far) +{ + float A, B; + + A = perspective[2][2]; + B = perspective[3][2]; + + if (perspective[3][3] == 0) { + *near = B / (A - 1.0); + } else { + *near = (B + 1.0) / A; + } + *far = B / A; +} + +/* +============= +Fog_EnableGFog + +called before drawing stuff that should be fogged +============= +*/ +GXColor color = {110, 110, 117, 255}; +void Fog_EnableGFog (void) +{ + float near, far; + float end; + float r, g, b; + + if (fog_red > 85) + fog_red = 85; + if (fog_green > 85) + fog_green = 85; + if (fog_blue > 85) + fog_blue = 85; + + r = fog_red*3; + g = fog_green*3; + b = fog_blue*3; + + GXColor FogColor = {r, g, b, 255}; //alpha what>? + + get_projection_info (&near, &far); + + end = fog_end/2.2; + + if (end < 500) + end = 500; + + //Con_Printf("enabled fog: e%f r%f g%f b%f\n", end, r, g, b); + if (r == 0 && g == 0 && b == 0 && end == 500) + GX_SetFog(GX_FOG_NONE, 0.0F, 1.0F, 0.0F, 1.0F, color); + else + GX_SetFog(GX_FOG_EXP2 /*GX_FOG_LIN*/, 0.0F, end, near, far, FogColor); +} + +/* +============= +Fog_DisableGFog + +called after drawing stuff that should be fogged +============= +*/ +void Fog_DisableGFog (void) +{ + GX_SetFog(GX_FOG_NONE, 0.0F, 1.0F, 0.0F, 1.0F, color); +} + +//============================================================================== +// +// INIT +// +//============================================================================== + +/* +============= +Fog_NewMap + +called whenever a map is loaded +============= +*/ + +void Fog_NewMap (void) +{ + Fog_ParseWorldspawn (); //for global fog +} + +/* +============= +Fog_Init + +called when quake initializes +============= +*/ +void Fog_Init (void) +{ + Cmd_AddCommand ("fog",Fog_FogCommand_f); + + //set up global fog + fog_start = 0; + fog_end = 650; + fog_red = 108; + fog_green = 132; + fog_blue = 147; + fade_time = 1; + fade_time = 1; + + //glFogi(GL_FOG_MODE, GL_LINEAR); + //GX_SetFog(GX_FOG_LIN, 0.0F, 1.0F, 0.1F, 1.0F, BLACK); +} \ No newline at end of file diff --git a/source/wii/gx/gx_mesh.c b/source/wii/gx/gx_mesh.c new file mode 100644 index 0000000..7cf020f --- /dev/null +++ b/source/wii/gx/gx_mesh.c @@ -0,0 +1,316 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// gl_mesh.c: triangle model functions + +#include "../../quakedef.h" + +/* +================================================================= + +ALIAS MODEL DISPLAY LIST GENERATION + +================================================================= +*/ + +model_t *aliasmodel; +aliashdr_t *paliashdr; + +int used[8192]; + +// the command list holds counts and s/t values that are valid for +// every frame +int commands[8192]; +int numcommands; + +// all frames will have their vertexes rearranged and expanded +// so they are in the order expected by the command list +int vertexorder[8192]; +int numorder; + +int allverts, alltris; + +int stripverts[128]; +int striptris[128]; +int stripcount; + +/* +================ +StripLength +================ +*/ +int StripLength (int starttri, int startv) +{ + int m1, m2; + int j; + mtriangle_t *last, *check; + int k; + + used[starttri] = 2; + + last = &triangles[starttri]; + + stripverts[0] = last->vertindex[(startv)%3]; + stripverts[1] = last->vertindex[(startv+1)%3]; + stripverts[2] = last->vertindex[(startv+2)%3]; + + striptris[0] = starttri; + stripcount = 1; + + m1 = last->vertindex[(startv+2)%3]; + m2 = last->vertindex[(startv+1)%3]; + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + { + if (check->facesfront != last->facesfront) + continue; + for (k=0 ; k<3 ; k++) + { + if (check->vertindex[k] != m1) + continue; + if (check->vertindex[ (k+1)%3 ] != m2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + if (stripcount & 1) + m2 = check->vertindex[ (k+2)%3 ]; + else + m1 = check->vertindex[ (k+2)%3 ]; + + stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jnumtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + +/* +=========== +FanLength +=========== +*/ +int FanLength (int starttri, int startv) +{ + int m1, m2; + int j; + mtriangle_t *last, *check; + int k; + + used[starttri] = 2; + + last = &triangles[starttri]; + + stripverts[0] = last->vertindex[(startv)%3]; + stripverts[1] = last->vertindex[(startv+1)%3]; + stripverts[2] = last->vertindex[(startv+2)%3]; + + striptris[0] = starttri; + stripcount = 1; + + m1 = last->vertindex[(startv+0)%3]; + m2 = last->vertindex[(startv+2)%3]; + + + // look for a matching triangle +nexttri: + for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + { + if (check->facesfront != last->facesfront) + continue; + for (k=0 ; k<3 ; k++) + { + if (check->vertindex[k] != m1) + continue; + if (check->vertindex[ (k+1)%3 ] != m2) + continue; + + // this is the next part of the fan + + // if we can't use this triangle, this tristrip is done + if (used[j]) + goto done; + + // the new edge + m2 = check->vertindex[ (k+2)%3 ]; + + stripverts[stripcount+2] = m2; + striptris[stripcount] = j; + stripcount++; + + used[j] = 2; + goto nexttri; + } + } +done: + + // clear the temp used flags + for (j=starttri+1 ; jnumtris ; j++) + if (used[j] == 2) + used[j] = 0; + + return stripcount; +} + + +/* +================ +BuildTris + +Generate a list of trifans or strips +for the model, which holds for all frames +================ +*/ +void BuildTris (void) +{ + int i, j, k; + int startv; + float s, t; + int len, bestlen, besttype=0; + int bestverts[1024]; + int besttris[1024]; + int type; + + // + // build tristrips + // + numorder = 0; + numcommands = 0; + memset (used, 0, sizeof(used)); + for (i=0 ; inumtris ; i++) + { + // pick an unused triangle and start the trifan + if (used[i]) + continue; + + bestlen = 0; + for (type = 0 ; type < 2 ; type++) +// type = 1; + { + for (startv =0 ; startv < 3 ; startv++) + { + if (type == 1) + len = StripLength (i, startv); + else + len = FanLength (i, startv); + if (len > bestlen) + { + besttype = type; + bestlen = len; + for (j=0 ; jskinwidth / 2; // on back side + s = (s + 0.5) / pheader->skinwidth; + t = (t + 0.5) / pheader->skinheight; + + *(float *)&commands[numcommands++] = s; + *(float *)&commands[numcommands++] = t; + } + } + + commands[numcommands++] = 0; // end of list marker + + //Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); + + allverts += numorder; + alltris += pheader->numtris; +} + + +/* +================ +GL_MakeAliasModelDisplayLists +================ +*/ +void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) +{ + int i, j; + int *cmds; + trivertx_t *verts; + + aliasmodel = m; + paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); + + // + // build it from scratch + // + //Con_Printf ("meshing %s...\n",m->name); // ELUTODO: cache them, using hashes to avoid original glquake problems + + BuildTris (); // trifans or lists + + // save the data out + + paliashdr->poseverts = numorder; + + cmds = Hunk_Alloc (numcommands * 4); + paliashdr->commands = (byte *)cmds - (byte *)paliashdr; + memcpy (cmds, commands, numcommands * 4); + + verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts + * sizeof(trivertx_t) ); + paliashdr->posedata = (byte *)verts - (byte *)paliashdr; + for (i=0 ; inumposes ; i++) + for (j=0 ; jcache); + if (r) + return r; + + Mod_LoadModel (mod, true); + + if (!mod->cache.data) + Sys_Error ("Mod_Extradata: caching failed"); + return mod->cache.data; +} + +/* +=============== +Mod_PointInLeaf +=============== +*/ +mleaf_t *Mod_PointInLeaf (float *p, model_t *model) +{ + mnode_t *node; + float d; + mplane_t *plane; + + if (!model || !model->nodes) + Sys_Error ("Mod_PointInLeaf: bad model"); + + node = model->nodes; + while (1) + { + if (node->contents < 0) + return (mleaf_t *)node; + plane = node->plane; + d = DotProduct (p,plane->normal) - plane->dist; + if (d > 0) + node = node->children[0]; + else + node = node->children[1]; + } + + return NULL; // never reached +} + + +/* +=================== +Mod_DecompressVis +=================== +*/ +byte *Mod_DecompressVis (byte *in, model_t *model) +{ + static byte decompressed[MAX_MAP_LEAFS/8]; + int c; + byte *out; + int row; + + row = (model->numleafs+7)>>3; + out = decompressed; + +#if 0 + memcpy (out, in, row); +#else + if (!in) + { // no vis info, so make all visible + while (row) + { + *out++ = 0xff; + row--; + } + return decompressed; + } + + do + { + if (*in) + { + *out++ = *in++; + continue; + } + + c = in[1]; + in += 2; + while (c) + { + *out++ = 0; + c--; + } + } while (out - decompressed < row); +#endif + + return decompressed; +} + +byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) +{ + if (leaf == model->leafs) + return mod_novis; + return Mod_DecompressVis (leaf->compressed_vis, model); +} + +/* +=================== +Mod_ClearAll +=================== +*/ +void Mod_ClearAll (void) +{ + int i; + model_t *mod; + + for (i=0 , mod=mod_known ; itype != mod_alias) + mod->needload = true; +} + +/* +================== +Mod_FindName + +================== +*/ +model_t *Mod_FindName (char *name) +{ + int i; + model_t *mod; + + if (!name[0]) + Sys_Error ("Mod_ForName: NULL name"); + +// +// search the currently loaded models +// + for (i=0 , mod=mod_known ; iname, name) ) + break; + + if (i == mod_numknown) + { + if (mod_numknown == MAX_MOD_KNOWN) + Sys_Error ("mod_numknown == MAX_MOD_KNOWN"); + strcpy (mod->name, name); + mod->needload = true; + mod_numknown++; + } + + return mod; +} + +/* +================== +Mod_TouchModel + +================== +*/ +void Mod_TouchModel (char *name) +{ + model_t *mod; + + mod = Mod_FindName (name); + + if (!mod->needload) + { + if (mod->type == mod_alias) + Cache_Check (&mod->cache); + } +} + +/* +================== +Mod_LoadModel + +Loads a model into the cache +================== +*/ +model_t *Mod_LoadModel (model_t *mod, qboolean crash) +{ + void *d; + unsigned *buf; + byte stackbuf[1024]; // avoid dirtying the cache heap + + if (!mod->needload) + { + if (mod->type == mod_alias) + { + d = Cache_Check (&mod->cache); + if (d) + return mod; + } + else + return mod; // not cached at all + } + +// +// because the world is so huge, load it one piece at a time +// + if (!crash) + { + + } + +// +// load the file +// + buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); + if (!buf) + { + // Reload with another .mdl + + buf = (unsigned *)COM_LoadStackFile("models/missing_model.mdl", stackbuf, sizeof(stackbuf)); + if (buf) + { + Con_Printf ("Missing model %s substituted\n", mod->name); + } + + return NULL; + } + +// +// allocate a new model +// + COM_FileBase (mod->name, loadname); + + loadmodel = mod; + +// +// fill it in +// + +// call the apropriate loader + mod->needload = false; + + switch (LittleLong(*(unsigned *)buf)) + { + case IDPOLYHEADER: + Mod_LoadAliasModel (mod, buf); + break; + + case IDSPRITEHEADER: + Mod_LoadSpriteModel (mod, buf); + break; + + default: + Mod_LoadBrushModel (mod, buf); + break; + } + + return mod; +} + +/* +================== +Mod_ForName + +Loads in a model for the given name +================== +*/ +model_t *Mod_ForName (char *name, qboolean crash) +{ + model_t *mod; + + mod = Mod_FindName (name); + + return Mod_LoadModel (mod, crash); +} + + +/* +=============================================================================== + + BRUSHMODEL LOADING + +=============================================================================== +*/ + +byte *mod_base; + + +/* +================= +Mod_ParseWadsFromEntityLump +For Half-life maps +================= +*/ +#if 0 +static void Mod_ParseWadsFromEntityLump(char *data) +{ + char *s, key[1024], value[1024]; + int i, j, k; + + if (!data || !(data = COM_Parse(data))) + return; + + if (com_token[0] != '{') + return; // error + + while (1) + { + if (!(data = COM_Parse(data))) + return; // error + + if (com_token[0] == '}') + break; // end of worldspawn + + Q_strncpyz(key, (com_token[0] == '_') ? com_token + 1 : com_token, sizeof(key)); + + for (s = key + strlen(key) - 1; s >= key && *s == ' '; s--) // remove trailing spaces + *s = 0; + + if (!(data = COM_Parse(data))) + return; // error + + Q_strncpyz(value, com_token, sizeof(value)); + + if (!strcmp("MaxRange", key)) + Cvar_Set("r_maxrange", value); + + if (!strcmp("wad", key)) + { + j = 0; + for (i = 0; i < strlen(value); i++) + { + if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':') + break; + } + if (!value[i]) + continue; + for ( ; i < sizeof(value); i++) + { + // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'... + if (value[i] == '\\' || value[i] == '/' || value[i] == ':') + { + j = i + 1; + } + else if (value[i] == ';' || value[i] == 0) + { + k = value[i]; + value[i] = 0; + if (value[j]) + WAD3_LoadTextureWadFile (value + j); + j = i + 1; + if (!k) + break; + } + } + } + } +} +#endif +/* +================= +Mod_LoadTextures +================= +*/ +byte *WAD3_LoadTexture(miptex_t *mt); +void Mod_LoadTextures (lump_t *l) +{ + int i, j,/* pixels, */num, max, altmax; + miptex_t *mt; + texture_t *tx, *tx2; + texture_t *anims[10]; + texture_t *altanims[10]; + dmiptexlump_t *m; + char filename[MAX_OSPATH], mapname[64]; + int data_ext; + + byte *data; + + if (!l->filelen) + { + loadmodel->textures = NULL; + return; + } + m = (dmiptexlump_t *)(mod_base + l->fileofs); + + m->nummiptex = LittleLong (m->nummiptex); + + loadmodel->numtextures = m->nummiptex; + loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); + + loading_num_step = loading_num_step + m->nummiptex; + + //if (loadmodel->bspversion == HL_BSPVERSION) + //Mod_ParseWadsFromEntityLump(loadmodel->entities); + + for (i=0 ; inummiptex ; i++) + { + m->dataofs[i] = LittleLong(m->dataofs[i]); + if (m->dataofs[i] == -1) + continue; + mt = (miptex_t *)((byte *)m + m->dataofs[i]); + mt->width = LittleLong (mt->width); + mt->height = LittleLong (mt->height); + for (j=0 ; joffsets[j] = LittleLong (mt->offsets[j]); + + if ( (mt->width & 15) || (mt->height & 15) ) + Sys_Error ("Texture %s is not 16 aligned", mt->name); + //pixels = mt->width*mt->height/64*85; + tx = Hunk_AllocName (sizeof(texture_t)/* +pixels*/, loadname ); + loadmodel->textures[i] = tx; + + memcpy (tx->name, mt->name, sizeof(tx->name)); + tx->width = mt->width; + tx->height = mt->height; + for (j=0 ; joffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); + // the pixels immediately follow the structures + //memcpy ( tx+1, mt+1, pixels); + + + if (loadmodel->bspversion != HL_BSPVERSION && !strncmp(mt->name,"sky",3)) { + R_InitSky (mt); + } else { + if (loadmodel->bspversion == HL_BSPVERSION) { + if (1) { + data = WAD3_LoadTexture(mt); + + bool choosealpha = mt->name[0] == '{' ? true : false; // naievil -- need to choose alpha mode for certain textures + if(data == NULL) + { + //external textures -- first look in "textures/mapname/" then look in "textures/" + + // sB WIP and still undecided if we want this feature on Wii. + // if it is included, maybe it should only be a backup to maps + // which weren't compiled with -nowadtextures + // this does work as a backup option ATM anyways..// + + + //mark = Hunk_LowMark (); + COM_StripExtension (loadmodel->name + 5, mapname); + //sprintf (filename, "textures/%s/%s", mapname, tx->name); + // don't keep map textures + data_ext = loadtextureimage (filename, 0, 0, true, true, false); + if (data_ext <= 0) + { + //Con_Printf ("mpath %s\n", filename); + sprintf (filename, "textures/%s", tx->name); + data_ext = loadtextureimage (filename, 0, 0, true, true, false); + if (data_ext <= 0) { + //Con_Printf ("mpath %s\n", filename); + //Con_Printf("no texture found, replacing with white (fixme) %s\n", tx->name); + tx->gl_texturenum = white_texturenum; + } + } + //Hunk_FreeToLowMark (mark); + } else { + tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(data), true, choosealpha, false, 4); + free(data); + } + } + } + else { + tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false, false, 1); + } + + } + strcpy(loading_name, mt->name); + loading_cur_step++; + SCR_UpdateScreen(); + } + +// +// sequence the animations +// + for (i=0 ; inummiptex ; i++) + { + tx = loadmodel->textures[i]; + if (!tx || tx->name[0] != '+') + continue; + if (tx->anim_next) + continue; // allready sequenced + + // find the number of frames in the animation + memset (anims, 0, sizeof(anims)); + memset (altanims, 0, sizeof(altanims)); + + max = tx->name[1]; + altmax = 0; + if (max >= 'a' && max <= 'z') + max -= 'a' - 'A'; + if (max >= '0' && max <= '9') + { + max -= '0'; + altmax = 0; + anims[max] = tx; + max++; + } + else if (max >= 'A' && max <= 'J') + { + altmax = max - 'A'; + max = 0; + altanims[altmax] = tx; + altmax++; + } + else + Sys_Error ("Bad animating texture %s", tx->name); + + for (j=i+1 ; jnummiptex ; j++) + { + tx2 = loadmodel->textures[j]; + if (!tx2 || tx2->name[0] != '+') + continue; + if (strcmp (tx2->name+2, tx->name+2)) + continue; + + num = tx2->name[1]; + if (num >= 'a' && num <= 'z') + num -= 'a' - 'A'; + if (num >= '0' && num <= '9') + { + num -= '0'; + anims[num] = tx2; + if (num+1 > max) + max = num + 1; + } + else if (num >= 'A' && num <= 'J') + { + num = num - 'A'; + altanims[num] = tx2; + if (num+1 > altmax) + altmax = num+1; + } + else + Sys_Error ("Bad animating texture %s", tx->name); + } + +#define ANIM_CYCLE 2 + // link them all together + for (j=0 ; jname); + tx2->anim_total = max * ANIM_CYCLE; + tx2->anim_min = j * ANIM_CYCLE; + tx2->anim_max = (j+1) * ANIM_CYCLE; + tx2->anim_next = anims[ (j+1)%max ]; + if (altmax) + tx2->alternate_anims = altanims[0]; + } + for (j=0 ; jname); + tx2->anim_total = altmax * ANIM_CYCLE; + tx2->anim_min = j * ANIM_CYCLE; + tx2->anim_max = (j+1) * ANIM_CYCLE; + tx2->anim_next = altanims[ (j+1)%altmax ]; + if (max) + tx2->alternate_anims = anims[0]; + } + } +} + +/* +================= +Mod_LoadLighting +================= +*/ +void Mod_LoadLighting (lump_t *l) +{ + // LordHavoc: .lit support begin + int i; + byte *in, *out, *data; + byte d; + char litfilename[128]; //1024?? + loadmodel->lightdata = NULL; + + // Diabolickal HLBSP + if (loadmodel->bspversion == HL_BSPVERSION) + { + if (!l->filelen) + { + return; + } + loadmodel->lightdata = (Hunk_AllocName ( l->filelen, loadname)); + memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); + return; + } + + // LordHavoc: check for a .lit file + strcpy(litfilename, loadmodel->name); + COM_StripExtension(litfilename, litfilename); + strcat(litfilename, ".lit"); + data = (byte*) COM_LoadHunkFile (litfilename); + if (data) + { + if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T') + { + i = LittleLong(((int *)data)[1]); + if (i == 1) + { + Con_DPrintf("%s loaded", litfilename); + + loadmodel->lightdata = data + 8; + return; + } + else + Con_Printf("Unknown .lit file version (%d)\n", i); + } + else + Con_Printf("Corrupt .lit file (old version?), ignoring\n"); + } + + // LordHavoc: no .lit found, expand the white lighting data to color + if (!l->filelen) + return; + loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, litfilename); + in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write + out = loadmodel->lightdata; + memcpy (in, mod_base + l->fileofs, l->filelen); + for (i = 0;i < l->filelen;i++) + { + d = *in++; + *out++ = d; + *out++ = d; + *out++ = d; + } + // LordHavoc: .lit support end + + //loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname); + //memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); +} + + +/* +================= +Mod_LoadVisibility +================= +*/ +void Mod_LoadVisibility (lump_t *l) +{ + if (!l->filelen) + { + loadmodel->visdata = NULL; + return; + } + loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname); + memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); +} + +/* +================= +Mod_LoadEntities +================= +*/ +void Mod_LoadEntities (lump_t *l) +{ + if (!l->filelen) + { + loadmodel->entities = NULL; + return; + } + loadmodel->entities = Hunk_AllocName ( l->filelen, loadname); + memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); +} + + +/* +================= +Mod_LoadVertexes +================= +*/ +void Mod_LoadVertexes (lump_t *l) +{ + dvertex_t *in; + mvertex_t *out; + int i, count; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name); + + count = l->filelen / sizeof(*in); + out = Hunk_AllocName(count * sizeof(*out), loadname); + + loadmodel->vertexes = out; + loadmodel->numvertexes = count; + + for (i = 0; i < count; i++, in++, out++) + { + out->position[0] = LittleFloat(in->point[0]); + out->position[1] = LittleFloat(in->point[1]); + out->position[2] = LittleFloat(in->point[2]); + } +} + +/* +================= +Mod_LoadSubmodels +================= +*/ +void Mod_LoadSubmodels (lump_t *l) +{ + dmodel_t *in; + dmodel_t *out; + int i, j, count; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->submodels = out; + loadmodel->numsubmodels = count; + + for ( i=0 ; imins[j] = LittleFloat (in->mins[j]) - 1; + out->maxs[j] = LittleFloat (in->maxs[j]) + 1; + out->origin[j] = LittleFloat (in->origin[j]); + } + for (j=0 ; jheadnode[j] = LittleLong (in->headnode[j]); + out->visleafs = LittleLong (in->visleafs); + out->firstface = LittleLong (in->firstface); + out->numfaces = LittleLong (in->numfaces); + } +} + +/* +================= +Mod_LoadEdges +================= +*/ +void Mod_LoadEdges (lump_t *l) +{ + dedge_t *in; + medge_t *out; + int i, count; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); + + loadmodel->edges = out; + loadmodel->numedges = count; + + for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); + out->v[1] = (unsigned short)LittleShort(in->v[1]); + } +} + +/* +================= +Mod_LoadTexinfo +================= +*/ +void Mod_LoadTexinfo (lump_t *l) +{ + texinfo_t *in; + mtexinfo_t *out; + int i, j, count; + int miptex; + float len1, len2; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->texinfo = out; + loadmodel->numtexinfo = count; + + for ( i=0 ; ivecs[0][j] = LittleFloat (in->vecs[0][j]); + len1 = Length (out->vecs[0]); + len2 = Length (out->vecs[1]); + len1 = (len1 + len2)/2; + if (len1 < 0.32) + out->mipadjust = 4; + else if (len1 < 0.49) + out->mipadjust = 3; + else if (len1 < 0.99) + out->mipadjust = 2; + else + out->mipadjust = 1; +#if 0 + if (len1 + len2 < 0.001) + out->mipadjust = 1; // don't crash + else + out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); +#endif + + miptex = LittleLong (in->miptex); + out->flags = LittleLong (in->flags); + + if (!loadmodel->textures) + { + out->texture = r_notexture_mip; // checkerboard texture + out->flags = 0; + } + else + { + if (miptex >= loadmodel->numtextures) + Sys_Error ("miptex >= loadmodel->numtextures"); + out->texture = loadmodel->textures[miptex]; + if (!out->texture) + { + out->texture = r_notexture_mip; // texture not found + out->flags = 0; + } + } + } +} + +/* +================ +CalcSurfaceExtents + +Fills in s->texturemins[] and s->extents[] +================ +*/ +void CalcSurfaceExtents (msurface_t *s) +{ + float mins[2], maxs[2], val; + int i,j, e; + mvertex_t *v; + mtexinfo_t *tex; + int bmins[2], bmaxs[2]; + + mins[0] = mins[1] = 999999; + maxs[0] = maxs[1] = -99999; + + tex = s->texinfo; + + for (i=0 ; inumedges ; i++) + { + e = loadmodel->surfedges[s->firstedge+i]; + if (e >= 0) + v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; + else + v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; + + for (j=0 ; j<2 ; j++) + { + val = v->position[0] * tex->vecs[j][0] + + v->position[1] * tex->vecs[j][1] + + v->position[2] * tex->vecs[j][2] + + tex->vecs[j][3]; + if (val < mins[j]) + mins[j] = val; + if (val > maxs[j]) + maxs[j] = val; + } + } + + for (i=0 ; i<2 ; i++) + { + bmins[i] = floor(mins[i]/16); + bmaxs[i] = ceil(maxs[i]/16); + + s->texturemins[i] = bmins[i] * 16; + s->extents[i] = (bmaxs[i] - bmins[i]) * 16; + if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ ) + Sys_Error ("Bad surface extents"); + } +} + + +/* +================= +Mod_LoadFaces +================= +*/ +extern char skybox_name[32]; +void Mod_LoadFaces (lump_t *l) +{ + dface_t *in; + msurface_t *out; + int i, count, surfnum; + int planenum, side; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->surfaces = out; + loadmodel->numsurfaces = count; + + for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); + out->numedges = LittleShort(in->numedges); + out->flags = 0; + + planenum = LittleShort(in->planenum); + side = LittleShort(in->side); + if (side) + out->flags |= SURF_PLANEBACK; + + out->plane = loadmodel->planes + planenum; + + out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); + + CalcSurfaceExtents (out); + + // lighting info + for (i=0 ; istyles[i] = in->styles[i]; + + if (loadmodel->bspversion == HL_BSPVERSION) //Diabolickal HLBSP + i = LittleLong(in->lightofs)/3; + else + i = LittleLong(in->lightofs); + if (i == -1) + out->samples = NULL; + else + out->samples = loadmodel->lightdata + (i * 3); + + // set the drawing flags flag + + if (!strncmp(out->texinfo->texture->name,"sky",3)) // sky + { + out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); +#ifndef QUAKE2 + GL_SubdivideSurface (out); // cut up polygon for warps +#endif + continue; + } + + if (!strncmp(out->texinfo->texture->name,"nodraw",6) || !strncmp(out->texinfo->texture->name,"NODRAW",6)) { + out->flags |= TEXFLAG_NODRAW; + continue; + } + + if (strstr(out->texinfo->texture->name,"light")) { + out->flags |= TEXFLAG_LIGHT; + continue; + } + + if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent + { + out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); + for (i=0 ; i<2 ; i++) + { + out->extents[i] = 16384; + out->texturemins[i] = -8192; + } + GL_SubdivideSurface (out); // cut up polygon for warps + continue; + } + + } +} + + +/* +================= +Mod_SetParent +================= +*/ +void Mod_SetParent (mnode_t *node, mnode_t *parent) +{ + node->parent = parent; + if (node->contents < 0) + return; + Mod_SetParent (node->children[0], node); + Mod_SetParent (node->children[1], node); +} + +/* +================= +Mod_LoadNodes +================= +*/ +void Mod_LoadNodes (lump_t *l) +{ + int i, j, count, p; + dnode_t *in; + mnode_t *out; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->nodes = out; + loadmodel->numnodes = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleShort (in->firstface); + out->numsurfaces = LittleShort (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleShort (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } + } + + Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs +} + +/* +================= +Mod_LoadLeafs +================= +*/ +void Mod_LoadLeafs (lump_t *l) +{ + dleaf_t *in; + mleaf_t *out; + int i, j, count, p; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->leafs = out; + loadmodel->numleafs = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->contents); + out->contents = p; + + out->firstmarksurface = loadmodel->marksurfaces + + LittleShort(in->firstmarksurface); + out->nummarksurfaces = LittleShort(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + out->efrags = NULL; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + + // gl underwater warp + if (out->contents != CONTENTS_EMPTY) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_UNDERWATER; + } + } +} + +/* +================= +Mod_LoadClipnodes +================= +*/ +void Mod_LoadClipnodes (lump_t *l) +{ + dclipnode_t *in, *out; + int i, count; + hull_t *hull; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->clipnodes = out; + loadmodel->numclipnodes = count; + + if (loadmodel->bspversion == HL_BSPVERSION) //Diabolickal HLBSP + { + hull = &loadmodel->hulls[1]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -36; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 36; + + hull = &loadmodel->hulls[2]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -32; + hull->clip_mins[1] = -32; + hull->clip_mins[2] = -32; + hull->clip_maxs[0] = 32; + hull->clip_maxs[1] = 32; + hull->clip_maxs[2] = 32; + + hull = &loadmodel->hulls[3]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -18; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 18; + } else { + + hull = &loadmodel->hulls[1]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 32; + + hull = &loadmodel->hulls[2]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -32; + hull->clip_mins[1] = -32; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 32; + hull->clip_maxs[1] = 32; + hull->clip_maxs[2] = 64; + } + for (i=0 ; iplanenum = LittleLong(in->planenum); + out->children[0] = LittleShort(in->children[0]); + out->children[1] = LittleShort(in->children[1]); + } +} + +/* +================= +Mod_MakeHull0 + +Deplicate the drawing hull structure as a clipping hull +================= +*/ +void Mod_MakeHull0 (void) +{ + mnode_t *in, *child; + dclipnode_t *out; + int i, j, count; + hull_t *hull; + + hull = &loadmodel->hulls[0]; + + in = loadmodel->nodes; + count = loadmodel->numnodes; + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + + for (i=0 ; iplanenum = in->plane - loadmodel->planes; + for (j=0 ; j<2 ; j++) + { + child = in->children[j]; + if (child->contents < 0) + out->children[j] = child->contents; + else + out->children[j] = child - loadmodel->nodes; + } + } +} + +/* +================= +Mod_LoadMarksurfaces +================= +*/ +void Mod_LoadMarksurfaces (lump_t *l) +{ + int i, j, count; + short *in; + msurface_t **out; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->marksurfaces = out; + loadmodel->nummarksurfaces = count; + + for ( i=0 ; i= loadmodel->numsurfaces) + Sys_Error ("Mod_ParseMarksurfaces: bad surface number"); + out[i] = loadmodel->surfaces + j; + } +} + +/* +================= +Mod_LoadSurfedges +================= +*/ +void Mod_LoadSurfedges (lump_t *l) +{ + int i, count; + int *in, *out; + + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->surfedges = out; + loadmodel->numsurfedges = count; + + for ( i=0 ; ifileofs); + if (l->filelen % sizeof(*in)) + Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*2*sizeof(*out), loadname); + + loadmodel->planes = out; + loadmodel->numplanes = count; + + for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); + if (out->normal[j] < 0) + bits |= 1<dist = LittleFloat (in->dist); + out->type = LittleLong (in->type); + out->signbits = bits; + } +} + +/* +================= +RadiusFromBounds +================= +*/ +float RadiusFromBounds (vec3_t mins, vec3_t maxs) +{ + int i; + vec3_t corner; + + for (i=0 ; i<3 ; i++) + { + corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]); + } + + return Length (corner); +} + +/* +================= +Mod_LoadBrushModel +================= +*/ +void Mod_LoadBrushModel (model_t *mod, void *buffer) +{ + int i, j; + dheader_t *header; + dmodel_t *bm; + + loadmodel->type = mod_brush; + + header = (dheader_t *)buffer; + i = LittleLong (header->version); + mod->bspversion = LittleLong (header->version); + + if (mod->bspversion != BSPVERSION && mod->bspversion != HL_BSPVERSION) + Host_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i (Quake) or %i (HalfLife))", mod->name, mod->bspversion, BSPVERSION, HL_BSPVERSION); + +// swap all the lumps + mod_base = (byte *)header; + + for (i=0 ; ilumps[LUMP_VERTEXES]); + loading_cur_step++; + strcpy(loading_name, "Edges"); + SCR_UpdateScreen (); + Mod_LoadEdges (&header->lumps[LUMP_EDGES]); + loading_cur_step++; + strcpy(loading_name, "Surfedges"); + SCR_UpdateScreen (); + Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); + loading_cur_step++; + strcpy(loading_name, "Textures"); + SCR_UpdateScreen (); + Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); + Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); + loading_cur_step++; + SCR_UpdateScreen (); + Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); + loading_cur_step++; + strcpy(loading_name, "Texinfo"); + SCR_UpdateScreen (); + Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); + loading_cur_step++; + strcpy(loading_name, "Faces"); + SCR_UpdateScreen (); + Mod_LoadFaces (&header->lumps[LUMP_FACES]); + loading_cur_step++; + strcpy(loading_name, "Marksurfaces"); + SCR_UpdateScreen (); + Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); + loading_cur_step++; + strcpy(loading_name, "Visibility"); + SCR_UpdateScreen (); + Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); + loading_cur_step++; + strcpy(loading_name, "Leafs"); + SCR_UpdateScreen (); + Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); + loading_cur_step++; + strcpy(loading_name, "Nodes"); + SCR_UpdateScreen (); + Mod_LoadNodes (&header->lumps[LUMP_NODES]); + loading_cur_step++; + strcpy(loading_name, "Clipnodes"); + SCR_UpdateScreen (); + Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); + loading_cur_step++; + strcpy(loading_name, "Entities"); + SCR_UpdateScreen (); + Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); + loading_cur_step++; + strcpy(loading_name, "Submodels"); + SCR_UpdateScreen (); + Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); + loading_cur_step++; + strcpy(loading_name, "Hull"); + SCR_UpdateScreen (); + Mod_MakeHull0 (); + + loading_cur_step++; + + loading_step = 3; + + strcpy(loading_name, "Screen"); + loading_cur_step++; + SCR_UpdateScreen (); + + mod->numframes = 2; // regular and alternate animation + +// +// set up the submodels (FIXME: this is confusing) +// + for (i=0 ; inumsubmodels ; i++) + { + bm = &mod->submodels[i]; + + mod->hulls[0].firstclipnode = bm->headnode[0]; + for (j=1 ; jhulls[j].firstclipnode = bm->headnode[j]; + mod->hulls[j].lastclipnode = mod->numclipnodes-1; + } + + mod->firstmodelsurface = bm->firstface; + mod->nummodelsurfaces = bm->numfaces; + + VectorCopy (bm->maxs, mod->maxs); + VectorCopy (bm->mins, mod->mins); + + mod->radius = RadiusFromBounds (mod->mins, mod->maxs); + + mod->numleafs = bm->visleafs; + + if (i < mod->numsubmodels-1) + { // duplicate the basic information + char name[12]; + + sprintf (name, "*%i", i+1); + loadmodel = Mod_FindName (name); + *loadmodel = *mod; + strcpy (loadmodel->name, name); + mod = loadmodel; + } + } +} + +/* +============================================================================== + +ALIAS MODELS + +============================================================================== +*/ + +aliashdr_t *pheader; + +stvert_t stverts[MAXALIASVERTS]; +mtriangle_t triangles[MAXALIASTRIS]; + +// a pose is a single set of vertexes. a frame may be +// an animating sequence of poses +trivertx_t *poseverts[MAXALIASFRAMES]; +int posenum; + +byte **player_8bit_texels_tbl; +byte *player_8bit_texels; + +int aliasbboxmins[3], aliasbboxmaxs[3]; + +/* +================= +Mod_LoadAliasFrame +================= +*/ +void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame) +{ + trivertx_t *pinframe; + int i; + daliasframe_t *pdaliasframe; + + pdaliasframe = (daliasframe_t *)pin; + + strcpy (frame->name, pdaliasframe->name); + frame->firstpose = posenum; + frame->numposes = 1; + + for (i=0 ; i<3 ; i++) + { + // these are byte values, so we don't have to worry about + // endianness + frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i]; + frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i]; + + //aliasbboxmins[i] = min (frame->bboxmin.v[i], aliasbboxmins[i]); + //aliasbboxmaxs[i] = max (frame->bboxmax.v[i], aliasbboxmaxs[i]); + } + + pinframe = (trivertx_t *)(pdaliasframe + 1); + + poseverts[posenum] = pinframe; + posenum++; + + pinframe += pheader->numverts; + + return (void *)pinframe; +} + + +/* +================= +Mod_LoadAliasGroup +================= +*/ +void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame) +{ + daliasgroup_t *pingroup; + int i, numframes; + daliasinterval_t *pin_intervals; + void *ptemp; + + pingroup = (daliasgroup_t *)pin; + + numframes = LittleLong (pingroup->numframes); + + frame->firstpose = posenum; + frame->numposes = numframes; + + for (i=0 ; i<3 ; i++) + { + // these are byte values, so we don't have to worry about endianness + frame->bboxmin.v[i] = pingroup->bboxmin.v[i]; + frame->bboxmin.v[i] = pingroup->bboxmax.v[i]; + + //aliasbboxmins[i] = min (frame->bboxmin.v[i], aliasbboxmins[i]); + //aliasbboxmaxs[i] = max (frame->bboxmax.v[i], aliasbboxmaxs[i]); + } + + pin_intervals = (daliasinterval_t *)(pingroup + 1); + + frame->interval = LittleFloat (pin_intervals->interval); + + pin_intervals += numframes; + + ptemp = (void *)pin_intervals; + + for (i=0 ; inumverts; + } + + return ptemp; +} + +//========================================================= + +/* +================= +Mod_FloodFillSkin + +Fill background pixels so mipmapping doesn't have haloes - Ed +================= +*/ + +typedef struct +{ + short x, y; +} floodfill_t; + +extern unsigned d_8to24table[]; + +// must be a power of 2 +#define FLOODFILL_FIFO_SIZE 0x1000 +#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1) + +#define FLOODFILL_STEP( off, dx, dy ) \ +{ \ + if (pos[off] == fillcolor) \ + { \ + pos[off] = 255; \ + fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \ + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \ + } \ + else if (pos[off] != 255) fdc = pos[off]; \ +} + +void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight ) +{ + byte fillcolor = *skin; // assume this is the pixel to fill + floodfill_t fifo[FLOODFILL_FIFO_SIZE]; + int inpt = 0, outpt = 0; + int filledcolor = -1; + int i; + + if (filledcolor == -1) + { + filledcolor = 0; + // attempt to find opaque black + for (i = 0; i < 256; ++i) + if (d_8to24table[i] == (255 << 0)) // alpha 1.0 + { + filledcolor = i; + break; + } + } + + // can't fill to filled color or to transparent color (used as visited marker) + if ((fillcolor == filledcolor) || (fillcolor == 255)) + { + //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor ); + return; + } + + fifo[inpt].x = 0, fifo[inpt].y = 0; + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + + while (outpt != inpt) + { + int x = fifo[outpt].x, y = fifo[outpt].y; + int fdc = filledcolor; + byte *pos = &skin[x + skinwidth * y]; + + outpt = (outpt + 1) & FLOODFILL_FIFO_MASK; + + if (x > 0) FLOODFILL_STEP( -1, -1, 0 ); + if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 ); + if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 ); + if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 ); + skin[x + skinwidth * y] = fdc; + } +} + +/* +=============== +Mod_LoadAllSkins +=============== +*/ +void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype) +{ + int i, j, k; + char name[128], model[128], model2[256]; + char *texname = malloc(32); + int s; + byte *skin; + byte *texels; + daliasskingroup_t *pinskingroup; + int groupskins; + daliasskininterval_t *pinskinintervals; + + skin = (byte *)(pskintype + 1); + + if (numskins < 1 || numskins > MAX_SKINS) + Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); + + s = pheader->skinwidth * pheader->skinheight; + + // + // General texture override stuff. + // + + // Mustang & Sally // v_biatch + + if (strcmp(loadmodel->name, "models/weapons/m1911/v_biatch_left.mdl") == 0 || + strcmp(loadmodel->name, "models/weapons/m1911/v_biatch_right.mdl") == 0) { + pheader->gl_texturenum[0][0] = + pheader->gl_texturenum[0][1] = + pheader->gl_texturenum[0][2] = + pheader->gl_texturenum[0][3] = loadtextureimage("models/weapons/m1911/v_biatch.mdl_0", 0, 0, true, false, true); + + pheader->gl_texturenum[1][0] = + pheader->gl_texturenum[1][1] = + pheader->gl_texturenum[1][2] = + pheader->gl_texturenum[1][3] = loadtextureimage("models/weapons/m1911/v_biatch.mdl_0", 0, 0, true, false, true); + + pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s); + return (void *)pskintype; + } + + for (i=0 ; itype == ALIAS_SKIN_SINGLE) { + Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight ); + COM_StripExtension(loadmodel->name, model); + + texels = Hunk_AllocName(s, loadname); + pheader->texels[i] = texels - (byte *)pheader; + memcpy (texels, (byte *)(pskintype + 1), s); + + // HACK HACK HACK + sprintf(model2, "%s.mdl_%i", model, i); + pheader->gl_texturenum[i][0] = + pheader->gl_texturenum[i][1] = + pheader->gl_texturenum[i][2] = + pheader->gl_texturenum[i][3] = loadtextureimage(model2, 0, 0, true, false, true); + + if (pheader->gl_texturenum[i][0] == 0) // did not find a matching TGA... + { + sprintf(name, "%s_%i", loadmodel->name, i); + int len = strlen(name); + texname = name + len - 20; + pheader->gl_texturenum[i][0] = + pheader->gl_texturenum[i][1] = + pheader->gl_texturenum[i][2] = + pheader->gl_texturenum[i][3] = GL_LoadTexture (texname, pheader->skinwidth, pheader->skinheight, (byte *)(pskintype + 1), false, false, true, 1); + } + + pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s); + } else { + // animating skin group. yuck. + pskintype++; + pinskingroup = (daliasskingroup_t *)pskintype; + groupskins = LittleLong (pinskingroup->numskins); + pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); + + pskintype = (void *)(pinskinintervals + groupskins); + + for (j=0 ; jskinwidth, pheader->skinheight ); + if (j == 0) { + texels = Hunk_AllocName(s, loadname); + pheader->texels[i] = texels - (byte *)pheader; + memcpy (texels, (byte *)(pskintype), s); + } + sprintf (name, "%s_%i_%i", loadmodel->name, i,j); + int len = strlen(name); + texname = name + len - 20; + pheader->gl_texturenum[i][j&3] = GL_LoadTexture (texname, pheader->skinwidth, + pheader->skinheight, (byte *)(pskintype), false, false, true, 1); + pskintype = (daliasskintype_t *)((byte *)(pskintype) + s); + } + k = j; + for (/* */; j < 4; j++) + pheader->gl_texturenum[i][j&3] = + pheader->gl_texturenum[i][j - k]; + } + } + + return (void *)pskintype; +} + +//========================================================================= + +/* +================= +Mod_LoadAliasModel +================= +*/ +void Mod_LoadAliasModel (model_t *mod, void *buffer) +{ + int i, j; + mdl_t *pinmodel; + stvert_t *pinstverts; + dtriangle_t *pintriangles; + int version, numframes; + int size; + daliasframetype_t *pframetype; + daliasskintype_t *pskintype; + int start, end, total; + + start = Hunk_LowMark (); + + pinmodel = (mdl_t *)buffer; + + version = LittleLong (pinmodel->version); + if (version != ALIAS_VERSION) + Sys_Error ("%s has wrong version number (%i should be %i)", + mod->name, version, ALIAS_VERSION); + +// +// allocate space for a working header, plus all the data except the frames, +// skin and group info +// + size = sizeof (aliashdr_t) + + (LittleLong (pinmodel->numframes) - 1) * + sizeof (pheader->frames[0]); + pheader = Hunk_AllocName (size, loadname); + + mod->flags = LittleLong (pinmodel->flags); + +// +// endian-adjust and copy the data, starting with the alias model header +// + pheader->boundingradius = LittleFloat (pinmodel->boundingradius); + pheader->numskins = LittleLong (pinmodel->numskins); + pheader->skinwidth = LittleLong (pinmodel->skinwidth); + pheader->skinheight = LittleLong (pinmodel->skinheight); + + if (pheader->skinheight > MAX_LBM_HEIGHT) + Sys_Error ("model %s has a skin taller than %d", mod->name, + MAX_LBM_HEIGHT); + + pheader->numverts = LittleLong (pinmodel->numverts); + + if (pheader->numverts <= 0) + Sys_Error ("model %s has no vertices", mod->name); + + if (pheader->numverts > MAXALIASVERTS) + Sys_Error ("model %s has too many vertices", mod->name); + + pheader->numtris = LittleLong (pinmodel->numtris); + + if (pheader->numtris <= 0) + Sys_Error ("model %s has no triangles", mod->name); + + pheader->numframes = LittleLong (pinmodel->numframes); + numframes = pheader->numframes; + if (numframes < 1) + Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); + + pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; + mod->synctype = LittleLong (pinmodel->synctype); + mod->numframes = pheader->numframes; + + for (i=0 ; i<3 ; i++) + { + pheader->scale[i] = LittleFloat (pinmodel->scale[i]); + pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); + pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); + } + + +// +// load the skins +// + pskintype = (daliasskintype_t *)&pinmodel[1]; + pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype); + +// +// load base s and t vertices +// + pinstverts = (stvert_t *)pskintype; + + for (i=0 ; inumverts ; i++) + { + stverts[i].onseam = LittleLong (pinstverts[i].onseam); + stverts[i].s = LittleLong (pinstverts[i].s); + stverts[i].t = LittleLong (pinstverts[i].t); + } + +// +// load triangle lists +// + pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts]; + + for (i=0 ; inumtris ; i++) + { + triangles[i].facesfront = LittleLong (pintriangles[i].facesfront); + + for (j=0 ; j<3 ; j++) + { + triangles[i].vertindex[j] = + LittleLong (pintriangles[i].vertindex[j]); + } + } + +// +// load the frames +// + posenum = 0; + pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris]; + + aliasbboxmins[0] = aliasbboxmins[1] = aliasbboxmins[2] = 99999; + aliasbboxmaxs[0] = aliasbboxmaxs[1] = aliasbboxmaxs[2] = -99999; + + for (i=0 ; itype); + + if (frametype == ALIAS_SINGLE) + { + pframetype = (daliasframetype_t *) + Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]); + } + else + { + pframetype = (daliasframetype_t *) + Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]); + } + } + + pheader->numposes = posenum; + + mod->type = mod_alias; +/* + for (i = 0; i < 3; i++) + { + // ELUTODO - we always have a minimum size of -16...16 + mod->mins[i] = min(-16, aliasbboxmins[i] * pheader->scale[i] + pheader->scale_origin[i]); + mod->maxs[i] = max(16, aliasbboxmaxs[i] * pheader->scale[i] + pheader->scale_origin[i]); + } +*/ + // FIXME: do this right + mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; + mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; + + // + // build the draw lists + // + GL_MakeAliasModelDisplayLists (mod, pheader); + +// +// move the complete, relocatable alias model to the cache +// + end = Hunk_LowMark (); + total = end - start; + + Cache_Alloc (&mod->cache, total, loadname); + if (!mod->cache.data) + return; + memcpy (mod->cache.data, pheader, total); + + Hunk_FreeToLowMark (start); +} + +//============================================================================= + +/* +================= +Mod_LoadSpriteFrame +================= +*/ +void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum) +{ + dspriteframe_t *pinframe; + mspriteframe_t *pspriteframe; + int /*i, */width, height, size, origin[2]; + //unsigned short *ppixout; + //byte *ppixin; + char /*name[128], */sprite[128], sprite2[256]; + char *texname = malloc(32); + + pinframe = (dspriteframe_t *)pin; + + width = LittleLong (pinframe->width); + height = LittleLong (pinframe->height); + size = width * height; + + pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname); + + memset (pspriteframe, 0, sizeof (mspriteframe_t)); + + *ppframe = pspriteframe; + + pspriteframe->width = width; + pspriteframe->height = height; + origin[0] = LittleLong (pinframe->origin[0]); + origin[1] = LittleLong (pinframe->origin[1]); + + pspriteframe->up = origin[1]; + pspriteframe->down = origin[1] - height; + pspriteframe->left = origin[0]; + pspriteframe->right = width + origin[0]; + + //sprintf (name, "%s_%i", loadmodel->name, framenum); + //pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, true, 1); + + // HACK HACK HACK + //sprintf (name, "%s.spr_%i", loadmodel->name, framenum); + + COM_StripExtension(loadmodel->name, sprite); + sprintf(sprite2, "%s.spr_%i", sprite, framenum); + pspriteframe->gl_texturenum = loadtextureimage(sprite2, 0, 0, true, false, true); + + if (pspriteframe->gl_texturenum <= 0) // did not find a matching TGA... + { + //COM_StripExtension(loadmodel->name, sprite); + //sprintf(sprite2, "%s.spr", sprite); + //pspriteframe->gl_texturenum = loadtextureimage(sprite2, 0, 0, true, false, true); + int len = strlen(sprite2); + texname = sprite2 + len - 20; + if (pspriteframe->gl_texturenum <= 0) { + pspriteframe->gl_texturenum = GL_LoadTexture (texname, width, height, (byte *)(pinframe + 1), false, true, true, 1); + } + } + + return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size); +} + + +/* +================= +Mod_LoadSpriteGroup +================= +*/ +void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum) +{ + dspritegroup_t *pingroup; + mspritegroup_t *pspritegroup; + int i, numframes; + dspriteinterval_t *pin_intervals; + float *poutintervals; + void *ptemp; + + pingroup = (dspritegroup_t *)pin; + + numframes = LittleLong (pingroup->numframes); + + pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + + (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); + + pspritegroup->numframes = numframes; + + *ppframe = (mspriteframe_t *)pspritegroup; + + pin_intervals = (dspriteinterval_t *)(pingroup + 1); + + poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + + pspritegroup->intervals = poutintervals; + + for (i=0 ; iinterval); + if (*poutintervals <= 0.0) + Sys_Error ("Mod_LoadSpriteGroup: interval<=0"); + + poutintervals++; + pin_intervals++; + } + + ptemp = (void *)pin_intervals; + + for (i=0 ; iframes[i], framenum * 100 + i); + } + + return ptemp; +} + + +/* +================= +Mod_LoadSpriteModel +================= +*/ +void Mod_LoadSpriteModel (model_t *mod, void *buffer) +{ + int i; + int version; + dsprite_t *pin; + msprite_t *psprite; + int numframes; + int size; + dspriteframetype_t *pframetype; + + pin = (dsprite_t *)buffer; + + version = LittleLong (pin->version); + if (version != SPRITE_VERSION) + Sys_Error ("%s has wrong version number " + "(%i should be %i)", mod->name, version, SPRITE_VERSION); + + numframes = LittleLong (pin->numframes); + + size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); + + psprite = Hunk_AllocName (size, loadname); + + mod->cache.data = psprite; + + psprite->type = LittleLong (pin->type); + psprite->maxwidth = LittleLong (pin->width); + psprite->maxheight = LittleLong (pin->height); + psprite->beamlength = LittleFloat (pin->beamlength); + mod->synctype = LittleLong (pin->synctype); + psprite->numframes = numframes; + + mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; + mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; + mod->mins[2] = -psprite->maxheight/2; + mod->maxs[2] = psprite->maxheight/2; + +// +// load the frames +// + if (numframes < 1) + Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); + + mod->numframes = numframes; + + pframetype = (dspriteframetype_t *)(pin + 1); + + for (i=0 ; itype); + psprite->frames[i].type = frametype; + + if (frametype == SPR_SINGLE) + { + pframetype = (dspriteframetype_t *) + Mod_LoadSpriteFrame (pframetype + 1, + &psprite->frames[i].frameptr, i); + } + else + { + pframetype = (dspriteframetype_t *) + Mod_LoadSpriteGroup (pframetype + 1, + &psprite->frames[i].frameptr, i); + } + } + + mod->type = mod_sprite; +} + +//============================================================================= + +/* +================ +Mod_Print +================ +*/ +void Mod_Print (void) +{ + int i; + model_t *mod; + + Con_Printf ("Cached models:\n"); + for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) + { + Con_Printf ("%8p : %s\n",mod->cache.data, mod->name); + } +} diff --git a/source/wii/gx/gx_model.h b/source/wii/gx/gx_model.h new file mode 100644 index 0000000..403fa53 --- /dev/null +++ b/source/wii/gx/gx_model.h @@ -0,0 +1,468 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __MODEL__ +#define __MODEL__ + +#include "../modelgen.h" +#include "../../spritegn.h" + +/* + +d*_t structures are on-disk representations +m*_t structures are in-memory + +*/ + +// entity effects + +#define EF_BRIGHTFIELD 1 +#define EF_MUZZLEFLASH 2 +#define EF_BRIGHTLIGHT 4 +#define EF_REDLIGHT 8 +#define EF_ORANGELIGHT 16 +#define EF_GREENLIGHT 32 +#define EF_PINKLIGHT 64 // formerly EF_LIGHT +#define EF_NODRAW 128 +#define EF_LIMELIGHT 256 // formerly EF_BRIGHTFIELD +#define EF_FULLBRIGHT 512 +#define EF_CYANLIGHT 1024 // formerly EF_DARKLIGHT +#define EF_YELLOWLIGHT 2048 // formerly EF_DARKFIELD +#define EF_PURPLELIGHT 4096 +#define EF_RAYRED 8196 // red trail for porter x2 +#define EF_RAYGREEN 16384 // green trail for ray gun + +/* +============================================================================== + +BRUSH MODELS + +============================================================================== +*/ + + +// +// in memory representation +// +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + vec3_t position; +} mvertex_t; + +#define SIDE_FRONT 0 +#define SIDE_BACK 1 +#define SIDE_ON 2 + + +// plane_t structure +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct mplane_s +{ + vec3_t normal; + float dist; + byte type; // for texture axis selection and fast side tests + byte signbits; // signx + signy<<1 + signz<<1 + byte pad[2]; +} mplane_t; + +typedef struct texture_s +{ + char name[16]; + unsigned width, height; + int gl_texturenum; + struct msurface_s *texturechain; // for gl_texsort drawing + int anim_total; // total tenths in sequence ( 0 = no) + int anim_min, anim_max; // time for this frame min <=time< max + struct texture_s *anim_next; // in the animation sequence + struct texture_s *alternate_anims; // bmodels in frmae 1 use these + unsigned offsets[MIPLEVELS]; // four mip maps stored +} texture_t; + + +#define SURF_PLANEBACK 2 +#define SURF_DRAWSKY 4 +#define SURF_DRAWSPRITE 8 +#define SURF_DRAWTURB 0x10 +#define SURF_DRAWTILED 0x20 +#define SURF_DRAWBACKGROUND 0x40 +#define SURF_UNDERWATER 0x80 + +#define TEXFLAG_NODRAW 256 +#define TEXFLAG_LIGHT 512 + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + unsigned short v[2]; + unsigned int cachededgeoffset; +} medge_t; + +typedef struct +{ + float vecs[2][4]; + float mipadjust; + texture_t *texture; + int flags; +} mtexinfo_t; + +#define VERTEXSIZE 7 + +typedef struct glpoly_s +{ + struct glpoly_s *next; + struct glpoly_s *chain; + int numverts; + int flags; // for SURF_UNDERWATER + float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) +} glpoly_t; + +typedef struct msurface_s +{ + int visframe; // should be drawn when node is crossed + + mplane_t *plane; + int flags; + + int firstedge; // look up in model->surfedges[], negative numbers + int numedges; // are backwards edges + + short texturemins[2]; + short extents[2]; + + int light_s, light_t; // gl lightmap coordinates + + glpoly_t *polys; // multiple if warped + struct msurface_s *texturechain; + + mtexinfo_t *texinfo; + +// lighting info + int dlightframe; + unsigned int dlightbits; + // int is 32 bits, need an array for MAX_DLIGHTS > 32 + + int lightmaptexturenum; + byte styles[MAXLIGHTMAPS]; + int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap + qboolean cached_dlight; // true if dynamic light in cache + byte *samples; // [numstyles*surfsize] +} msurface_t; + +typedef struct mnode_s +{ +// common with leaf + int contents; // 0, to differentiate from leafs + int visframe; // node needs to be traversed if current + + float minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// node specific + mplane_t *plane; + struct mnode_s *children[2]; + + unsigned short firstsurface; + unsigned short numsurfaces; +} mnode_t; + + + +typedef struct mleaf_s +{ +// common with node + int contents; // wil be a negative contents number + int visframe; // node needs to be traversed if current + + float minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// leaf specific + byte *compressed_vis; + efrag_t *efrags; + + msurface_t **firstmarksurface; + int nummarksurfaces; + int key; // BSP sequence number for leaf's contents + byte ambient_sound_level[NUM_AMBIENTS]; +} mleaf_t; + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + dclipnode_t *clipnodes; + mplane_t *planes; + int firstclipnode; + int lastclipnode; + vec3_t clip_mins; + vec3_t clip_maxs; +} hull_t; + +/* +============================================================================== + +SPRITE MODELS + +============================================================================== +*/ + + +// FIXME: shorten these? +typedef struct mspriteframe_s +{ + int width; + int height; + float up, down, left, right; + int gl_texturenum; +} mspriteframe_t; + +typedef struct +{ + int numframes; + float *intervals; + mspriteframe_t *frames[1]; +} mspritegroup_t; + +typedef struct +{ + spriteframetype_t type; + mspriteframe_t *frameptr; +} mspriteframedesc_t; + +typedef struct +{ + int type; + int maxwidth; + int maxheight; + int numframes; + float beamlength; // remove? + void *cachespot; // remove? + mspriteframedesc_t frames[1]; +} msprite_t; + + +/* +============================================================================== + +ALIAS MODELS + +Alias models are position independent, so the cache manager can move them. +============================================================================== +*/ + +typedef struct +{ + int firstpose; + int numposes; + float interval; + trivertx_t bboxmin; + trivertx_t bboxmax; + int frame; + char name[16]; +} maliasframedesc_t; + +typedef struct +{ + trivertx_t bboxmin; + trivertx_t bboxmax; + int frame; +} maliasgroupframedesc_t; + +typedef struct +{ + int numframes; + int intervals; + maliasgroupframedesc_t frames[1]; +} maliasgroup_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct mtriangle_s { + int facesfront; + int vertindex[3]; +} mtriangle_t; + + +#define MAX_SKINS 32 +typedef struct { + int ident; + int version; + vec3_t scale; + vec3_t scale_origin; + float boundingradius; + vec3_t eyeposition; + int numskins; + int skinwidth; + int skinheight; + int numverts; + int numtris; + int numframes; + synctype_t synctype; + int flags; + float size; + + int numposes; + int poseverts; + int posedata; // numposes*poseverts trivert_t + int commands; // gl command list with embedded s/t + int gl_texturenum[MAX_SKINS][4]; + int texels[MAX_SKINS]; // only for player skins + maliasframedesc_t frames[1]; // variable sized +} aliashdr_t; + +#define MAXALIASVERTS 2048 // TODO: tune this +#define MAXALIASFRAMES 256 +#define MAXALIASTRIS 2048 +extern aliashdr_t *pheader; +extern stvert_t stverts[MAXALIASVERTS]; +extern mtriangle_t triangles[MAXALIASTRIS]; +extern trivertx_t *poseverts[MAXALIASFRAMES]; + +//=================================================================== + +// +// Whole model +// + +typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; + +#define EF_ROCKET 1 // leave a trail +#define EF_GRENADE 2 // leave a trail +#define EF_GIB 4 // leave a trail +#define EF_ROTATE 8 // rotate (bonus items) +#define EF_TRACER 16 // green split trail +#define EF_ZOMGIB 32 // small blood trail +#define EF_TRACER2 64 // orange split trail + rotate +#define EF_TRACER3 128 // purple trail + +//johnfitz -- extra flags for rendering +#define MOD_NOLERP 256 +//johnfits + +// some models are special +typedef enum +{ + MOD_NORMAL, + MOD_PLAYER, + MOD_EYES, + MOD_FLAME, + MOD_THUNDERBOLT, + MOD_WEAPON, + MOD_LAVABALL, + MOD_SPIKE, + MOD_SHAMBLER, + MOD_SPR, + MOD_SPR32, +// MOD_GKEY, +// MOD_SKEY, +} modhint_t; +typedef struct model_s +{ + char name[MAX_QPATH]; + qboolean needload; // bmodels and sprites don't cache normally + + modhint_t modhint; + modtype_t type; + int numframes; + synctype_t synctype; + + int flags; + +// +// volume occupied by the model graphics +// + vec3_t mins, maxs; + float radius; + +// +// solid volume for clipping +// + qboolean clipbox; + vec3_t clipmins, clipmaxs; + +// +// brush model +// + int firstmodelsurface, nummodelsurfaces; + + int numsubmodels; + dmodel_t *submodels; + + int numplanes; + mplane_t *planes; + + int numleafs; // number of visible leafs, not counting 0 + mleaf_t *leafs; + + int numvertexes; + mvertex_t *vertexes; + + int numedges; + medge_t *edges; + + int numnodes; + mnode_t *nodes; + + int numtexinfo; + mtexinfo_t *texinfo; + + int numsurfaces; + msurface_t *surfaces; + + int numsurfedges; + int *surfedges; + + int numclipnodes; + dclipnode_t *clipnodes; + + int nummarksurfaces; + msurface_t **marksurfaces; + + hull_t hulls[MAX_MAP_HULLS]; + + int numtextures; + texture_t **textures; + + byte *visdata; + byte *lightdata; + char *entities; + + int bspversion; + +// +// additional model data +// + cache_user_t cache; // only access through Mod_Extradata + +} model_t; + +//============================================================================ + +void Mod_Init (void); +void Mod_ClearAll (void); +model_t *Mod_ForName (char *name, qboolean crash); +void *Mod_Extradata (model_t *mod); // handles caching +void Mod_TouchModel (char *name); + +mleaf_t *Mod_PointInLeaf (float *p, model_t *model); +byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); + +#endif // __MODEL__ diff --git a/source/wii/gx/gx_qmb.c b/source/wii/gx/gx_qmb.c new file mode 100644 index 0000000..71318e8 --- /dev/null +++ b/source/wii/gx/gx_qmb.c @@ -0,0 +1,3061 @@ +/* +Copyright (C) 2002-2003, Dr Labman, A. Nourai +Copyright (C) 2009, Crow_bar psp port + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// gx_qmb.c + +#include "../../quakedef.h" +//#define DEFAULT_NUM_PARTICLES 8192 +#define ABSOLUTE_MIN_PARTICLES 512 +#define ABSOLUTE_MAX_PARTICLES 6144 + +extern int decal_blood1, decal_blood2, decal_blood3, decal_q3blood, decal_burn, decal_mark, decal_glow; + +typedef enum +{ + p_spark, + p_rayspark, + p_raysmoke, + p_smoke, + p_fire, + p_fire2, + p_bubble, + p_gunblast, + p_chunk, + p_shockwave, + p_inferno_flame, + p_inferno_trail, + p_sparkray, + p_staticbubble, + p_trailpart, + p_dpsmoke, + p_dpfire, + p_teleflare, + p_blood1, + p_blood2, + p_blood3, + p_bloodcloud, + p_flame, + p_lavatrail, + p_bubble2, + p_rain, + p_streak, + p_streaktrail, + p_streakwave, + p_lightningbeam, + p_glow, + p_alphatrail,//R00k + p_torch_flame, + p_flare, + p_dot, + p_muzzleflash, + p_muzzleflash2, + p_muzzleflash3, + p_q3flame, + num_particletypes +} part_type_t; + +typedef enum +{ + pm_static, + pm_normal, + pm_bounce, + pm_die, + pm_nophysics, + pm_float, + pm_rain, + pm_streak, + pm_streakwave, +} part_move_t; + +typedef enum +{ + ptex_none, + ptex_smoke, + ptex_generic, + ptex_dpsmoke, + ptex_blood1, + ptex_blood2, + ptex_blood3, + ptex_lightning, + ptex_flame, + ptex_muzzleflash, + ptex_muzzleflash2, + ptex_muzzleflash3, + ptex_bloodcloud, + ptex_q3flame, + num_particletextures +} part_tex_t; + +typedef enum +{ + pd_spark, + pd_sparkray, + pd_billboard, + pd_billboard_vel, + pd_hide, + pd_beam, + pd_q3flame, + pd_q3gunshot, + pd_q3teleport +} part_draw_t; + +typedef struct particle_s +{ + struct particle_s *next; + vec3_t org, endorg; + col_t color; + float growth; + vec3_t vel; + float rotangle; + float rotspeed; + float size; + float start; + float die; + byte hit; + byte texindex; + byte bounces; +} particle_t; + +typedef struct particle_type_s +{ + particle_t *start; + part_type_t id; + part_draw_t drawtype; + int SrcBlend; + int DstBlend; + part_tex_t texture; + float startalpha; + float grav; + float accel; + part_move_t move; + float custom; +} particle_type_t; + +#define MAX_PTEX_COMPONENTS 8 + +typedef struct particle_texture_s +{ + int texnum; + int components; + float coords[MAX_PTEX_COMPONENTS][4]; +} particle_texture_t; + +static particle_t *particles, *free_particles; +static particle_type_t particle_types[num_particletypes];//R00k +static int particle_type_index[num_particletypes]; +static particle_texture_t particle_textures[num_particletextures]; + +int lightning_texture;//Vult +float varray_vertex[16];//Vult +void R_CalcBeamVerts (float *vert, vec3_t org1, vec3_t org2, float width);//Vult + +vec3_t NULLVEC = {0,0,0};//r00k + +static int r_numparticles; +static vec3_t zerodir = {22, 22, 22}; +static int particle_count = 0; +static float particle_time; +qboolean qmb_initialized = false; +int particle_mode = 0; // 0: classic (default), 1: QMB, 2: mixed + +qboolean OnChange_gl_particle_count (cvar_t *var, char *string) +{ + float f; + + f = bound(ABSOLUTE_MIN_PARTICLES, (atoi(string)), ABSOLUTE_MAX_PARTICLES); + Cvar_SetValue("r_particle_count", f); + + QMB_ClearParticles (); // also re-allocc particles + + return true; +} + +cvar_t r_particle_count = {"r_particle_count", "2048", true}; +cvar_t r_bounceparticles = {"r_bounceparticles", "1",true}; +cvar_t r_decal_blood = {"r_decal_blood", "1",true}; +cvar_t r_decal_bullets = {"r_decal_bullets","1",true}; +cvar_t r_decal_sparks = {"r_decal_sparks","1",true}; +cvar_t r_decal_explosions = {"r_decal_explosions","1",true}; +cvar_t r_decaltime = {"r_decaltime", "12", true}; +cvar_t r_decal_viewdistance = {"r_decal_viewdistance", "1024"}; + +int decals_enabled; + +extern cvar_t sv_gravity; + +static byte *ColorForParticle (part_type_t type) +{ + static col_t color; + int lambda; + + switch (type) + { + case p_spark: + color[0] = 224 + (rand() & 31); + color[1] = 100 + (rand() & 31); + color[2] = 50; + break; + + case p_torch_flame: + case p_glow: + color[0] = color[1] = color[2] = 255; + break; + + case p_smoke: + color[0] = color[1] = color[2] = 128; + color[3] = 64; + break; + + case p_q3flame: + color[0] = color[1] = color[2] = 255; + break; + + case p_fire: + color[0] = 255; + color[1] = 122; + color[2] = 62; + break; + case p_fire2: + color[0] = 80; + color[1] = 80; + color[2] = 80; + color[3] = 64; + break; + + case p_bubble: + case p_bubble2: + case p_staticbubble: + color[0] = color[1] = color[2] = 192 + (rand() & 63); + break; + + case p_teleflare: + color[0] = color[1] = color[2] = 128 + (rand() & 127); + break; + + case p_gunblast: + color[0]= 224 + (rand() & 31); + color[1] = 170 + (rand() & 31); + color[2] = 0; + break; + + case p_chunk: + color[0] = color[1] = color[2] = (32 + (rand() & 127)); + break; + + case p_shockwave: + color[0] = color[1] = color[2] = 64 + (rand() & 31); + break; + + case p_inferno_flame: + case p_inferno_trail: + color[0] = 255; + color[1] = 77; + color[2] = 13; + break; + + case p_sparkray: + color[0] = 255; + color[1] = 102; + color[2] = 25; + break; + + case p_dpsmoke: + color[0] = color[1] = color[2] = 48 + (((rand() & 0xFF) * 48) >> 8); + break; + + case p_dpfire: + lambda = rand() & 0xFF; + color[0] = 160 + ((lambda * 48) >> 8); + color[1] = 16 + ((lambda * 148) >> 8); + color[2] = 16 + ((lambda * 16) >> 8); + break; + + case p_blood1: + case p_blood2: + color[0] = 30; + color[1] = 5; + color[2] = 5; + color[3] = 255; + break; + + case p_blood3: + color[0] = (50 + (rand() & 31)); + color[1] = color[2] = 0; + color[3] = 200; + break; + + case p_flame: + color[0] = 255; + color[1] = 100; + color[2] = 25; + color[3] = 128; + break; + + case p_lavatrail: + color[0] = 255; + color[1] = 102; + color[2] = 25; + color[3] = 255; + break; + + default: + Con_Printf ("ColorForParticle: unexpected type\n"); + break; + } + + return color; +} + +// sB Translated these functions for debugging purposes +// if everything is working okay then I see no harm in keeping them +// as #defines +/* +#define ADD_PARTICLE_TEXTURE(_ptex, _texnum, _texindex, _components, _s1, _t1, _s2, _t2)\ +do { \ + particle_textures[_ptex].texnum = _texnum; \ + particle_textures[_ptex].components = _components; \ + particle_textures[_ptex].coords[_texindex][0] = (_s1 + 1) / max_s; \ + particle_textures[_ptex].coords[_texindex][1] = (_t1 + 1) / max_t; \ + particle_textures[_ptex].coords[_texindex][2] = (_s2 - 1) / max_s; \ + particle_textures[_ptex].coords[_texindex][3] = (_t2 - 1) / max_t; \ +} while(0) +*/ +float max_s, max_t; //For ADD_PARTICLE_TEXTURE +void ADD_PARTICLE_TEXTURE(part_tex_t ptex, int texnum, int texindex, int components, int s1, int t1, int s2, int t2) +{ + particle_textures[ptex].texnum = texnum; + particle_textures[ptex].components = components; + particle_textures[ptex].coords[texindex][0] = (s1 + 1) / max_s; + particle_textures[ptex].coords[texindex][1] = (t1 + 1) / max_t; + particle_textures[ptex].coords[texindex][2] = (s2 - 1) / max_s; + particle_textures[ptex].coords[texindex][3] = (t2 - 1) / max_t; +} + +/* +#define ADD_PARTICLE_TYPE(_id, _drawtype, _SrcBlend, _DstBlend, _texture, _startalpha, _grav, _accel, _move, _custom)\ +do {\ + particle_types[count].id = (_id);\ + particle_types[count].drawtype = (_drawtype);\ + particle_types[count].SrcBlend = (_SrcBlend);\ + particle_types[count].DstBlend = (_DstBlend);\ + particle_types[count].texture = (_texture);\ + particle_types[count].startalpha = (_startalpha);\ + particle_types[count].grav = 9.8 * (_grav);\ + particle_types[count].accel = (_accel);\ + particle_types[count].move = (_move);\ + particle_types[count].custom = (_custom);\ + particle_type_index[_id] = count;\ + count++;\ +} while(0) +*/ + +int count = 0; +void ADD_PARTICLE_TYPE(part_type_t id, part_draw_t drawtype, int SrcBlend, int DstBlend, part_tex_t texture, float startalpha, float grav, float accel, part_move_t move, float custom) +{ + particle_types[count].id = (id); + particle_types[count].drawtype = (drawtype); + particle_types[count].SrcBlend = (SrcBlend); + particle_types[count].DstBlend = (DstBlend); + particle_types[count].texture = (texture); + particle_types[count].startalpha = (startalpha); + particle_types[count].grav = 9.8 * (grav); + particle_types[count].accel = (accel); + particle_types[count].move = (move); + particle_types[count].custom = (custom); + particle_type_index[id] = count; + count++; +} + +void QMB_AllocParticles (void) +{ + extern cvar_t r_particle_count; + + r_numparticles = bound(ABSOLUTE_MIN_PARTICLES, r_particle_count.value, ABSOLUTE_MAX_PARTICLES); + + //if (particles) + // Con_Printf("QMB_AllocParticles: internal error >particles<\n"); + + if (r_numparticles < 1) { + Con_Printf("QMB_AllocParticles: internal error >num particles<\n"); + } + + // can't alloc on Hunk, using native memory + particles = (particle_t *) malloc (r_numparticles * sizeof(particle_t)); +} + +void QMB_InitParticles (void) +{ + int /*i, */particleimage; + + particle_mode = pm_classic; + + Cvar_RegisterVariable (&r_bounceparticles); + Cvar_RegisterVariable (&r_flametype); + Cvar_RegisterVariable (&r_decal_blood); + Cvar_RegisterVariable (&r_decal_bullets); + Cvar_RegisterVariable (&r_decal_sparks); + Cvar_RegisterVariable (&r_decal_explosions); + Cvar_RegisterVariable (&r_particle_count); + + loading_num_step = loading_num_step + 24; + + particleimage = loadtextureimage("textures/particles/particlefont", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + Con_Printf ("PARTICLE INIT FAILED"); + return; + } + + loading_cur_step++; + strcpy(loading_name, "Particles"); + SCR_UpdateScreen (); + + max_s = max_t = 128.0; + // LAST 4 PARAMS = START X, START Y, END X, END Y + ADD_PARTICLE_TEXTURE(ptex_none, 0, 0, 1, 0, 0, 0, 0); + ADD_PARTICLE_TEXTURE(ptex_blood1, particleimage, 0, 1, 0, 0, 64, 64); + ADD_PARTICLE_TEXTURE(ptex_blood2, particleimage, 0, 1, 64, 0, 128, 64); + ADD_PARTICLE_TEXTURE(ptex_generic, particleimage, 0, 1, 0, 64, 32, 96); + ADD_PARTICLE_TEXTURE(ptex_smoke, particleimage, 0, 1, 32, 64, 96, 128); + ADD_PARTICLE_TEXTURE(ptex_blood3, particleimage, 0, 1, 0, 96, 32, 128); + + //for (i=0 ; i<8 ; i++) + //ADD_PARTICLE_TEXTURE(ptex_dpsmoke, particleimage, i, 8, i * 32, 64, (i + 1) * 32, 96); + + loading_cur_step++; + SCR_UpdateScreen (); + + max_s = max_t = 64.0; + + particleimage = loadtextureimage("textures/particles/flame", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + return; + } + + ADD_PARTICLE_TEXTURE(ptex_q3flame, particleimage, 0, 1, 0, 0, 64, 64); + loading_cur_step++; + SCR_UpdateScreen (); + + max_s = max_t = 64.0; + + particleimage = loadtextureimage("textures/particles/inferno", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + return; + } + max_s = max_t = 256.0; + ADD_PARTICLE_TEXTURE(ptex_flame, particleimage, 0, 1, 0, 0, 256, 256); + + loading_cur_step++; + SCR_UpdateScreen (); + + particleimage = loadtextureimage("textures/particles/zing1", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + return; + } + + max_s = 256.0; max_t = 128.0; + ADD_PARTICLE_TEXTURE(ptex_lightning, particleimage, 0, 1, 0, 0, 256, 128);//R00k changed + + loading_cur_step++; + SCR_UpdateScreen (); + max_s = max_t = 128.0; + + particleimage = loadtextureimage("textures/mzfl/mzfl0", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + return; + } + //max_s = max_t = 256.0; + ADD_PARTICLE_TEXTURE(ptex_muzzleflash, particleimage, 0, 1, 0, 0, 128, 128); + + loading_cur_step++; + SCR_UpdateScreen (); + + particleimage = loadtextureimage("textures/mzfl/mzfl1", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + return; + } + //max_s = max_t = 256.0; + ADD_PARTICLE_TEXTURE(ptex_muzzleflash2, particleimage, 0, 1, 0, 0, 128, 128); + + loading_cur_step++; + SCR_UpdateScreen (); + particleimage = loadtextureimage("textures/mzfl/mzfl2", 0, 0, true, false, true); + if (particleimage <= 0) + { + //Clear_LoadingFill (); + return; + } + //max_s = max_t = 256.0; + ADD_PARTICLE_TEXTURE(ptex_muzzleflash3, particleimage, 0, 1, 0, 0, 128, 128); + + loading_cur_step++; + SCR_UpdateScreen (); + + max_s = max_t = 64.0; + particleimage = loadtextureimage("textures/particles/bloodcloud", 0, 0, true, false, true); + if (particleimage <= 0) + { + Con_Printf("could not load bloodcloud texture"); + //Clear_LoadingFill (); + return; + } + //max_s = max_t = 256.0; + ADD_PARTICLE_TEXTURE(ptex_bloodcloud, particleimage, 0, 1, 0, 0, 64, 64); + + loading_cur_step++; + SCR_UpdateScreen (); + + QMB_AllocParticles (); + + ADD_PARTICLE_TYPE(p_spark, pd_spark, GX_BL_SRCALPHA, GX_BL_ONE, ptex_none, 255, -8, 0, pm_normal, 1.3); + ADD_PARTICLE_TYPE(p_gunblast, pd_spark, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_none, 255, 0, 0, pm_normal, 1.3); + ADD_PARTICLE_TYPE(p_sparkray, pd_sparkray, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_none, 255, -0, 0, pm_nophysics, 0); + ADD_PARTICLE_TYPE(p_fire, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_smoke, 204, 0, -2.95, pm_die, 0); + + loading_cur_step++; + SCR_UpdateScreen (); + + ADD_PARTICLE_TYPE(p_fire2, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_smoke, 204, 0, -2.95, pm_die, 0); + ADD_PARTICLE_TYPE(p_chunk, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 255, -16, 0, pm_bounce, 1.475); + ADD_PARTICLE_TYPE(p_shockwave, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 255, 0, -4.85, pm_nophysics, 0); + ADD_PARTICLE_TYPE(p_inferno_flame, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 153, 0, 0, pm_static, 0); + + loading_cur_step++; + SCR_UpdateScreen (); + + ADD_PARTICLE_TYPE(p_inferno_trail, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 204, 0, 0, pm_die, 0); + ADD_PARTICLE_TYPE(p_trailpart, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 230, 0, 0, pm_static, 0); + ADD_PARTICLE_TYPE(p_smoke, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_smoke, 140, 3, 0, pm_normal, 0); + ADD_PARTICLE_TYPE(p_raysmoke, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_smoke, 140, 3, 0, pm_normal, 0); + //ADD_PARTICLE_TYPE(p_dpfire, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_dpsmoke, 144, 0, 0, pm_die, 0); + + loading_cur_step++; + SCR_UpdateScreen (); + + //ADD_PARTICLE_TYPE(p_dpsmoke, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_dpsmoke, 85, 3, 0, pm_die, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + ADD_PARTICLE_TYPE(p_dot, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 255, 0, 0, pm_static, 0); + ADD_PARTICLE_TYPE(p_blood1, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_blood1, 255, -20, 0, pm_die, 0); + ADD_PARTICLE_TYPE(p_blood2, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_blood3, 255, -45, 0, pm_normal, 0.018);//disisgonnabethegibchunks + ADD_PARTICLE_TYPE(p_blood3, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_blood3, 255, -30, 0, pm_normal, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + ADD_PARTICLE_TYPE(p_flame, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 200, 10, 0, pm_die, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + //ADD_PARTICLE_TYPE(p_lavatrail, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_dpsmoke, 255, 3, 0, pm_normal, 0);//R00k + ADD_PARTICLE_TYPE(p_glow, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 204, 0, 0, pm_die, 0); + ADD_PARTICLE_TYPE(p_alphatrail, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_generic, 100, 0, 0, pm_static, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + ADD_PARTICLE_TYPE(p_torch_flame, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_flame, 255, 12, 0, pm_die, 0); + ADD_PARTICLE_TYPE(p_streak, pd_hide, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_none, 255, -64, 0, pm_streak, 1.5); + ADD_PARTICLE_TYPE(p_streakwave, pd_hide, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_none, 255, 0, 0, pm_streakwave, 0); + ADD_PARTICLE_TYPE(p_streaktrail, pd_beam, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_none, 255, 0, 0, pm_die, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + ADD_PARTICLE_TYPE(p_lightningbeam, pd_beam, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_lightning, 255, 0, 0, pm_die, 0); + ADD_PARTICLE_TYPE(p_muzzleflash, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_muzzleflash, 255, 0, 0, pm_static, 0); + ADD_PARTICLE_TYPE(p_muzzleflash2, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_muzzleflash2, 255, 0, 0, pm_static, 0); + ADD_PARTICLE_TYPE(p_muzzleflash3, pd_billboard, GX_BL_SRCALPHA, GX_BL_ONE, ptex_muzzleflash3, 255, 0, 0, pm_static, 0); + ADD_PARTICLE_TYPE(p_rain, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_generic, 255, -16, 0, pm_rain, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + //shpuldeditedthis(GI_ONE_MINUS_DST_ALPHA->GX_BL_INVSRCALPHA) (edited one right after this comment) + ADD_PARTICLE_TYPE(p_bloodcloud, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_bloodcloud, 255, -2, 0, pm_normal, 0); + + loading_cur_step++; + SCR_UpdateScreen(); + + //old: ADD_PARTICLE_TYPE(p_q3flame, pd_q3flame, GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, ptex_q3flame, 204, 0, 0, pm_static, -1); + ADD_PARTICLE_TYPE(p_q3flame, pd_billboard, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, ptex_q3flame, 180, 0.66, 0, pm_nophysics, 0); + + loading_cur_step++; + strcpy(loading_name, "Particles"); + SCR_UpdateScreen (); + + Clear_LoadingFill (); + + qmb_initialized = true; +} + +#define INIT_NEW_PARTICLE(_pt, _p, _color, _size, _time) \ + _p = free_particles; \ + free_particles = _p->next; \ + _p->next = _pt->start; \ + _pt->start = _p; \ + _p->size = _size; \ + _p->hit = 0; \ + _p->start = cl.time; \ + _p->die = cl.time + _time; \ + _p->growth = 0; \ + _p->rotspeed = 0; \ + _p->texindex = (rand() % particle_textures[_pt->texture].components); \ + _p->bounces = 0; \ + VectorCopy(_color, _p->color); + + +//sBTODO this is the problem area +/* +void INIT_NEW_PARTICLE(particle_type_t *pt, particle_t *p, byte *color, float size, float time) +{ + p = free_particles; + free_particles = p->next; + p->next = pt->start; + pt->start = p; + p->size = size; + p->hit = 0; + p->start = cl.time; + p->die = cl.time + time; + p->growth = 0; + p->rotspeed = 0; + p->texindex = (rand() % particle_textures[pt->texture].components); + p->bounces = 0; + VectorCopy(color, p->color); +} +*/ +void AddParticle (part_type_t type, vec3_t org, int count, float size, float time, col_t col, vec3_t dir) +{ + byte *color; + int i, j; + float tempSize; //stage; + particle_t *p; + particle_type_t *pt; + + if (!qmb_initialized) + Sys_Error ("QMB particle added without initialization"); + + //assert (size > 0 && time > 0); + + if (type < 0 || type >= num_particletypes) { + Sys_Error ("AddParticle: Invalid type (%d)", type); + } + + pt = &particle_types[particle_type_index[type]]; + + for (i=0 ; i < count && free_particles ; i++) + { + + color = col ? col : ColorForParticle (type); + + //Con_Printf("addsize: %f\n", size); + INIT_NEW_PARTICLE(pt, p, color, size, time); + switch (type) + { + case p_spark: + p->size = 1.175; + VectorCopy (org, p->org); + tempSize = size * 2; + p->vel[0] = (rand() % (int)tempSize) - ((int)tempSize / 2); + p->vel[1] = (rand() % (int)tempSize) - ((int)tempSize / 2); + p->vel[2] = (rand() % (int)tempSize) - ((int)tempSize / 2); + break; + case p_rayspark: + p->size = 1.175; + VectorCopy (org, p->org); + tempSize = size * 2; + p->vel[0] = (rand() % (int)tempSize) - ((int)tempSize/6); + p->vel[1] = (rand() % (int)tempSize) - ((int)tempSize/6); + p->vel[2] = /*(rand() % (int)tempSize) - (*/(int)tempSize; + break; + case p_raysmoke: + for (j=0 ; j<3 ; j++) + p->org[j] = org[j] + ((rand() & 31) - 16) / 2.0; + + p->vel[0] = ((rand() % 10)+2); + p->vel[1] = ((rand() % 10)+2); + p->vel[2] = ((rand() % 10)+2)*5; + p->growth = 7.5; + break; + case p_smoke: + for (j=0 ; j<3 ; j++) + p->org[j] = org[j] + ((rand() & 31) - 24) / 2.0; + for (j=0 ; j<3 ; j++) + p->vel[j] = ((rand() % 10) - 5) / 20.0; + p->growth = 4.5; + break; + case p_fire: + VectorCopy (org, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() & 159) - 80; + p->org[0] = org[0] + ((rand() & 63) - 32); + p->org[1] = org[1] + ((rand() & 63) - 32); + p->org[2] = org[2] + ((rand() & 63) - 10); + break; + + case p_fire2: + VectorCopy (org, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() & 199) - 100; + p->org[0] = org[0] + ((rand() & 99) - 50); + p->org[1] = org[1] + ((rand() & 99) - 50); + p->org[2] = org[2] + ((rand() & 99) - 18); + p->growth = 12; + break; + + case p_bubble: + p->start += (rand() & 15) / 36.0; + p->org[0] = org[0] + ((rand() & 31) - 16); + p->org[1] = org[1] + ((rand() & 31) - 16); + p->org[2] = org[2] + ((rand() & 63) - 32); + VectorClear (p->vel); + break; + + case p_streak: + case p_streakwave: + case p_shockwave: + VectorCopy (org, p->org); + VectorCopy (dir, p->vel); + break; + + case p_gunblast: + p->size = 1; + VectorCopy (org, p->org); + p->vel[0] = (rand() & 159) - 80; + p->vel[1] = (rand() & 159) - 80; + p->vel[2] = (rand() & 159) - 80; + break; + + case p_chunk: + VectorCopy (org, p->org); + p->vel[0] = (rand() % 40) - 20; + p->vel[1] = (rand() % 40) - 20; + p->vel[2] = (rand() % 40) - 5; + break; + + case p_rain: + VectorCopy(org, p->org); + p->vel[0] = (rand() % 180) - 90; + p->vel[1] = (rand() % 180) - 90; + p->vel[2] = (rand() % -100 - 1200); + break; + + case p_inferno_trail: + for (j=0 ; j<3 ; j++) + p->org[j] = org[j] + (rand() & 15) - 8; + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() & 3) - 2; + p->growth = -1.5; + break; + + case p_inferno_flame: + VectorCopy (org, p->org); + VectorClear (p->vel); + p->growth = -30; + break; + + case p_sparkray: + VectorCopy (org, p->endorg); + VectorCopy (dir, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() & 127) - 64; + p->growth = -16; + break; + + case p_bloodcloud: //shpuld + VectorCopy (org, p->org); + p->size = size * (rand() % 2) + 0.50;//r00k + p->vel[0] = (rand() & 39) - 20; + p->vel[1] = (rand() & 39) - 20; + p->vel[2] = (rand() & 39) - 20; + p->growth = 24; + break; + + case p_staticbubble: + VectorCopy (org, p->org); + VectorClear (p->vel); + break; + + case p_muzzleflash: + case p_muzzleflash2: + case p_muzzleflash3: + VectorCopy (org, p->org); + p->rotspeed = (rand() & 45) - 90; + //p->size = size * (rand() % 6) / 4;//r00k + p->size = size * (0.75 +((0.05 * (rand() % 20)) * 0.5));//blubs: resultant size range: [size * 0.75, size * 1.25) + break; + + case p_teleflare: + case p_flare: + VectorCopy (org, p->org); + VectorCopy (dir, p->vel); + p->growth = 1.75; + break; + + case p_blood1: + p->size = size * (rand() % 2) + 0.50;//r00k + for (j=0 ; j<3 ; j++) + p->org[j] = org[j] + (rand() & 15) - 8; + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() & 63) - 32; + break; + + case p_blood2: //shpuld + VectorCopy (org, p->org); + p->vel[0] = (rand() & 200) - 100; + p->vel[1] = (rand() & 200) - 100; + p->vel[2] = (rand() & 250) - 70; + //p->growth = 0.1; + break; + + case p_blood3: + p->size = size * (rand() % 20) / 5.0; + VectorCopy (org, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() % 40) - 20; + break; + + case p_flame: + VectorCopy (org, p->org); + p->growth = -p->size / 2; + VectorClear (p->vel); + for (j=0 ; j<2 ; j++) + p->vel[j] = (rand() % 6) - 3; + break; + + case p_q3flame: //shpuld + VectorCopy (org, p->org); + p->vel[0] = (rand() & 3) - 2; + p->vel[1] = (rand() & 3) - 2; + p->vel[2] = (rand() & 2); + p->growth = 6; + break; + + case p_torch_flame: + for (j=0 ; j<3 ; j++) + p->org[j] = org[j] + (rand() & 3) - 2; + p->vel[0] = rand() % 15 - 8; + p->vel[1] = rand() % 15 - 8; + p->vel[2] = rand() % 15; + p->rotspeed = (rand() & 31) + 32; + break; + + case p_dot: + case p_glow: + VectorCopy (org, p->org); + VectorCopy (dir, p->vel); + p->growth = -1.5; + break; + + case p_streaktrail: + case p_lightningbeam: + VectorCopy(org, p->org); + VectorCopy(dir, p->endorg); + VectorClear(p->vel); + p->growth = -p->size/time; + p->bounces = color[3]; + break; + + default: + Con_Printf ("AddParticle: unexpected type\n"); + break; + } + } +} + +void AddParticleTrail (part_type_t type, vec3_t start, vec3_t end, float size, float time, col_t col) +{ + byte *color; + int i, j, num_particles; + float count, length; + vec3_t point, delta; + particle_t *p; + particle_type_t *pt; + count = 0; + + if (!qmb_initialized) + Sys_Error ("QMB particle added without initialization"); + + if (type < 0 || type >= num_particletypes) + Sys_Error ("AddParticle: Invalid type (%d)", type); + + pt = &particle_types[particle_type_index[type]]; + + VectorCopy(start, point); + VectorSubtract(end, start, delta); + if (!(length = VectorLength(delta))) + return; + + switch (type) + { + case p_alphatrail: + case p_trailpart: + case p_lavatrail: + count = length / 1.1; + break; + + case p_blood3: + count = length / 8; + break; + + case p_bubble: + case p_bubble2: + count = length / 5.0; + break; + + case p_smoke: + count = length / 3.8; + break; + + case p_dpsmoke: + count = length / 2.5; + break; + + case p_dpfire: + count = length / 2.8; + break; + + default: + Con_Printf ("AddParticleTrail: unexpected type\n"); + break; + } + + if (!(num_particles = (int)count)) + num_particles = 1; + + VectorScale(delta, 1.0 / num_particles, delta); + + for (i=0 ; i < num_particles && free_particles ; i++) + { + color = col ? col : ColorForParticle (type); + INIT_NEW_PARTICLE(pt, p, color, size, time); + + switch (type) + { + case p_alphatrail: + case p_trailpart: + VectorCopy (point, p->org); + VectorClear (p->vel); + p->growth = -size / time; + break; + + case p_blood3: + VectorCopy (point, p->org); + for (j=0 ; j<3 ; j++) + p->org[j] += ((rand() & 15) - 8) / 8.0; + for (j=0 ; j<3 ; j++) + p->vel[j] = ((rand() & 15) - 8) / 2.0; + p->size = size * (rand() % 20) / 10.0; + p->growth = 6; + break; + + case p_bubble2: + VectorCopy(point, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() % 10) - 5; + break; + + //R00k added + case p_bubble: + VectorCopy (point, p->org); + + for (j=0 ; j<3 ; j++) + p->org[j] += ((rand() & 15) - 8) / 8.0; + + for (j=0 ; j<3 ; j++) + p->vel[j] = ((rand() & 15) - 8) / 2.0; + + p->size = size * (rand() % 20) / 10.0; + p->growth = 1; + break; + + case p_smoke: + VectorCopy (point, p->org); + for (j=0 ; j<3 ; j++) + p->org[j] += ((rand() & 7) - 4) / 8.0; + p->vel[0] = p->vel[1] = 0; + p->vel[2] = rand() & 3; + p->growth = 4.5; + p->rotspeed = (rand() & 63) + 96; + break; + + case p_dpsmoke: + VectorCopy (point, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() % 10) - 5; + p->growth = 3; + p->rotspeed = (rand() & 63) + 96; + break; + + case p_dpfire: + VectorCopy (point, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = (rand() % 40) - 20; + break; + + case p_lavatrail: + VectorCopy (point, p->org); + for (j=0 ; j<3 ; j++) + p->org[j] += ((rand() & 7) - 4); + p->vel[0] = p->vel[1] = 0; + p->vel[2] = rand() & 3; + break; + + default: + Con_Printf ("AddParticleTrail: unexpected type\n"); + break; + } + + VectorAdd(point, delta, point); + } +} + +void QMB_ClearParticles (void) +{ + int i; + + if (!qmb_initialized) + return; + + free (particles); // free + QMB_AllocParticles (); // and alloc again + particle_count = 0; + memset (particles, 0, r_numparticles * sizeof(particle_t)); + free_particles = &particles[0]; + + for (i=0 ; i+1 < r_numparticles ; i++) + particles[i].next = &particles[i + 1]; + particles[r_numparticles-1].next = NULL; + + for (i=0 ; i < num_particletypes ; i++) + particle_types[i].start = NULL; +} + +void QMB_UpdateParticles(void) +{ + int i, c; + float grav, bounce/*, frametime*/, distance[3]; + vec3_t oldorg, stop, normal; + particle_type_t *pt; + particle_t *p; + particle_t *kill; + + if (!qmb_initialized) + return; + + particle_count = 0; + //frametime = cl.ctime - cl.oldtime; + grav = sv_gravity.value / 800.0; + + for (i=0 ; istart) + { + p = pt->start; + while (p && p->next) + { + kill = p->next; + if (kill->die <= particle_time) + { + p->next = kill->next; + kill->next = free_particles; + free_particles = kill; + } + else + { + p = p->next; + } + } + if (pt->start->die <= particle_time) + { + kill = pt->start; + pt->start = kill->next; + kill->next = free_particles; + free_particles = kill; + } + } + + for (p = pt->start ; (p); p = p->next) + { + if (particle_time < p->start) + continue; + + particle_count++; + + // sBTODO growth is too intense? + // can't use frametime for this. + // this alternative works fine for now + + // actualy host_frametime might be more + // appropriate for this application. + p->size += p->growth * host_frametime; + + //Con_Printf("frametime: %f host_frametime %f\n", frametime, host_frametime); + + if (p->size <= 0) + { + p->die = 0; + continue; + } + VectorCopy (p->org, oldorg); + VectorSubtract(r_refdef.vieworg,oldorg, distance); + + if (VectorLength(distance) >= r_farclip.value) + p->die = 0; + + switch (pt->id) + { + case p_streaktrail://R00k + case p_lightningbeam: + p->color[3] = p->bounces * ((p->die - particle_time) / (p->die - p->start)); + break; + + //shpuld + case p_q3flame: + p->color[3] = pt->startalpha * ((p->die - particle_time) / (p->die - p->start)); + p->color[0] = p->color[1] = p->color[2] = pt->startalpha * ((p->die - particle_time) / (p->die - p->start)); + break; + + default: + p->color[3] = pt->startalpha * ((p->die - particle_time) / (p->die - p->start)); + break; + } + + p->rotangle += p->rotspeed * host_frametime; + + if (p->hit) + continue; + + p->vel[2] += pt->grav * grav * host_frametime; + + VectorScale (p->vel, 1 + pt->accel * host_frametime, p->vel); + + switch (pt->move) + { + case pm_static: + break; + + case pm_normal: + VectorCopy (p->org, oldorg); + VectorMA (p->org, host_frametime, p->vel, p->org); + + if (CONTENTS_SOLID == TruePointContents(p->org)) + { + p->hit = 1; + + if ((pt->id == p_blood3)&&(r_decal_blood.value) && (decals_enabled) && (particle_mode)) + { + TraceLineN(oldorg, p->org, stop, normal); + + if ((stop != p->org)&&(VectorLength(stop)!=0)) + { + vec3_t tangent; + VectorCopy(stop, p->org); + VectorCopy(normal, p->vel); + CrossProduct(normal,p->vel,tangent); + #if 1 // naievil -- fixme + R_SpawnDecal(p->org, normal, tangent, decal_blood3, 12, 0); + #endif + } + p->die = 0; + } + VectorCopy (oldorg, p->org); + VectorClear (p->vel); + } + + break; + + case pm_float: + VectorMA (p->org, host_frametime, p->vel, p->org); + p->org[2] += p->size + 1; + if (!ISUNDERWATER(TruePointContents(p->org))) + p->die = 0; + p->org[2] -= p->size + 1; + break; + + case pm_nophysics: + VectorMA (p->org, host_frametime, p->vel, p->org); + break; + + case pm_die: + VectorCopy (p->org, oldorg); + VectorMA (p->org, host_frametime, p->vel, p->org); + + if (CONTENTS_SOLID == TruePointContents(p->org)) + { + if ((decals_enabled) && (particle_mode)) + { + TraceLineN(oldorg, p->org, stop, normal); + + if ((stop != p->org)&&(VectorLength(stop)!=0)) + { + vec3_t tangent; + + VectorCopy(stop, p->org); + VectorCopy(normal, p->vel); + CrossProduct(normal,p->vel,tangent); +/* + if ((pt->id == p_blood1)&&(r_decal_blood.value)) + { + R_SpawnDecal(p->org, normal, tangent, decal_blood1, 12, 0); + } + else + { + if ((pt->id == p_blood2)&&(r_decal_blood.value)) + { + R_SpawnDecal(p->org, normal, tangent, decal_blood2, 12, 0); + } + } +*/ + // sBTODO + // Will attempt to fix :) + // + #if 0// naievil -- fixme + if ((pt->id == p_fire || pt->id == p_dpfire) && r_decal_explosions.value) + R_SpawnDecal (p->org, normal, tangent, decal_burn, 32, 0); + else if (pt->id == p_blood1 && r_decal_blood.value) + R_SpawnDecal (p->org, normal, tangent, decal_blood1, 12, 0); + else if (pt->id == p_blood2 && r_decal_blood.value) + R_SpawnDecal (p->org, normal, tangent, decal_blood2, 12, 0); + //else if (pt->id == p_q3blood_trail && r_decal_blood.value) + //R_SpawnDecal (p->org, normal, tangent, decal_q3blood, 48, 0); + #endif + + } + } + VectorCopy (oldorg, p->org); + VectorClear (p->vel);//R00k added Needed? + p->die = 0; + p->growth = 0; //reset size/growth + p->size = 0; + } + + break; + + case pm_bounce: + if (!r_bounceparticles.value || p->bounces) + { + VectorMA(p->org, host_frametime, p->vel, p->org); + if (CONTENTS_SOLID == TruePointContents(p->org)) + { + p->die = 0; + } + } + else + { + VectorCopy (p->org, oldorg); + VectorMA (p->org, host_frametime, p->vel, p->org); + + if (CONTENTS_SOLID == TruePointContents(p->org)) + { + if (TraceLineN(oldorg, p->org, stop, normal)) + { + VectorCopy (stop, p->org); + bounce = -pt->custom * DotProduct(p->vel, normal); + VectorMA(p->vel, bounce, normal, p->vel); + p->bounces++; + } + } + + } + break; + + case pm_streak: + VectorCopy(p->org, oldorg); + VectorMA(p->org, host_frametime, p->vel, p->org); + if (CONTENTS_SOLID == TruePointContents(p->org)) + { + if (TraceLineN(oldorg, p->org, stop, normal)) + { + VectorCopy(stop, p->org); + bounce = -pt->custom * DotProduct(p->vel, normal); + VectorMA(p->vel, bounce, normal, p->vel); + } + } + + AddParticle (p_streaktrail, oldorg, 1, p->size, 0.2, p->color, p->org); + + if (!VectorLength(p->vel)) + p->die = 0; + break; + + case pm_rain: + VectorCopy(p->org, oldorg); + VectorMA(p->org, host_frametime, p->vel, p->org); + + VectorSubtract(r_refdef.vieworg,oldorg, distance); + + if (VectorLength(distance) < r_farclip.value) + { + if ((rand()%10+1 > 6)) + AddParticle (p_streaktrail, oldorg, 1, ((rand() % 1) + 0.5), 0.2, p->color, p->org); + + c = TruePointContents(p->org); + + if ((CONTENTS_SOLID == c) || (ISUNDERWATER(c))) + { + VectorClear (p->vel); + p->die = 0; + } + } + break; + + case pm_streakwave: + VectorCopy(p->org, oldorg); + VectorMA(p->org, host_frametime, p->vel, p->org); + AddParticle (p_streaktrail, oldorg, 1, p->size, 0.5, p->color, p->org); + p->vel[0] = 19 * p->vel[0] / 20; + p->vel[1] = 19 * p->vel[1] / 20; + p->vel[2] = 19 * p->vel[2] / 20; + break; + + default: + Con_Printf ("QMB_UpdateParticles: unexpected pt->move\n"); + break; + } + } + } +} + +//from darkplaces engine - finds which corner of a particle goes where, so I don't have to :D +void R_CalcBeamVerts (float *vert, vec3_t org1, vec3_t org2, float width) +{ + vec3_t right1, right2, diff, normal; + + VectorSubtract (org2, org1, normal); + VectorNormalize (normal); + + //width = width / 2; + // calculate 'right' vector for start + VectorSubtract (r_origin, org1, diff); + VectorNormalize (diff); + CrossProduct (normal, diff, right1); + + // calculate 'right' vector for end + VectorSubtract (r_origin, org2, diff); + VectorNormalize (diff); + CrossProduct (normal, diff, right2); + + vert[ 0] = org1[0] + width * right1[0]; + vert[ 1] = org1[1] + width * right1[1]; + vert[ 2] = org1[2] + width * right1[2]; + vert[ 4] = org1[0] - width * right1[0]; + vert[ 5] = org1[1] - width * right1[1]; + vert[ 6] = org1[2] - width * right1[2]; + vert[ 8] = org2[0] - width * right2[0]; + vert[ 9] = org2[1] - width * right2[1]; + vert[10] = org2[2] - width * right2[2]; + vert[12] = org2[0] + width * right2[0]; + vert[13] = org2[1] + width * right2[1]; + vert[14] = org2[2] + width * right2[2]; +} + +// naievil -- hacky particle drawing...NOT OPTIMIZED -- from NX +void DRAW_PARTICLE_BILLBOARD(particle_texture_t *ptex, particle_t *p, vec3_t *coord) { + float scale = 0; + vec3_t up, right, p_downleft, p_upleft, p_downright, p_upright; + //GLubyte color[4], *c; + float color[4]; + + VectorScale (vup, 1.5, up); + VectorScale (vright, 1.5, right); + + //glEnable (GL_BLEND); + //QGX_Alpha(false); + //QGX_Blend(true); + //glDepthMask (GL_FALSE); + //GX_SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE); + + //GL_Bind0 (ptex->texnum); + + //glBegin (GL_QUADS); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + scale = p->size; + //Con_Printf("new scale: %f\n", scale); + color[0] = p->color[0]; + color[1] = p->color[1]; + color[2] = p->color[2]; + color[3] = p->color[3]; + //glColor4ubv(color); + + float subTexLeft = ptex->coords[p->texindex][0]; + float subTexTop = ptex->coords[p->texindex][1]; + float subTexRight = ptex->coords[p->texindex][2]; + float subTexBottom = ptex->coords[p->texindex][3]; + + //glTexCoord2f(subTexLeft, subTexTop); + VectorMA(p->org, -scale * 0.5, up, p_downleft); + VectorMA(p_downleft, -scale * 0.5, right, p_downleft); + GX_Position3f32(p_downleft[0], p_downleft[1], p_downleft[2]); + GX_Color4u8(color[0], color[1], color[2], color[3]); + GX_TexCoord2f32(subTexLeft, subTexTop); + // glVertex3fv (p_downleft); + + // glTexCoord2f(subTexRight, subTexTop); + VectorMA (p_downleft, scale, up, p_upleft); + GX_Position3f32 (p_upleft[0], p_upleft[1], p_upleft[2]); + GX_Color4u8(color[0], color[1], color[2], color[3]); + GX_TexCoord2f32(subTexRight, subTexTop); + //glVertex3fv (p_upleft); + + //glTexCoord2f(subTexRight, subTexBottom); + VectorMA (p_upleft, scale, right, p_upright); + GX_Position3f32 (p_upright[0], p_upright[1], p_upright[2]); + GX_Color4u8(color[0], color[1], color[2], color[3]); + GX_TexCoord2f32(subTexRight, subTexBottom); + //glVertex3fv (p_upright); + + //glTexCoord2f(subTexLeft, subTexBottom); + VectorMA (p_downleft, scale, right, p_downright); + GX_Position3f32 (p_downright[0], p_downright[1], p_downright[2]); + GX_Color4u8(color[0], color[1], color[2], color[3]); + GX_TexCoord2f32(subTexLeft, subTexBottom); + //glVertex3fv (p_downright); + + //glEnd (); + + GX_End (); + + //glDepthMask (GL_TRUE); + //GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + + //QGX_Blend(false); + //QGX_Alpha(true); + //glDisable (GL_BLEND); + //glColor3f(1,1,1); +} + +void QMB_DrawParticles (void) +{ + int j, i; + vec3_t up, right, billboard[4], velcoord[4]/*, neworg*/; + particle_t *p; + particle_type_t *pt; + particle_texture_t *ptex; + + //float varray_vertex[16]; + //vec3_t distance; + + if (!qmb_initialized) + return; + + particle_time = cl.time; + + if (!cl.paused && key_dest == key_game) + QMB_UpdateParticles (); + + VectorAdd (vup, vright, billboard[2]); + VectorSubtract (vright, vup, billboard[3]); + VectorNegate (billboard[2], billboard[0]); + VectorNegate (billboard[3], billboard[1]); + + /*glDepthMask (GL_TRUE);*/ + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + //glEnable (GL_BLEND); + QGX_Blend (true); + // + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + //glShadeModel (GL_SMOOTH); + + for (i = 0 ; i < num_particletypes ; i++) + { + pt = &particle_types[i]; + + if (!pt->start) { + //Con_Printf("Particle type %d (want %d) does not have start\n", pt->drawtype, pd_billboard); + continue; + } + + //glBlendFunc (pt->SrcBlend, pt->DstBlend); + GX_SetBlendMode(GX_BM_BLEND, pt->SrcBlend, pt->DstBlend, GX_LO_CLEAR); + + switch (pt->drawtype) + { + case pd_hide: + break; + case pd_beam: + /* + ptex = &particle_textures[pt->texture]; + GL_Bind (ptex->texnum); + for (p = pt->start ; p ; p = p->next) + { + if (particle_time < p->start || particle_time >= p->die) + continue; + + VectorSubtract(r_refdef.vieworg, p->org, distance); + if (VectorLength(distance) > r_farclip.value) + continue; + // Allocate the vertices. + struct vertex + { + float u, v; + float x, y, z; + }; + + struct vertex* const out = (struct vertex*)(malloc(sizeof(struct vertex) * 4)); + + glColor4f(p->color[0]/255, p->color[1]/255, p->color[2]/255, p->color[3]/255); + R_CalcBeamVerts (varray_vertex, p->org, p->endorg, p->size / 3.0); + + out[0].u = 1; + out[0].v = 0; + + out[0].x = varray_vertex[0]; + out[0].y = varray_vertex[1]; + out[0].z = varray_vertex[2]; + + out[1].u = 1; + out[1].v = 1; + + out[1].x = varray_vertex[4]; + out[1].y = varray_vertex[5]; + out[1].z = varray_vertex[6]; + + out[2].u = 0; + out[2].v = 1; + + out[2].x = varray_vertex[8]; + out[2].y = varray_vertex[9]; + out[2].z = varray_vertex[10]; + + out[3].u = 0; + out[3].v = 0; + + out[3].x = varray_vertex[12]; + out[3].y = varray_vertex[13]; + out[3].z = varray_vertex[14]; + + glBegin (GL_TRIANGLE_FAN); + glVertex4fv (out); + glEnd (); + glColor4f(1,1,1,1); //return to normal color + } + */ + break; + case pd_spark: + /* + glDisable (GL_TEXTURE_2D); + for (p = pt->start ; p ; p = p->next) + { + if (particle_time < p->start || particle_time >= p->die) + continue; + + VectorSubtract(r_refdef.vieworg, p->org, distance); + if (VectorLength(distance) > r_farclip.value) + continue; + + struct vertex + { + vec3_t xyz; + }; + + struct vertex* const out = (struct vertex*)(malloc(sizeof(struct vertex) * 9)); + + glColor4f(p->color[0]/255, p->color[1]/255, p->color[2]/255, p->color[3]/255); + + for (int gh=0 ; gh<3 ; gh++) + out[0].xyz[gh] = p->org[gh]; + + glColor4f((p->color[0] >> 1)/255, (p->color[1] >> 1)/255, (p->color[2] >> 1)/255, (p->color[3] >> 1)/255); + + int vt = 1; + + for (j=7; j>=0 ; j--) + { + + for (int k=0 ; k<3 ; k++) + out[vt].xyz[k] = p->org[k] - p->vel[k] / 8 + vright[k] * cost[1%7] * p->size + vup[k] * sint[j%7] * p->size; + vt = vt + 1; + } + + glBegin (GL_TRIANGLE_FAN); + glVertex4fv (out); + glEnd (); + glColor4f(1,1,1,1); //return to normal color + } + glEnable (GL_TEXTURE_2D); + */ + break; + case pd_sparkray: + /* + glDisable (GL_TEXTURE_2D); + for (p = pt->start ; p ; p = p->next) + { + if (particle_time < p->start || particle_time >= p->die) + continue; + + VectorSubtract(r_refdef.vieworg, p->org, distance); + if (VectorLength(distance) > r_farclip.value) + continue; + + if (!TraceLineN(p->endorg, p->org, neworg, NULLVEC)) + VectorCopy(p->org, neworg); + + //R00k added -start- + //glEnable (GL_BLEND); + //p->color[3] = bound(0, 0.3, 1) * 255; + //R00k added -end- + //glColor4ubv (p->color); + + struct vertex + { + vec3_t xyz; + }; + + struct vertex* const out = (struct vertex*)(malloc(sizeof(struct vertex) * 9)); + + glColor4f(p->color[0]/255, p->color[1]/255, p->color[2]/255, p->color[3]/255); + + for (int gh=0 ; gh<3 ; gh++) + out[0].xyz[gh] = p->endorg[gh]; + + + glColor4f((p->color[0] >> 1)/255, (p->color[1] >> 1)/255, (p->color[2] >> 1)/255, (p->color[3] >> 1)/255); + + int vt = 1; + + for (j=7 ; j>=0 ; j--) + { + for (int k=0 ; k<3 ; k++) + out[vt].xyz[k] = neworg[k] + vright[k] * cost[j%7] * p->size + vup[k] * sint[j%7] * p->size; + + vt = vt + 1; + } + glBegin (GL_TRIANGLE_FAN); + glVertex4fv (out); + glEnd (); + glColor4f(1,1,1,1); //return to normal color + + } + glEnable (GL_TEXTURE_2D); + */ + break; + case pd_billboard: + ptex = &particle_textures[pt->texture]; + //GL_Bind (ptex->texnum); + GL_Bind0 (ptex->texnum); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + + for (p = pt->start ; p ; p = p->next) + { + if (particle_time < p->start || particle_time >= p->die) { + p->growth = 0; + continue; + } + + for (j = 0 ; j < cl.maxclients ; j++) + { + if (pt->custom != -1 && VectorSupCompare(p->org, cl_entities[1+j].origin, 40)) + { + p->die = 0; + continue; + } + } + + // sBTODO Figure out a similar depth setting for GX + + //if(pt->texture == ptex_muzzleflash || pt->texture == ptex_muzzleflash2 || pt->texture == ptex_muzzleflash3) + //GX_SetZMode(GX_TRUE, GX_GEQUAL, GX_TRUE); + //glDepthRange (0, 0.3); + + DRAW_PARTICLE_BILLBOARD(ptex, p, billboard); + + //if(pt->texture == ptex_muzzleflash || pt->texture == ptex_muzzleflash2 || pt->texture == ptex_muzzleflash3) + //GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + //glDepthRange(0, 1); + } + break; + + case pd_billboard_vel: + ptex = &particle_textures[pt->texture]; + GL_Bind0 (ptex->texnum); + for (p = pt->start ; p ; p = p->next) + { + if (particle_time < p->start || particle_time >= p->die) + continue; + + VectorCopy (p->vel, up); + CrossProduct (vpn, up, right); + VectorNormalizeFast (right); + VectorScale (up, pt->custom, up); + + VectorAdd (up, right, velcoord[2]); + VectorSubtract (right, up, velcoord[3]); + VectorNegate (velcoord[2], velcoord[0]); + VectorNegate (velcoord[3], velcoord[1]); + DRAW_PARTICLE_BILLBOARD(ptex, p, velcoord); + } + break; + + /*case pd_q3flame: + ptex = &particle_textures[pt->texture]; + GL_Bind (ptex->texnum); + for (p = pt->start ; p ; p = p->next) + { + float varray_vertex[16]; + float xhalf = p->size / 2.0, yhalf = p->size; + // vec3_t org, v, end, normal; + + if (particle_time < p->start || particle_time >= p->die) + continue; + + glDisable (GL_CULL_FACE); + + for (j=0 ; j<2 ; j++) + { + glPushMatrix (); + + glTranslatef(p->org[0], p->org[1], p->org[2]); + + //glRotatef (!j ? 45 : -45, 0, 0, 1); + + // naievil -- I don't know the equivalent of this + //sceGumRotateZ(!j ? 45 : -45 * (M_PI / 180.0f)); + + glColor4f(p->color[0]/255, p->color[1]/255, p->color[2]/255, p->color[3]/255); + + // sigh. The best would be if the flames were always orthogonal to their surfaces + // but I'm afraid it's impossible to get that work (w/o progs modification of course) + varray_vertex[0] = 0; + varray_vertex[1] = xhalf; + varray_vertex[2] = -yhalf; + varray_vertex[4] = 0; + varray_vertex[5] = xhalf; + varray_vertex[6] = yhalf; + varray_vertex[8] = 0; + varray_vertex[9] = -xhalf; + varray_vertex[10] = yhalf; + varray_vertex[12] = 0; + varray_vertex[13] = -xhalf; + varray_vertex[14] = -yhalf; + + struct vertex + { + float u, v; + float x, y, z; + }; + + struct vertex* const out = (struct vertex*)(malloc(sizeof(struct vertex) * 4)); + + out[0].u = ptex->coords[p->texindex][0]; + out[0].v = ptex->coords[p->texindex][3]; + out[0].x = varray_vertex[0]; + out[0].y = varray_vertex[1]; + out[0].z = varray_vertex[2]; + + + out[1].u = ptex->coords[p->texindex][0]; + out[1].v = ptex->coords[p->texindex][1]; + out[1].x = varray_vertex[4]; + out[1].y = varray_vertex[5]; + out[1].z = varray_vertex[6]; + + + out[2].u = ptex->coords[p->texindex][2]; + out[2].v = ptex->coords[p->texindex][1]; + out[2].x = varray_vertex[8]; + out[2].y = varray_vertex[9]; + out[2].z = varray_vertex[10]; + + + out[3].u = ptex->coords[p->texindex][2]; + out[3].v = ptex->coords[p->texindex][3]; + out[3].x = varray_vertex[12]; + out[3].y = varray_vertex[13]; + out[3].z = varray_vertex[14]; + + glBegin (GL_TRIANGLE_FAN); + glVertex4fv (out); + glEnd (); + glPopMatrix (); + } + glEnable (GL_CULL_FACE); + glColor4f(1,1,1,1); //return to normal color + } + break; + + case pd_q3gunshot: + for (p = pt->start ; p ; p = p->next) + QMB_Q3Gunshot (p->org, (int)p->texindex, (float)p->color[3] / 255.0); + break; + + case pd_q3teleport: + for (p = pt->start ; p ; p = p->next) + QMB_Q3Teleport (p->org, (float)p->color[3] / 255.0); + break;*/ + default: + Con_Printf ("QMB_DrawParticles: unexpected drawtype %d\n", pt->drawtype); + break; + } + } + + //glDisable (GL_BLEND); + //glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + QGX_Blend (false); + //glDepthMask (GL_FALSE); + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + //glShadeModel (GL_SMOOTH); +} + +void QMB_Shockwave_Splash(vec3_t org, int radius) +{ + float theta; + vec3_t angle; + + angle[2] = 0; + + for (theta = 0; theta < 6.283185307179586476925286766559; theta += 0.069813170079773183076947630739545) + { + angle[0] = cos(theta) * radius; + angle[1] = sin(theta) * radius; + AddParticle(p_shockwave, org, 1, 2, 0.625f, NULL, angle); + } +} + +//R00k: revamped to coincide with classic particle style... + +void QMB_ParticleExplosion (vec3_t org) +{ + if (r_explosiontype.value == 2)//no explosion what so ever + return; + + if (ISUNDERWATER(TruePointContents(org))) + { + AddParticle (p_bubble, org, 6, 3.0, 2.5, NULL, zerodir); + AddParticle (p_bubble, org, 4, 2.35, 2.5, NULL, zerodir); + + AddParticle (p_fire, org, 16, 120, 1, NULL, zerodir); + if (r_explosiontype.value != 1) + { + AddParticle (p_spark, org, 50, 250, 0.925f, NULL, zerodir); + AddParticle (p_spark, org, 25, 150, 0.925f, NULL, zerodir); + } + } + else + + { + /* original + if (r_explosiontype.value != 3) + { + if (r_flametype.value < 1)//R00k + { + AddParticle (p_fire2, org, 16, 18, 1, NULL, zerodir); + } + else + { + AddParticle (p_fire, org, 16, 18, 1, NULL, zerodir); + } + } + + if ((r_explosiontype.value == 0) || (r_explosiontype.value == 1) || (r_explosiontype.value == 3)) + { + AddParticle (p_spark, org, 50, 250, 0.925f, NULL, zerodir); + AddParticle (p_spark, org, 25, 150, 0.925f, NULL, zerodir); + } + */ + + //shpuld + AddParticle (p_fire, org, 10, 40, 0.5, NULL, zerodir); + AddParticle (p_fire2, org, 14, 36, 1.8, NULL, zerodir); + } +} + +void d8to24col (col_t colourv, int colour) +{ + byte *colourByte; + + colourByte = (byte *)&d_8to24table[colour]; + colourv[0] = colourByte[0]; + colourv[1] = colourByte[1]; + colourv[2] = colourByte[2]; +} + +void AddColoredParticle (part_type_t type, vec3_t org, int count, float size, float time, int colorStart, int colorLength, vec3_t dir) +{ + col_t color; + int i, j, colorMod = 0; + float tempSize; + particle_t *p; + particle_type_t *pt; + + if (!qmb_initialized) + Sys_Error ("QMB particle added without initialization"); + + //assert (size > 0 && time > 0); + + if (type < 0 || type >= num_particletypes) + Sys_Error ("AddColoredParticle: Invalid type (%d)", type); + + pt = &particle_types[particle_type_index[type]]; + + for (i=0 ; i < count && free_particles ; i++) + { + d8to24col (color, colorStart + (colorMod % colorLength)); + colorMod++; + INIT_NEW_PARTICLE(pt, p, color, size, time); + + switch (type) + { + case p_spark: + p->size = 1.175; + VectorCopy (org, p->org); + tempSize = size * 2; + p->vel[0] = (rand() % (int)tempSize) - ((int)tempSize / 4); + p->vel[1] = (rand() % (int)tempSize) - ((int)tempSize / 4); + p->vel[2] = (rand() % (int)tempSize) - ((int)tempSize / 6); + break; + + case p_fire: + VectorCopy (org, p->org); + for (j=0 ; j<3 ; j++) + p->vel[j] = ((rand() % 160) - 80) * (size / 25.0); + break; + + default: + Con_Printf ("AddColoredParticle: unexpected type\n"); + break; + } + } +} + +void QMB_ColorMappedExplosion (vec3_t org, int colorStart, int colorLength) +{ + + if (ISUNDERWATER(TruePointContents(org))) + { + //AddColoredParticle (p_fire, org, 16, 18, 1, colorStart, colorLength, zerodir); + AddParticle (p_bubble, org, 6, 3.0, 2.5, NULL, zerodir); + AddParticle (p_bubble, org, 4, 2.35, 2.5, NULL, zerodir); + if (r_explosiontype.value != 2) + { + AddColoredParticle (p_spark, org, 50, 100, 0.5, colorStart, colorLength, zerodir); + AddColoredParticle (p_spark, org, 25, 60, 0.5, colorStart, colorLength, zerodir); + } + } + else + { + if (r_flametype.value < 1)//R00k + { + AddColoredParticle (p_fire2, org, 16, 18, 1, colorStart, colorLength, zerodir); + } + else + { + AddColoredParticle (p_fire, org, 16, 18, 1, colorStart, colorLength, zerodir); + } + + if (r_explosiontype.value < 2) + { + AddColoredParticle (p_spark, org, 50, 250, 0.625f, colorStart, colorLength, zerodir); + if (r_explosiontype.value < 1) + AddColoredParticle (p_spark, org, 25, 150, 0.625f, colorStart, colorLength, zerodir); + } + } +} + +/* Original + +void QMB_Blood_Splat(part_type_t type, vec3_t org) //R00k :) +{ + int j; + col_t color; + vec3_t neworg, angle; + + VectorClear (angle); + + color[0]=100; + color[1]=0; + color[2]=0; + color[3]=255; + + AddParticle(p_bloodcloud, org, 1, 6, 0.5, color, zerodir); + + for (j=0 ; j<4 ; j++) + { + AngleVectors (angle, NULLVEC, NULLVEC, neworg); + VectorMA (org, 70, neworg, neworg); + + AddParticle (type, org, 5, 1, 2, color, neworg); + angle[1] += 360 / 4; + } +}*/ + +void QMB_Blood_Splat(part_type_t type, vec3_t org) //Shpuldified +{ + int j; + col_t color; + vec3_t neworg, angle; + + VectorClear (angle); + + color[0]=100; + color[1]=0; + color[2]=0; + color[3]=255; + + if(type == p_blood1) + { + AddParticle(p_bloodcloud, org, 3, 5, 0.3, color, zerodir); + } + + else if(type == p_blood2) + { + AddParticle(p_bloodcloud, org, 3, 7, 0.3, color, zerodir); + color[0] = 40; + AddParticle(p_blood2, org, 16, 3, 1.0, color, zerodir); + } + + else //p_blood3, trail? + { + AddParticle(p_bloodcloud, org, 3, 2, 0.6, color, zerodir); + for (j=0 ; j<4 ; j++) + { + AngleVectors (angle, NULLVEC, NULLVEC, neworg); + VectorMA (org, 70, neworg, neworg); + + AddParticle (type, org, 5, 1, 2, color, neworg); + angle[1] += 360 / 4; + } + } +} + +void QMB_RunParticleEffect (vec3_t org, vec3_t dir, int col, int count) +{ + col_t color; + vec3_t neworg, newdir; + int i, j, particlecount; + int contents;//R00k Added + + if (col == 73) + { + QMB_Blood_Splat(p_blood1, org); + return; + } + else if (col == 225) + { + QMB_Blood_Splat(p_blood2, org); + return; + } + else if (col == 20 && count == 30) + { + color[0] = color[2] = 51; + color[1] = 255; + AddParticle (p_chunk, org, 1, 1, 0.75, color, zerodir); + AddParticle (p_spark, org, 12, 75, 0.4, color, zerodir); + return; + } + else if (col == 226 && count == 20) + { + color[0] = 230; + color[1] = 204; + color[2] = 26; + AddParticle (p_chunk, org, 1, 1, 0.75, color, zerodir); + AddParticle (p_spark, org, 12, 75, 0.4, color, zerodir); + return; + } + else if(col == 111) //we will use this color for flames + { + // sBTODO + color[0] = color[1] = color[2] = 255; + AddParticle (p_q3flame, org, 3, 3, 2, color, dir); + return; + } + else if(col == 112) //we will use this color for big flames + { + color[0] = color[1] = color[2] = 255; + AddParticle (p_q3flame, org, 3, 6, 2, color, dir); + return; + } + + switch (count) + { + case 9: + case 10://nailgun + { + color[0] = 200; color[1] = 200; color[2] = 125; + + AddParticle (p_spark, org, 22, 100, 0.2, NULL, zerodir); + + //AddParticle (p_chunk, org, 3, 1, 0.75, NULL, zerodir); + + contents = TruePointContents (org);//R00k Added + + if (ISUNDERWATER(contents))//R00k + { + AddParticle (p_bubble, org, 1, 2, 0.825f + ((rand() % 10) - 5) / 40.0, NULL, zerodir); + } + else + + { + //AddParticle (p_smoke, org, 1, 4, 0.825f + ((rand() % 10) - 5) / 40.0, NULL, zerodir); + + // from Quakespasm + AddParticle (p_smoke, org, 3, 12, 1.225 + ((rand() % 10) - 5) / 40.0, NULL, zerodir); + } + } + break; + + case 20://super nailgun + color[0] = 200; color[1] = 200; color[2] = 125; + + AddParticle (p_spark, org, 22, 100, 0.2, NULL, zerodir); + + //AddParticle (p_chunk, org, 22, 2, 0.75, NULL, zerodir); + + contents = TruePointContents (org);//R00k Added + + if (ISUNDERWATER(contents))//R00k + { + AddParticle (p_bubble, org, 1, 2, 0.825f + ((rand() % 10) - 5) / 40.0, NULL, zerodir); + } + else + + { + AddParticle (p_smoke, org, 3, 12, 1.225f + ((rand() % 10) - 5) / 40.0, NULL, zerodir); + } + break; + + case 24:// gunshot + particlecount = count >> 1; + AddParticle (p_gunblast, org, 1, 1.04, 0.2, NULL, zerodir); + for (i=0 ; i>3) ; i++) + { + for (j=0 ; j<3 ; j++) + neworg[j] = org[j] + ((rand() % 24) - 12); + newdir[0] = dir[0] * (10 + (rand() % 5)); + newdir[1] = dir[1] * (10 + (rand() % 5)); + newdir[2] = dir[2] * 15; + d8to24col (color, (col & ~7) + (rand() & 7)); + AddParticle (p_glow, neworg, 1, 3.5, 0.5 + 0.1 * (rand() % 3), color, newdir); + } + return; + } + } +*/ + particlecount = fmax(1, count>>1); + for (i=0 ; iv.Flash_Size; + + if (cl.stats[STAT_ZOOM] == 1) + size = size/1.5f; + + if(size == 0 || cl.stats[STAT_ZOOM] == 2) + return; + + switch(rand() % 3 + 1) + { + case 1: + AddParticle (p_muzzleflash, org, 1, size, timemod * host_frametime, color, zerodir); + break; + case 2: + AddParticle (p_muzzleflash2, org, 1, size, timemod * host_frametime, color, zerodir); + break; + case 3: + AddParticle (p_muzzleflash3, org, 1, size, timemod * host_frametime, color, zerodir); + break; + default: + AddParticle (p_muzzleflash, org, 1, size, timemod * host_frametime, color, zerodir); + break; + } + } +} + +void QMB_RocketTrail (vec3_t start, vec3_t end, trail_type_t type) +{ + col_t color; + + switch (type) + { + case GRENADE_TRAIL://r00K mODIFIED + + if (ISUNDERWATER(TruePointContents(start))) + { + AddParticleTrail (p_bubble, start, end, 1, 0.30, NULL); + } + else + + { + if (r_part_trails.value > 1) + { + color[0] = 15; color[1] = 15; color[2] = 10; + AddParticleTrail (p_alphatrail, start, end, 8, 1, color); + } + else + AddParticleTrail (p_smoke, start, end, 1.45, 0.825, NULL); + } + break; + + case BLOOD_TRAIL: + case SLIGHT_BLOOD_TRAIL: + AddParticleTrail (p_blood3, start, end, type == BLOOD_TRAIL ? 1.35 : 2.4, 2, NULL); + break; + + case TRACER1_TRAIL: + color[0] = color[2] = 0; + color[1] = 124; + AddParticleTrail (p_trailpart, start, end, 3.75, 0.5, color); + break; + + case TRACER2_TRAIL: + color[0] = 255; + color[1] = 77; + color[2] = 0; + AddParticleTrail (p_trailpart, start, end, 1.75, 0.2, color); + break; + + case VOOR_TRAIL: + color[0] = 77; + color[1] = 0; + color[2] = 255; + AddParticleTrail (p_trailpart, start, end, 3.75, 0.5, color); + break; + + case ALT_ROCKET_TRAIL: + + if (ISUNDERWATER(TruePointContents(start))) + { + AddParticleTrail (p_bubble, start, end, 1, 2.5, NULL); + } + else + + { + if (r_part_trails.value > 1) + { + color[0] = 15; color[1] = 15; color[2] = 10; + AddParticleTrail (p_alphatrail, start, end, 8, 1, color); + } + else + { + AddParticleTrail (p_dpfire, start, end, 3, 0.26, NULL); + AddParticleTrail (p_dpsmoke, start, end, 3, 0.825, NULL); + } + } + break; + + case LAVA_TRAIL: + AddParticleTrail (p_lavatrail, start, end, 5, 0.25, NULL); + AddParticleTrail (p_dpsmoke, start, end, 5, 0.825, NULL); + break; + + case BUBBLE_TRAIL: + + if (ISUNDERWATER(TruePointContents(start))) + AddParticleTrail (p_bubble2, start, end, 1.5, 0.825, NULL); + + break; + + case NEHAHRA_SMOKE: + AddParticleTrail (p_smoke, start, end, 0.8, 0.825, NULL); + break; + case RAYGREEN_TRAIL: + color[0] = 0; + color[1] = 255; + color[2] = 0; + AddParticleTrail (p_alphatrail, start, end, 8, 0.6, color); + break; + case RAYRED_TRAIL: + color[0] = 255; + color[1] = 0; + color[2] = 0; + AddParticleTrail (p_alphatrail, start, end, 8, 0.6, color); + break; + case ROCKET_TRAIL: + default: + color[0] = 255; + color[1] = 56; + color[2] = 9; +// AddParticleTrail (p_trailpart, start, end, 6.2, 0.31, color); + if (ISUNDERWATER(TruePointContents(start))) + { + AddParticleTrail (p_trailpart, start, end, 1, 0.30, color); + AddParticleTrail (p_bubble, start, end, 1, 2.5, NULL); + } + else + + { + if (r_part_trails.value > 1) + { + color[0] = 15; color[1] = 15; color[2] = 10; + AddParticleTrail (p_alphatrail, start, end, 8, 3, color); + } + else + { + AddParticleTrail (p_trailpart, start, end, 6.2, 0.31, color); + AddParticleTrail (p_smoke, start, end, 1.8, 0.825, NULL); + } + } + break; + case NAIL_TRAIL://R00k added + + if (ISUNDERWATER(TruePointContents(start))) + { + AddParticleTrail (p_bubble, start, end, 0.25, 0.50, NULL); + } + else + + { + color[0] = 15; color[1] = 15; color[2] = 15; + AddParticleTrail (p_alphatrail, start, end, 1, 0.25, color); + } + break; + } +} + +void QMB_BlobExplosion (vec3_t org) +{ + float theta; + col_t color; + vec3_t neworg, vel; + + color[0] = 60; + color[1] = 100; + color[2] = 240; + AddParticle (p_spark, org, 44, 250, 1.15, color, zerodir); + + color[0] = 90; + color[1] = 47; + color[2] = 207; + AddParticle (p_fire, org, 15, 30, 1.4, color, zerodir); + + vel[2] = 0; + for (theta = 0 ; theta < 6.28318530717958647692528676655901 ; theta += 0.0897597901025655210989326680937001) + { + color[0] = (60 + (rand() & 15)); + color[1] = (65 + (rand() & 15)); + color[2] = (200 + (rand() & 15)); + + #ifdef PSP_VFPU + vel[0] = vfpu_cosf(theta) * 125; + vel[1] = vfpu_sinf(theta) * 125; + neworg[0] = org[0] + vfpu_cosf(theta) * 6; + neworg[1] = org[1] + vfpu_sinf(theta) * 6; + #else + vel[0] = cos(theta) * 125; + vel[1] = sin(theta) * 125; + neworg[0] = org[0] + cos(theta) * 6; + neworg[1] = org[1] + sin(theta) * 6; + #endif + neworg[2] = org[2] + 0 - 10; + AddParticle (p_shockwave, neworg, 1, 4, 0.8, color, vel); + neworg[2] = org[2] + 0 + 10; + AddParticle (p_shockwave, neworg, 1, 4, 0.8, color, vel); + + vel[0] *= 1.15; + vel[1] *= 1.15; + #ifdef PSP_VFPU + neworg[0] = org[0] + vfpu_cosf(theta) * 13; + neworg[1] = org[1] + vfpu_sinf(theta) * 13; + #else + neworg[0] = org[0] + cos(theta) * 13; + neworg[1] = org[1] + sin(theta) * 13; + #endif + neworg[2] = org[2] + 0; + AddParticle (p_shockwave, neworg, 1, 6, 1.0, color, vel); + } +} + +void QMB_LavaSplash (vec3_t org) +{ + int i, j; + float vel; + vec3_t dir/*, neworg*/; + + for (i=-16 ; i<16; i++) + { + for (j=-16 ; j<16 ; j++) + { + dir[0] = j * 8 + (rand() & 7); + dir[1] = i * 8 + (rand() & 7); + dir[2] = 256; + + //neworg[0] = org[0] + dir[0]; + //neworg[1] = org[1] + dir[1]; + //neworg[2] = org[2] + (rand() & 63); + + VectorNormalizeFast (dir); + vel = 50 + (rand() & 63); + VectorScale (dir, vel, dir); + } + } +} + +void QMB_TeleportSplash (vec3_t org) +{ + int i, j, k; + vec3_t neworg, angle; + col_t color; + + //QMB_Shockwave_Splash(org, 120); + for (i=-12 ; i<=12 ; i+=6) + { + for (j=-12 ; j<=12 ; j+=6) + { + for (k=-24 ; k<=32 ; k+=8) + { + neworg[0] = org[0] + i + (rand() & 3) - 1; + neworg[1] = org[1] + j + (rand() & 3) - 1; + neworg[2] = org[2] + k + (rand() & 3) - 1; + angle[0] = (rand() & 15) - 7; + angle[1] = (rand() & 15) - 7; + angle[2] = (rand() % 160) - 80; + AddParticle (p_teleflare, neworg, 1, 1.8, 0.30 + (rand() & 7) * 0.02, NULL, angle); + } + } + } + + VectorSet (color, 140, 140, 255); + VectorClear (angle); + for (i=0 ; i<5 ; i++) + { + angle[2] = 0; + for (j=0 ; j<5 ; j++) + { + AngleVectors (angle, NULLVEC, NULLVEC, neworg); + VectorMA (org, 70, neworg, neworg); + AddParticle (p_sparkray, org, 1, 6 + (i & 3), 5, color, neworg); + angle[2] += 360 / 5; + } + angle[0] += 180 / 5; + } +} + + +void QMB_InfernoFlame (vec3_t org) +{ + float frametime = fabs(cl.ctime - cl.oldtime); + + if (ISUNDERWATER(TruePointContents(org))) + return; + + if (frametime) + { + if (r_flametype.value < 1) + { + AddParticle (p_torch_flame, org, 1, 5, 0.5, NULL, zerodir);//R00k + } + else + { + AddParticle (p_inferno_flame, org, 1, 30, 13.125 * host_frametime, NULL, zerodir); + AddParticle (p_inferno_trail, org, 2, 1.75, 45.0 * host_frametime, NULL, zerodir); + AddParticle (p_inferno_trail, org, 2, 1.0, 52.5 * host_frametime, NULL, zerodir); + } + } +} + +void QMB_StaticBubble (entity_t *ent) +{ + AddParticle (p_staticbubble, ent->origin, 1, ent->frame == 1 ? 1.85 : 2.9, 0.001, NULL, zerodir); +} + +void QMB_TorchFlame (vec3_t org) +{ + if (fabs(cl.ctime - cl.oldtime)) + AddParticle (p_torch_flame, org, 2, 2.5, 0.5, NULL, zerodir); +} + +void QMB_FlameGt (vec3_t org, float size, float time) +{ + if (fabs(cl.ctime - cl.oldtime)) + AddParticle (p_flame, org, 1, size, time, NULL, zerodir); +} + +void QMB_BigTorchFlame (vec3_t org) +{ + if (fabs(cl.ctime - cl.oldtime)) + AddParticle (p_torch_flame, org, 2, 7, 0.5, NULL, zerodir); +} + +void QMB_Q3TorchFlame (vec3_t org, float size) +{ + static double flametime = 0; + + if (flametime + 0.125 < cl.time || flametime >= cl.time) + flametime = cl.time; + else + return; + + if (fabs(cl.ctime - cl.oldtime)) + AddParticle (p_q3flame, org, 1, size, 0.25, NULL, zerodir); +} + +void QMB_ShamblerCharge (vec3_t org) +{ + vec3_t pos, vec, dir; + col_t col = {60, 100, 240, 128}; + float time, len; + int i; + + for (i=0 ; i<5 ; i++) + { + VectorClear(vec); + VectorClear(dir); + + VectorCopy(org, pos); + pos[0] += (rand() % 200) - 100; + pos[1] += (rand() % 200) - 100; + pos[2] += (rand() % 200) - 100; + + VectorSubtract(pos, org, vec); + len = VectorLength (vec); + VectorNormalize (vec); + VectorMA(dir, -200, vec, dir); + time = len / 200; + + AddParticle (p_streakwave, pos, 1, 3, time, col, dir); + } +} + +void QMB_LaserSight (void) +{ + float frametime = fabs(cl.time - cl.oldtime); + col_t color; + int c; + + extern cvar_t r_laserpoint; + extern cvar_t scr_ofsx; + //extern cvar_t cl_gun_offset; + + //blubs-- Issue with this is that there's no particle texture assigned, need to either create, or fix rendering of null particle texture. + vec3_t dest, start, stop, forward, right,up; + trace_t trace; + + if (!particle_mode) + return; + + if (frametime) + { + if (qmb_initialized) + { + VectorClear(stop); + AngleVectors (r_refdef.viewangles, forward, right, up); + VectorCopy(cl_entities[cl.viewentity].origin, start); + + start[2] += 16; + start[2] += cl.crouch + bound(-7, scr_ofsx.value, 4); + + VectorMA (start, 0, right, start); + VectorMA (start, 4096, forward, dest); + + c = lt_default; + + switch ((int)r_laserpoint.value) + { + case 1: + color[0] = 000;color[1] = 000;color[2] = 255;color[3] = 50;//B + c = lt_blue; + break; + case 2: + color[0] = 255;color[1] = 000;color[2] = 000;color[3] = 50;//R + c = lt_red; + break; + case 3: + color[0] = 255;color[1] = 255;color[2] = 000;color[3] = 50;//Y + //c = lt_yellow; + c = lt_red; + break; + case 4: + color[0] = 000;color[1] = 255;color[2] = 000;color[3] = 50;//G + c = lt_green; + break; + } + + memset (&trace, 0, sizeof(trace_t)); + trace.fraction = 1; + SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, start, dest, &trace); + + start[2]+=cl.crouch; + AddParticle (p_streaktrail, start, 1, 2, 0.02, color, trace.endpos);// draw the line + //the 2 value above is size + + if (trace.fraction != 1) + { + color[3] = 200; + AddParticle (p_dot, trace.endpos, 1, 4, 0.01, color, zerodir);//pinpoint on wall + if ((cl.maxclients < 2) && (cl.time > cl.laser_point_time)) + { + CL_NewDlight (0, trace.endpos, (rand() % 10 + 30), 0.02, c); + cl.laser_point_time = cl.time + 0.02; + } + } + } + } +} + +void QMB_Lightning_Splash(vec3_t org) +{ + int i, j; + vec3_t neworg, angle; + col_t color; + col_t col2 = {200, 100, 100, 255}; + + VectorSet (color, 40, 40, 128); + VectorClear (angle); + + for (i=0 ; i<5 ; i++) + { + angle[2] = 0; + for (j=0 ; j<5 ; j++) + { + AngleVectors (angle, NULLVEC, NULLVEC, neworg); + VectorMA (org, 20, neworg, neworg); + AddParticle (p_spark, org, 2, 85, 0.05f, NULL, zerodir); + AddParticle (p_spark, org, 2, 100, 0.1f, col2, neworg); + angle[2] += 360 / 5; + } + angle[0] += 180 / 5; + } + color[0] = 224 + (rand() & 31); + color[1] = 100 + (rand() & 31); + color[2] = 0; + + AddParticle (p_spark, org, 1, 70, 0.2, color, zerodir); +} + +void QMB_LightningBeam (vec3_t start, vec3_t end) +{ + float frametime = fabs(cl.time - cl.oldtime); + col_t color = {255,255,255,255}; + trace_t trace; + + if (frametime) + { + if (qmb_initialized && r_part_lightning.value ) + { + if (qmb_initialized && r_part_sparks.value) + { + memset (&trace, 0, sizeof(trace_t)); + if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, start, end, &trace)) + { + if (trace.fraction < 1) + { + VectorCopy (trace.endpos, end); + if ((r_decal_sparks.value) && (particle_mode) && (decals_enabled)) + { + R_SpawnDecalStatic(end, decal_glow, 10); + } + QMB_Lightning_Splash (end); + } + } + } + + //R00k v1.84 moved down here + AddParticle(p_lightningbeam, start, 1, 80, host_frametime * 2, color, end); + } + } +} + +void QMB_Q3Gunshot (vec3_t org, int skinnum, float alpha) +{ + Con_Printf("Q3 drawing is not present in this engine!\n"); +} + +void QMB_Q3Teleport (vec3_t org, float alpha) +{ + Con_Printf("Q3 drawing is not present in this engine!\n"); +} + +#define NUMVERTEXNORMALS 162 + +extern float r_avertexnormals[NUMVERTEXNORMALS][3]; +extern vec3_t avelocities[NUMVERTEXNORMALS]; + +/* +=============== +R_EntityParticles +=============== +*/ +void QMB_EntityParticles (entity_t *ent) +{ + int i; + float angle, dist, sp, sy, cp, cy; + vec3_t forward, org; + col_t color = {255,255,0,100}; + + dist = 64; + + if (!avelocities[0][0]) + for (i=0 ; iorigin[0] + r_avertexnormals[i][0]*dist + forward[0]*16; + org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*16; + org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*16; + AddParticle (p_flare, org, 1, 2,0.005, color, forward); + } +} + +void R_GetParticleMode (void) +{ + if (!r_part_explosions.value && !r_part_trails.value && !r_part_spikes.value && + !r_part_gunshots.value && !r_part_blood.value && !r_part_telesplash.value && + !r_part_blobs.value && !r_part_lavasplash.value && !r_part_flames.value && + !r_part_lightning.value) + particle_mode = pm_classic; + else if (r_part_explosions.value == 1 && r_part_trails.value == 1 && r_part_spikes.value == 1 && + r_part_gunshots.value == 1 && r_part_blood.value == 1 && r_part_telesplash.value == 1 && + r_part_blobs.value == 1 && r_part_lavasplash.value == 1 && r_part_flames.value == 1 && + r_part_lightning.value == 1) + particle_mode = pm_qmb; + else if (r_part_explosions.value == 2 && r_part_trails.value == 2 && r_part_spikes.value == 2 && + r_part_gunshots.value == 2 && r_part_blood.value == 2 && r_part_telesplash.value == 2 && + r_part_blobs.value == 2 && r_part_lavasplash.value == 2 && r_part_flames.value == 2 && + r_part_lightning.value == 2) + particle_mode = pm_quake3; + else + particle_mode = pm_mixed; +} + +void R_SetParticleMode (part_mode_t val) +{ + particle_mode = val; + + Cvar_SetValue ("r_part_explosions", particle_mode); + Cvar_SetValue ("r_part_trails", particle_mode); + Cvar_SetValue ("r_part_sparks", particle_mode); + Cvar_SetValue ("r_part_spikes", particle_mode); + Cvar_SetValue ("r_part_gunshots", particle_mode); + Cvar_SetValue ("r_part_blood", particle_mode); + Cvar_SetValue ("r_part_telesplash", particle_mode); + Cvar_SetValue ("r_part_blobs", particle_mode); + Cvar_SetValue ("r_part_lavasplash", particle_mode); + Cvar_SetValue ("r_part_flames", particle_mode); + Cvar_SetValue ("r_part_lightning", particle_mode); + Cvar_SetValue ("r_part_flies", particle_mode); + Cvar_SetValue ("r_part_muzzleflash", particle_mode); +} + +char *R_NameForParticleMode (void) +{ + char *name; + + switch (particle_mode) + { + case pm_classic: + name = "Classic"; + break; + + case pm_qmb: + name = "QMB"; + break; + + case pm_quake3: + name = "Quake3"; + break; + + case pm_mixed: + name = "mixed"; + break; + + default: + name = "derp"; + break; + } + + return name; +} + +/* +=============== +R_ToggleParticles_f + +function that toggles between classic and QMB particles +=============== +*/ +void R_ToggleParticles_f (void) +{ + if (cmd_source != src_command) + return; + + if (particle_mode == pm_classic) + R_SetParticleMode (pm_qmb); + else if (particle_mode == pm_qmb) + R_SetParticleMode (pm_quake3); + else + R_SetParticleMode (pm_classic); + + if (key_dest != key_menu && key_dest != key_menu_pause) + Con_Printf ("Using %s particles\n", R_NameForParticleMode()); +} + +void CheckDecals (void) +{ + if (!r_decal_bullets.value && !r_decal_explosions.value && !r_decal_sparks.value && !r_decal_blood.value) + decals_enabled = 0; + else + if (r_decal_bullets.value && r_decal_explosions.value && r_decal_sparks.value && r_decal_blood.value) + decals_enabled = 1; + else + decals_enabled = 2; +} + +void R_SetDecals (int val) +{ + decals_enabled = val; + Cvar_SetValue ("r_decal_bullets", val); + Cvar_SetValue ("r_decal_explosions", val); + Cvar_SetValue ("r_decal_sparks", val); + Cvar_SetValue ("r_decal_blood", val); +} + +/* +=============== +R_ToggleDecals_f +=============== +*/ +void R_ToggleDecals_f (void) +{ + if (cmd_source != src_command) + return; + CheckDecals (); + R_SetDecals (!(decals_enabled)); + Con_Printf ("All Decals are %s.\n", !decals_enabled ? "disabled" : "enabled"); +} diff --git a/source/wii/gx/gx_refrag.c b/source/wii/gx/gx_refrag.c new file mode 100644 index 0000000..f984b62 --- /dev/null +++ b/source/wii/gx/gx_refrag.c @@ -0,0 +1,234 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_efrag.c + +#include "../../quakedef.h" + +mnode_t *r_pefragtopnode; + + +//=========================================================================== + +/* +=============================================================================== + + ENTITY FRAGMENT FUNCTIONS + +=============================================================================== +*/ + +efrag_t **lastlink; + +vec3_t r_emins, r_emaxs; + +entity_t *r_addent; + + +/* +================ +R_RemoveEfrags + +Call when removing an object from the world or moving it to another position +================ +*/ +void R_RemoveEfrags (entity_t *ent) +{ + efrag_t *ef, *old, *walk, **prev; + + ef = ent->efrag; + + while (ef) + { + prev = &ef->leaf->efrags; + while (1) + { + walk = *prev; + if (!walk) + break; + if (walk == ef) + { // remove this fragment + *prev = ef->leafnext; + break; + } + else + prev = &walk->leafnext; + } + + old = ef; + ef = ef->entnext; + + // put it on the free list + old->entnext = cl.free_efrags; + cl.free_efrags = old; + } + + ent->efrag = NULL; +} + +/* +=================== +R_SplitEntityOnNode +=================== +*/ +void R_SplitEntityOnNode (mnode_t *node) +{ + efrag_t *ef; + mplane_t *splitplane; + mleaf_t *leaf; + int sides; + + if (node->contents == CONTENTS_SOLID) + { + return; + } + +// add an efrag if the node is a leaf + + if ( node->contents < 0) + { + if (!r_pefragtopnode) + r_pefragtopnode = node; + + leaf = (mleaf_t *)node; + +// grab an efrag off the free list + ef = cl.free_efrags; + if (!ef) + { + Con_Printf ("Too many efrags!\n"); + return; // no free fragments... + } + cl.free_efrags = cl.free_efrags->entnext; + + ef->entity = r_addent; + +// add the entity link + *lastlink = ef; + lastlink = &ef->entnext; + ef->entnext = NULL; + +// set the leaf links + ef->leaf = leaf; + ef->leafnext = leaf->efrags; + leaf->efrags = ef; + + return; + } + +// NODE_MIXED + + splitplane = node->plane; + sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); + + if (sides == 3) + { + // split on this plane + // if this is the first splitter of this bmodel, remember it + if (!r_pefragtopnode) + r_pefragtopnode = node; + } + +// recurse down the contacted sides + if (sides & 1) + R_SplitEntityOnNode (node->children[0]); + + if (sides & 2) + R_SplitEntityOnNode (node->children[1]); +} + + + +/* +=========== +R_AddEfrags +=========== +*/ +void R_AddEfrags (entity_t *ent) +{ + model_t *entmodel; + int i; + + if (!ent->model) + return; + + r_addent = ent; + + lastlink = &ent->efrag; + r_pefragtopnode = NULL; + + entmodel = ent->model; + + for (i=0 ; i<3 ; i++) + { + r_emins[i] = ent->origin[i] + entmodel->mins[i]; + r_emaxs[i] = ent->origin[i] + entmodel->maxs[i]; + } + + R_SplitEntityOnNode (cl.worldmodel->nodes); + + ent->topnode = r_pefragtopnode; +} + + +/* +================ +R_StoreEfrags + +// FIXME: a lot of this goes away with edge-based +================ +*/ +void R_StoreEfrags (efrag_t **ppefrag) +{ + entity_t *pent; + model_t *clmodel; + efrag_t *pefrag; + + + while ((pefrag = *ppefrag) != NULL) + { + pent = pefrag->entity; + clmodel = pent->model; + + switch (clmodel->type) + { + case mod_alias: + case mod_brush: + case mod_sprite: + pent = pefrag->entity; + + if ((pent->visframe != r_framecount) && + (cl_numvisedicts < MAX_VISEDICTS)) + { + cl_visedicts[cl_numvisedicts++] = pent; + + // mark that we've recorded this entity for this frame + pent->visframe = r_framecount; + } + + ppefrag = &pefrag->leafnext; + break; + + default: + Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); + } + } +} + + diff --git a/source/wii/gx/gx_rlight.c b/source/wii/gx/gx_rlight.c new file mode 100644 index 0000000..4385794 --- /dev/null +++ b/source/wii/gx/gx_rlight.c @@ -0,0 +1,297 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_light.c + +#include "../../quakedef.h" +int r_dlightframecount; + + +/* +================== +R_AnimateLight +================== +*/ +void R_AnimateLight (void) +{ + int i,j,k; + +// +// light animations +// 'm' is normal light, 'a' is no light, 'z' is double bright + i = (int)(cl.time*10); + for (j=0 ; jcontents < 0) + return; + + splitplane = node->plane; +// dist = PlaneDiff(light->origin, splitplane); + + if (splitplane->type < 3) + dist = light->origin[splitplane->type] - splitplane->dist; + else + dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; + + if (dist > light->radius) + { + node = node->children[0]; + goto loc0; + } + if (dist < -light->radius) + { + node = node->children[1]; + goto loc0; + } + + maxdist = light->radius * light->radius; +// mark the polygons + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i=0 ; inumsurfaces ; i++, surf++) + { + dist = DotProduct (light->origin, surf->plane->normal) - surf->plane->dist; // JT030305 - fix light bleed through + if (dist >= 0) + sidebit = 0; + else + sidebit = SURF_PLANEBACK; + + if ( (surf->flags & SURF_PLANEBACK) != sidebit ) //Discoloda + continue; //Discoloda + + for (j=0 ; j<3 ; j++) + impact[j] = light->origin[j] - surf->plane->normal[j]*dist; + + // clamp center of light to corner and check brightness + l = DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; + s = l + 0.5; + s = bound(0, s, surf->extents[0]); + s = l - s; + l = DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; + t = l + 0.5; + t = bound(0, t, surf->extents[1]); + t = l - t; + + // compare to minimum light + if ((s*s + t*t + dist*dist) < maxdist) + { + if (surf->dlightframe != r_dlightframecount) // not dynamic until now + { + surf->dlightbits = bit; + surf->dlightframe = r_dlightframecount; + } + else // already dynamic + { + surf->dlightbits |= bit; + } + } + } + if (node->children[0]->contents >= 0) + R_MarkLights (light, bit, node->children[0]); + if (node->children[1]->contents >= 0) + R_MarkLights (light, bit, node->children[1]); +} + + +/* +============= +R_PushDlights +============= +*/ +void R_PushDlights (void) +{ + int i; + dlight_t *l; + + r_dlightframecount = r_framecount + 1; // because the count hasn't + // advanced yet for this frame + l = cl_dlights; + + for (i=0 ; idie < cl.time || !l->radius) + continue; + R_MarkLights ( l, 1<nodes ); + } +} + +/* +============================================================================= + +LIGHT SAMPLING + +============================================================================= +*/ + +mplane_t *lightplane; +vec3_t lightspot; + +// LordHavoc: .lit support begin +// LordHavoc: original code replaced entirely +int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end) +{ + float front, back, frac; + vec3_t mid; + +loc0: + if (node->contents < 0) + return false; // didn't hit anything + +// calculate mid point + if (node->plane->type < 3) + { + front = start[node->plane->type] - node->plane->dist; + back = end[node->plane->type] - node->plane->dist; + } + else + { + front = DotProduct(start, node->plane->normal) - node->plane->dist; + back = DotProduct(end, node->plane->normal) - node->plane->dist; + } + + // LordHavoc: optimized recursion + if ((back < 0) == (front < 0)) +// return RecursiveLightPoint (color, node->children[front < 0], start, end); + { + node = node->children[front < 0]; + goto loc0; + } + + frac = front / (front-back); + mid[0] = start[0] + (end[0] - start[0])*frac; + mid[1] = start[1] + (end[1] - start[1])*frac; + mid[2] = start[2] + (end[2] - start[2])*frac; + +// go down front side + if (RecursiveLightPoint (color, node->children[front < 0], start, mid)) + return true; // hit something + else + { + int i, ds, dt; + msurface_t *surf; + // check for impact on this node + VectorCopy (mid, lightspot); + lightplane = node->plane; + + surf = cl.worldmodel->surfaces + node->firstsurface; + for (i = 0;i < node->numsurfaces;i++, surf++) + { + if (surf->flags & SURF_DRAWTILED) + continue; // no lightmaps + + ds = (int) ((float) DotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]); + dt = (int) ((float) DotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]); + + if (ds < surf->texturemins[0] || dt < surf->texturemins[1]) + continue; + + ds -= surf->texturemins[0]; + dt -= surf->texturemins[1]; + + if (ds > surf->extents[0] || dt > surf->extents[1]) + continue; + + if (surf->samples) + { + // LordHavoc: enhanced to interpolate lighting + byte *lightmap; + int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0; + float scale; + line3 = ((surf->extents[0]>>4)+1)*3; + + lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color + + for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++) + { + scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0; + r00 += (float) lightmap[ 0] * scale;g00 += (float) lightmap[ 1] * scale;b00 += (float) lightmap[2] * scale; + r01 += (float) lightmap[ 3] * scale;g01 += (float) lightmap[ 4] * scale;b01 += (float) lightmap[5] * scale; + r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale; + r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale; + lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting + } + + color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00))); + color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00))); + color[2] += (float) ((int) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00))); + } + return true; // success + } + + // go down back side + return RecursiveLightPoint (color, node->children[front >= 0], mid, end); + } +} + +vec3_t lightcolor; // LordHavoc: used by model rendering +int R_LightPoint (vec3_t p) +{ + vec3_t end; + + if (r_fullbright.value || !cl.worldmodel->lightdata) + { + lightcolor[0] = lightcolor[1] = lightcolor[2] = 255; + return 255; + } + + end[0] = p[0]; + end[1] = p[1]; + end[2] = p[2] - 2048; + + lightcolor[0] = lightcolor[1] = lightcolor[2] = 0; + RecursiveLightPoint (lightcolor, cl.worldmodel->nodes, p, end); + return ((lightcolor[0] + lightcolor[1] + lightcolor[2]) * (1.0f / 3.0f)); +} +// LordHavoc: .lit support end diff --git a/source/wii/gx/gx_rmain.c b/source/wii/gx/gx_rmain.c new file mode 100644 index 0000000..5f7f6fc --- /dev/null +++ b/source/wii/gx/gx_rmain.c @@ -0,0 +1,2072 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_main.c + +#include "../../quakedef.h" + +extern vec3_t lightcolor; // LordHavoc: .lit support to the definitions at the top + +entity_t r_worldentity; + +qboolean r_cache_thrash; // compatability + +vec3_t modelorg, r_entorigin; +entity_t *currententity; + +int r_visframecount; // bumped when going to a new PVS +int r_framecount; // used for dlight push checking + +mplane_t frustum[4]; + +int c_brush_polys, c_alias_polys; + +qboolean envmap; // true during envmap command capture + +int currenttexture0 = -1; // to avoid unnecessary texture sets +int currenttexture1 = -1; // to avoid unnecessary texture sets + +int cnttextures[2] = {-1, -1}; // cached + +int particletexture; // little dot for particles +int playertextures[MAX_SCOREBOARD]; // up to 16 color translated skins + +int mirrortexturenum; // quake texturenum, not gltexturenum +qboolean mirror; +mplane_t *mirror_plane; + +// +// view origin +// +vec3_t vup; +vec3_t vpn; +vec3_t vright; +vec3_t r_origin; + +float r_world_matrix[16]; +float r_base_world_matrix[16]; + +// +// screen size info +// +refdef_t r_refdef; + +mleaf_t *r_viewleaf, *r_oldviewleaf; + +texture_t *r_notexture_mip; + +int d_lightstylevalue[256]; // 8.8 fraction of base light value + + +void R_MarkLeaves (void); + +cvar_t r_norefresh = {"r_norefresh","0"}; +cvar_t r_drawentities = {"r_drawentities","1"}; +cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; +cvar_t r_speeds = {"r_speeds","0"}; +cvar_t r_fullbright = {"r_fullbright","0"}; +cvar_t r_lightmap = {"r_lightmap","0"}; +cvar_t r_shadows = {"r_shadows","0"}; +cvar_t r_mirroralpha = {"r_mirroralpha","1"}; +cvar_t r_wateralpha = {"r_wateralpha","0.5"}; +cvar_t r_dynamic = {"r_dynamic","1"}; +cvar_t r_novis = {"r_novis","0"}; +cvar_t r_lerpmodels = {"r_lerpmodels", "1"}; +cvar_t r_lerpmove = {"r_lerpmove", "1"}; +cvar_t r_skyfog = {"r_skyfog", "0"}; // sB sky is fogged naturally + +cvar_t gl_finish = {"gl_finish","0"}; +cvar_t gl_clear = {"gl_clear","0"}; +cvar_t gl_cull = {"gl_cull","1"}; +cvar_t gl_smoothmodels = {"gl_smoothmodels","1"}; +cvar_t gl_affinemodels = {"gl_affinemodels","0"}; +cvar_t gl_polyblend = {"gl_polyblend","1"}; +cvar_t gl_playermip = {"gl_playermip","0"}; +cvar_t gl_nocolors = {"gl_nocolors","0"}; +cvar_t gl_keeptjunctions = {"gl_keeptjunctions","1"}; // sB was 0, but this caused white dots in world geo +cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; +cvar_t gl_doubleeyes = {"gl_doubleeys", "1"}; + +//QMB +cvar_t r_explosiontype = {"r_explosiontype", "0",true}; +cvar_t r_laserpoint = {"r_laserpoint", "0",true}; +cvar_t r_part_explosions = {"r_part_explosions", "1",true}; +cvar_t r_part_trails = {"r_part_trails", "1",true}; +cvar_t r_part_sparks = {"r_part_sparks", "1",true}; +cvar_t r_part_spikes = {"r_part_spikes", "1",true}; +cvar_t r_part_gunshots = {"r_part_gunshots", "1",true}; +cvar_t r_part_blood = {"r_part_blood", "1",true}; +cvar_t r_part_telesplash = {"r_part_telesplash", "1",true}; +cvar_t r_part_blobs = {"r_part_blobs", "1",true}; +cvar_t r_part_lavasplash = {"r_part_lavasplash", "1",true}; +cvar_t r_part_flames = {"r_part_flames", "1",true}; +cvar_t r_part_lightning = {"r_part_lightning", "1",true}; +cvar_t r_part_flies = {"r_part_flies", "1",true}; +cvar_t r_part_muzzleflash = {"r_part_muzzleflash", "1",true}; +cvar_t r_flametype = {"r_flametype", "2",true}; + +cvar_t r_farclip = {"r_farclip", "4096"}; //far cliping for QMB + +cvar_t r_flatlightstyles = {"r_flatlightstyles", "0"}; +cvar_t r_model_brightness = { "r_model_brightness", "1", true}; // Toggle high brightness model lighting + +cvar_t r_overbright = {"r_overbright", "1", true}; //overbrights + +//johnfitz -- struct for passing lerp information to drawing functions +typedef struct { + short pose1; + short pose2; + float blend; + vec3_t origin; + vec3_t angles; +} lerpdata_t; +//johnfitz + +extern cvar_t gl_ztrick; +extern cvar_t scr_fov; +extern cvar_t scr_fov_viewmodel; + +float viewport_size[4]; + +/* +================= +R_CullBox + +Returns true if the box is completely outside the frustom +================= +*/ +qboolean R_CullBox (vec3_t mins, vec3_t maxs) +{ + /* + int i; + + // ELUTODO: check for failure cases (rendering to an aspect different of that of the quake-calculated frustum, etc + for (i=0 ; i<4 ; i++) + if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) + return true; + */ + return false; +} + +guVector axis2 = {0,0,1}; +guVector axis1 = {0,1,0}; +guVector axis0 = {1,0,0}; +void R_RotateForEntity (entity_t *e, unsigned char scale) +{ + Mtx temp; + + // ELUTODO: change back to asm when ALL functions have been corrected + + // sB changed back to asm. + + guMtxTrans(temp, e->origin[0], e->origin[1], e->origin[2]); + guMtxConcat(model, temp, model); + + guMtxRotAxisRad(temp, &axis2, DegToRad(e->angles[1])); + guMtxConcat(model, temp, model); + guMtxRotAxisRad(temp, &axis1, DegToRad(-e->angles[0])); + guMtxConcat(model, temp, model); + guMtxRotAxisRad(temp, &axis0, DegToRad(e->angles[2])); + guMtxConcat(model, temp, model); + + if (scale != ENTSCALE_DEFAULT) { + float scalefactor = ENTSCALE_DECODE(scale); + + guMtxScale (temp, scalefactor, scalefactor, scalefactor); + guMtxConcat(model, temp, model); + //glScalef(scalefactor, scalefactor, scalefactor); + } +} + +/* +============================================================= + + SPRITE MODELS + +============================================================= +*/ + +/* +================ +R_GetSpriteFrame +================ +*/ +mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, numframes, frame; + float *pintervals, fullinterval, targettime, time; + + psprite = currententity->model->cache.data; + frame = currententity->frame; + + if ((frame >= psprite->numframes) || (frame < 0)) + { + //Con_Printf ("R_DrawSprite: no such frame %d\n", frame); + frame = 0; + } + + if (psprite->frames[frame].type == SPR_SINGLE) + { + pspriteframe = psprite->frames[frame].frameptr; + } + else + { + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes-1]; + + time = cl.time + currententity->syncbase; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by 0 + targettime = time - ((int)(time / fullinterval)) * fullinterval; + + for (i=0 ; i<(numframes-1) ; i++) + { + if (pintervals[i] > targettime) + break; + } + + pspriteframe = pspritegroup->frames[i]; + } + + return pspriteframe; +} + + +/* +================= +R_DrawSpriteModel + +================= +*/ +void R_DrawSpriteModel (entity_t *e) +{ + vec3_t point; + mspriteframe_t *frame; + float *up, *right; + vec3_t v_forward, v_right, v_up; + msprite_t *psprite; + + // don't even bother culling, because it's just a single + // polygon without a surface cache + frame = R_GetSpriteFrame (e); + psprite = currententity->model->cache.data; + + if (psprite->type == SPR_ORIENTED) + { // bullet marks on walls + AngleVectors (currententity->angles, v_forward, v_right, v_up); + up = v_up; + right = v_right; + } + else + { // normal sprite + up = vup; + right = vright; + } + + //GL_DisableMultitexture(); + + GL_Bind0(frame->gl_texturenum); + + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + + //Fog_DisableGFog (); + //GX_SetZMode(GX_TRUE, GX_GEQUAL, GX_TRUE); + QGX_Alpha(false); + QGX_Blend(true); + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + VectorMA (e->origin, frame->down, up, point); + VectorMA (point, frame->left, right, point); + GX_Position3f32(point[0], point[1], point[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(0, 1); + + VectorMA (e->origin, frame->up, up, point); + VectorMA (point, frame->left, right, point); + GX_Position3f32(point[0], point[1], point[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(0, 0); + + VectorMA (e->origin, frame->up, up, point); + VectorMA (point, frame->right, right, point); + GX_Position3f32(point[0], point[1], point[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(1, 0); + + VectorMA (e->origin, frame->down, up, point); + VectorMA (point, frame->right, right, point); + GX_Position3f32(point[0], point[1], point[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(1, 1); + + GX_End(); + QGX_Alpha(true); + QGX_Blend(false); + //GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + //Fog_EnableGFog (); +} + +/* +============================================================= + + ALIAS MODELS + +============================================================= +*/ + + +#define NUMVERTEXNORMALS 162 + +float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "../../anorms.h" +}; + +vec3_t shadevector; +float shadelight, ambientlight; + +// precalculated dot products for quantized angles +#define SHADEDOT_QUANT 16 +float r_avertexnormal_dots[SHADEDOT_QUANT][256] = +#include "anorm_dots.h" +; + +float *shadedots = r_avertexnormal_dots[0]; + +int lastposenum; + +/* +============= +GL_DrawAliasFrame +============= +*/ +void GL_DrawAliasFrame (aliashdr_t *paliashdr, lerpdata_t lerpdata) +{ + //float l; + trivertx_t *verts1, *verts2; + int *commands; + int count; + float blend, iblend; + //float u, v; + qboolean lerping; + + if (lerpdata.pose1 != lerpdata.pose2) + { + lerping = true; + verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts2 = verts1; + verts1 += lerpdata.pose1 * paliashdr->poseverts; + verts2 += lerpdata.pose2 * paliashdr->poseverts; + blend = lerpdata.blend; + iblend = 1.0f - blend; + } + else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled + { + lerping = false; + verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts2 = verts1; // avoid bogus compiler warning + verts1 += lerpdata.pose1 * paliashdr->poseverts; + blend = iblend = 0; // avoid bogus compiler warning + } + + commands = (int *)((byte *)paliashdr + paliashdr->commands); + + //l = shadedots[verts1->lightnormalindex]; + + //glColor4f(lightcolor[0]/255, lightcolor[1]/255, lightcolor[2]/255, 1.0f); + // + + while (1) + { + // get the vertex count and primitive type + count = *commands++; + if (!count) + break; // done + + if (count < 0) + { + count = -count; + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, count); + } + else + GX_Begin (GX_TRIANGLESTRIP, GX_VTXFMT0, count); + + do + { + //u = ((float *)commands)[0]; + //v = ((float *)commands)[1]; + + //glTexCoord2f (u, v); + //GX_TexCoord2f32(u, v); + + if (lerping) { + //glVertex3f (verts1->v[0]*iblend + verts2->v[0]*blend, + //verts1->v[1]*iblend + verts2->v[1]*blend, + //verts1->v[2]*iblend + verts2->v[2]*blend); + GX_Position3f32(verts1->v[0]*iblend + verts2->v[0]*blend, + verts1->v[1]*iblend + verts2->v[1]*blend, + verts1->v[2]*iblend + verts2->v[2]*blend); + GX_Color4u8(lightcolor[0], lightcolor[1], lightcolor[2], 0xff); + verts1++; + verts2++; + } else { + //glVertex3f (verts1->v[0], verts1->v[1], verts1->v[2]); + GX_Position3f32(verts1->v[0], verts1->v[1], verts1->v[2]); + GX_Color4u8(lightcolor[0], lightcolor[1], lightcolor[2], 0xff); + verts1++; + + } + GX_TexCoord2f32(((float *)commands)[0], ((float *)commands)[1]); + + commands += 2; + + } while (--count); + + GX_End (); + } +} + + +/* +============= +GL_DrawAliasShadow +============= +*/ +extern vec3_t lightspot; + +void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) +{ + //float s, t, l; + //int i, j; + //int index; + + trivertx_t /**v,*/ *verts; + //int list; + int *order; + vec3_t point; + //float *normal; + float height, lheight; + int count; + + lheight = currententity->origin[2] - lightspot[2]; + + height = 0; + verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts += posenum * paliashdr->poseverts; + order = (int *)((byte *)paliashdr + paliashdr->commands); + + height = -lheight + 1.0; + + //sB should be working now. + while (1) + { + // get the vertex count and primitive type + count = *order++; + if (!count) + break; // done + if (count < 0) + { + count = -count; + //glBegin (GL_TRIANGLE_FAN); + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, count); + } + else + //glBegin (GL_TRIANGLE_STRIP); + GX_Begin (GX_TRIANGLESTRIP, GX_VTXFMT0, count); + + do + { + // texture coordinates come from the draw list + // (skipped for shadows) glTexCoord2fv ((float *)order); + + // normals and vertexes come from the frame list + point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; + point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; + point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; + + point[0] -= shadevector[0]*(point[2]+lheight); + point[1] -= shadevector[1]*(point[2]+lheight); + point[2] = height; +// height -= 0.001; + //glVertex3fv (point); + + GX_Position3f32(point[0], point[1], point[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + verts++; + order += 2; + + } while (--count); + + //glEnd (); + GX_End(); + } + +} + + + +/* +================= +R_SetupAliasFrame -- johnfitz -- rewritten to support lerping +================= +*/ +void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata) +{ + entity_t *e = currententity; + int posenum, numposes; + + if ((frame >= paliashdr->numframes) || (frame < 0)) + { + //Con_DPrintf ("R_AliasSetupFrame: no such frame %d for '%s'\n", frame, e->model->name); + frame = 0; + } + + posenum = paliashdr->frames[frame].firstpose; + numposes = paliashdr->frames[frame].numposes; + + if (numposes > 1) + { + e->lerptime = paliashdr->frames[frame].interval; + posenum += (int)(cl.time / e->lerptime) % numposes; + } + else + e->lerptime = 0.1; + + if (e->lerpflags & LERP_RESETANIM) //kill any lerp in progress + { + e->lerpstart = 0; + e->previouspose = posenum; + e->currentpose = posenum; + e->lerpflags -= LERP_RESETANIM; + } + else if (e->currentpose != posenum) // pose changed, start new lerp + { + if (e->lerpflags & LERP_RESETANIM2) //defer lerping one more time + { + e->lerpstart = 0; + e->previouspose = posenum; + e->currentpose = posenum; + e->lerpflags -= LERP_RESETANIM2; + } + else + { + e->lerpstart = cl.time; + e->previouspose = e->currentpose; + e->currentpose = posenum; + } + } + + //set up values + if (r_lerpmodels.value && !(e->model->flags & MOD_NOLERP && r_lerpmodels.value != 2)) + { + if (e->lerpflags & LERP_FINISH && numposes == 1) + lerpdata->blend = CLAMP (0, (cl.time - e->lerpstart) / (e->lerpfinish - e->lerpstart), 1); + else + lerpdata->blend = CLAMP (0, (cl.time - e->lerpstart) / e->lerptime, 1); + lerpdata->pose1 = e->previouspose; + lerpdata->pose2 = e->currentpose; + } + else //don't lerp + { + lerpdata->blend = 1; + lerpdata->pose1 = posenum; + lerpdata->pose2 = posenum; + } +} + +/* +================= +R_SetupEntityTransform -- johnfitz -- set up transform part of lerpdata +================= +*/ +void R_SetupEntityTransform (entity_t *e, lerpdata_t *lerpdata) +{ + float blend; + vec3_t d; + int i; + + // if LERP_RESETMOVE, kill any lerps in progress + if (e->lerpflags & LERP_RESETMOVE) + { + e->movelerpstart = 0; + VectorCopy (e->origin, e->previousorigin); + VectorCopy (e->origin, e->currentorigin); + VectorCopy (e->angles, e->previousangles); + VectorCopy (e->angles, e->currentangles); + e->lerpflags -= LERP_RESETMOVE; + } + else if (!VectorCompare (e->origin, e->currentorigin) || !VectorCompare (e->angles, e->currentangles)) // origin/angles changed, start new lerp + { + e->movelerpstart = cl.time; + VectorCopy (e->currentorigin, e->previousorigin); + VectorCopy (e->origin, e->currentorigin); + VectorCopy (e->currentangles, e->previousangles); + VectorCopy (e->angles, e->currentangles); + } + + //set up values + if (r_lerpmove.value && e != &cl.viewent && e->lerpflags & LERP_MOVESTEP) + { + if (e->lerpflags & LERP_FINISH) + blend = CLAMP (0, (cl.time - e->movelerpstart) / (e->lerpfinish - e->movelerpstart), 1); + else + blend = CLAMP (0, (cl.time - e->movelerpstart) / 0.1, 1); + + //translation + VectorSubtract (e->currentorigin, e->previousorigin, d); + lerpdata->origin[0] = e->previousorigin[0] + d[0] * blend; + lerpdata->origin[1] = e->previousorigin[1] + d[1] * blend; + lerpdata->origin[2] = e->previousorigin[2] + d[2] * blend; + + //rotation + VectorSubtract (e->currentangles, e->previousangles, d); + for (i = 0; i < 3; i++) + { + if (d[i] > 180) d[i] -= 360; + if (d[i] < -180) d[i] += 360; + } + lerpdata->angles[0] = e->previousangles[0] + d[0] * blend; + lerpdata->angles[1] = e->previousangles[1] + d[1] * blend; + lerpdata->angles[2] = e->previousangles[2] + d[2] * blend; + } + else //don't lerp + { + VectorCopy (e->origin, lerpdata->origin); + VectorCopy (e->angles, lerpdata->angles); + } +} + +/* +================= +R_DrawZombieLimb + +================= +*/ +//Blubs Z hacks: need this declaration. +model_t *Mod_FindName (char *name); +extern int zombie_skins[4]; +void R_DrawZombieLimb (entity_t *e, int which) +{ + model_t *clmodel; + aliashdr_t *paliashdr; + entity_t *limb_ent; + lerpdata_t lerpdata; + Mtx temp; + float add; + + switch(which) { + case 1: + limb_ent = &cl_entities[e->z_head]; + break; + case 2: + limb_ent = &cl_entities[e->z_larm]; + break; + case 3: + limb_ent = &cl_entities[e->z_rarm]; + break; + default: + return; + } + + clmodel = limb_ent->model; + + if (clmodel == NULL) + return; + + VectorCopy(e->origin, r_entorigin); + VectorSubtract(r_origin, r_entorigin, modelorg); + + for(int g = 0; g < 3; g++) + { + if(lightcolor[g] < 12) + lightcolor[g] = 12; + if(lightcolor[g] > 125) + lightcolor[g] = 125; + } + + // locate the proper data + paliashdr = (aliashdr_t *)Mod_Extradata(clmodel);//e->model + c_alias_polys += paliashdr->numtris; + + //GL_DisableMultitexture(); + + //Shpuld + if(r_model_brightness.value) + { + lightcolor[0] += 32; + lightcolor[1] += 32; + lightcolor[2] += 32; + } + + add = 72.0f - (lightcolor[0] + lightcolor[1] + lightcolor[2]); + if (add > 0.0f) + { + lightcolor[0] += add / 3.0f; + lightcolor[1] += add / 3.0f; + lightcolor[2] += add / 3.0f; + } + + //glPushMatrix (); + guMtxIdentity(model); + R_RotateForEntity (e, e->scale); + //R_RotateForEntity (e); + + //glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + //glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + + guMtxTrans (temp, paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + guMtxConcat(model, temp, model); + guMtxScale (temp, paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + guMtxConcat(model, temp, model); + + guMtxConcat(view,model,modelview); + GX_LoadPosMtxImm(modelview, GX_PNMTX0); //(modelview, GX_PNMTX0) +/* + if (gl_smoothmodels.value) + glShadeModel (GL_SMOOTH); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +*/ + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); +/* + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); +*/ + + R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); + R_SetupEntityTransform (e, &lerpdata); + GL_DrawAliasFrame(paliashdr, lerpdata); + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); +/* + glShadeModel (GL_FLAT); + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +*/ + //glPopMatrix (); +} + +/* +================= +R_DrawTransparentAliasModel + +================= +*/ +void R_DrawTransparentAliasModel (entity_t *e) +{ + //int i, j; + //int lnum; + //vec3_t dist; + //float add; + model_t *clmodel; + vec3_t mins, maxs; + aliashdr_t *paliashdr; + //trivertx_t *verts, *v; + //int index; + //float s, t, an; + int anim; + Mtx temp; + lerpdata_t lerpdata; + + clmodel = currententity->model; + + VectorAdd (currententity->origin, clmodel->mins, mins); + VectorAdd (currententity->origin, clmodel->maxs, maxs); + + //Con_Printf("drawing transparent mdl"); + +// naievil -- fixme: on psp this is == 2 ? + if (R_CullBox (mins, maxs)) + return; + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + QGX_Blend(true); + QGX_Alpha(false); + + R_LightPoint (currententity->origin); + + // // + // // get lighting information + // // + /* + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + if (add > 0) + { + lightcolor[0] += add * cl_dlights[lnum].color[0]; + lightcolor[1] += add * cl_dlights[lnum].color[1]; + lightcolor[2] += add * cl_dlights[lnum].color[2]; + } + + } + } + */ + for(int g = 0; g < 3; g++) + { + if(lightcolor[g] < 8) + lightcolor[g] = 8; + if(lightcolor[g] > 125) + lightcolor[g] = 125; + } + + if(e->effects & EF_FULLBRIGHT) + { + lightcolor[0] = lightcolor[1] = lightcolor[2] = 255; + } + + // clamp lighting so it doesn't overbright as much + /* + if (ambientlight > 128) + ambientlight = 128; + if (ambientlight + shadelight > 192) + shadelight = 192 - ambientlight; + */ + // shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; + // shadelight = shadelight / 200.0; + + // an = e->angles[1]/180*M_PI; + // shadevector[0] = cos(-an); + // shadevector[1] = sin(-an); + // shadevector[2] = 1; + // VectorNormalize (shadevector); + + // + // locate the proper data + // + paliashdr = (aliashdr_t *)Mod_Extradata (e->model); + c_alias_polys += paliashdr->numtris; + + // + // draw all the triangles + // + + //GL_DisableMultitexture(); + + //Shpuld + /* + if(r_model_brightness.value) + { + lightcolor[0] += 16; + lightcolor[1] += 16; + lightcolor[2] += 16; + } + */ + guMtxIdentity(model); + R_RotateForEntity (e, e->scale); + + guMtxTrans (temp, paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + guMtxConcat(model, temp, model); + guMtxScale (temp, paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + guMtxConcat(model, temp, model); + + guMtxConcat(view,model,modelview); + GX_LoadPosMtxImm(modelview, GX_PNMTX0); + + anim = (int)(cl.time*10) & 3; + GL_Bind0(paliashdr->gl_texturenum[e->skinnum][anim]); + + /* + if (gl_smoothmodels.value) + glShadeModel (GL_SMOOTH); + */ + + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + /* ELUTODO + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);*/ + + R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); + R_SetupEntityTransform (e, &lerpdata); + GL_DrawAliasFrame(paliashdr, lerpdata); + + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + + QGX_Blend(false); + QGX_Alpha(true); + /* + glShadeModel (GL_FLAT); + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glPopMatrix (); + + if (r_shadows.value) + { + glPushMatrix (); + R_RotateForEntity (e, e->scale); + glDisable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glColor4f (0,0,0,0.5); + GL_DrawAliasShadow (paliashdr, lastposenum); + glEnable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + glColor4f (1,1,1,1); + glPopMatrix (); + } + */ +} + +/* +================= +R_DrawAliasModel + +================= +*/ +int doZHack; +void R_DrawAliasModel (entity_t *e) +{ + char specChar; + //int i; + int lnum; + vec3_t dist; + float add; + model_t *clmodel; + vec3_t mins, maxs; + aliashdr_t *paliashdr; + float an; + int anim; + Mtx temp, temp2; + lerpdata_t lerpdata; + + clmodel = currententity->model; + + VectorAdd (currententity->origin, clmodel->mins, mins); + VectorAdd (currententity->origin, clmodel->maxs, maxs); + + if (R_CullBox (mins, maxs)) + return; + + specChar = clmodel->name[strlen(clmodel->name) - 5]; + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // + // get lighting information + // + + //ambientlight = shadelight = R_LightPoint (currententity->origin); + + R_LightPoint (currententity->origin); + + /* + // allways give the gun some light + if (e == &cl.viewent && ambientlight < 24) + ambientlight = shadelight = 24; + */ + + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + /* + if (add > 0) { + ambientlight += add; + //ZOID models should be affected by dlights as well + shadelight += add; + } + */ + if (add > 0) + { + lightcolor[0] += add * cl_dlights[lnum].color[0]; + lightcolor[1] += add * cl_dlights[lnum].color[1]; + lightcolor[2] += add * cl_dlights[lnum].color[2]; + } + + } + } + /* + // clamp lighting so it doesn't overbright as much + if (ambientlight > 128) + ambientlight = 128; + if (ambientlight + shadelight > 192) + shadelight = 192 - ambientlight; + */ + + // ZOID: never allow players to go totally black + /* + i = currententity - cl_entities; + if (i >= 1 && i<=cl.maxclients && !strcmp (currententity->model->name, "progs/player.mdl")) + { + if (lightcolor[0] < 8) + lightcolor[0] = 8; + if (lightcolor[1] < 8) + lightcolor[1] = 8; + if (lightcolor[2] < 8) + lightcolor[2] = 8; + } + */ + //if (ambientlight < 8) + //ambientlight = shadelight = 8; + + //shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; + //shadelight = shadelight / 200.0; + //VectorScale(lightcolor, 1.0f / 200.0f, lightcolor); + + an = e->angles[1]/180*M_PI; + shadevector[0] = cosf(-an); + shadevector[1] = sinf(-an); + shadevector[2] = 1; + VectorNormalize (shadevector); + + // + // locate the proper data + // + + if(doZHack && specChar == '%') + { + if(clmodel->name[12] == 'c') + paliashdr = (aliashdr_t *) Mod_Extradata(Mod_FindName("models/ai/zcfull.mdl")); + else + paliashdr = (aliashdr_t *) Mod_Extradata(Mod_FindName("models/ai/zfull.mdl")); + } + else + paliashdr = (aliashdr_t *)Mod_Extradata (e->model); + + c_alias_polys += paliashdr->numtris; + + // + // draw all the triangles + // + + //GL_DisableMultitexture(); + /* + add = 72.0f - (lightcolor[0] + lightcolor[1] + lightcolor[2]); + if (add > 0.0f && specChar != '!' && !(e->effects & EF_FULLBRIGHT)) + { + lightcolor[0] += add / 3.0f; + lightcolor[1] += add / 3.0f; + lightcolor[2] += add / 3.0f; + } + */ + if(specChar == '!' || (e->effects & EF_FULLBRIGHT)) + { + lightcolor[0] = lightcolor[1] = lightcolor[2] = 255; + } + + //Shpuld + if(r_model_brightness.value && specChar != '!' && !(e->effects & EF_FULLBRIGHT)) + { + lightcolor[0] += 32; + lightcolor[1] += 32; + lightcolor[2] += 32; + } + + if (e == &cl.viewent || e == &cl.viewent2) + { + if (lightcolor[0] < 64) + lightcolor[0] = 64; + if (lightcolor[1] < 64) + lightcolor[1] = 64; + if (lightcolor[2] < 64) + lightcolor[2] = 64; + } + + for(int g = 0; g < 3; g++) + { + if(lightcolor[g] < 32) + lightcolor[g] = 32; + if(lightcolor[g] > 255) + lightcolor[g] = 255; + } + + // HACK HACK HACK -- no fullbright colors, so make torches full light + if (!strcmp (clmodel->name, "progs/flame2.mdl") + || !strcmp (clmodel->name, "progs/flame.mdl") + || !strcmp (clmodel->name, "progs/lavaball.mdl") + || !strcmp (clmodel->name, "progs/bolt.mdl") + || !strcmp (clmodel->name, "models/misc/bolt2.mdl") + || !strcmp (clmodel->name, "progs/bolt3.mdl") ) { + lightcolor[0] = lightcolor[1] = lightcolor[2] = 255; + } + + guMtxIdentity(model); + R_RotateForEntity (e, ENTSCALE_DEFAULT); + + if ((e == &cl.viewent || e == &cl.viewent2)/* && scr_fov_viewmodel.value*/) { + float scale = 1.0f / tan (DEG2RAD (scr_fov.value / 2.0f)) * scr_fov_viewmodel.value / 90.0f; + if (e->scale != ENTSCALE_DEFAULT && e->scale != 0) + scale *= ENTSCALE_DECODE(e->scale); + //glTranslatef (paliashdr->scale_origin[0] * scale, paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + //glScalef (paliashdr->scale[0] * scale, paliashdr->scale[1], paliashdr->scale[2]); + guMtxTrans (temp, paliashdr->scale_origin[0] * scale, paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + guMtxConcat(model, temp, model); + guMtxScale (temp, paliashdr->scale[0] * scale, paliashdr->scale[1], paliashdr->scale[2]); + guMtxConcat(model, temp, model); + } else { + float scale = 1.0f; + if (e->scale != ENTSCALE_DEFAULT && e->scale != 0) + scale *= ENTSCALE_DECODE(e->scale); + //glTranslatef (paliashdr->scale_origin[0] * scale, paliashdr->scale_origin[1] * scale, paliashdr->scale_origin[2] * scale); + //glScalef (paliashdr->scale[0] * scale, paliashdr->scale[1] * scale, paliashdr->scale[2] * scale); + guMtxTrans (temp, paliashdr->scale_origin[0] * scale, paliashdr->scale_origin[1] * scale, paliashdr->scale_origin[2] * scale); + guMtxConcat(model, temp, model); + guMtxScale (temp2, paliashdr->scale[0] * scale, paliashdr->scale[1] * scale, paliashdr->scale[2] * scale); + guMtxConcat(model, temp2, model); + } + + /* + c_guMtxTrans (temp, paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + c_guMtxConcat(model, temp, model); + c_guMtxScale (temp, paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + c_guMtxConcat(model, temp, model); + */ + + guMtxConcat(view,model,modelview); + GX_LoadPosMtxImm(modelview, GX_PNMTX0); + + if (specChar == '%')//Zombie body + { + switch(e->skinnum) + { + case 0: + GL_Bind0(zombie_skins[0]); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + break; + case 1: + GL_Bind0(zombie_skins[1]); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + break; + case 2: + GL_Bind0(zombie_skins[2]); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + break; + case 3: + GL_Bind0(zombie_skins[3]); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + break; + default: //out of bounds? assuming 0 + Con_Printf("Zombie tex out of bounds: Tex[%i]\n",e->skinnum); + GL_Bind0(zombie_skins[0]); + GX_SetMinMag (GX_LINEAR, GX_NEAR); + break; + } + } + else + { + anim = (int)(cl.time*10) & 3; + GL_Bind0(paliashdr->gl_texturenum[currententity->skinnum][anim]); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + } + + // we can't dynamically colormap textures, so they are cached + // seperately for the players. Heads are just uncolored. + /* + if (currententity->colormap != vid.colormap && !gl_nocolors.value) + { + i = currententity - cl_entities; + if (i >= 1 && i<=cl.maxclients) + GL_Bind0(playertextures[i - 1]); + } + */ + + /* ELUTODO if (gl_smoothmodels.value) + glShadeModel (GL_SMOOTH);*/ + + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + /* ELUTODO + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);*/ + + R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); + R_SetupEntityTransform (e, &lerpdata); + GL_DrawAliasFrame(paliashdr, lerpdata); + + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + + if (doZHack == 0 && specChar == '%')//if we're drawing zombie, also draw its limbs in one call + { + if(e->z_head) + R_DrawZombieLimb(e,1); + if(e->z_larm) + R_DrawZombieLimb(e,2); + if(e->z_rarm) + R_DrawZombieLimb(e,3); + } + +/* ELUTODO + glShadeModel (GL_FLAT); + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);*/ + + /* ELUTODO if (r_shadows.value) + { + glPushMatrix (); + R_RotateForEntity (e); + glDisable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glColor4f (0,0,0,0.5); + GL_DrawAliasShadow (paliashdr, lastposenum); + glEnable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + glColor4f (1,1,1,1); + glPopMatrix (); + } +*/ +} + +//================================================================================== + +//================================================================================== +int SetFlameModelState (void) +{ + if (!r_part_flames.value && !strcmp(currententity->model->name, "progs/flame0.mdl")) + { + currententity->model = cl.model_precache[cl_modelindex[mi_flame1]]; + } + else if (r_part_flames.value) + { + vec3_t liteorg; + + VectorCopy (currententity->origin, liteorg); + if (currententity->baseline.modelindex == cl_modelindex[mi_flame0]) + { + if (r_part_flames.value == 2) + { + liteorg[2] += 14; + QMB_Q3TorchFlame (liteorg, 15); + } + else + { + liteorg[2] += 5.5; + + if(r_flametype.value == 2) + QMB_FlameGt (liteorg, 7, 0.8); + else + QMB_TorchFlame(liteorg); + } + } + else if (currententity->baseline.modelindex == cl_modelindex[mi_flame1]) + { + if (r_part_flames.value == 2) + { + liteorg[2] += 14; + QMB_Q3TorchFlame (liteorg, 15); + } + else + { + liteorg[2] += 5.5; + + if(r_flametype.value > 1) + QMB_FlameGt (liteorg, 7, 0.8); + else + QMB_TorchFlame(liteorg); + + } + currententity->model = cl.model_precache[cl_modelindex[mi_flame0]]; + } + else if (currententity->baseline.modelindex == cl_modelindex[mi_flame2]) + { + if (r_part_flames.value == 2) + { + liteorg[2] += 14; + QMB_Q3TorchFlame (liteorg, 32); + } + else + { + liteorg[2] -= 1; + + if(r_flametype.value > 1) + QMB_FlameGt (liteorg, 12, 1); + else + QMB_BigTorchFlame(liteorg); + } + return -1; //continue; + } + else if (!strcmp(currententity->model->name, "progs/wyvflame.mdl")) + { + liteorg[2] -= 1; + + if(r_flametype.value > 1) + QMB_FlameGt (liteorg, 12, 1); + else + QMB_BigTorchFlame(liteorg); + + return -1; //continue; + } + } + + return 0; +} + + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList (void) +{ + int i; + + if (!r_drawentities.value) + return; + + int zHackCount = 0; + doZHack = 0; + char specChar; + + // draw sprites seperately, because of alpha blending + for (i=0 ; imodel->name[strlen(currententity->model->name)-5]; + + if(specChar == '(' || specChar == '^')//skip heads and arms: it's faster to do this than a strcmp... + { + continue; + } + doZHack = 0; + if(specChar == '%') + { + if(zHackCount > 5 || ((currententity->z_head != 0) && (currententity->z_larm != 0) && (currententity->z_rarm != 0))) + { + doZHack = 1; + } + else + { + zHackCount ++;//drawing zombie piece by piece. + } + } + if(specChar == '$')//This is for smooth alpha, draw in the following loop, not this one + { + continue; + } + + switch (currententity->model->type) + { + case mod_alias: + R_DrawAliasModel (currententity); + break; + + case mod_brush: + R_DrawBrushModel (currententity); + break; + + default: + break; + } + doZHack = 0; + } + + GX_LoadPosMtxImm(view, GX_PNMTX0); + for (i=0 ; imodel)) + { + continue; + } + + specChar = currententity->model->name[strlen(currententity->model->name)-5]; + + switch (currententity->model->type) + { + case mod_sprite: + R_DrawSpriteModel (currententity); + break; + case mod_alias: + + if (qmb_initialized && SetFlameModelState() == -1) + continue; + + if(specChar == '$') { //mdl model with blended alpha + R_DrawTransparentAliasModel(currententity); + } + break; + + default: + break; + } + } +} + +/* +============= +R_DrawView2Model +============= +*/ +void R_DrawView2Model (void) +{ + /* + float ambient[4], diffuse[4]; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + int ambientlight, shadelight; + */ + + if (!r_drawviewmodel.value) + return; + + if (chase_active.value) + return; + + if (envmap) + return; + + if (!r_drawentities.value) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent2; + if (!currententity->model) + return; + + // hack the depth range to prevent view model from poking into walls + GX_SetViewport(viewport_size[0], viewport_size[1], viewport_size[2], viewport_size[3], 0.0f, 0.3f); + R_DrawAliasModel (currententity); + GX_SetViewport(viewport_size[0], viewport_size[1], viewport_size[2], viewport_size[3], 0.0f, 1.0f); +} + +/* +============= +R_DrawViewModel +============= +*/ +void R_DrawViewModel (void) +{ + /* + float ambient[4], diffuse[4]; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + int ambientlight, shadelight; + */ + + if (!r_drawviewmodel.value) + return; + + if (chase_active.value) + return; + + if (envmap) + return; + + if (!r_drawentities.value) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent; + if (!currententity->model) + return; + + // hack the depth range to prevent view model from poking into walls + GX_SetViewport(viewport_size[0], viewport_size[1], viewport_size[2], viewport_size[3], 0.0f, 0.3f); + R_DrawAliasModel (currententity); + GX_SetViewport(viewport_size[0], viewport_size[1], viewport_size[2], viewport_size[3], 0.0f, 1.0f); +} + +#if 0 +/* +============ +R_PolyBlend +============ +*/ +void R_PolyBlend (void) +{ + Mtx temp; + + if (!gl_polyblend.value) + return; + if (!v_blend[3] && v_gamma.value == 1.0f) + return; + + QGX_Alpha(false); + QGX_Blend(true); + QGX_ZMode(false); + GL_Bind0(white_texturenum); // ELUTODO: do not use a texture + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + c_guMtxIdentity(view); + c_guMtxRotAxisRad(temp, &axis0, DegToRad(-90.0f)); // put Z going up + c_guMtxConcat(view, temp, view); + c_guMtxRotAxisRad(temp, &axis2, DegToRad(90.0f)); // put Z going up + c_guMtxConcat(view, temp, view); + GX_LoadPosMtxImm(view, GX_PNMTX0); + + // ELUTODO: check if v_blend gets bigger than 1.0f + if (v_blend[3]) + { + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(10.0f, 100.0f, 100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(1.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, 100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(0.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, -100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(0.0f, 0.0f); + + GX_Position3f32(10.0f, 100.0f, -100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(1.0f, 0.0f); + + GX_End(); + } + + // ELUTODO quick hack + if (v_gamma.value != 1.0f) + { + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(10.0f, 100.0f, 100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(1.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, 100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(0.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, -100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(0.0f, 0.0f); + + GX_Position3f32(10.0f, 100.0f, -100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(1.0f, 0.0f); + + GX_End(); + } + + QGX_Blend(false); + QGX_Alpha(true); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); +} +#else +/* +============ +R_PolyBlend +============ +*/ +void R_PolyBlend (void) +{ + if (!gl_polyblend.value) + return; + if (!v_blend[3]) + return; + + Mtx temp; + + //GL_DisableMultitexture(); + + QGX_Alpha(false); + QGX_Blend(true); + QGX_ZMode(false); + /* + GX_SetNumChans(0); + GX_SetNumTexGens(0); + */ + GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + + guMtxIdentity(view); + guMtxRotAxisRad(temp, &axis0, DegToRad(-90.0f)); // put Z going up + guMtxConcat(view, temp, view); + guMtxRotAxisRad(temp, &axis2, DegToRad(90.0f)); // put Z going up + guMtxConcat(view, temp, view); + GX_LoadPosMtxImm(view, GX_PNMTX0); + + //GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + //GX_Position3f32(10.0f, 100.0f, 100.0f); + //GX_Color4u8(v_blend[0]/* * 255*/, v_blend[1]/* * 255*/, v_blend[2]/* * 255*/, v_blend[3]/* * 255*/); + //GX_TexCoord2f32(1.0f, 1.0f); + + //GX_Position3f32(10.0f, -100.0f, 100.0f); + //GX_Color4u8(v_blend[0]/* * 255*/, v_blend[1]/* * 255*/, v_blend[2]/* * 255*/, v_blend[3]/* * 255*/); + //GX_TexCoord2f32(0.0f, 1.0f); + + //GX_Position3f32(10.0f, -100.0f, -100.0f); + //GX_Color4u8(v_blend[0]/* * 255*/, v_blend[1]/* * 255*/, v_blend[2]/* * 255*/, v_blend[3]/* * 255*/); + //GX_TexCoord2f32(0.0f, 0.0f); + + //GX_Position3f32(10.0f, 100.0f, -100.0f); + //GX_Color4u8(v_blend[0]/* * 255*/, v_blend[1]/* * 255*/, v_blend[2]/* * 255*/, v_blend[3]/* * 255*/); + //GX_TexCoord2f32(1.0f, 0.0f); + + // ELUTODO: check if v_blend gets bigger than 1.0f + if (v_blend[3]) + { + Con_Printf("polyblending\n"); + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(10.0f, 100.0f, 100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(1.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, 100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(0.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, -100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(0.0f, 0.0f); + + GX_Position3f32(10.0f, 100.0f, -100.0f); + GX_Color4u8(v_blend[0] * 255, v_blend[1] * 255, v_blend[2] * 255, v_blend[3] * 255); + GX_TexCoord2f32(1.0f, 0.0f); + + GX_End(); + } + + // ELUTODO quick hack + if (v_gamma.value != 1.0f) + { + Con_Printf("polyblending gamma\n"); + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + + GX_Position3f32(10.0f, 100.0f, 100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(1.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, 100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(0.0f, 1.0f); + + GX_Position3f32(10.0f, -100.0f, -100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(0.0f, 0.0f); + + GX_Position3f32(10.0f, 100.0f, -100.0f); + GX_Color4u8(0xff, 0xff, 0xff, (v_gamma.value * -1.0f + 1.0f) * 0xff); + GX_TexCoord2f32(1.0f, 0.0f); + + GX_End(); + } + + //GX_End(); + /* + GX_SetNumChans(1); + GX_SetNumTexGens(1); + */ + + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + QGX_Blend(false); + QGX_Alpha(true); +} +#endif + +int SignbitsForPlane (mplane_t *out) +{ + int bits, j; + + // for fast box on planeside test + + bits = 0; + for (j=0 ; j<3 ; j++) + { + if (out->normal[j] < 0) + bits |= 1< 1) + Cvar_Set ("r_fullbright", "0"); + + R_AnimateLight (); + + r_framecount++; + +// build the transformation matrix for the given view angles + VectorCopy (r_refdef.vieworg, r_origin); + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + +// current viewleaf + r_oldviewleaf = r_viewleaf; + r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + + V_SetContentsColor (r_viewleaf->contents); + V_CalcBlend (); + + r_cache_thrash = false; + + c_brush_polys = 0; + c_alias_polys = 0; + +} + +/* +============= +R_SetupGL +============= +*/ +void R_SetupGL (void) +{ + float screenaspect; + extern int glwidth, glheight; + int x, x2, y2, y, w, h; + Mtx temp; + GXFogAdjTbl table[10]; + + // + // set up viewpoint + // + x = r_refdef.vrect.x * glwidth/vid.width; + x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; + y = r_refdef.vrect.y * glheight/vid.height; + y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * glheight/vid.height; + + // fudge around because of frac screen scale + if (x > 0) + x--; + if (x2 < glwidth) + x2++; + if (y > 0) + y--; + if (y2 < glheight) + y2++; + + w = x2 - x; + h = y2 - y; + + if (envmap) + { + x = y2 = 0; + w = h = 256; + } + + viewport_size[0] = glx + x; + viewport_size[1] = gly + y; + viewport_size[2] = w; + viewport_size[3] = h; + //GX_SetViewport(viewport_size[0], viewport_size[1], viewport_size[2], viewport_size[3], 0.0f, 1.0f); + GX_SetViewport(glx, gly, glwidth, glheight, 0.0f, 1.0f); + screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; + guPerspective (perspective, r_refdef.fov_y, screenaspect, ZMIN3D, ZMAX3D); + + // ELUTODO: perspective is 4x4, these ops are 4x3 + if (mirror) + { + if (mirror_plane->normal[2]) + { + guMtxScale (temp, 1, -1, 1); + guMtxConcat(perspective, temp, perspective); + } + else { + guMtxScale (temp, -1, 1, 1); + guMtxConcat(perspective, temp, perspective); + GX_SetCullMode(GX_CULL_FRONT); + } + } + else { + GX_SetCullMode(GX_CULL_BACK); + } + + GX_LoadProjectionMtx(perspective, GX_PERSPECTIVE); + + guMtxIdentity(view); + + guMtxRotAxisRad(temp, &axis0, DegToRad(-90.0f)); // put Z going up + guMtxConcat(view, temp, view); + guMtxRotAxisRad(temp, &axis2, DegToRad(90.0f)); // put Z going up + guMtxConcat(view, temp, view); + + guMtxRotAxisRad(temp, &axis0, DegToRad(-r_refdef.viewangles[2])); + guMtxConcat(view, temp, view); + guMtxRotAxisRad(temp, &axis1, DegToRad(-r_refdef.viewangles[0])); + guMtxConcat(view, temp, view); + guMtxRotAxisRad(temp, &axis2, DegToRad(-r_refdef.viewangles[1])); + guMtxConcat(view, temp, view); + + + guMtxTrans(temp, -r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); + guMtxConcat(view, temp, view); + + GX_InitFogAdjTable (table, r_refdef.vrect.width, perspective); + + GX_SetFogRangeAdj(GX_ENABLE, screenaspect, table); + + Fog_EnableGFog (); + + // ELUTODOglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); + + // + // set drawing parms + // + if (!gl_cull.value) + GX_SetCullMode(GX_CULL_NONE); + + QGX_Blend(false); + QGX_Alpha(false); + QGX_ZMode(true); +} + +/* +================ +R_RenderScene + +r_refdef must be set before the first call +================ +*/ +void R_RenderScene (void) +{ + //GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + + R_SetupFrame (); + + R_SetFrustum (); + + R_SetupGL (); + + R_MarkLeaves (); // done here so we know if we're in water + + GX_LoadPosMtxImm(view, GX_PNMTX0); + R_DrawWorld (); // adds static entities to the list + + S_ExtraUpdate (); // don't let sound get messed up if going slow + + // for the entities, we load the matrices separately + R_DrawEntitiesOnList (); + + //GL_DisableMultitexture(); + + GX_LoadPosMtxImm(view, GX_PNMTX0); + // sBTODO: Fix TexCoord mapping for decals + //R_DrawDecals(); + R_DrawParticles (); +} + + +/* +============= +R_Clear +============= +*/ +void R_Clear (void) +{ + // Not needed, GX clears the efb while copying to the xfb +} + +/* +============= +R_Mirror +============= +*/ +void R_Mirror (void) +{ + float d; + //msurface_t *s; + entity_t *ent; + + if (!mirror) + return; + + memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix)); + + d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist; + VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg); + + d = DotProduct (vpn, mirror_plane->normal); + VectorMA (vpn, -2*d, mirror_plane->normal, vpn); + + r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180; + r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180; + r_refdef.viewangles[2] = -r_refdef.viewangles[2]; + + ent = &cl_entities[cl.viewentity]; + if (cl_numvisedicts < MAX_VISEDICTS) + { + cl_visedicts[cl_numvisedicts] = ent; + cl_numvisedicts++; + } +/* ELUTODO + gldepthmin = 0.5; + gldepthmax = 1; + glDepthRange (gldepthmin, gldepthmax); + glDepthFunc (GL_LEQUAL); + + R_RenderScene (); + R_DrawWaterSurfaces (); + + gldepthmin = 0; + gldepthmax = 0.5; + glDepthRange (gldepthmin, gldepthmax); + glDepthFunc (GL_LEQUAL); + + // blend on top + glEnable (GL_BLEND); + glMatrixMode(GL_PROJECTION); + if (mirror_plane->normal[2]) + glScalef (1,-1,1); + else + glScalef (-1,1,1); + glCullFace(GL_FRONT); + glMatrixMode(GL_MODELVIEW); + + glLoadMatrixf (r_base_world_matrix); + + glColor4f (1,1,1,r_mirroralpha.value); + s = cl.worldmodel->textures[mirrortexturenum]->texturechain; + for ( ; s ; s=s->texturechain) + R_RenderBrushPoly (s); + cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; + glDisable (GL_BLEND); + glColor4f (1,1,1,1); +*/ +} + +/* +================ +R_RenderView + +r_refdef must be set before the first call +================ +*/ +void R_RenderView (void) +{ + double time1=0, time2=0; + // ELUTODO GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20}; + + if (r_norefresh.value) + return; + + if (!r_worldentity.model || !cl.worldmodel) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (r_speeds.value) + { + // ELUTODO glFinish (); + time1 = Sys_FloatTime (); + c_brush_polys = 0; + c_alias_polys = 0; + } + + mirror = false; + +/* ELUTODO + if (gl_finish.value) + glFinish (); +*/ + + R_Clear (); + + // render normal view + + R_RenderScene (); + R_DrawViewModel (); + R_DrawView2Model (); + GX_LoadPosMtxImm(view, GX_PNMTX0); + R_DrawWaterSurfaces (); + + //Fog_DisableGFog (); //johnfitz + + // render mirror view + R_Mirror (); + + R_PolyBlend (); + + if (r_speeds.value) + { +// glFinish (); + time2 = Sys_FloatTime (); + Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); + } +} diff --git a/source/wii/gx/gx_rmisc.c b/source/wii/gx/gx_rmisc.c new file mode 100644 index 0000000..932f2a5 --- /dev/null +++ b/source/wii/gx/gx_rmisc.c @@ -0,0 +1,423 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_misc.c + +#include "../../quakedef.h" + +cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; + +int zombie_skins[4]; +int decal_blood1, decal_blood2, decal_blood3, decal_q3blood, decal_burn, decal_mark, decal_glow; + +extern cvar_t r_flatlightstyles; + +byte dottexture[8][8] = +{ + {0,1,1,0,0,0,0,0}, + {1,1,1,1,0,0,0,0}, + {1,1,1,1,0,0,0,0}, + {0,1,1,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0}, +}; +void R_InitParticleTexture (void) +{ + int x,y; + byte data[8][8]; + + // + // particle texture + // + for (x=0 ; x<8 ; x++) + { + for (y=0 ; y<8 ; y++) + { + data[y][x] = dottexture[x][y] ? 15 : 255; // ELUTODO assumes 15 is white + } + } + + particletexture = GL_LoadTexture("particletex", 8, 8, (byte *)data, false, true, true, 1); +} + +/* +================== +R_InitOtherTextures +================== +*/ +void R_InitOtherTextures (void) +{ + + //static decals + decal_blood1 = loadtextureimage ("textures/decals/blood_splat01", 0, 0, true, false, true); + decal_blood2 = loadtextureimage ("textures/decals/blood_splat02", 0, 0, true, false, true); + decal_blood3 = loadtextureimage ("textures/decals/blood_splat03", 0, 0, true, false, true); + decal_q3blood = loadtextureimage ("textures/decals/blood_stain", 0, 0, true, false, true); + decal_burn = loadtextureimage ("textures/decals/explo_burn01", 0, 0, true, false, true); + decal_mark = loadtextureimage ("textures/decals/particle_burn01", 0, 0, true, false, true); + decal_glow = loadtextureimage ("textures/decals/glow2", 0, 0, true, false, true); + + // external zombie skins + + zombie_skins[0] = loadtextureimage ("models/ai/zfull.mdl_0", 0, 0, true, false, true); + zombie_skins[1] = loadtextureimage ("models/ai/zfull.mdl_1", 0, 0, true, false, true); + zombie_skins[2] = loadtextureimage ("models/ai/zfull.mdl_2", 0, 0, true, false, true); + zombie_skins[3] = loadtextureimage ("models/ai/zfull.mdl_3", 0, 0, true, false, true); + +} + +/* +=============== +R_Envmap_f + +Grab six views for environment mapping tests +=============== +*/ +/* ELUTODO +void R_Envmap_f (void) +{ + byte buffer[256*256*4]; + char name[1024]; + + glDrawBuffer (GL_FRONT); + glReadBuffer (GL_FRONT); + envmap = true; + + r_refdef.vrect.x = 0; + r_refdef.vrect.y = 0; + r_refdef.vrect.width = 256; + r_refdef.vrect.height = 256; + + r_refdef.viewangles[0] = 0; + r_refdef.viewangles[1] = 0; + r_refdef.viewangles[2] = 0; + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + R_RenderView (); + glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + COM_WriteFile ("env0.rgb", buffer, sizeof(buffer)); + + r_refdef.viewangles[1] = 90; + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + R_RenderView (); + glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + COM_WriteFile ("env1.rgb", buffer, sizeof(buffer)); + + r_refdef.viewangles[1] = 180; + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + R_RenderView (); + glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + COM_WriteFile ("env2.rgb", buffer, sizeof(buffer)); + + r_refdef.viewangles[1] = 270; + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + R_RenderView (); + glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + COM_WriteFile ("env3.rgb", buffer, sizeof(buffer)); + + r_refdef.viewangles[0] = -90; + r_refdef.viewangles[1] = 0; + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + R_RenderView (); + glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + COM_WriteFile ("env4.rgb", buffer, sizeof(buffer)); + + r_refdef.viewangles[0] = 90; + r_refdef.viewangles[1] = 0; + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + R_RenderView (); + glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + COM_WriteFile ("env5.rgb", buffer, sizeof(buffer)); + + envmap = false; + glDrawBuffer (GL_BACK); + glReadBuffer (GL_BACK); + GL_EndRendering (); +} +*/ +/* +=============== +R_Init +=============== +*/ +void R_Init (void) +{ + extern cvar_t gl_finish; + + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); + Cmd_AddCommand ("pointfile", R_ReadPointFile_f); + + Cvar_RegisterVariable (&r_norefresh); + Cvar_RegisterVariable (&r_lightmap); + Cvar_RegisterVariable (&r_fullbright); + Cvar_RegisterVariable (&r_drawentities); + Cvar_RegisterVariable (&r_drawviewmodel); + Cvar_RegisterVariable (&r_shadows); + Cvar_RegisterVariable (&r_mirroralpha); + Cvar_RegisterVariable (&r_wateralpha); + Cvar_RegisterVariable (&r_dynamic); + Cvar_RegisterVariable (&r_novis); + Cvar_RegisterVariable (&r_lerpmodels); + Cvar_RegisterVariable (&r_lerpmove); + Cvar_RegisterVariable (&r_speeds); + + Cvar_RegisterVariable (&gl_finish); + Cvar_RegisterVariable (&gl_clear); + + Cvar_RegisterVariable (&gl_cull); + Cvar_RegisterVariable (&gl_smoothmodels); + Cvar_RegisterVariable (&gl_affinemodels); + Cvar_RegisterVariable (&gl_polyblend); + Cvar_RegisterVariable (&gl_playermip); + Cvar_RegisterVariable (&gl_nocolors); + + Cvar_RegisterVariable (&gl_keeptjunctions); + Cvar_RegisterVariable (&gl_reporttjunctions); + + Cvar_RegisterVariable (&gl_doubleeyes); + + Cvar_RegisterVariable (&gl_cshiftpercent); + + Cvar_RegisterVariable (&r_explosiontype); + Cvar_RegisterVariable (&r_laserpoint); + Cvar_RegisterVariable (&r_part_explosions); + Cvar_RegisterVariable (&r_part_trails); + Cvar_RegisterVariable (&r_part_sparks); + Cvar_RegisterVariable (&r_part_gunshots); + Cvar_RegisterVariable (&r_part_blood); + Cvar_RegisterVariable (&r_part_telesplash); + Cvar_RegisterVariable (&r_part_blobs); + Cvar_RegisterVariable (&r_part_lavasplash); + Cvar_RegisterVariable (&r_part_flames); + Cvar_RegisterVariable (&r_part_lightning); + Cvar_RegisterVariable (&r_part_flies); + Cvar_RegisterVariable (&r_part_muzzleflash); + Cvar_RegisterVariable (&r_skyfog); + Cvar_RegisterVariable (&r_model_brightness); + + Cvar_RegisterVariable (&r_farclip); + + Cvar_RegisterVariable (&r_flatlightstyles); + Cvar_RegisterVariable (&r_overbright); + + R_InitParticles (); + R_InitDecals (); + R_InitOtherTextures (); + //R_InitParticleTexture (); + + Sky_Init (); //johnfitz + Fog_Init (); //johnfitz + +#ifdef GLTEST + Test_Init (); +#endif + + memset(playertextures, 0xFF, sizeof(playertextures)); +} + +/* +=============== +R_TranslatePlayerSkin + +Translates a skin texture by the per-player color lookup +=============== +*/ +void R_TranslatePlayerSkin (int playernum) +{ + /* + int top, bottom; + byte translate[256]; + unsigned translate32[256]; + int i, j, s; + model_t *model; + aliashdr_t *paliashdr; + byte *original; + unsigned pixels[512*256], *out; + unsigned scaled_width, scaled_height; + int inwidth, inheight; + byte *inrow; + unsigned frac, fracstep; + + //GL_DisableMultitexture(); + + //top = cl.scores[playernum].colors & 0xf0; + //bottom = (cl.scores[playernum].colors &15)<<4; + + top = 0xf0; + bottom = (15)<<4; + + for (i=0 ; i<256 ; i++) + translate[i] = i; + + for (i=0 ; i<16 ; i++) + { + if (top < 128) // the artists made some backwards ranges. sigh. + translate[TOP_RANGE+i] = top+i; + else + translate[TOP_RANGE+i] = top+15-i; + + if (bottom < 128) + translate[BOTTOM_RANGE+i] = bottom+i; + else + translate[BOTTOM_RANGE+i] = bottom+15-i; + } + + // + // locate the original skin pixels + // + currententity = &cl_entities[1+playernum]; + model = currententity->model; + if (!model) + return; // player doesn't have a model yet + if (model->type != mod_alias) + return; // only translate skins on alias models + + paliashdr = (aliashdr_t *)Mod_Extradata (model); + s = paliashdr->skinwidth * paliashdr->skinheight; + if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) { + Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum); + original = (byte *)paliashdr + paliashdr->texels[0]; + } else + original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum]; + if (s & 3) + Sys_Error ("R_TranslateSkin: s&3"); + + inwidth = paliashdr->skinwidth; + inheight = paliashdr->skinheight; + + // because this happens during gameplay, do it fast + // instead of sending it through gl_update 8 + + scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512; + scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256; + + for (i=0 ; i<256 ; i++) + translate32[i] = d_8to24table[translate[i]]; + + out = pixels; + fracstep = inwidth*0x10000/scaled_width; + for (i=0 ; i> 1; + for (j=0 ; j>16]]; + frac += fracstep; + out[j+1] = translate32[inrow[frac>>16]]; + frac += fracstep; + out[j+2] = translate32[inrow[frac>>16]]; + frac += fracstep; + out[j+3] = translate32[inrow[frac>>16]]; + frac += fracstep; + } + } + + // ELUTODO: skin changes, cache mismatches, ugly hacks + if (playertextures[playernum] < 0 || playertextures[playernum] >= MAX_GLTEXTURES) + { + playertextures[playernum] = GL_LoadTexture (va("player%d_skin", playernum), scaled_width, scaled_height, (u8 *)pixels, true, true, true, 1); // HACK HACK HACK + } + + GL_Update32 (&gltextures[playertextures[playernum]], pixels, scaled_width, scaled_height, true, true); + */ +} + + +/* +=============== +R_NewMap +=============== +*/ +void R_NewMap (void) +{ + int i; + + for (i=0 ; i<256 ; i++) + d_lightstylevalue[i] = 264; // normal light value + + memset (&r_worldentity, 0, sizeof(r_worldentity)); + r_worldentity.model = cl.worldmodel; + +// clear out efrags in case the level hasn't been reloaded +// FIXME: is this one short? + for (i=0 ; inumleafs ; i++) + cl.worldmodel->leafs[i].efrags = NULL; + + r_viewleaf = NULL; + R_ClearParticles (); + R_ClearDecals(); + + GL_BuildLightmaps (); + + Sky_NewMap (); //johnfitz -- skybox in worldspawn + Fog_NewMap (); // johnfitz -- global fog in worldspawn + + //Fog_EnableGFog (); + + // identify sky texture + skytexturenum = -1; + mirrortexturenum = -1; + for (i=0 ; inumtextures ; i++) + { + if (!cl.worldmodel->textures[i]) + continue; + if (!strncmp(cl.worldmodel->textures[i]->name,"sky",3) ) + skytexturenum = i; + if (!strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) ) + mirrortexturenum = i; + cl.worldmodel->textures[i]->texturechain = NULL; + } +} + + +/* +==================== +R_TimeRefresh_f + +For program optimization +==================== +*/ +void R_TimeRefresh_f (void) +{ + int i; + float start, stop, time; + +/* ELUTODO + glDrawBuffer (GL_FRONT); + glFinish (); +*/ + + start = Sys_FloatTime (); + for (i=0 ; i<128 ; i++) + { + r_refdef.viewangles[1] = i/128.0*360.0; + R_RenderView (); + } + + // ELUTODO glFinish (); + stop = Sys_FloatTime (); + time = stop-start; + Con_Printf ("%f seconds (%f fps)\n", time, 128/time); + + // ELUTODO glDrawBuffer (GL_BACK); + //GL_EndRendering (); +} \ No newline at end of file diff --git a/source/wii/gx/gx_rpart.c b/source/wii/gx/gx_rpart.c new file mode 100644 index 0000000..7867895 --- /dev/null +++ b/source/wii/gx/gx_rpart.c @@ -0,0 +1,858 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../../quakedef.h" + +#define MAX_PARTICLES 6144 // default max # of particles at one + // time +#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's + // on the command line + +int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; +int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; +int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; + +particle2_t *active_particles; +particle2_t *free_particles; + +particle2_t *particles; +int r_numparticles; + +vec3_t r_pright, r_pup, r_ppn; + +/* +=============== +R_InitParticles +=============== +*/ +void R_InitParticles (void) +{ + int i; + + i = COM_CheckParm ("-particles"); + + if (i) + { + r_numparticles = (int)(atoi(com_argv[i+1])); + if (r_numparticles < ABSOLUTE_MIN_PARTICLES) + r_numparticles = ABSOLUTE_MIN_PARTICLES; + } + else + { + r_numparticles = MAX_PARTICLES; + } + + particles = (particle2_t *) + Hunk_AllocName (r_numparticles * sizeof(particle2_t), "particles"); + + QMB_InitParticles(); +} + +/* +=============== +R_EntityParticles +=============== +*/ + +#define NUMVERTEXNORMALS 162 +extern float r_avertexnormals[NUMVERTEXNORMALS][3]; +vec3_t avelocities[NUMVERTEXNORMALS]; +float beamlength = 16; +vec3_t avelocity = {23, 7, 3}; +float partstep = 0.01; +float timescale = 0.01; + +void R_Entity_Classic_Particles (entity_t *ent) +{ + int i; + particle2_t *p; + float angle; + float sp, sy, cp, cy; + vec3_t forward; + float dist; + + dist = 64; + + if (!avelocities[0][0]) + { + for (i=0 ; inext; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.01; + p->color = 0x6f; + p->type = pt_explode; + + p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength; + p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength; + p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength; + } +} + +void R_EntityParticles (entity_t *ent) +{ + if (qmb_initialized && r_part_trails.value) + QMB_EntityParticles (ent); + else + R_Entity_Classic_Particles (ent); +} + + +/* +=============== +R_ClearParticles +=============== +*/ +void R_ClearParticles (void) +{ + int i; + + free_particles = &particles[0]; + active_particles = NULL; + + for (i=0 ;inext; + p->next = active_particles; + active_particles = p; + + p->die = 99999; + p->color = (-c)&15; + p->type = pt_static; + VectorCopy (vec3_origin, p->vel); + VectorCopy (org, p->org); + } + + fclose (f); + Con_Printf ("%i points read\n", c); +} + +/* +=============== +R_ParseParticleEffect + +Parse an effect out of the server message +=============== +*/ +void R_ParseParticleEffect (void) +{ + vec3_t org, dir; + int i, count, msgcount, color; + + for (i=0 ; i<3 ; i++) + org[i] = MSG_ReadCoord (); + for (i=0 ; i<3 ; i++) + dir[i] = MSG_ReadChar () * (1.0/16); + msgcount = MSG_ReadByte (); + color = MSG_ReadByte (); + + if (msgcount == 255) + count = 1024; + else + count = msgcount; + + R_RunParticleEffect (org, dir, color, count); +} + +/* +=============== +R_Classic_ParticleExplosion + +=============== +*/ +void R_Classic_ParticleExplosion (vec3_t org) +{ + int i, j; + particle2_t *p; + + for (i=0 ; i<1024 ; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 5; + p->color = ramp1[0]; + p->ramp = rand()&3; + if (i & 1) + { + p->type = pt_explode; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_explode2; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } +} + +/* +=============== +R_ParticleExplosion + +=============== +*/ +void R_ParticleExplosion (vec3_t org) +{ + if (!qmb_initialized) + R_Classic_ParticleExplosion (org); + else + QMB_ParticleExplosion (org); +} + +/* +=============== +R_ParticleExplosion2 + +=============== +*/ +void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength) +{ + int i, j; + particle2_t *p; + int colorMod = 0; + + for (i=0; i<512; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.3; + p->color = colorStart + (colorMod % colorLength); + colorMod++; + + p->type = pt_blob; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } +} + +/* +=============== +R_Classic_BlobExplosion + +=============== +*/ +void R_Classic_BlobExplosion (vec3_t org) +{ + int i, j; + particle2_t *p; + + for (i=0 ; i<1024 ; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 1 + (rand()&8)*0.05; + + if (i & 1) + { + p->type = pt_blob; + p->color = 66 + rand()%6; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_blob2; + p->color = 150 + rand()%6; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } +} + +/* +=============== +R_BlobExplosion + +=============== +*/ +void R_BlobExplosion (vec3_t org) +{ + if (!qmb_initialized) + R_Classic_BlobExplosion (org); + else + QMB_BlobExplosion (org); +} + +/* +=============== +Run_Classic_ParticleEffect +=============== +*/ + +void Run_Classic_ParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + int i, j; + particle2_t *p; + + for (i=0 ; inext; + p->next = active_particles; + active_particles = p; + + if (count == 1024) + { // rocket explosion + p->die = cl.time + 5; + p->color = ramp1[0]; + p->ramp = rand()&3; + if (i & 1) + { + p->type = pt_explode; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_explode2; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } + else + { + p->die = cl.time + 0.1*(rand()%5); + p->color = (color&~7) + (rand()&7); + p->type = pt_slowgrav; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()&15)-8); + p->vel[j] = dir[j]*15;// + (rand()%300)-150; + } + } + } +} + +/* +=============== +R_RunParticleEffect + +=============== +*/ + +void RunParticleEffect (vec3_t org, vec3_t dir, int col, int count) +{ + if (qmb_initialized) + QMB_RunParticleEffect (org, dir, col, count); + else + Run_Classic_ParticleEffect (org, dir, col, count); +} + +void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + + if (color == 73 || color == 225) + { + RunParticleEffect(org, dir, color, count); + return; + } + + switch (count) + { + case 10: + case 20: + case 30: + RunParticleEffect(org, dir, color, count); + break; + default: + RunParticleEffect(org, dir, color, count); + } + +} + +/* +=============== +R_LavaSplash + +=============== +*/ +void R_LavaSplash (vec3_t org) +{ + int i, j, k; + particle2_t *p; + float vel; + vec3_t dir; + + for (i=-16 ; i<16 ; i++) + for (j=-16 ; j<16 ; j++) + for (k=0 ; k<1 ; k++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 2 + (rand()&31) * 0.02; + p->color = 224 + (rand()&7); + p->type = pt_slowgrav; + + dir[0] = j*8 + (rand()&7); + dir[1] = i*8 + (rand()&7); + dir[2] = 256; + + p->org[0] = org[0] + dir[0]; + p->org[1] = org[1] + dir[1]; + p->org[2] = org[2] + (rand()&63); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} + +/* +=============== +R_Classic_TeleportSplash + +=============== +*/ +void R_Classic_TeleportSplash (vec3_t org) +{ + int i, j, k; + particle2_t *p; + float vel; + vec3_t dir; + + for (i=-16 ; i<16 ; i+=4) + for (j=-16 ; j<16 ; j+=4) + for (k=-24 ; k<32 ; k+=4) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.2 + (rand()&7) * 0.02; + p->color = 7 + (rand()&7); + p->type = pt_slowgrav; + + dir[0] = j*8; + dir[1] = i*8; + dir[2] = k*8; + + p->org[0] = org[0] + i + (rand()&3); + p->org[1] = org[1] + j + (rand()&3); + p->org[2] = org[2] + k + (rand()&3); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} + +void R_TeleportSplash (vec3_t org) +{ + if (!qmb_initialized) + R_Classic_TeleportSplash (org); + else + QMB_TeleportSplash(org); + +} + +void R_Classic_RocketTrail (vec3_t start, vec3_t end, int type) +{ + vec3_t vec; + float len; + int j; + particle2_t *p; + int dec; + static int tracercount; + + VectorSubtract (end, start, vec); + len = VectorNormalize (vec); + if (type < 128) + dec = 3; + else + { + dec = 1; + type -= 128; + } + + while (len > 0) + { + len -= dec; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorCopy (vec3_origin, p->vel); + p->die = cl.time + 2; + + switch (type) + { + case 0: // rocket trail + p->ramp = (rand()&3); + p->color = ramp3[(int)p->ramp]; + p->type = pt_fire; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + break; + + case 1: // smoke smoke + p->ramp = (rand()&3) + 2; + p->color = ramp3[(int)p->ramp]; + p->type = pt_fire; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + break; + + case 2: // blood + p->type = pt_grav; + p->color = 67 + (rand()&3); + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + break; + + case 3: + case 5: // tracer + p->die = cl.time + 0.5; + p->type = pt_static; + if (type == 3) + p->color = 52 + ((tracercount&4)<<1); + else + p->color = 230 + ((tracercount&4)<<1); + + tracercount++; + + VectorCopy (start, p->org); + if (tracercount & 1) + { + p->vel[0] = 30*vec[1]; + p->vel[1] = 30*-vec[0]; + } + else + { + p->vel[0] = 30*-vec[1]; + p->vel[1] = 30*vec[0]; + } + break; + + case 4: // slight blood + p->type = pt_grav; + p->color = 67 + (rand()&3); + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + len -= 3; + break; + + case 6: // voor trail + p->color = 9*16 + 8 + (rand()&3); + p->type = pt_static; + p->die = cl.time + 0.3; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()&15)-8); + break; + } + + + VectorAdd (start, vec, start); + } +} + +void R_RocketTrail (vec3_t start, vec3_t end, int type) +{ + + if (qmb_initialized && r_part_trails.value) + QMB_RocketTrail (start, end, (trail_type_t)type); + else + R_Classic_RocketTrail (start, end, type); +} + + +/* +=============== +R_Classic_DrawParticles +=============== +*/ +extern cvar_t sv_gravity; + +void R_Classic_DrawParticles (void) +{ + particle2_t *p, *kill; + float grav; + int i; + float time2, time3; + float time1; + float dvel; + float frametime; + + vec3_t up, right; + float scale; + unsigned color; + + GL_Bind0(particletexture); + QGX_Blend (true); + + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + VectorScale (vup, 1.5, up); + VectorScale (vright, 1.5, right); + + frametime = cl.time - cl.oldtime; + time3 = frametime * 15; + time2 = frametime * 10; // 15; + time1 = frametime * 5; + grav = frametime * sv_gravity.value * 0.05; + dvel = 4*frametime; + + for ( ;; ) + { + kill = active_particles; + if (kill && kill->die < cl.time) + { + active_particles = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + for (p=active_particles ; p ; p=p->next) + { + for ( ;; ) + { + kill = p->next; + if (kill && kill->die < cl.time) + { + p->next = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + GX_Begin (GX_TRIANGLES, GX_VTXFMT0, 3); + + // hack a scale up to keep particles from disapearing + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + if (scale < 20) + scale = 1; + else + scale = 1 + scale * 0.004; + + color = d_8to24table[(int)p->color]; + + GX_Position3f32(p->org[0], p->org[1], p->org[2]); + GX_Color4u8(color & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); + GX_Color4u8(color & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); + GX_Color4u8(color & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); + GX_TexCoord2f32(0, 1); + + GX_End(); + + p->org[0] += p->vel[0]*frametime; + p->org[1] += p->vel[1]*frametime; + p->org[2] += p->vel[2]*frametime; + + switch (p->type) + { + case pt_static: + break; + case pt_fire: + p->ramp += time1; + if (p->ramp >= 6) + p->die = -1; + else + p->color = ramp3[(int)p->ramp]; + p->vel[2] += grav; + break; + + case pt_explode: + p->ramp += time2; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp1[(int)p->ramp]; + for (i=0 ; i<3 ; i++) + p->vel[i] += p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_explode2: + p->ramp += time3; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp2[(int)p->ramp]; + for (i=0 ; i<3 ; i++) + p->vel[i] -= p->vel[i]*frametime; + p->vel[2] -= grav; + break; + + case pt_blob: + for (i=0 ; i<3 ; i++) + p->vel[i] += p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_blob2: + for (i=0 ; i<2 ; i++) + p->vel[i] -= p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_grav: +#ifdef QUAKE2 + p->vel[2] -= grav * 20; + break; +#endif + case pt_slowgrav: + p->vel[2] -= grav; + break; + } + } + + QGX_Blend(false); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); +} + +///////////////////////////////////// + +/* +=============== +R_DrawParticles +=============== +*/ + +void R_DrawParticles (void) +{ + R_Classic_DrawParticles (); + QMB_DrawParticles (); +} + diff --git a/source/wii/gx/gx_rsurf.c b/source/wii/gx/gx_rsurf.c new file mode 100644 index 0000000..1d0ba80 --- /dev/null +++ b/source/wii/gx/gx_rsurf.c @@ -0,0 +1,1534 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_surf.c: surface-related refresh code + +#include "../../quakedef.h" + +int skytexturenum; + + +int lightmap_bytes; // 1, 2, or 4 + +int lightmap_textures; + +unsigned blocklights[3*18*18]; // LordHavoc: .lit support (*3 for RGB) to the definitions at the top + +#define BLOCK_WIDTH 128 +#define BLOCK_HEIGHT 128 + +#define MAX_LIGHTMAPS 64 +int active_lightmaps; + +typedef struct glRect_s { + unsigned char l,t,w,h; +} glRect_t; + +glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; +qboolean lightmap_modified[MAX_LIGHTMAPS]; +glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; + +int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; + +// the lightmap texture data needs to be kept in +// main memory so texsubimage can update properly +byte lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT]; + +// For gl_texsort 0 +msurface_t *skychain = NULL; +msurface_t *waterchain = NULL; + +extern char skybox_name[32]; + +void R_RenderDynamicLightmaps (msurface_t *fa); + +/* +=============== +R_AddDynamicLights +=============== +*/ +void R_AddDynamicLights (msurface_t *surf) +{ + // LordHavoc: .lit support begin + float cred, cgreen, cblue, brightness; + unsigned *bl; + // LordHavoc: .lit support end + int lnum; + int sd, td; + float dist, rad, minlight; + vec3_t impact, local; + int s, t; + int i; + int smax, tmax; + mtexinfo_t *tex; + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + tex = surf->texinfo; + + for (lnum=0 ; lnumdlightbits & (1<plane->normal) - + surf->plane->dist; + rad -= fabs(dist); + minlight = cl_dlights[lnum].minlight; + if (rad < minlight) + continue; + minlight = rad - minlight; + + for (i=0 ; i<3 ; i++) + { + impact[i] = cl_dlights[lnum].origin[i] - + surf->plane->normal[i]*dist; + } + + local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; + local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; + + local[0] -= surf->texturemins[0]; + local[1] -= surf->texturemins[1]; + + // LordHavoc: .lit support begin + bl = blocklights; + cred = cl_dlights[lnum].color[0] * 256.0f; + cgreen = cl_dlights[lnum].color[1] * 256.0f; + cblue = cl_dlights[lnum].color[2] * 256.0f; + // LordHavoc: .lit support end + + for (t = 0 ; t td) + dist = sd + (td>>1); + else + dist = td + (sd>>1); + if (dist < minlight){ + // LordHavoc: .lit support begin + brightness = rad - dist; + bl[0] += (int) (brightness * cred); + bl[1] += (int) (brightness * cgreen); + bl[2] += (int) (brightness * cblue); + // LordHavoc: .lit support end + } + bl += 3; + } + } + } +} + +/* +=============== +R_BuildLightMap + +Combine and scale multiple lightmaps into the 8.8 format in blocklights +=============== +*/ +void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) +{ + int smax, tmax; + int t; + int i, j, size; + byte *lightmap; + unsigned scale; + int maps; + unsigned *bl; + + surf->cached_dlight = (surf->dlightframe == r_framecount); + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + size = smax*tmax; + lightmap = surf->samples; + +// set to full bright if no light data + if (r_fullbright.value || !cl.worldmodel->lightdata) + { + // LordHavoc: .lit support begin + bl = blocklights; + for (i=0 ; istyles[maps] != 255 ; + maps++) + { + scale = d_lightstylevalue[surf->styles[maps]]; + surf->cached_light[maps] = scale; // 8.8 fraction + // LordHavoc: .lit support begin + bl = blocklights; + + for (i=0 ; idlightframe == r_framecount) + R_AddDynamicLights (surf); + +// bound, invert, and shift +store: + stride -= (smax<<2); + bl = blocklights; + for (i=0 ; i> 8; + } else { + t = bl[0] >> 7; + } + if (t > 255) + t = 255; + *dest++ = t; + + if(r_overbright.value) { + t = bl[1] >> 8; + } else { + t = bl[1] >> 7; + } + if (t > 255) + t = 255; + *dest++ = t; + + if(r_overbright.value) { + t = bl[2] >> 8; + } else { + t = bl[2] >> 7; + } + if (t > 255) + t = 255; + *dest++ = t; + + bl += 3; + *dest++ = 255; + //dest += 4; + // LordHavoc: .lit support end + /* + // LordHavoc: .lit support begin + // LordHavoc: positive lighting (would be 255-t if it were inverse like glquake was) + t = bl[0] >> 7;if (t > 255) t = 255;dest[3] = t; + t = bl[1] >> 7;if (t > 255) t = 255;dest[2] = t; + t = bl[2] >> 7;if (t > 255) t = 255;dest[1] = t; + dest[0] = 255; + bl += 3; + // LordHavoc: .lit support end + */ + } + } +} + + +/* +=============== +R_TextureAnimation + +Returns the proper texture for a given time and base texture +=============== +*/ +texture_t *R_TextureAnimation (texture_t *base) +{ + int reletive; + int count; + + if (currententity->frame) + { + if (base->alternate_anims) + base = base->alternate_anims; + } + + if (!base->anim_total) + return base; + + reletive = (int)(cl.time*10) % base->anim_total; + + count = 0; + while (base->anim_min > reletive || base->anim_max <= reletive) + { + base = base->anim_next; + if (!base) + Sys_Error ("R_TextureAnimation: broken cycle"); + if (++count > 100) + Sys_Error ("R_TextureAnimation: infinite cycle"); + } + + return base; +} + + +/* +============================================================= + + BRUSH MODELS + +============================================================= +*/ + + +extern int solidskytexture; +extern int alphaskytexture; +extern float speedscale; // for top sky and bottom sky +#if 0 +/* +================ +R_DrawSequentialPoly + +Systems that have fast state and texture changes can +just do everything as it passes with no need to sort +================ +*/ +void R_DrawSequentialPoly (msurface_t *s) +{ + glpoly_t *p; + float *v; + int i; + texture_t *t; + vec3_t nv; + glRect_t *theRect; + + // + // normal lightmaped poly + // + + if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) ) + { + R_RenderDynamicLightmaps (s); + + p = s->polys; + + t = R_TextureAnimation (s->texinfo->texture); + // Binds world to texture env 0 + GL_Bind0 (t->gl_texturenum); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + // Binds lightmap to texenv 1 + GL_EnableMultitexture(); + + GL_Bind1 (lightmap_textures + s->lightmaptexturenum); + i = s->lightmaptexturenum; + if (lightmap_modified[i]) + { + lightmap_modified[i] = false; + theRect = &lightmap_rectchange[i]; + GL_UpdateLightmapTextureRegion (lightmap_textures + s->lightmaptexturenum, BLOCK_WIDTH, theRect->h, 0, theRect->t, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes); + theRect->l = BLOCK_WIDTH; + theRect->t = BLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + } + v = p->verts[0]; + GL_Bind0 (t->gl_texturenum); + GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT1, p->numverts); + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(v[3], v[4]); + GX_TexCoord2f32(v[5], v[6]); + } + GX_End(); + return; + } + + // + // subdivided water surface warp + // + + if (s->flags & SURF_DRAWTURB) + { + //GL_DisableMultitexture(); + GL_Bind0 (s->texinfo->texture->gl_texturenum); + EmitWaterPolys (s); + return; + } + + // + // underwater warped with lightmap + // + R_RenderDynamicLightmaps (s); + + p = s->polys; + + t = R_TextureAnimation (s->texinfo->texture); + GL_Bind0 (t->gl_texturenum); + + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GL_EnableMultitexture(); + + GL_Bind1 (lightmap_textures + s->lightmaptexturenum); + i = s->lightmaptexturenum; + if (lightmap_modified[i]) + { + lightmap_modified[i] = false; + theRect = &lightmap_rectchange[i]; + GL_UpdateLightmapTextureRegion (lightmap_textures + s->lightmaptexturenum, BLOCK_WIDTH, theRect->h, 0, theRect->t, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes); + theRect->l = BLOCK_WIDTH; + theRect->t = BLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + } + + v = p->verts[0]; + GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT1, p->numverts); + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + // ELUTODO: may warp too far and get culled when should be visible + nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); + nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); + nv[2] = v[2]; + + GX_Position3f32(nv[0], nv[1], nv[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(v[3], v[4]); + GX_TexCoord2f32(v[5], v[6]); + } + GX_End(); +} +#endif +/* +================ +DrawGXWaterPoly + +Warp the vertex coordinates +================ +*/ +void DrawGXWaterPoly (glpoly_t *p) +{ + int i; + float *v; + vec3_t nv; + + //GL_DisableMultitexture(); + + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, p->numverts); + v = p->verts[0]; + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); + nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); + nv[2] = v[2]; + + GX_Position3f32(nv[0], nv[1], nv[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (v[3], v[4]); + } + GX_End (); +} + +void DrawGXWaterPolyLightmap (glpoly_t *p) +{ + int i; + float *v; + vec3_t nv; + + //GL_DisableMultitexture(); + + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, p->numverts); + v = p->verts[0]; + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); + nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); + nv[2] = v[2]; + + GX_Position3f32(nv[0], nv[1], nv[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (v[5], v[6]); + } + GX_End (); +} + +/* +================ +DrawGXPoly +================ +*/ +void DrawGXPoly (glpoly_t *p) +{ + int i; + float *v; + + GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, p->numverts); + v = p->verts[0]; + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (v[3], v[4]); + } + GX_End (); +} + +/* +================ +R_BlendLightmaps +================ +*/ +void R_BlendLightmaps (void) +{ + int i, j; + glpoly_t *p; + float *v; + glRect_t *theRect; + + if (r_fullbright.value) + return; + + GX_SetZMode(GX_TRUE, GX_EQUAL, GX_TRUE); + QGX_BlendMap(true); + + for (i=0 ; it)*BLOCK_WIDTH*lightmap_bytes, (BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes, BLOCK_WIDTH, theRect->h, gx_lightmap_format); + + + //GX_LoadSubAndBind (lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes, 0, theRect->t, BLOCK_WIDTH, theRect->h, gx_lightmap_format); + // data, xoffset, yoffset, width, height format + + + GL_UpdateLightmapTextureRegion (lightmap_textures + i, BLOCK_WIDTH, theRect->h, 0, theRect->t, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes); + + // picid, width, height, xoffset, yoffset, data + + //GL_LoadLightmapTexture ("", BLOCK_WIDTH, BLOCK_HEIGHT, lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); + //GL_UpdateLightmapTextureRegion (lightmap_textures + i, BLOCK_WIDTH, theRect->h, 0, theRect->t, lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); + theRect->l = BLOCK_WIDTH; + theRect->t = BLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + } + for ( ; p ; p=p->chain) + { + if (p->flags & SURF_UNDERWATER) { + DrawGXWaterPolyLightmap (p); + } + else + { + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, p->numverts); + v = p->verts[0]; + for (j=0 ; jnumverts ; j++, v+= VERTEXSIZE) + { + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (v[5], v[6]); + } + GX_End (); + } + } + } + + QGX_Blend(false); + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); +} + +/* +================ +R_RenderDynamicLightmaps +Multitexture +================ +*/ +void R_RenderDynamicLightmaps (msurface_t *fa) +{ + byte *base; + int maps; + glRect_t *theRect; + int smax, tmax; + + c_brush_polys++; + + if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) ) + return; + + fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; + lightmap_polys[fa->lightmaptexturenum] = fa->polys; + + // check for lightmap modification + for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; + maps++) + if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]) + goto dynamic; + + if (fa->dlightframe == r_framecount // dynamic this frame + || fa->cached_dlight) // dynamic previously + { +dynamic: + if (r_dynamic.value) + { + lightmap_modified[fa->lightmaptexturenum] = true; + theRect = &lightmap_rectchange[fa->lightmaptexturenum]; + if (fa->light_t < theRect->t) { + if (theRect->h) + theRect->h += theRect->t - fa->light_t; + theRect->t = fa->light_t; + } + if (fa->light_s < theRect->l) { + if (theRect->w) + theRect->w += theRect->l - fa->light_s; + theRect->l = fa->light_s; + } + smax = (fa->extents[0]>>4)+1; + tmax = (fa->extents[1]>>4)+1; + if ((theRect->w + theRect->l) < (fa->light_s + smax)) + theRect->w = (fa->light_s-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t + tmax)) + theRect->h = (fa->light_t-theRect->t)+tmax; + base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; + base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; + R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes); + } + } +} + + +/* +================ +R_RenderBrushPoly +================ +*/ +void R_RenderBrushPoly (msurface_t *fa) +{ + texture_t *t; + byte *base; + int maps; + glRect_t *theRect; + int smax, tmax; + + c_brush_polys++; + + if (fa->flags & SURF_DRAWSKY) + { + if (strcmp(skybox_name, "") == 0) + EmitBothSkyLayers (fa); + return; + } + + t = R_TextureAnimation (fa->texinfo->texture); + GL_Bind0 (t->gl_texturenum); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + + if (fa->flags & SURF_DRAWTURB) + { // warp texture, no lightmaps + EmitWaterPolys (fa); + return; + } + + if (fa->flags & SURF_UNDERWATER) + DrawGXWaterPoly (fa->polys); + else + DrawGXPoly (fa->polys); + + // add the poly to the proper lightmap chain + + fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; + lightmap_polys[fa->lightmaptexturenum] = fa->polys; + + // check for lightmap modification + for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; + maps++) + if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]) + goto dynamic; + + if (fa->dlightframe == r_framecount // dynamic this frame + || fa->cached_dlight) // dynamic previously + { +dynamic: + if (r_dynamic.value) + { + lightmap_modified[fa->lightmaptexturenum] = true; + theRect = &lightmap_rectchange[fa->lightmaptexturenum]; + if (fa->light_t < theRect->t) { + if (theRect->h) + theRect->h += theRect->t - fa->light_t; + theRect->t = fa->light_t; + } + if (fa->light_s < theRect->l) { + if (theRect->w) + theRect->w += theRect->l - fa->light_s; + theRect->l = fa->light_s; + } + smax = (fa->extents[0]>>4)+1; + tmax = (fa->extents[1]>>4)+1; + if ((theRect->w + theRect->l) < (fa->light_s + smax)) + theRect->w = (fa->light_s-theRect->l)+smax; + if ((theRect->h + theRect->t) < (fa->light_t + tmax)) + theRect->h = (fa->light_t-theRect->t)+tmax; + base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; + base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; + R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes); + } + } +} + + +/* +================ +R_MirrorChain +================ +*/ +void R_MirrorChain (msurface_t *s) +{ + if (mirror) + return; + mirror = true; + mirror_plane = s->plane; +} + + +/* +================ +R_DrawWaterSurfaces +================ +*/ +void R_DrawWaterSurfaces (void) +{ + int i; + msurface_t *s; + texture_t *t; + + if (r_wateralpha.value == 1.0) + return; + + // + // go back to the world matrix + // + +/* ELUTODO - check when implementing mirrors + glLoadMatrixf (r_world_matrix);*/ + + QGX_Blend (true); + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); +/* + for ( s = waterchain ; s ; s=s->texturechain) { + GL_Bind0 (s->texinfo->texture->gl_texturenum); + EmitWaterPolys (s); + } + + waterchain = NULL; +*/ + for (i=0 ; inumtextures ; i++) + { + t = cl.worldmodel->textures[i]; + if (!t) + continue; + s = t->texturechain; + if (!s) + continue; + if ( !(s->flags & SURF_DRAWTURB ) ) + continue; + + // set modulate mode explicitly + + GL_Bind0 (t->gl_texturenum); + + for ( ; s ; s=s->texturechain) + EmitWaterPolys (s); + + t->texturechain = NULL; + } + + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + QGX_Blend (false); +} + +/* +================ +DrawTextureChains +================ +*/ +void DrawTextureChains (void) +{ + int i; + msurface_t *s; + texture_t *t; + + /* + GL_DisableMultitexture(); + + if (skychain) { + R_DrawSkyChain(skychain); + skychain = NULL; + } + + return; + */ + + //QGX_Alpha(true); + GX_SetAlphaCompare(GX_GREATER,0xaa,GX_AOP_AND,GX_ALWAYS,0xff); + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + for (i=0 ; inumtextures ; i++) + { + t = cl.worldmodel->textures[i]; + if (!t) + continue; + s = t->texturechain; + if (!s) + continue; + else if (i == mirrortexturenum && r_mirroralpha.value != 1.0) + { + R_MirrorChain (s); + continue; + } + else + { + if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0) + continue; // draw translucent water later + for ( ; s ; s=s->texturechain) + R_RenderBrushPoly (s); + } + + t->texturechain = NULL; + } + + GX_SetAlphaCompare(GX_GREATER,0,GX_AOP_AND,GX_ALWAYS,0xff); + QGX_Alpha(false); +} + +/* +================= +R_DrawBrushModel +================= +*/ +void R_DrawBrushModel (entity_t *e) +{ + int k; + vec3_t mins, maxs; + int i; + msurface_t *psurf; + float dot; + mplane_t *pplane; + model_t *clmodel; + qboolean rotated; + + currententity = e; + currenttexture0 = -1; + //currenttexture1 = -1; + + clmodel = e->model; + + if (e->angles[0] || e->angles[1] || e->angles[2]) + { + rotated = true; + for (i=0 ; i<3 ; i++) + { + mins[i] = e->origin[i] - clmodel->radius; + maxs[i] = e->origin[i] + clmodel->radius; + } + } + else + { + rotated = false; + VectorAdd (e->origin, clmodel->mins, mins); + VectorAdd (e->origin, clmodel->maxs, maxs); + } + + if (R_CullBox (mins, maxs)) + return; + + //GX_Color4u8(255, 255, 255, 255); + memset (lightmap_polys, 0, sizeof(lightmap_polys)); + + VectorSubtract (r_refdef.vieworg, e->origin, modelorg); + if (rotated) + { + vec3_t temp; + vec3_t forward, right, up; + + VectorCopy (modelorg, temp); + AngleVectors (e->angles, forward, right, up); + modelorg[0] = DotProduct (temp, forward); + modelorg[1] = -DotProduct (temp, right); + modelorg[2] = DotProduct (temp, up); + } + + psurf = &clmodel->surfaces[clmodel->firstmodelsurface]; + +// calculate dynamic lighting for bmodel if it's not an +// instanced model + if (clmodel->firstmodelsurface != 0) + { + for (k=0 ; knodes + clmodel->hulls[0].firstclipnode); + } + } + + + guMtxIdentity(model); +e->angles[0] = -e->angles[0]; // stupid quake bug + R_RotateForEntity (e, e->scale); +e->angles[0] = -e->angles[0]; // stupid quake bug + + //sBTODO at somepoint... will require more in depth studying of GX blendmodes + guMtxConcat(view,model,modelview); + GX_LoadPosMtxImm(modelview, GX_PNMTX0); + + // naievil -- fixme + /* + //Crow_bar half_life render. + if (ISADDITIVE(e)) + { + //Con_DPrintf("ISADDITIVE:brush\n"); + float deg = e->renderamt; + float alpha1 = deg; + float alpha2 = 1 - deg; + if(deg <= 0.7) + sceGuDepthMask(GU_TRUE); + + sceGuEnable (GU_BLEND); + sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, + GU_COLOR(alpha1,alpha1,alpha1,alpha1), + GU_COLOR(alpha2,alpha2,alpha2,alpha2)); + dlight = qfalse; + } + else if (ISSOLID(e)) + { + sceGuEnable(GU_ALPHA_TEST); + int c = (int)(e->renderamt * 255.0f); + sceGuAlphaFunc(GU_GREATER, c, 0xff); + dlight = qfalse; + } + else if (ISGLOW(e)) + { + sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA); + sceGuDepthMask(GU_TRUE); + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0xFFFFFFFF); + R_GlowSetupBegin(e); + } + else if (ISTEXTURE(e)) + { + sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); + sceGuColor(GU_RGBA(255, 255, 255, (int)(e->renderamt * 255.0f))); + dlight = qfalse; + } + else if (ISCOLOR(e)) + { + sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); + sceGuColor(GU_RGBA((int)(e->rendercolor[0] * 255.0f), + (int)(e->rendercolor[1] * 255.0f), + (int)(e->rendercolor[2] * 255.0f), 255)); + } + */ + + // + // draw texture + // + for (i=0 ; inummodelsurfaces ; i++, psurf++) + { + // find which side of the node we are on + pplane = psurf->plane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + R_RenderBrushPoly (psurf); + } + } + R_BlendLightmaps (); +} + +/* +============================================================= + + WORLD MODEL + +============================================================= +*/ + +/* +================ +R_RecursiveWorldNode +================ +*/ +void R_RecursiveWorldNode (mnode_t *node) +{ + int c, side; + mplane_t *plane; + msurface_t *surf, **mark; + mleaf_t *pleaf; + double dot; + + if (node->contents == CONTENTS_SOLID) + return; // solid + + if (node->visframe != r_visframecount) + return; + if (R_CullBox (node->minmaxs, node->minmaxs+3)) + return; + +// if a leaf node, draw stuff + if (node->contents < 0) + { + pleaf = (mleaf_t *)node; + + mark = pleaf->firstmarksurface; + c = pleaf->nummarksurfaces; + + if (c) + { + do + { + (*mark)->visframe = r_framecount; + mark++; + } while (--c); + } + + // deal with model fragments in this leaf + if (pleaf->efrags) + R_StoreEfrags (&pleaf->efrags); + + return; + } + +// node is just a decision point, so go down the apropriate sides + +// find which side of the node we are on + plane = node->plane; + + switch (plane->type) + { + case PLANE_X: + dot = modelorg[0] - plane->dist; + break; + case PLANE_Y: + dot = modelorg[1] - plane->dist; + break; + case PLANE_Z: + dot = modelorg[2] - plane->dist; + break; + default: + dot = DotProduct (modelorg, plane->normal) - plane->dist; + break; + } + + if (dot >= 0) + side = 0; + else + side = 1; + +// recurse down the children, front side first + R_RecursiveWorldNode (node->children[side]); + +// draw stuff + c = node->numsurfaces; + + if (c) + { + surf = cl.worldmodel->surfaces + node->firstsurface; + + if (dot < 0 -BACKFACE_EPSILON) + side = SURF_PLANEBACK; + else if (dot > BACKFACE_EPSILON) + side = 0; + { + for ( ; c ; c--, surf++) + { + if (surf->visframe != r_framecount) + continue; + + // don't backface underwater surfaces, because they warp + if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) ) + continue; // wrong side + + if (!mirror + || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum]) + { + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; + } +/* + if (surf->flags & SURF_DRAWSKY) { + if (strcmp(skybox_name, "") != 0) { + continue; + } else { + surf->texturechain = skychain; + skychain = surf; + } + } else if (surf->flags & SURF_DRAWTURB) { + surf->texturechain = waterchain; + waterchain = surf; + } else + R_DrawSequentialPoly (surf); +*/ + } + } + + } + +// recurse down the back side + R_RecursiveWorldNode (node->children[!side]); +} + +void R_AddBrushModelToChains (entity_t * e) +{ + model_t * clmodel = e->model; + vec3_t mins, maxs; + VectorAdd (e->origin, clmodel->mins, mins); + VectorAdd (e->origin, clmodel->maxs, maxs); + + if (R_CullBox(mins, maxs)) + { + return; + } + + msurface_t * psurf = &clmodel->surfaces[clmodel->firstmodelsurface]; + + /* + if (clmodel->firstmodelsurface != 0) + { + for (int k = 0; k < MAX_DLIGHTS; k++) + { + if ((cl_dlights[k].die < cl.time) || + (!cl_dlights[k].radius)) + continue; + R_MarkLights (&cl_dlights[k], 1<nodes + clmodel->hulls[0].firstclipnode); + } + } + */ + + for (int j = 0; j < clmodel->nummodelsurfaces; j++, psurf++) + { + // find which side of the node we are on + mplane_t * pplane = psurf->plane; + float dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + // psurf->flags &= ~SURF_NEEDSCLIPPING; + // psurf->flags |= SURF_NEEDSCLIPPING * (frustum_check > 1); + + psurf->texturechain = psurf->texinfo->texture->texturechain; + psurf->texinfo->texture->texturechain = psurf; + } + } +} + +void R_AddStaticBrushModelsToChains () +{ + // Con_Printf("static models %d\n", cl_numstaticbrushmodels); + for (int i = 0; i < cl_numstaticbrushmodels; i++) + { + // if (i >= 1) return; + R_AddBrushModelToChains(cl_staticbrushmodels[i]); + } +} + +/* +============= +R_DrawWorld +============= +*/ +void R_DrawWorld (void) +{ + entity_t ent; + + memset (&ent, 0, sizeof(ent)); + ent.model = cl.worldmodel; + + VectorCopy (r_refdef.vieworg, modelorg); + + currententity = &ent; + currenttexture0 = -1; + //currenttexture1 = -1; + + //GX_Color4u8(255, 255, 255, 255); + memset (lightmap_polys, 0, sizeof(lightmap_polys)); + + R_ClearSkyBox (); + if (strcmp(skybox_name, "") != 0) + R_DrawSkyBox(); + + R_RecursiveWorldNode (cl.worldmodel->nodes); + + R_AddStaticBrushModelsToChains (); // shpuld + + DrawTextureChains (); + + R_BlendLightmaps(); +} + + +/* +=============== +R_MarkLeaves +=============== +*/ +void R_MarkLeaves (void) +{ + byte *vis; + mnode_t *node; + int i; + byte solid[4096]; + + if (r_oldviewleaf == r_viewleaf && !r_novis.value) + return; + + if (mirror) + return; + + r_visframecount++; + r_oldviewleaf = r_viewleaf; + + if (r_novis.value) + { + vis = solid; + memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3); + } + else + vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); + + for (i=0 ; inumleafs ; i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + node = (mnode_t *)&cl.worldmodel->leafs[i+1]; + do + { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + node = node->parent; + } while (node); + } + } +} + + + +/* +============================================================================= + + LIGHTMAP ALLOCATION + +============================================================================= +*/ + +// returns a texture number and the position inside it +int AllocBlock (int w, int h, int *x, int *y) +{ + int i, j; + int best, best2; + int texnum; + + for (texnum=0 ; texnum= best) + break; + if (allocated[texnum][i+j] > best2) + best2 = allocated[texnum][i+j]; + } + if (j == w) + { // this is a valid spot + *x = i; + *y = best = best2; + } + } + + if (best + h > BLOCK_HEIGHT) + continue; + + for (i=0 ; iedges; + lnumverts = fa->numedges; + //vertpage = 0; + + // + // draw texture + // + poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float)); + poly->next = fa->polys; + poly->flags = fa->flags; + fa->polys = poly; + poly->numverts = lnumverts; + + for (i=0 ; isurfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + vec = r_pcurrentvertbase[r_pedge->v[0]].position; + } + else + { + r_pedge = &pedges[-lindex]; + vec = r_pcurrentvertbase[r_pedge->v[1]].position; + } + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + s /= fa->texinfo->texture->width; + + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + t /= fa->texinfo->texture->height; + + VectorCopy (vec, poly->verts[i]); + poly->verts[i][3] = s; + poly->verts[i][4] = t; + + // + // lightmap texture coordinates + // + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + s -= fa->texturemins[0]; + s += fa->light_s*16; + s += 8; + s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width; + + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + t -= fa->texturemins[1]; + t += fa->light_t*16; + t += 8; + t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height; + + poly->verts[i][5] = s; + poly->verts[i][6] = t; + } + + // + // remove co-linear points - Ed + // + if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) ) + { + for (i = 0 ; i < lnumverts ; ++i) + { + vec3_t v1, v2; + float *prev, *this, *next; + + prev = poly->verts[(i + lnumverts - 1) % lnumverts]; + this = poly->verts[i]; + next = poly->verts[(i + 1) % lnumverts]; + + VectorSubtract( this, prev, v1 ); + VectorNormalize( v1 ); + VectorSubtract( next, prev, v2 ); + VectorNormalize( v2 ); + + // skip co-linear points + #define COLINEAR_EPSILON 0.001 + if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) && + (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && + (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON)) + { + int j; + for (j = i + 1; j < lnumverts; ++j) + { + int k; + for (k = 0; k < VERTEXSIZE; ++k) + poly->verts[j - 1][k] = poly->verts[j][k]; + } + --lnumverts; + ++nColinElim; + // retry next vertex next time, which is now current vertex + --i; + } + } + } + poly->numverts = lnumverts; + +} + +/* +======================== +GL_CreateSurfaceLightmap +======================== +*/ +void GL_CreateSurfaceLightmap (msurface_t *surf) +{ + int smax, tmax; + byte *base; + + if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) + return; + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + + surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); + base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; + base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; + R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes); +} + + +/* +================== +GL_BuildLightmaps + +Builds the lightmap texture +with all the surfaces from all brush models +================== +*/ +void GL_BuildLightmaps (void) +{ + int i, j; + model_t *m; + char name[32]; + + memset (allocated, 0, sizeof(allocated)); + + r_framecount = 1; // no dlightcache + + lightmap_textures = numgltextures; + /* + if (!lightmap_textures) + { + lightmap_textures = texture_extension_number; + texture_extension_number += MAX_LIGHTMAPS; + } + */ + lightmap_bytes = 4; + + for (j=1 ; jname[0] == '*') + continue; + r_pcurrentvertbase = m->vertexes; + currentmodel = m; + for (i=0 ; inumsurfaces ; i++) + { + GL_CreateSurfaceLightmap (m->surfaces + i); + if ( m->surfaces[i].flags & SURF_DRAWTURB ) + continue; +//#ifndef QUAKE2 + if ( m->surfaces[i].flags & SURF_DRAWSKY ) + continue; +//#endif + BuildSurfaceDisplayList (m->surfaces + i); + } + } + + // + // upload all lightmaps that were filled + // + for (i=0 ; i + +/* + +background clear +rendering +turtle/net/ram icons +sbar +centerprint / slow centerprint +notify lines +intermission / finale overlay +loading plaque +console +menu + +required background clears +required update regions + + +syncronous draw mode or async +One off screen buffer, with updates either copied or xblited +Need to double buffer? + + +async draw will require the refresh area to be cleared, because it will be +xblited, but sync draw can just ignore it. + +sync +draw + +CenterPrint () +SlowPrint () +Screen_Update (); +Con_Printf (); + +net +turn off messages option + +the refresh is allways rendered, unless the console is full screen + + +console is: + notify lines + half + full + + +*/ + + +int glx, gly, glwidth, glheight; + +// only the refresh window will be updated unless these variables are flagged +int scr_copytop; +int scr_copyeverything; + +float scr_con_current; +float scr_conlines; // lines of console to display + +float oldscreensize, oldfov; +cvar_t scr_viewsize = {"viewsize","100", true}; +cvar_t scr_fov = {"fov","70"}; // 10 - 170 +cvar_t scr_fov_viewmodel = {"r_viewmodel_fov","70"}; +cvar_t scr_conspeed = {"scr_conspeed","300"}; +cvar_t scr_centertime = {"scr_centertime","2"}; +cvar_t scr_showram = {"showram","0"}; +cvar_t scr_showturtle = {"showturtle","0"}; +cvar_t scr_showpause = {"showpause","1"}; +cvar_t scr_printspeed = {"scr_printspeed","8"}; +cvar_t scr_loadscreen = {"scr_loadscreen","1"}; +cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true }; +cvar_t cl_crosshair_debug = {"cl_crosshair_debug", "0", true}; + +extern cvar_t crosshair; +extern cvar_t cl_crossx; +extern cvar_t cl_crossy; + +qboolean scr_initialized; // ready to draw + +qpic_t *scr_ram; +qpic_t *scr_net; +qpic_t *scr_turtle; + +qpic_t *hitmark; +qpic_t *lscreen; + +int loadingScreen; +int ShowBlslogo; + +qboolean loadscreeninit; + +char* loadname2; +char* loadnamespec; + +int scr_fullupdate; + +int clearconsole; +int clearnotify; + +int sb_lines; + +viddef_t vid; // global video state + +vrect_t scr_vrect; + +qboolean scr_disabled_for_loading; +qboolean scr_drawloading; +float scr_disabled_time; + +qboolean block_drawing; + +void SCR_ScreenShot_f (void); + +/* +=============================================================================== + +CENTER PRINTING + +=============================================================================== +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + +/* +============== +SCR_CenterPrint + +Called for important messages that should stay in the center of the screen +for a few moments +============== +*/ +void SCR_CenterPrint (char *str) +{ + strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + scr_centertime_off = scr_centertime.value; + scr_centertime_start = cl.time; + +// count the number of lines for centering + scr_center_lines = 1; + while (*str) + { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + + +void SCR_DrawCenterString (void) +{ + char *start; + int l; + int j; + int x, y; + int remaining; + +// the finale prints the characters one at a time + if (cl.intermission) + remaining = scr_printspeed.value * (cl.time - scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.conheight*0.35; + else + y = 48; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.conwidth - getTextWidth(start, 1)/*l*8*/)/2; + for (j=0 ; j 126) + x += 8; + else + x += (font_kerningamount[(int)(start[j] - 33)] + 1); + + if (!remaining--) + return; + } + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } while (1); +} + +void SCR_CheckDrawCenterString (void) +{ + scr_copytop = 1; + if (scr_center_lines > scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= host_frametime; + + if (scr_centertime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +/* +=============================================================================== + +Press somthing printing + +=============================================================================== +*/ + +char scr_usestring[64]; +char scr_usestring2[64]; +float scr_usetime_off = 0.0f; +int button_pic_x; + +extern qpic_t *b_abutton; +extern qpic_t *b_bbutton; +extern qpic_t *b_cbutton; +extern qpic_t *b_zbutton; +extern qpic_t *b_left; +extern qpic_t *b_right; +extern qpic_t *b_up; +extern qpic_t *b_down; +extern qpic_t *b_minus; +extern qpic_t *b_plus; +extern qpic_t *b_home; +extern qpic_t *b_one; +extern qpic_t *b_two; + +/* +============== +SCR_UsePrint + +Similiar to above, but will also print the current button for the action. +============== +*/ + +qpic_t *GetButtonIcon (char *buttonname) +{ + + int j; + int l; + char *b; + l = strlen(buttonname); + + for (j=0 ; j<256 ; j++) + { + b = keybindings[j]; + if (!b) + continue; + if (!strncmp (b, buttonname, l) ) + { + if (!strcmp(Key_KeynumToString(j), "PADUP")) + return b_up; + else if (!strcmp(Key_KeynumToString(j), "PADDOWN")) + return b_down; + else if (!strcmp(Key_KeynumToString(j), "PADLEFT")) + return b_left; + else if (!strcmp(Key_KeynumToString(j), "PADRIGHT")) + return b_right; + else if (!strcmp(Key_KeynumToString(j), "JOY17")) + return b_minus; + else if (!strcmp(Key_KeynumToString(j), "PLUS")) + return b_plus; + else if (!strcmp(Key_KeynumToString(j), "ABUTTON")) + return b_abutton; + else if (!strcmp(Key_KeynumToString(j), "BBUTTON")) + return b_bbutton; + else if (!strcmp(Key_KeynumToString(j), "ZBUTTON")) + return b_zbutton; + else if (!strcmp(Key_KeynumToString(j), "CBUTTON")) + return b_cbutton; + else if (!strcmp(Key_KeynumToString(j), "HOME")) + return b_home; + else if (!strcmp(Key_KeynumToString(j), "ONE")) + return b_one; + else if (!strcmp(Key_KeynumToString(j), "TWO")) + return b_two; + } + } + return b_abutton; +} + +char *GetUseButtonL () +{ + int j; + int l; + char *b; + l = strlen("+use"); + + for (j=0 ; j<256 ; j++) + { + b = keybindings[j]; + if (!b) + continue; + if (!strncmp (b, "+use", l) ) + { + if (!strcmp(Key_KeynumToString(j), "JOY17") || + !strcmp(Key_KeynumToString(j), "ABUTTON") || + !strcmp(Key_KeynumToString(j), "BBUTTON") || + !strcmp(Key_KeynumToString(j), "HOME")) + return " "; + else + return " "; + } + } + return " "; +} + +char *GetGrenadeButtonL () +{ + int j; + int l; + char *b; + l = strlen("impulse 33"); + + for (j=0 ; j<256 ; j++) + { + b = keybindings[j]; + if (!b) + continue; + if (!strncmp (b, "impulse 33", l) ) + { + if (!strcmp(Key_KeynumToString(j), "JOY17") || + !strcmp(Key_KeynumToString(j), "ABUTTON") || + !strcmp(Key_KeynumToString(j), "BBUTTON") || + !strcmp(Key_KeynumToString(j), "HOME")) + return " "; + else + return ""; + } + } + return " "; +} + +char *GetPerkName (int perk) +{ + switch (perk) + { + case 1: + return "Quick Revive"; + case 2: + return "Juggernog"; + case 3: + return "Speed Cola"; + case 4: + return "Double Tap"; + case 5: + return "Stamin-Up"; + case 6: + return "PhD Flopper"; + case 7: + return "Deadshot Daiquiri"; + case 8: + return "Mule Kick"; + default: + return "NULL"; + } +} + +void SCR_UsePrint (int type, int cost, int weapon) +{ + //naievil -- fixme + char s[128]; + char c[128]; + + switch (type) + { + case 0://clear + strcpy(s, ""); + strcpy(c, ""); + break; + case 1://door + strcpy(s, va("Hold %s to open Door\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 2://debris + strcpy(s, va("Hold %s to remove Debris\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 3://ammo + strcpy(s, va("Hold %s to buy Ammo for %s\n", GetUseButtonL(), pr_strings+sv_player->v.Weapon_Name_Touch)); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 4://weapon + strcpy(s, va("Hold %s to buy %s\n", GetUseButtonL(), pr_strings+sv_player->v.Weapon_Name_Touch)); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 5://window + strcpy(s, va("Hold %s to Rebuild Barrier\n", GetUseButtonL())); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 6://box + strcpy(s, va("Hold %s to for Mystery Box\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 7://box take + strcpy(s, va("Hold %s for %s\n", GetUseButtonL(), pr_strings+sv_player->v.Weapon_Name_Touch)); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 8://power + strcpy(s, "The Power must be Activated first\n"); + strcpy(c, ""); + button_pic_x = 100; + break; + case 9://perk + strcpy(s, va("Hold %s to buy %s\n", GetUseButtonL(), GetPerkName(weapon))); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 10://turn on power + strcpy(s, va("Hold %s to Turn On the Power\n", GetUseButtonL())); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 11://turn on trap + strcpy(s, va("Hold %s to Activate the Trap\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 12://PAP + strcpy(s, va("Hold %s to Pack-a-Punch\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 13://revive + strcpy(s, va("Hold %s to Fix your Code.. :)\n", GetUseButtonL())); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 14://use teleporter (free) + strcpy(s, va("Hold %s to use Teleporter\n", GetUseButtonL())); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 15://use teleporter (cost) + strcpy(s, va("Hold %s to use Teleporter\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 16://tp cooldown + strcpy(s, "Teleporter is cooling down\n"); + strcpy(c, ""); + button_pic_x = 100; + break; + case 17://link + strcpy(s, va("Hold %s to initiate link to pad\n", GetUseButtonL())); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 18://no link + strcpy(s, "Link not active\n"); + strcpy(c, ""); + button_pic_x = 100; + break; + case 19://finish link + strcpy(s, va("Hold %s to link pad with core\n", GetUseButtonL())); + strcpy(c, ""); + button_pic_x = getTextWidth("Hold", 1.5); + break; + case 20://buyable ending + strcpy(s, va("Hold %s to End the Game\n", GetUseButtonL())); + strcpy(c, va("[Cost: %i]\n", cost)); + button_pic_x = getTextWidth("Hold", 1.5); + break; + default: + Con_Printf ("No type defined in engine for useprint\n"); + break; + } + + strncpy (scr_usestring, va(s), sizeof(scr_usestring)-1); + strncpy (scr_usestring2, va(c), sizeof(scr_usestring2)-1); + scr_usetime_off = 0.1; +} + +void SCR_DrawUseString (void) +{ + //int l, l2; + int x, /*x2,*/ y; + + if (cl.stats[STAT_HEALTH] < 0) + return; +// the finale prints the characters one at a time + + y = vid.height/2 + (30 * 1.5); + //l = strlen (scr_usestring); + //x = (vid.width - l*12)/2; + x = (vid.width - getTextWidth(scr_usestring, 1.5))/2; + + //l2 = strlen (scr_usestring2); + //x2 = (vid.width - l2*12)/2; + + //Draw_String (x, y, scr_usestring); + //Draw_String (x2, y + 20, scr_usestring2); + Draw_ColoredStringCentered(y, scr_usestring, 255, 255, 255, 255, 1.5); + Draw_ColoredStringCentered(y + 22, scr_usestring2, 255, 255, 255, 255, 1.5); + + if (button_pic_x != 100) { + Draw_StretchPic (x + button_pic_x + 4, y - 3, GetButtonIcon("+use"), 18, 18); + } +} + +void SCR_CheckDrawUseString (void) +{ + scr_copytop = 1; + + scr_usetime_off -= host_frametime; + + if (scr_usetime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + if (cl.stats[STAT_HEALTH] <= 0) + return; + else + + SCR_DrawUseString (); +} + +//============================================================================= + +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) +{ + float a; + float x; + + if (fov_x < 1 || fov_x > 179) + Sys_Error ("Bad fov: %f", fov_x); + + x = width/tan(fov_x/360*M_PI); + + a = atan (height/x); + + a = a*360/M_PI; + + return a; +} + +/* +================= +SCR_CalcRefdef + +Must be called whenever vid changes +Internal use only +================= +*/ +static void SCR_CalcRefdef (void) +{ + int size; + int h; + qboolean full = false; + + scr_fullupdate = 0; // force a background redraw + vid.recalc_refdef = 0; + +//======================================== + +// bound viewsize + if (scr_viewsize.value < 100) + Cvar_Set ("viewsize","100"); + if (scr_viewsize.value > 120) + Cvar_Set ("viewsize","120"); + +// bound field of view + if (scr_fov.value < 10) + Cvar_Set ("fov","10"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + +// intermission is always full screen + full = true; + size = 1; + + h = vid.height; + + r_refdef.vrect.width = vid.width * size; + if (r_refdef.vrect.width < 96) + { + size = 96.0 / r_refdef.vrect.width; + r_refdef.vrect.width = 96; // min for icons + } + + r_refdef.vrect.height = vid.height * size; + if (r_refdef.vrect.height > vid.height) + r_refdef.vrect.height = vid.height; + if (r_refdef.vrect.height > vid.height) + r_refdef.vrect.height = vid.height; + r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2; + + if (full) + r_refdef.vrect.y = 0; + else + r_refdef.vrect.y = (h - r_refdef.vrect.height)/2; + + r_refdef.fov_x = scr_fov.value; + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); + + scr_vrect = r_refdef.vrect; +} + + +/* +================= +SCR_SizeUp_f + +Keybinding command +================= +*/ +void SCR_SizeUp_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value+10); + vid.recalc_refdef = 1; +} + + +/* +================= +SCR_SizeDown_f + +Keybinding command +================= +*/ +void SCR_SizeDown_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value-10); + vid.recalc_refdef = 1; +} + +//============================================================================ + +/* +================== +SCR_Init +================== +*/ +void SCR_Init (void) +{ + + Cvar_RegisterVariable (&scr_fov); + Cvar_RegisterVariable (&scr_fov_viewmodel); + Cvar_RegisterVariable (&scr_viewsize); + Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_showram); + Cvar_RegisterVariable (&scr_showturtle); + Cvar_RegisterVariable (&scr_showpause); + Cvar_RegisterVariable (&scr_centertime); + Cvar_RegisterVariable (&scr_printspeed); + Cvar_RegisterVariable (&gl_triplebuffer); + Cvar_RegisterVariable (&scr_loadscreen); + Cvar_RegisterVariable (&cl_crosshair_debug); + +// +// register our commands +// + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + + hitmark = Draw_CachePic("gfx/hud/hit_marker"); + + scr_initialized = true; +} + + + +/* +============== +SCR_DrawRam +============== +*/ +void SCR_DrawRam (void) +{ + if (!scr_showram.value) + return; + + if (!r_cache_thrash) + return; + + Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); +} + +/* +============== +SCR_DrawTurtle +============== +*/ +void SCR_DrawTurtle (void) +{ + static int count; + + if (!scr_showturtle.value) + return; + + if (host_frametime < 0.1) + { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); +} + +/* +============== +SCR_DrawNet +============== +*/ +void SCR_DrawNet (void) +{ + if (realtime - cl.last_received_message < 0.3) + return; + if (cls.demoplayback) + return; + + Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); +} + +/* +============== +DrawPause +============== +*/ +void SCR_DrawPause (void) +{ + //qpic_t *pic; + + if (!scr_showpause.value) // turn off for screenshots + return; + + if (!cl.paused) + return; + /* + pic = Draw_CachePic ("gfx/pause.lmp"); + Draw_Pic ( (vid.conwidth - pic->width)/2, + (vid.conheight - 48 - pic->height)/2, pic); + */ +} + +/* +//muff - hacked out of SourceForge implementation + modified +============== + +SCR_DrawFPS + +============== +*/ +void SCR_DrawFPS (void) +{ + extern cvar_t show_fps; + static double lastframetime; + double t; + extern int fps_count; + static int lastfps; + int x, y; + char st[80]; + + if (!show_fps.value) + return; + + t = Sys_FloatTime (); + + if ((t - lastframetime) >= 1.0) { + lastfps = fps_count; + fps_count = 0; + lastframetime = t; + } + + sprintf(st, "%3d FPS", lastfps); + + x = vid.width - strlen(st) * 16 - 2; + y = 8 ; //vid.height - (sb_lines * (vid.height/240) )- 16; + +// Draw_TileClear(x, y, strlen(st)*16, 16); + + Draw_String(x, y, st); + +} + +/* +============== +SCR_DrawLoading +============== +*/ +void SCR_DrawLoading (void) +{ + //qpic_t *pic; + + if (!scr_drawloading) + return; + /* + pic = Draw_CachePic ("gfx/loading.lmp"); + Draw_Pic ( (vid.conwidth - pic->width)/2, + (vid.conheight - 48 - pic->height)/2, pic); + */ +} + +/* +============== +SCR_DrawLoadScreen +============== +*/ + +/* + Creds to the following people from the 2020 + Loading Screen Hint Submission/Contest: + + * BCDeshiG + * Derped_Crusader + * Aidan + * yasen + * greg + * Asher + * Bernerd + * Omar Alejandro + * TheSmashers +*/ + +int Random_Int (int max_int) +{ + float f; + f = (rand ()&0x7fff) / ((float)0x7fff) * max_int; + if (f > 0) + return (int)(f + 0.5) + 1; + else + return (int)(f - 0.5) + 1; +} + +// 47 character limit + +double loadingtimechange; +int loadingdot; +int loadingtextwidth; +char *lodinglinetext; +qpic_t *awoo; +char *ReturnLoadingtex (void) +{ + int StringNum = Random_Int(80); + switch(StringNum) + { + case 1: + return "Released in 1996, Quake is over 25 years old!"; + break; + case 2: + return "Use the Kar98k to be the hero we need!"; + break; + case 3: + return "Lots of modern engines are based on Quake!"; + break; + case 4: + return "NZ:P began development on September 27 2009!"; + break; + case 5: + return "NZ:P was first released on December 25, 2010!"; + break; + case 6: + return "NZ:P Beta 1.1 has over 300,000 downloads!"; + break; + case 7: + return "NZ:P has been downloaded over 500,000 times!"; + break; + case 8: + return "A lot of people have worked on NZ:P!"; + break; + case 9: + return "Blubswillrule, or \"blubs\", is from the US."; + break; + case 10: + return "Jukki is from Finland."; + break; + case 11: + return "Ju[s]tice, or \"tom\" is from Lithuania."; + break; + case 12: + return "This game has given us bad sleeping habits!"; + break; + case 13: + return "We had a lot of fun making this game!"; + break; + case 14: + return "Pro Tip: you can make your own custom map!"; + break; + case 15: + return "Try Retro Mode, it's in the Graphics Settings!"; + break; + case 16: + return "Tired of our maps? Go make your own!"; + break; + case 17: + return "Slay zombies & be grateful."; + break; + case 18: + return "Custom maps, CUSTOM MAPS!"; + break; + case 19: + return "Go outside & build a snowman!"; + break; + case 20: + return "Please surround yourself with zombies!"; + break; + case 21: + return "Don't play for too long.. zombies may eat you."; + break; + case 22: + return "That was epic... EPIC FOR THE WIIIN!"; //why + break; + case 23: + return "Dolphin is an awesome Wii emulator!"; + break; + case 24: + return "You dead yet?"; + break; + case 25: + return "Now 21% cooler!"; + break; + case 26: + return "your lg is nothink on the lan!"; //what + break; + case 27: + return "I'm not your chaotic on dm6!"; + break; + case 28: + return "Shoot or knife zombies to kill them, up to you!"; + break; + case 29: + return "How many people forgot to Compile today?"; + break; + case 30: + return "ggnore"; + break; + case 31: + return "NZ:P is also on PC, Switch, Vita, 3DS, and PSP!"; + break; + case 32: + return "Submerge your device in water for godmode!"; + break; + case 33: + return "10/10/10 was a good day."; + break; + case 34: + return "Also check out \"Quake\" for Wii!"; + break; + case 35: + return "CypressImplex, or \"Ivy\", is from the USA."; + break; + case 36: + return "Zombies don't like bullets."; + break; + case 37: + return "Thanks for being an awesome fan!"; + break; + case 38: + return "Removed Herobrine"; + break; + case 39: + return "Pack-a-Punch the Kar98k to get to round 100000."; + break; + case 40: + return "I feel like I'm being gaslit."; + break; + case 41: + return "Heads up! You will die if you are killed!"; + break; + case 42: + return "Zombies legally can't kill you if you say no!"; + break; + case 43: + return "Please help me find the meaning of . Thanks."; + break; + case 44: + return "Discord is ONLY for Thomas the Tank Engine RP!"; + break; + case 45: + return "\"Get rid of the 21% tip, it's an MLP reference.\""; + break; + case 46: + return "You're playing on a Wii!"; + break; + case 47: + return "Don't leak the beta!"; + break; + case 48: + return "Jugger-Nog increases your health!"; + break; + case 49: + return "greg was here"; + break; + case 50: + return "Where the hell is the Mystery Box?!"; + break; + case 51: + return "Zombies like getting shot.. I think."; + break; + case 52: + return "pro tip: aiming helps"; + break; + case 53: + return "\"my mom gave me plunger money\""; + break; + case 54: + return "dolphin dive on top of your friend for god mode"; + break; + case 55: + return "no free rides. ass, grass, or cash!"; + break; + case 56: + return "nzp-team.github.io/latest/game.html"; + break; + case 57: + return "im an mlg gamer girl so its pretty guaranteed"; + break; + case 58: + return "this is a w because you cant have enough fnaf"; + break; + case 59: + return "i hope santa drops bombs on the uk"; + break; + case 60: + return "Hoyl shit, bro! You fucking ported fortnite!"; + break; + case 61: + return "icarly feet futtishist."; + break; + case 62: + return "Well, it's impossible to play, I'm disgusted."; + break; + case 63: + return "I like my women to not be cartoons"; + break; + case 64: + return "Plot twist: NZP was always broken"; + break; + case 65: + return "testing some think."; + break; + case 66: + return "fnaf is older than gay marriage in the US"; + break; + case 67: + return "i want that twink Obliterated"; + break; + case 68: + return "i think he started the femboy transition process"; + break; + case 69: + return "nice"; + break; + case 70: + return "He's FRIKING annoying"; + break; + case 71: + return "yeah pog female bikers"; + break; + case 72: + return "Its either a stroke of genius or just a stroke"; + break; + case 73: + return "Play some Custom Maps!"; + break; + case 74: + return "Real OGs play on Wii c:"; + break; + case 75: + return "Adding this tip improved framerate by 39%!"; + break; + case 76: + return "The NZ in NZP stands for New Zealand!"; + break; + case 77: + return "The P in NZP stands for Professional!"; + break; + case 78: + return "Remember to stay hydrated!"; + break; + case 79: + return "cofe"; + break; + } + return "wut wut"; +} +qboolean load_screen_exists; +void SCR_DrawLoadScreen (void) +{ + + if (developer.value) { + return; + } + if (!con_forcedup) { + return; + } + + if (loadingScreen) { + Draw_FillByColor(0, 0, vid.width, vid.height, 0, 0, 0, 255); + if (!loadscreeninit) { + load_screen_exists = true; + + char* lpath; + lpath = (char*)malloc(sizeof(char)*128); + strcpy(lpath, "gfx/lscreen/"); + strcat(lpath, loadname2); + + lscreen = Draw_CachePic(lpath); + awoo = Draw_CachePic("gfx/menu/awoo"); + + if (lscreen == 0) + load_screen_exists = false; + + loadscreeninit = true; + free(lpath); + } + + if (load_screen_exists == true) + Draw_StretchPic(0, 0, lscreen, vid.width, vid.height); + else + Draw_FillByColor(0, 0, vid.width, vid.height, 0, 0, 0, 255); + + Draw_FillByColor(0, 0, vid.width, 48, 0, 0, 0, 175); + Draw_FillByColor(0, vid.height - 48, vid.width, 48, 0, 0, 0, 175); + + Draw_ColoredString(2, 4, loadnamespec, 255, 255, 0, 255, 3); + } + + if (loadingtimechange < Sys_FloatTime ()) + { + lodinglinetext = ReturnLoadingtex(); + //loadingtextwidth = strlen(lodinglinetext)*12; + loadingtimechange = Sys_FloatTime () + 5; + } + + if (key_dest == key_game) { + //Draw_ColoredString((vid.width - loadingtextwidth)/2, 460, lodinglinetext, 255, 255, 255, 255, 1.5); + Draw_ColoredStringCentered(vid.height - 20, lodinglinetext, 255, 255, 255, 255, 1.5f); + + if (strcmp(lodinglinetext, "Please help me find the meaning of . Thanks.") == 0) { + Draw_StretchPic(120, vid.height - 22, awoo, 24, 24); + } + } +} + + + +//============================================================================= + + +/* +================== +SCR_SetUpToDrawConsole +================== +*/ +void SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + + if (scr_drawloading) + return; // never a console with loading plaque + + con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; + + +// decide on the height of the console + if (!cl.worldmodel || cls.signon != SIGNONS)//blubs here, undid it actually + { + con_forcedup = true; + } + else + { + con_forcedup = false; + } + + + if (con_forcedup) + { + scr_conlines = vid.conheight; // full screen + scr_con_current = scr_conlines; + } + else if (key_dest == key_console) + scr_conlines = vid.conheight/2; // half screen + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) + { + scr_con_current -= scr_conspeed.value*host_frametime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } + else if (scr_conlines > scr_con_current) + { + scr_con_current += scr_conspeed.value*host_frametime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } + + if (clearconsole++ < vid.numpages) + { + } + else if (clearnotify++ < vid.numpages) + { + } + else + con_notifylines = 0; + +} + +/* +================== +SCR_DrawConsole +================== +*/ +void SCR_DrawConsole (void) +{ + if (scr_con_current) + { + scr_copyeverything = 1; + Con_DrawConsole (scr_con_current, true); + clearconsole = 0; + } + + else + { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } + +} + + +/* +============================================================================== + + SCREEN SHOTS + +============================================================================== +*/ + +typedef struct _TargaHeader { + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; +} TargaHeader; + + +/* +================== +SCR_ScreenShot_f +================== +*/ +void SCR_ScreenShot_f (void) +{ + byte *buffer; + char pcxname[80]; + char checkname[MAX_OSPATH]; + int i, c, temp; +// +// find a file name to save it to +// + strcpy(pcxname,"quake00.tga"); + + for (i=0 ; i<=99 ; i++) + { + pcxname[5] = i/10 + '0'; + pcxname[6] = i%10 + '0'; + sprintf (checkname, "%s/%s", com_gamedir, pcxname); + if (Sys_FileTime(checkname) == -1) + break; // file doesn't exist + } + if (i==100) + { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); + return; + } + + + buffer = malloc(glwidth*glheight*3 + 18); + memset (buffer, 0, 18); + buffer[2] = 2; // uncompressed type + buffer[12] = glwidth&255; + buffer[13] = glwidth>>8; + buffer[14] = glheight&255; + buffer[15] = glheight>>8; + buffer[16] = 24; // pixel size + + // ELUTODO glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); + + // swap rgb to bgr + c = 18+glwidth*glheight*3; + for (i=18 ; i 0) { + // left + Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines); + // right + Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - sb_lines); + } + if (r_refdef.vrect.y > 0) { + // top + Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); + // bottom + Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - sb_lines - + (r_refdef.vrect.height + r_refdef.vrect.y)); + } + */ +} + +int GetWeaponZoomAmmount (void) +{ + switch (cl.stats[STAT_ACTIVEWEAPON]) + { + case W_COLT: + return 10; + break; + case W_SPRING: + case W_PULVERIZER: + case W_KAR: + case W_ARMAGEDDON: + return 25; + break; + case W_KAR_SCOPE: + case W_HEADCRACKER: + return 47; + break; + case W_THOMPSON: + case W_GIBS: + return 10; + break; + case W_TRENCH: + case W_GUT: + return 10; + break; + case W_357: + case W_KILLU: + return 5; + break; + case W_MG: + case W_BARRACUDA: + return 15; + break; + case W_DB: + case W_BORE: + case W_SAWNOFF: + return 10; + break; + case W_M1A1: + case W_WIDDER: + return 20; + break; + case W_BAR: + case W_WIDOW: + return 30; + break; + case W_FG: + case W_IMPELLER: + return 30; + break; + case W_GEWEHR: + case W_COMPRESSOR: + return 25; + break; + case W_PPSH: + case W_REAPER: + return 10; + break; + case W_MP40: + case W_AFTERBURNER: + return 10; + break; + case W_MP5: + case W_KOLLIDER: + return 10; + break; + case W_STG: + case W_SPATZ: + return 20; + break; + case W_M1: + case W_M1000: + return 25; + break; + case W_BROWNING: + case W_ACCELERATOR: + return 15; + break; + case W_PTRS: + case W_PENETRATOR: + return 50; + break; + case W_TYPE: + case W_SAMURAI: + return 10; + break; + case W_RAY: + case W_PORTER: + return 5; + break; + default: + return 5; + break; + } +} + +/* +================== +SCR_UpdateScreen + +This is called every frame, and can also be called explicitly to flush +text to the screen. + +WARNING: be very careful calling this from elsewhere, because the refresh +needs almost the entire 256k of stack space! +================== +*/ +void Draw_LoadingFill(void); +void Draw_Crosshair (void); +float zoomin_time; +int original_fov; +int original_view_fov; +void SCR_UpdateScreen (void) +{ + if (block_drawing) + return; + + vid.numpages = 2 + gl_triplebuffer.value; + + scr_copytop = 0; + scr_copyeverything = 0; + + if (scr_disabled_for_loading) + { + if (realtime - scr_disabled_time > 60) + { + scr_disabled_for_loading = false; + Con_Printf ("load failed.\n"); + } + else + return; + } + + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + + GL_BeginRendering (&glx, &gly, &glwidth, &glheight); + + if (cl.stats[STAT_ZOOM] == 1) + { + if(!original_fov) { + original_fov = scr_fov.value; + original_view_fov = scr_fov_viewmodel.value; + } + + if(scr_fov.value > (GetWeaponZoomAmmount() + 1))//+1 for accounting for floating point inaccurraces + { + scr_fov.value += ((original_fov - GetWeaponZoomAmmount()) - scr_fov.value) * 0.25; + scr_fov_viewmodel.value += ((original_view_fov - GetWeaponZoomAmmount()) - scr_fov_viewmodel.value) * 0.25; + Cvar_SetValue("fov",scr_fov.value); + Cvar_SetValue("r_viewmodel_fov", scr_fov_viewmodel.value); + } + } + else if (cl.stats[STAT_ZOOM] == 2) + { + Cvar_SetValue ("fov", 30); + Cvar_SetValue ("r_viewmodel_fov", 30); + zoomin_time = 0; + } + else if (cl.stats[STAT_ZOOM] == 0 && original_fov != 0) + { + if(scr_fov.value < (original_fov + 1))//+1 for accounting for floating point inaccuracies + { + scr_fov.value += (original_fov - scr_fov.value) * 0.25; + scr_fov_viewmodel.value += (original_view_fov - scr_fov_viewmodel.value) * 0.25; + Cvar_SetValue("fov",scr_fov.value); + Cvar_SetValue("r_viewmodel_fov", scr_fov_viewmodel.value); + } + else + { + original_fov = 0; + original_view_fov = 0; + } + } + + // + // determine size of refresh window + // + if (oldfov != scr_fov.value) + { + oldfov = scr_fov.value; + vid.recalc_refdef = true; + } + + if (oldscreensize != scr_viewsize.value) + { + oldscreensize = scr_viewsize.value; + vid.recalc_refdef = true; + } + + if (vid.recalc_refdef) + { + SCR_CalcRefdef (); + VID_ConModeUpdate(); + } + +// +// do 3D refresh drawing, and then update the screen +// + SCR_SetUpToDrawConsole (); + + V_RenderView (); + + Fog_DisableGFog (); + + GL_Set2D (); + + Draw_Crosshair (); + + // + // draw any areas not covered by the refresh + // + //SCR_TileClear (); + /* + if (crosshair.value) { + Draw_Character ((scr_vrect.x + scr_vrect.width/2 + cl_crossx.value) * vid.conwidth/vid.width, + (scr_vrect.y + scr_vrect.height/2 + cl_crossy.value) * vid.conheight/vid.height, '+'); + } + */ + + //muff - to show FPS on screen + SCR_DrawFPS (); + SCR_DrawPause (); + SCR_CheckDrawCenterString (); + SCR_CheckDrawUseString (); + HUD_Draw (); + //Sbar_Draw (); + SCR_DrawConsole (); + M_Draw (); + + if(scr_loadscreen.value) { + SCR_DrawLoadScreen(); + } + + Draw_LoadingFill(); + + V_UpdatePalette (); + + GL_EndRendering (); +} diff --git a/source/wii/gx/gx_textures.c b/source/wii/gx/gx_textures.c new file mode 100644 index 0000000..76394c6 --- /dev/null +++ b/source/wii/gx/gx_textures.c @@ -0,0 +1,1221 @@ +/* +Copyright (C) 2008 Eluan Costa Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include +#include +#include + +#include "../../quakedef.h" + +#include +#include + +// ELUTODO: mipmap + +cvar_t gl_max_size = {"gl_max_size", "1024"}; +cvar_t vid_retromode = {"vid_retromode", "1", false}; + +gltexture_t gltextures[MAX_GLTEXTURES]; +int numgltextures; + +heap_cntrl texture_heap; +void *texture_heap_ptr; +u32 texture_heap_size; + +void R_InitTextureHeap (void) +{ + u32 level, size; + + _CPU_ISR_Disable(level); + texture_heap_ptr = SYS_GetArena2Lo(); + texture_heap_size = 12 * 1024 * 1024; + if ((u32)texture_heap_ptr + texture_heap_size > (u32)SYS_GetArena2Hi()) + { + _CPU_ISR_Restore(level); + Sys_Error("texture_heap + texture_heap_size > (u32)SYS_GetArena2Hi()"); + } + else + { + SYS_SetArena2Lo(texture_heap_ptr + texture_heap_size); + _CPU_ISR_Restore(level); + } + + memset(texture_heap_ptr, 0, texture_heap_size); + + size = __lwp_heap_init(&texture_heap, texture_heap_ptr, texture_heap_size, PPC_CACHE_ALIGNMENT); + + Con_Printf("Allocated %dM texture heap.\n", size / (1024 * 1024)); + +} + +/* +================== +R_InitTextures +================== +*/ +void R_InitTextures (void) +{ + int x,y, m; + byte *dest; + + R_InitTextureHeap(); + + Cvar_RegisterVariable (&gl_max_size); + + numgltextures = 0; + +// create a simple checkerboard texture for the default + r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); + + r_notexture_mip->width = r_notexture_mip->height = 16; + r_notexture_mip->offsets[0] = sizeof(texture_t); + r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; + r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; + r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; + + for (m=0 ; m<4 ; m++) + { + dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; + for (y=0 ; y< (16>>m) ; y++) + for (x=0 ; x< (16>>m) ; x++) + { + if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) + *dest++ = 0; + else + *dest++ = 0xff; + } + } + +} + +void GL_Bind0 (int texnum) +{ + if (currenttexture0 == texnum) + return; + + if (!gltextures[texnum].used) + Sys_Error("Tried to bind a inactive texture0."); + + currenttexture0 = texnum; + GX_LoadTexObj(&(gltextures[texnum].gx_tex), GX_TEXMAP0); +} + +void GX_SetMinMag (int minfilt, int magfilt) +{ + if(gltextures[currenttexture0].data != NULL) + { + GX_InitTexObjFilterMode(&gltextures[currenttexture0].gx_tex, minfilt, magfilt); + }; +} + +void GX_SetMaxAniso (int aniso) +{ + if(gltextures[currenttexture0].data != NULL) + { + GX_InitTexObjMaxAniso(&gltextures[currenttexture0].gx_tex, aniso); + }; +} + +void QGX_ZMode(qboolean state) +{ + if (state) + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + else + GX_SetZMode(GX_FALSE, GX_LEQUAL, GX_TRUE); +} + +void QGX_Alpha(qboolean state) +{ + if (state) + GX_SetAlphaCompare(GX_GREATER,0,GX_AOP_AND,GX_ALWAYS,0); + else + GX_SetAlphaCompare(GX_ALWAYS,0,GX_AOP_AND,GX_ALWAYS,0); + +} + +void QGX_Blend(qboolean state) +{ + if (state) + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + else + GX_SetBlendMode(GX_BM_NONE,GX_BL_ONE,GX_BL_ZERO,GX_LO_COPY); +} + +void QGX_BlendMap(qboolean state) +{ + if (state) + GX_SetBlendMode(GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_SRCCLR, GX_LO_CLEAR); + else + GX_SetBlendMode(GX_BM_NONE,GX_BL_ONE,GX_BL_ZERO,GX_LO_COPY); +} + +//==================================================================== + +/* +================ +GL_FindTexture +================ +*/ +int GL_FindTexture (char *identifier) +{ + int i; + gltexture_t *glt; + + for (i=0, glt=gltextures ; iidentifier)) + return gltextures[i].texnum; + } + + return -1; +} + +/* +================ +GL_ResampleTexture +================ +*/ +void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight) +{ + int i, j; + unsigned *inrow; + unsigned frac, fracstep; + + fracstep = inwidth*0x10000/outwidth; + for (i=0 ; i> 1; + for (j=0 ; j>16]; + frac += fracstep; + out[j+1] = inrow[frac>>16]; + frac += fracstep; + out[j+2] = inrow[frac>>16]; + frac += fracstep; + out[j+3] = inrow[frac>>16]; + frac += fracstep; + } + } +} + +int GX_RGBA_To_RGB5A3(u32 srccolor, qboolean flip) +{ + u16 color; + + u32 r, g, b, a; + if (flip){ + r = srccolor & 0xFF; + srccolor >>= 8; + g = srccolor & 0xFF; + srccolor >>= 8; + b = srccolor & 0xFF; + srccolor >>= 8; + a = srccolor & 0xFF; + } else { + a = srccolor & 0xFF; + srccolor >>= 8; + b = srccolor & 0xFF; + srccolor >>= 8; + g = srccolor & 0xFF; + srccolor >>= 8; + r = srccolor & 0xFF; + } + + if (a > 0xe0) + { + r = r >> 3; + g = g >> 3; + b = b >> 3; + + color = (r << 10) | (g << 5) | b; + color |= 0x8000; + } + else + { + r = r >> 4; + g = g >> 4; + b = b >> 4; + a = a >> 5; + + color = (a << 12) | (r << 8) | (g << 4) | b; + } + + return color; +} + +int GX_LinearToTiled(int x, int y, int width) +{ + int x0, x1, y0, y1; + int offset; + + x0 = x & 3; + x1 = x >> 2; + y0 = y & 3; + y1 = y >> 2; + offset = x0 + 4 * y0 + 16 * x1 + 4 * width * y1; + + return offset; +} + + +/* +=============== +GL_CopyRGB5A3 + +Converts from linear to tiled during copy +=============== +*/ +void GX_CopyRGB5A3(u16 *dest, u32 *src, int x1, int y1, int x2, int y2, int src_width) +{ + int i, j; + + for (i = y1; i < y2; i++) + for (j = x1; j < x2; j++) + dest[GX_LinearToTiled(j, i, src_width)] = src[j + i * src_width]; +} + +/* +=============== +GL_CopyRGB5A3 + +Converts from linear RGBA8 to tiled RGB5A3 during copy +=============== +*/ +void GX_CopyRGBA8_To_RGB5A3(u16 *dest, u32 *src, int x1, int y1, int x2, int y2, int src_width, qboolean flip) +{ + int i, j; + + for (i = y1; i < y2; i++) + for (j = x1; j < x2; j++) + dest[GX_LinearToTiled(j, i, src_width)] = GX_RGBA_To_RGB5A3(src[j + i * src_width], flip); +} + +/* +================ +GL_MipMap + +Operates in place, quartering the size of the texture +================ +*/ +void GX_MipMap (byte *in, int width, int height) +{ + int i, j; + byte *out; + + width <<=2; + height >>= 1; + out = in; + for (i=0 ; i>2; + out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2; + out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2; + out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2; + } + } +} + +// Given w,h,level,and bpp, returns the offset to the mipmap at level "level" +static int _calc_mipmap_offset(int level, int w, int h, int b) { + int size = 0; + while (level > 0) { + int mipsize = ((w*h)*b); + if ((mipsize % 32) != 0) + mipsize += (32-(mipsize % 32)); // Alignment + size += mipsize; + if (w != 1) w = w/2; + if (h != 1) h = h/2; + level--; + } + return size; +} + +// FIXME, temporary +static unsigned scaled[640*480]; +static unsigned trans[640*480]; + +/* +=============== +GL_Upload32 +=============== +*/ +void GL_Upload32 (gltexture_t *destination, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean flipRGBA) +{ + int s; + int scaled_width, scaled_height; + int sw, sh; + u32 texbuffs; + u32 texbuffs_mip; + int max_mip_level; + //heap_iblock info; + + for (scaled_width = 1 << 5 ; scaled_width < width ; scaled_width<<=1) + ; + for (scaled_height = 1 << 5 ; scaled_height < height ; scaled_height<<=1) + ; + + if (scaled_width > gl_max_size.value) + scaled_width = gl_max_size.value; + if (scaled_height > gl_max_size.value) + scaled_height = gl_max_size.value; + + if (scaled_width * scaled_height > sizeof(scaled)/4) + Sys_Error ("GL_Upload32: too big"); + + if (scaled_width != width || scaled_height != height) + { + GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); + + } else { + memcpy(scaled, data, scaled_width * scaled_height * 4); + } + + // start at mip level 0 + max_mip_level = 0; + if (mipmap) { + sw = scaled_width; + sh = scaled_height; + + while (sw > 4 && sh > 4) + { + sw >>= 1; + sh >>= 1; + max_mip_level++; + }; + + if (max_mip_level != 0) { + // account for memory offset + max_mip_level += 1; + } + } + + //get exact buffer size of memory aligned on a 32byte boundery + texbuffs = GX_GetTexBufferSize (scaled_width, scaled_height, GX_TF_RGB5A3, mipmap ? GX_TRUE : GX_FALSE, max_mip_level); + destination->data = __lwp_heap_allocate(&texture_heap, texbuffs/*scaled_width * scaled_height * 2*/); + //__lwp_heap_getinfo(&texture_heap, &info); + //Con_Printf ("tex buff size %d\n", texbuffs); + //Con_Printf("Used Heap: %dM\n", info.used_size / (1024*1024)); + + if (!destination->data) + Sys_Error("GL_Upload32: Out of memory."); + + s = scaled_width * scaled_height; + if (s & 31) + Sys_Error ("GL_Upload32: s&31"); + + if ((int)destination->data & 31) + Sys_Error ("GL_Upload32: destination->data&31"); + + destination->scaled_width = scaled_width; + destination->scaled_height = scaled_height; + + // + // sBTODO finish mipmap implementation + // + + if (mipmap == true) { + + int mip_level; + int sw, sh; + unsigned mipmaptex[640*480]; + + texbuffs_mip = GX_GetTexBufferSize (scaled_width, scaled_height, GX_TF_RGB5A3, GX_TRUE, max_mip_level); + + // this should never happen currently however, + // I plan on circumventing reloading textures + // which are already loaded, and this check will be neccesary + // once that happens + if (texbuffs < texbuffs_mip) { + // copy the texture mem to a temporary buffer + unsigned char * tempbuf = malloc(texbuffs); + memcpy(tempbuf,destination->data,texbuffs); + + // free the used heap memory + if (!__lwp_heap_free(&texture_heap, destination->data)) + Sys_Error ("Failed to free texture mem for mipmap"); + + // reallocate in a section of memory big enough for mipmaps and copy in the OG texture buffer + destination->data = __lwp_heap_allocate (&texture_heap, texbuffs_mip); + memcpy(destination->data,tempbuf,texbuffs); + free (tempbuf); + } + + // copy texture to dst addr and convert to RGB5A3 + GX_CopyRGBA8_To_RGB5A3((u16 *)destination->data, scaled, 0, 0, scaled_width, scaled_height, scaled_width, flipRGBA); + // copy texture to new buffer + memcpy((void *)mipmaptex, scaled, scaled_width * scaled_height * 4); + + sw = scaled_width; + sh = scaled_height; + mip_level = 1; + + //Con_Printf ("mip max: %i\n", mip_level); + //Con_Printf ("texbuffs: %d\n", texbuffs); + //Con_Printf ("texbuffs_mip: %d\n", texbuffs_mip); + + while (sw > 4 && sh > 4 && mip_level < 10) { + // Operates in place, quartering the size of the texture + GX_MipMap ((byte *)mipmaptex, sw, sh); + + sw >>= 1; + sh >>= 1; + if (sw < 4) + sw = 4; + if (sh < 4) + sh = 4; + + //Con_Printf ("gen mipmaps: %i\n", mip_level); + + // Calculate the offset and address of the mipmap + int offset = _calc_mipmap_offset(mip_level, scaled_width, scaled_height, 2); + unsigned char* dst_addr = (unsigned char*)destination->data; + dst_addr += offset; + + //Con_Printf ("mipmap mem offset: %i\n", offset); + + mip_level++; + + GX_CopyRGBA8_To_RGB5A3((u16 *)dst_addr, (u32 *)mipmaptex, 0, 0, sw, sh, sw, flipRGBA); + DCFlushRange(dst_addr, sw * sh * 2); + GX_InitTexObj(&destination->gx_tex, dst_addr, sw, sh, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, GX_TRUE); + GX_InitTexObjLOD(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN, mip_level, max_mip_level, 0, GX_ENABLE, GX_ENABLE, GX_ANISO_2); + } + + DCFlushRange(destination->data, texbuffs_mip/*scaled_width * scaled_height * 2*/); + GX_InvalidateTexAll(); + GX_InitTexObj(&destination->gx_tex, destination->data, scaled_width, scaled_height, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, GX_TRUE); + GX_InitTexObjLOD(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN, 0, max_mip_level, 0, GX_ENABLE, GX_ENABLE, GX_ANISO_2); + //GX_LoadTexObj((&destination->gx_tex), GX_TEXMAP0); + + if (vid_retromode.value == 1) { + GX_InitTexObjFilterMode(&destination->gx_tex, GX_NEAR_MIP_NEAR, GX_NEAR_MIP_NEAR); + } else { + GX_InitTexObjFilterMode(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN); + } + + } else { + GX_CopyRGBA8_To_RGB5A3((u16 *)destination->data, scaled, 0, 0, scaled_width, scaled_height, scaled_width, flipRGBA); + DCFlushRange(destination->data, texbuffs/*scaled_width * scaled_height * 2*/); + GX_InvalidateTexAll(); + GX_InitTexObj(&destination->gx_tex, destination->data, scaled_width, scaled_height, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, /*mipmap ? GX_TRUE :*/ GX_FALSE); + // do not init mipmaps for lightmaps + if (destination->type != 1) { + GX_InitTexObjLOD(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN, 0, max_mip_level, 0, GX_ENABLE, GX_ENABLE, GX_ANISO_2); + } + } +} + +/* +=============== +GL_Upload8 +=============== +*/ +void GL_Upload8 (gltexture_t *destination, byte *data, int width, int height, qboolean mipmap, qboolean alpha) +{ + int i, s; + qboolean noalpha; + int p; + + s = width*height; + // if there are no transparent pixels, make it a 3 component + // texture even if it was specified as otherwise + + if (alpha) + { + noalpha = true; + for (i=0 ; i 1) in_gamma = 1.0; + } else { + in_gamma = 1; + } + + if (in_gamma != 1) { + for (i=0 ; i<256 ; i++) { + inf = MIN(255 * pow((i + 0.5) / 255.5, in_gamma) + 0.5, 255); + vid_gamma_table[i] = inf; + } + } else { + for (i=0 ; i<256 ; i++) + vid_gamma_table[i] = i; + } + +} + +/* +================ +GL_LoadTexture +================ +*/ + +//Diabolickal TGA Begin + +int lhcsumtable[256]; +int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, qboolean keep, int bytesperpixel) +{ + int i, s, lhcsum; + gltexture_t *glt; + // occurances. well this isn't exactly a checksum, it's better than that but + // not following any standards. + lhcsum = 0; + s = width*height*bytesperpixel; + + for (i = 0;i < 256;i++) lhcsumtable[i] = i + 1; + for (i = 0;i < s;i++) lhcsum += (lhcsumtable[data[i] & 255]++); + + // see if the texture is allready present + if (identifier[0]) + { + for (i=0, glt=gltextures ; iused) + { + // ELUTODO: causes problems if we compare to a texture with NO name? + // sBTODO we definitely have issues with identifier strings. will investigate later.. + if (!strcmp (identifier, glt->identifier)) + { + if (width != glt->width || height != glt->height) + { + Con_Printf ("GL_LoadTexture: cache mismatch, reloading"); + if (!__lwp_heap_free(&texture_heap, glt->data)) + Sys_Error("GL_ClearTextureCache: Error freeing data."); + goto reload; // best way to do it + } + return glt->texnum; + } + } + } + } + + for (i = 0, glt = gltextures; i < numgltextures; i++, glt++) + { + if (!glt->used) + break; + } + + if (i == MAX_GLTEXTURES) + Sys_Error ("GL_LoadTexture: numgltextures == MAX_GLTEXTURES\n"); + +reload: + strcpy (glt->identifier, identifier); + + gltextures[glt->texnum].checksum = lhcsum; + gltextures[glt->texnum].lhcsum = lhcsum; + + glt->texnum = i; + glt->width = width; + glt->height = height; + glt->mipmap = mipmap; + glt->type = 0; + glt->keep = keep; + glt->used = true; + + GL_Bind0 (glt->texnum); + + //Con_Printf ("tex %s\n", identifier); + if (bytesperpixel == 1) { + GL_Upload8 (glt, data, width, height, mipmap, alpha); + } + else if (bytesperpixel == 4) { + GL_Upload32 (glt, (unsigned*)data, width, height, mipmap, alpha, false); + } + else { + Sys_Error("GL_LoadTexture: unknown bytesperpixel\n"); + } + + if (glt->texnum == numgltextures) + numgltextures++; + + return glt->texnum; +} + +/* +====================== +GL_LoadLightmapTexture +====================== +*/ +int GL_LoadLightmapTexture (char *identifier, int width, int height, byte *data) +{ + gltexture_t *glt; + + // They need to be allocated sequentially + if (numgltextures == MAX_GLTEXTURES) + Sys_Error ("GL_LoadLightmapTexture: numgltextures == MAX_GLTEXTURES\n"); + + glt = &gltextures[numgltextures]; + //Con_Printf("gltexnum: %i", numgltextures); + strcpy (glt->identifier, identifier); + //Con_Printf("Identifier: %s", identifier); + glt->texnum = numgltextures; + glt->width = width; + glt->height = height; + glt->mipmap = false; // ELUTODO + glt->type = 1; + glt->keep = false; + glt->used = true; + + GL_Upload32 (glt, (unsigned *)data, width, height, false /*mipmap?*/, false, false); + + if (width != glt->scaled_width || height != glt->scaled_height) + Sys_Error("GL_LoadLightmapTexture: Tried to scale lightmap\n"); + + numgltextures++; + + return glt->texnum; +} + +/* +================================ +GL_UpdateLightmapTextureRegion32 +================================ +*/ +void GL_UpdateLightmapTextureRegion32 (gltexture_t *destination, unsigned *data, int width, int height, int xoffset, int yoffset, qboolean mipmap, qboolean alpha) +{ + int x, y; + int realwidth = width + xoffset; + int realheight = height + yoffset; + u16 *dest = (u16 *)destination->data; + + // ELUTODO: mipmaps + // ELUTODO samples = alpha ? GX_TF_RGBA8 : GX_TF_RGBA8; + + if ((int)destination->data & 31) + Sys_Error ("GL_Update32: destination->data&31"); + + for (y = yoffset; y < realheight; y++) + for (x = xoffset; x < realwidth; x++) + dest[GX_LinearToTiled(x, y, width)] = GX_RGBA_To_RGB5A3(data[x + y * realwidth], false); + + DCFlushRange(destination->data, destination->scaled_width * destination->scaled_height * 2/*sizeof(data)*/); + GX_InvalidateTexAll(); +} + +/* +============================== +GL_UpdateLightmapTextureRegion +============================== +*/ +void GL_UpdateLightmapTextureRegion (int pic_id, int width, int height, int xoffset, int yoffset, byte *data) +{ + gltexture_t *destination; + + // see if the texture is allready present + destination = &gltextures[pic_id]; + + GL_UpdateLightmapTextureRegion32 (destination, (unsigned *)data, width, height, xoffset, yoffset, false, true); +} + +/* +================ +GL_LoadPicTexture +================ +*/ +int GL_LoadPicTexture (qpic_t *pic, char *name) +{ + return GL_LoadTexture (name, pic->width, pic->height, pic->data, false, true, true, 1); +} + +// ELUTODO: clean the disable/enable multitexture calls around the engine + +void GL_DisableMultitexture(void) +{ + // ELUTODO: we shouldn't need the color atributes for the vertices... + + // setup the vertex descriptor + // tells the flipper to expect direct data + GX_ClearVtxDesc(); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + + GX_SetNumTexGens(1); + GX_SetNumTevStages(1); +} + +void GL_EnableMultitexture(void) +{ + // ELUTODO: we shouldn't need the color atributes for the vertices... + + // setup the vertex descriptor + // tells the flipper to expect direct data + GX_ClearVtxDesc(); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GX_SetVtxDesc(GX_VA_TEX1, GX_DIRECT); + + GX_SetNumTexGens(2); + GX_SetNumTevStages(2); +} + +void GL_ClearTextureCache(void) +{ + int i; + int oldnumgltextures = numgltextures; + void *newdata; + u32 texbuffs; + qboolean mipmap; + int mip_level; + int sw, sh; + + numgltextures = 0; + + for (i = 0; i < oldnumgltextures; i++) + { + if (gltextures[i].used) + { + if (gltextures[i].keep) + { + mipmap = gltextures[i].mipmap; + + mip_level = 1; + + if (mipmap) { + sw = gltextures[i].scaled_width; + sh = gltextures[i].scaled_height; + + while (sw > 4 && sh > 4) + { + sw >>= 1; + sh >>= 1; + mip_level++; + }; + } + + texbuffs = GX_GetTexBufferSize (gltextures[i].scaled_width, gltextures[i].scaled_height, GX_TF_RGB5A3, mipmap ? GX_TRUE : GX_FALSE, mip_level); + + numgltextures = i + 1; + + newdata = __lwp_heap_allocate(&texture_heap, texbuffs/*gltextures[i].scaled_width * gltextures[i].scaled_height * sizeof(data)*/); + if (!newdata) + Sys_Error("GL_ClearTextureCache: Out of memory."); + + // ELUTODO Pseudo-defragmentation that helps a bit :) + memcpy(newdata, gltextures[i].data, texbuffs/*gltextures[i].scaled_width * gltextures[i].scaled_height * sizeof(data)*/); + + if (!__lwp_heap_free(&texture_heap, gltextures[i].data)) + Sys_Error("GL_ClearTextureCache: Error freeing data."); + + gltextures[i].data = newdata; + GX_InitTexObj(&gltextures[i].gx_tex, gltextures[i].data, gltextures[i].scaled_width, gltextures[i].scaled_height, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, mipmap ? GX_TRUE : GX_FALSE); + + DCFlushRange(gltextures[i].data, texbuffs/*gltextures[i].scaled_width * gltextures[i].scaled_height * sizeof(data)*/); + } + else + { + gltextures[i].used = false; + if (!__lwp_heap_free(&texture_heap, gltextures[i].data)) + Sys_Error("GL_ClearTextureCache: Error freeing data."); + } + } + } + + GX_InvalidateTexAll(); +} +/* +// +// +// +// +// +// +*/ +int image_width; +int image_height; +/* +================================================================= + +PCX LOADING + +================================================================= +*/ +typedef struct +{ + char manufacturer; + char version; + char encoding; + char bits_per_pixel; + unsigned short xmin,ymin,xmax,ymax; + unsigned short hres,vres; + unsigned char palette[48]; + char reserved; + char color_planes; + unsigned short bytes_per_line; + unsigned short palette_type; + char filler[58]; + unsigned char data; // unbounded +} pcx_t; +/* +============ +LoadPCX +============ +*/ +byte* LoadPCX (char* filename, int matchwidth, int matchheight) +{ + pcx_t *pcx; + byte *palette; + byte *out; + byte *pix, *image_rgba; + int x, y; + int dataByte, runLength; + byte *pcx_data; + byte *pic; + +// +// parse the PCX file +// + + // Load the raw data into memory, then store it + pcx_data = COM_LoadFile(filename, 5); + + pcx = (pcx_t *)pcx_data; + + pcx->xmin = LittleShort(pcx->xmin); + pcx->ymin = LittleShort(pcx->ymin); + pcx->xmax = LittleShort(pcx->xmax); + pcx->ymax = LittleShort(pcx->ymax); + pcx->hres = LittleShort(pcx->hres); + pcx->vres = LittleShort(pcx->vres); + pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); + pcx->palette_type = LittleShort(pcx->palette_type); + + if (pcx->manufacturer != 0x0a + || pcx->version != 5 + || pcx->encoding != 1 + || pcx->bits_per_pixel != 8 + || pcx->xmax >= 640 + || pcx->ymax >= 480) + { + Con_Printf ("Bad pcx file %i\n"); + return 0; + } + + image_rgba = &pcx->data; + + out = malloc ((pcx->ymax+1)*(pcx->xmax+1)*4); + pic = out; + pix = out; + + if (matchwidth && (pcx->xmax+1) != matchwidth) + return 0; + if (matchheight && (pcx->ymax+1) != matchheight) + return 0; + + palette = malloc(768); + memcpy (palette, (byte *)pcx + com_filesize - 768, 768); + + for (y=0 ; y<=pcx->ymax ; y++) + { + pix = out + 4*y*(pcx->xmax+1); + + for (x=0 ; x<=pcx->xmax ; ) + { + dataByte = *image_rgba++; + + if((dataByte & 0xC0) == 0xC0) + { + runLength = dataByte & 0x3F; + dataByte = *image_rgba++; + } + else + runLength = 1; + + while(runLength-- > 0) { + pix[0] = palette[dataByte*3+0]; + pix[1] = palette[dataByte*3+1]; + pix[2] = palette[dataByte*3+2]; + pix[3] = 255; + pix += 4; + x++; + } + } + } + + image_width = pcx->xmax+1; + image_height = pcx->ymax+1; + + free (palette); + free (pcx_data); + return pic; +} + +/*small function to read files with stb_image - single-file image loader library. +** downloaded from: https://raw.githubusercontent.com/nothings/stb/master/stb_image.h +** only use jpeg+png formats, because tbh there's not much need for the others. +** */ +#define STB_IMAGE_IMPLEMENTATION +#define STBI_FAILURE_USERMSG +#define STBI_ONLY_JPEG +#define STBI_ONLY_PNG +#define STBI_ONLY_TGA +#define STBI_ONLY_PIC +#include "../../stb_image.h" +byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight, int reverseRGBA) +{ + int bpp; + int width, height; + + byte* rgba_data; + + // Load the raw data into memory, then store it + rgba_data = COM_LoadFile(filename, 5); + + if (rgba_data == NULL) { + Con_Printf("NULL: %s\n", filename); + return 0; + } + + byte *image = stbi_load_from_memory(rgba_data, com_filesize, &width, &height, &bpp, 4); + + if(image == NULL) { + Con_Printf("%s\n", stbi_failure_reason()); + return 0; + } + + //set image width/height for texture uploads + image_width = width; + image_height = height; + + free(rgba_data); + + return image; +} + +int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean keep) +{ + int f = 0; + int texnum; + char basename[128], name[128]; + char *texname = malloc(32); + byte *data; + byte *c; + + if (complain == false) + COM_StripExtension(filename, basename); // strip the extension to allow TGA + else + strcpy(basename, filename); + + c = (byte*)basename; + while (*c) + { + if (*c == '*') + *c = '+'; + c++; + } + + int len = strlen(basename); + texname = basename + len - 20; + + //Try PCX + sprintf (name, "%s.pcx", basename); + COM_FOpenFile (name, &f); + if (f > 0) { + COM_CloseFile (f); + data = LoadPCX (name, matchwidth, matchheight); + if (data == 0) { + Con_Printf("PCX: can't load %s\n", name); + return 0; + } + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, true, true, 4); + free(data); + return texnum; + } + //Try TGA + sprintf (name, "%s.tga", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 4); + if (data == 0) { + Con_Printf("TGA: can't load %s\n", name); + return 0; + } + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, true, keep, 4); + free(data); + return texnum; + } + //Try PNG + sprintf (name, "%s.png", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 1); + if (data == 0) { + Con_Printf("PNG: can't load %s\n", name); + return 0; + } + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, true, keep, 4); + free(data); + return texnum; + } + //Try JPEG + sprintf (name, "%s.jpeg", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 1); + if (data == 0) { + Con_Printf("JPEG: can't load %s\n", name); + return 0; + } + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, true, keep, 4); + free(data); + return texnum; + } + sprintf (name, "%s.jpg", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 1); + if (data == 0) { + Con_Printf("JPG: can't load %s\n", name); + return 0; + } + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, true, keep, 4); + free(data); + return texnum; + } + return 0; +} + +extern char skybox_name[32]; +extern char skytexname[32]; +int loadskyboximage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap) +{ + int f = 0; + int texnum; + char basename[128], name[128]; + char *texname = malloc(32); + + int image_size = 128 * 128; + + byte* data = (byte*)malloc(image_size * 4); + byte *c; + + if (complain == false) + COM_StripExtension(filename, basename); // strip the extension to allow TGA + else + strcpy(basename, filename); + + c = (byte*)basename; + while (*c) + { + if (*c == '*') + *c = '+'; + c++; + } + + if (strcmp(skybox_name, "")) + return 0; +//Try PCX + + int len = strlen(basename); + texname = basename + len - 20; + + sprintf (name, "%s.pcx", basename); + COM_FOpenFile (name, &f); + if (f > 0) { + COM_CloseFile (f); + data = LoadPCX (name, matchwidth, matchheight); + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, true, true, 4); + free(data); + return texnum; + } + //Try TGA + sprintf (name, "%s.tga", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 4); + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, false, true, 4); + free(data); + return texnum; + } + //Try PNG + sprintf (name, "%s.png", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 1); + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, false, true, 4); + free(data); + return texnum; + } + //Try JPEG + sprintf (name, "%s.jpeg", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 1); + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, false, true, 4); + free(data); + return texnum; + } + sprintf (name, "%s.jpg", basename); + COM_FOpenFile (name, &f); + if (f > 0){ + COM_CloseFile (f); + data = loadimagepixels (name, complain, matchwidth, matchheight, 1); + texnum = GL_LoadTexture (texname, image_width, image_height, data, false, false, true, 4); + free(data); + return texnum; + } + return 0; +} diff --git a/source/wii/gx/gx_warp.c b/source/wii/gx/gx_warp.c new file mode 100644 index 0000000..f422c58 --- /dev/null +++ b/source/wii/gx/gx_warp.c @@ -0,0 +1,784 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// gl_warp.c -- sky and water polygons + +#include "../../quakedef.h" + +extern model_t *loadmodel; + +extern int skytexturenum; + +int solidskytexture; +int alphaskytexture; + +gltexture_t *skybox_textures[6]; + +float speedscale; // for top sky and bottom sky + +int skyimage[5]; // Where sky images are stored +char skybox_name[32] = ""; //name of current skybox, or "" if no skybox +// cut off down for half skybox +char *suf[5] = {"rt", "bk", "lf", "ft", "up" }; + +msurface_t *warpface; + +extern cvar_t gl_subdivide_size; + +void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) +{ + int i, j; + float *v; + + mins[0] = mins[1] = mins[2] = 9999; + maxs[0] = maxs[1] = maxs[2] = -9999; + v = verts; + for (i=0 ; i maxs[j]) + maxs[j] = *v; + } +} + +void SubdividePolygon (int numverts, float *verts) +{ + int i, j, k; + vec3_t mins, maxs; + float m; + float *v; + vec3_t front[64], back[64]; + int f, b; + float dist[64]; + float frac; + glpoly_t *poly; + float s, t; + + if (numverts > 60) + Sys_Error ("numverts = %i", numverts); + + BoundPoly (numverts, verts, mins, maxs); + + for (i=0 ; i<3 ; i++) + { + m = (mins[i] + maxs[i]) * 0.5; + m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5); + if (maxs[i] - m < 8) + continue; + if (m - mins[i] < 8) + continue; + + // cut it + v = verts + i; + for (j=0 ; j= 0) + { + VectorCopy (v, front[f]); + f++; + } + if (dist[j] <= 0) + { + VectorCopy (v, back[b]); + b++; + } + if (dist[j] == 0 || dist[j+1] == 0) + continue; + if ( (dist[j] > 0) != (dist[j+1] > 0) ) + { + // clip point + frac = dist[j] / (dist[j] - dist[j+1]); + for (k=0 ; k<3 ; k++) + front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); + f++; + b++; + } + } + + SubdividePolygon (f, front[0]); + SubdividePolygon (b, back[0]); + return; + } + + poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float)); + poly->next = warpface->polys; + warpface->polys = poly; + poly->numverts = numverts; + for (i=0 ; iverts[i]); + s = DotProduct (verts, warpface->texinfo->vecs[0]); + t = DotProduct (verts, warpface->texinfo->vecs[1]); + poly->verts[i][3] = s; + poly->verts[i][4] = t; + } +} + +/* +================ +GL_SubdivideSurface + +Breaks a polygon up along axial 64 unit +boundaries so that turbulent and sky warps +can be done reasonably. +================ +*/ +void GL_SubdivideSurface (msurface_t *fa) +{ + vec3_t verts[64]; + int numverts; + int i; + int lindex; + float *vec; + + warpface = fa; + + // + // convert edges back to a normal polygon + // + numverts = 0; + for (i=0 ; inumedges ; i++) + { + lindex = loadmodel->surfedges[fa->firstedge + i]; + + if (lindex > 0) + vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; + else + vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; + VectorCopy (vec, verts[numverts]); + numverts++; + } + + SubdividePolygon (numverts, verts[0]); +} + +//========================================================= + + + +// speed up sin calculations - Ed +float turbsin[] = +{ + #include "gx_warp_sin.h" +}; +#define TURBSCALE (256.0 / (2 * M_PI)) + +/* +============= +EmitWaterPolys + +Does a water warp on the pre-fragmented glpoly_t chain +============= +*/ +void EmitWaterPolys (msurface_t *fa) +{ + glpoly_t *p; + float *v; + int i; + float s, t, os, ot; + + QGX_Blend(true); + + for (p=fa->polys ; p ; p=p->next) + { + GX_Begin (GX_TRIANGLEFAN, GX_VTXFMT0, p->numverts); + for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) + { + os = v[3]; + ot = v[4]; + + s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; + s *= (1.0/64); + + t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; + t *= (1.0/64); + + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, r_wateralpha.value * 0xff); // ELUTODO issues with draw order AND shoudn't be enabled if the map doesn't have watervis info + GX_TexCoord2f32(s, t); + } + GX_End (); + } + + QGX_Blend(false); +} + + + + +/* +============= +EmitSkyPolys +============= +*/ +void EmitSkyPolys (msurface_t *fa) +{ + glpoly_t *p; + float *v; + int i; + float s, t; + vec3_t dir; + float length; + + for (p=fa->polys ; p ; p=p->next) + { + GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, p->numverts); + for (i=0,v=p->verts[0] ; inumverts ; i++, v+=VERTEXSIZE) + { + VectorSubtract (v, r_origin, dir); + dir[2] *= 3; // flatten the sphere + + length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; + length = sqrt (length); + length = 6*63/length; + + dir[0] *= length; + dir[1] *= length; + + s = (speedscale + dir[0]) * (1.0/128); + t = (speedscale + dir[1]) * (1.0/128); + + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32(s, t); + } + GX_End (); + } +} + +/* +=============== +EmitBothSkyLayers + +Does a sky warp on the pre-fragmented gxpoly_t chain +This will be called for brushmodels, the world +will have them chained together. +=============== +*/ +void EmitBothSkyLayers (msurface_t *fa) +{ + //GL_DisableMultitexture(); + + GL_Bind0 (solidskytexture); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + speedscale = realtime*8; + speedscale -= (int)speedscale & ~127 ; + + EmitSkyPolys (fa); + + QGX_Blend(true); + GL_Bind0 (alphaskytexture); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + speedscale = realtime*16; + speedscale -= (int)speedscale & ~127 ; + + EmitSkyPolys (fa); + + QGX_Blend(false); +} + +#ifndef QUAKE2 + +/* +================= +R_DrawSkyChain +================= +*/ +void R_DrawSkyChain (msurface_t *s) +{ + msurface_t *fa; + + //GL_DisableMultitexture(); + + GL_Bind0(solidskytexture); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + speedscale = realtime*8; + speedscale -= (int)speedscale & ~127 ; + + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + QGX_Blend(true); + GL_Bind0 (alphaskytexture); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + speedscale = realtime*16; + speedscale -= (int)speedscale & ~127 ; + + for (fa=s ; fa ; fa=fa->texturechain) + EmitSkyPolys (fa); + + QGX_Blend(false); +} + +#endif + +/* +================================================================= + + Quake 2 environment sky + +================================================================= +*/ +#define SKY_TEX 2000 + + +#if 1 +/* +================== +Sky_LoadSkyBox +================== +*/ +//char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; +char skytexname[32]; +void Sky_LoadSkyBox(char* name) +{ + if (strcmp(skybox_name, name) == 0) + return; //no change + + //turn off skybox if sky is set to "" + if (name[0] == '0') { + skybox_name[0] = 0; + skytexname[0] = 0; + return; + } + + // Do sides one way and top another, bottom is not done + for (int i = 0; i < 4; i++) + { + //int mark = Hunk_LowMark (); + + sprintf (skytexname, "%s%s", name, suf[i]); + skyimage[i] = loadskyboximage (va("gfx/env/%s%s", name, suf[i]), 0, 0, true, false); + if(skyimage[i] == 0) + { + //Con_Printf("Sky: %s%s not found, used std\n", "gfx/env/ndu%s", suf[i]); + skyimage[i] = loadskyboximage (va("gfx/env/ndu%s", suf[i]), 0, 0, true, false); + if(skyimage[i] == 0) + { + Con_Printf("STD SKY NOT FOUND!"); + return; + + } + } + //Hunk_FreeToLowMark (mark); + } + + //int mark = Hunk_LowMark (); + + sprintf (skytexname, "%sup", name); + skyimage[4] = loadskyboximage (va("gfx/env/%sup", name), 0, 0, true, false); + if(skyimage[4] == 0) + { + Con_Printf("Sky: %s[%s] not found, used std\n", name, suf[4]); + skyimage[4] = loadskyboximage (va("gfx/env/ndu%s", suf[4]), 0, 0, true, false); + if(skyimage[4] == 0) + { + Con_Printf("STD SKY NOT FOUND!"); + return; + } + } + //Hunk_FreeToLowMark (mark); + strcpy(skybox_name, name); +} + +/* +================= +Sky_NewMap +================= +*/ +void Sky_NewMap (void) +{ + char key[128], value[4096]; + char *data; + int i; + + //purge old sky textures + //UnloadSkyTexture (); + + // + // initially no sky + // + Sky_LoadSkyBox (""); //not used + for (i=0; i<5; i++) + skyimage[i] = 0; + skybox_name[0] = 0; + + // + // read worldspawn (this is so ugly, and shouldn't it be done on the server?) + // + data = cl.worldmodel->entities; + if (!data) + return; //FIXME: how could this possibly ever happen? -- if there's no + // worldspawn then the sever wouldn't send the loadmap message to the client + + data = COM_Parse(data); + + if (!data) //should never happen + return; // error + + if (com_token[0] != '{') //should never happen + return; // error + + while (1) + { + data = COM_Parse(data); + + if (!data) + return; // error + + if (com_token[0] == '}') + break; // end of worldspawn + + if (com_token[0] == '_') + strcpy(key, com_token + 1); + else + strcpy(key, com_token); + while (key[strlen(key)-1] == ' ') // remove trailing spaces + key[strlen(key)-1] = 0; + + data = COM_Parse(data); + if (!data) + return; // error + + strcpy(value, com_token); + + if (!strcmp("sky", key)) + Sky_LoadSkyBox(value); + else if (!strcmp("skyname", key)) //half-life + Sky_LoadSkyBox(value); + else if (!strcmp("qlsky", key)) //quake lives + Sky_LoadSkyBox(value); + } +} + +/* +================= +Sky_SkyCommand_f +================= +*/ +void Sky_SkyCommand_f (void) +{ + switch (Cmd_Argc()) + { + case 1: + Con_Printf("\"sky\" is \"%s\"\n", skybox_name); + break; + case 2: + Sky_LoadSkyBox(Cmd_Argv(1)); + break; + default: + Con_Printf("usage: sky \n"); + } +} + +/* +============= +Sky_Init +============= +*/ +void Sky_Init (void) +{ + int i; + + Cmd_AddCommand ("sky",Sky_SkyCommand_f); + + for (i=0; i<5; i++) + skyimage[i] = 0; +} + +#endif + +int c_sky; +// 1 = s, 2 = t, 3 = 2048 +static int st_to_vec[6][3] = +{ + {3,-1,2}, + {-3,1,2}, + + {1,3,2}, + {-1,-3,2}, + + {-2,-1,3}, // 0 degrees yaw, look straight up + {2,-1,-3} // look straight down + +// {-1,2,3}, +// {1,2,-3} +}; + +static float skymins[2][6], skymaxs[2][6]; + +/* +============== +R_ClearSkyBox +============== +*/ +void R_ClearSkyBox (void) +{ + int i; + + for (i=0 ; i<5 ; i++) + { + skymins[0][i] = skymins[1][i] = 9999; + skymaxs[0][i] = skymaxs[1][i] = -9999; + } +} + + +void MakeSkyVec (float s, float t, int axis) +{ + vec3_t v, b; + int j, k; + + b[0] = s*2048; + b[1] = t*2048; + b[2] = 2048; + + for (j=0 ; j<3 ; j++) + { + k = st_to_vec[axis][j]; + if (k < 0) + v[j] = -b[-k - 1]; + else + v[j] = b[k - 1]; + v[j] += r_origin[j]; + } + + // avoid bilerp seam + s = (s+1)*0.5; + t = (t+1)*0.5; + + if (s < 1.0/512) + s = 1.0/512; + else if (s > 511.0/512) + s = 511.0/512; + if (t < 1.0/512) + t = 1.0/512; + else if (t > 511.0/512) + t = 511.0/512; + + t = 1.0 - t; + GX_Position3f32(*v, *(v+1), *(v+2)); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (s, t); +} + +/* +============== +R_DrawSkyBox +============== +*/ + +float skynormals[5][3] = { + { 1.f, 0.f, 0.f }, + { -1.f, 0.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 0.f, -1.f, 0.f }, + { 0.f, 0.f, 1.f } +}; + +float skyrt[5][3] = { + { 0.f, -1.f, 0.f }, + { 0.f, 1.f, 0.f }, + { 1.f, 0.f, 0.f }, + { -1.f, 0.f, 0.f }, + { 0.f, -1.f, 0.f } +}; + +float skyup[5][3] = { + { 0.f, 0.f, 1.f }, + { 0.f, 0.f, 1.f }, + { 0.f, 0.f, 1.f }, + { 0.f, 0.f, 1.f }, + { -1.f, 0.f, 0.f } +}; + +//#ifdef QUAKE2 + +/* +============== +R_DrawSkyBox +============== +*/ +//Currently under construction +int skytexorder[6] = {0,2,1,3,4,5}; +void R_DrawSkyBox (void) +{ + int i; + vec3_t v; +#if 1 + float skydepth = 1000.0f; + + //QGX_Blend(false); + //QGX_Alpha(false); + //GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + //Fog_DisableGFog (); + QGX_ZMode(false); + + for (i=0 ; i<5 ; i++) + { + const int vertex_count = 4; + glvert_t sky_vertices[vertex_count]; + + // check if poly needs to be drawn at all + float dot = DotProduct(skynormals[i], vpn); + // < 0 check would work at fov 90 or less, just guess a value that's high enough? + if (dot < -0.25f) continue; + + GL_Bind0(skyimage[skytexorder[i]]); + if (vid_retromode.value == 1) + GX_SetMinMag (GX_NEAR, GX_NEAR); + else + GX_SetMinMag (GX_LINEAR, GX_LINEAR); + + // if direction is not up, cut "down" vector to zero to only render half cube + //float upnegfact = i == 4 ? 1.0f : 0.0f; + float upnegfact = 1.0f; + float skyboxtexsize = 128.0f; + // move ever so slightly less towards forward to make edges overlap a bit, just to not have shimmering pixels between sky edges + float forwardfact = 0.98f; + + GX_Begin (GX_QUADS, GX_VTXFMT0, 4); + + sky_vertices[0].s = 0.5f / skyboxtexsize; + sky_vertices[0].t = (skyboxtexsize - 0.5f) / skyboxtexsize; + sky_vertices[0].x = r_origin[0] + (forwardfact * skynormals[i][0] - skyrt[i][0] - skyup[i][0] * upnegfact) * skydepth; + sky_vertices[0].y = r_origin[1] + (forwardfact * skynormals[i][1] - skyrt[i][1] - skyup[i][1] * upnegfact) * skydepth; + sky_vertices[0].z = r_origin[2] + (forwardfact * skynormals[i][2] - skyrt[i][2] - skyup[i][2] * upnegfact) * skydepth; + v[0] = sky_vertices[0].x; + v[1] = sky_vertices[0].y; + v[2] = sky_vertices[0].z; + //glTexCoord2f (sky_vertices[0].s, sky_vertices[0].t); + //glVertex3fv (v); + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (sky_vertices[0].s, sky_vertices[0].t); + + sky_vertices[1].s = 0.5f / skyboxtexsize; + sky_vertices[1].t = 0.5f / skyboxtexsize; + sky_vertices[1].x = r_origin[0] + (forwardfact * skynormals[i][0] - skyrt[i][0] + skyup[i][0]) * skydepth; + sky_vertices[1].y = r_origin[1] + (forwardfact * skynormals[i][1] - skyrt[i][1] + skyup[i][1]) * skydepth; + sky_vertices[1].z = r_origin[2] + (forwardfact * skynormals[i][2] - skyrt[i][2] + skyup[i][2]) * skydepth; + v[0] = sky_vertices[1].x; + v[1] = sky_vertices[1].y; + v[2] = sky_vertices[1].z; + //glTexCoord2f (sky_vertices[1].s, sky_vertices[1].t); + //glVertex3fv (v); + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (sky_vertices[1].s, sky_vertices[1].t); + + sky_vertices[2].s = (skyboxtexsize - 0.5f) / skyboxtexsize; + sky_vertices[2].t = 0.5f / skyboxtexsize; + sky_vertices[2].x = r_origin[0] + (forwardfact * skynormals[i][0] + skyrt[i][0] + skyup[i][0]) * skydepth; + sky_vertices[2].y = r_origin[1] + (forwardfact * skynormals[i][1] + skyrt[i][1] + skyup[i][1]) * skydepth; + sky_vertices[2].z = r_origin[2] + (forwardfact * skynormals[i][2] + skyrt[i][2] + skyup[i][2]) * skydepth; + v[0] = sky_vertices[2].x; + v[1] = sky_vertices[2].y; + v[2] = sky_vertices[2].z; + //glTexCoord2f (sky_vertices[2].s, sky_vertices[2].t); + //glVertex3fv (v); + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (sky_vertices[2].s, sky_vertices[2].t); + + sky_vertices[3].s = (skyboxtexsize - 0.5f) / skyboxtexsize; + sky_vertices[3].t = (skyboxtexsize - 0.5f) / skyboxtexsize; + sky_vertices[3].x = r_origin[0] + (forwardfact * skynormals[i][0] + skyrt[i][0] - skyup[i][0] * upnegfact) * skydepth; + sky_vertices[3].y = r_origin[1] + (forwardfact * skynormals[i][1] + skyrt[i][1] - skyup[i][1] * upnegfact) * skydepth; + sky_vertices[3].z = r_origin[2] + (forwardfact * skynormals[i][2] + skyrt[i][2] - skyup[i][2] * upnegfact) * skydepth; + v[0] = sky_vertices[3].x; + v[1] = sky_vertices[3].y; + v[2] = sky_vertices[3].z; + //glTexCoord2f (sky_vertices[3].s, sky_vertices[3].t); + //glVertex3fv (v); + GX_Position3f32(v[0], v[1], v[2]); + GX_Color4u8(0xff, 0xff, 0xff, 0xff); + GX_TexCoord2f32 (sky_vertices[3].s, sky_vertices[3].t); + + GX_End (); + } + QGX_ZMode(true); + //QGX_Alpha(true); + //Fog_EnableGFog (); +#endif +} + +//#endif + +//=============================================================== + +/* +============= +R_InitSky + +A sky texture is 256*128, with the right side being a masked overlay +============== +*/ +void R_InitSky (miptex_t *mt) +{ + int i, j, p; + byte *src; + byte trans[128*128]; + + src = (byte *)mt + mt->offsets[0]; + + for (i=0 ; i<128 ; i++) + for (j=0 ; j<128 ; j++) + trans[(i*128) + j] = src[i*256 + j + 128]; + + solidskytexture = GL_LoadTexture("render_solidskytexture", 128, 128, trans, true, true, false, 1); + + for (i=0 ; i<128 ; i++) + for (j=0 ; j<128 ; j++) + { + p = src[i*256 + j]; + if (p == 0) + trans[(i*128) + j] = 255; + else + trans[(i*128) + j] = p; + } + + alphaskytexture = GL_LoadTexture("render_alphaskytexture", 128, 128, trans, true, true, false, 1); +} + diff --git a/source/wii/gx/gx_warp_sin.h b/source/wii/gx/gx_warp_sin.h new file mode 100644 index 0000000..22976a7 --- /dev/null +++ b/source/wii/gx/gx_warp_sin.h @@ -0,0 +1,51 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + 0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677, + 1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916, + 3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998, + 4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632, + 5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068, + 6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368, + 7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562, + 7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759, + 8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222, + 7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394, + 7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883, + 6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398, + 5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647, + 4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193, + 3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281, + 1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633, + 9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677, + -1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916, + -3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998, + -4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632, + -5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068, + -6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368, + -7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562, + -7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759, + -8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222, + -7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394, + -7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883, + -6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398, + -5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647, + -4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193, + -3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281, + -1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633, diff --git a/source/wii/gx/gxquake.h b/source/wii/gx/gxquake.h new file mode 100644 index 0000000..496176d --- /dev/null +++ b/source/wii/gx/gxquake.h @@ -0,0 +1,428 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include + +void GL_BeginRendering (int *x, int *y, int *width, int *height); +void GL_EndRendering (void); +void VID_ConModeUpdate(void); + +extern float gldepthmin, gldepthmax; + +typedef struct +{ + float x, y, z; + float s, t; + float r, g, b; +} glvert_t; + +extern glvert_t glv; + +extern int glx, gly, glwidth, glheight; + +/* +--------------------------------- +half-life Render Modes. Crow_bar +--------------------------------- +*/ + +#define TEX_COLOR 1 +#define TEX_TEXTURE 2 +#define TEX_GLOW 3 +#define TEX_SOLID 4 +#define TEX_ADDITIVE 5 +#define TEX_LMPOINT 6 //for light point + +#define ISCOLOR(ent) ((ent)->rendermode == TEX_COLOR && ((ent)->rendercolor[0] <= 1|| \ + (ent)->rendercolor[1] <= 1|| \ + (ent)->rendercolor[2] <= 1)) + +#define ISTEXTURE(ent) ((ent)->rendermode == TEX_TEXTURE && (ent)->renderamt > 0 && (ent)->renderamt <= 1) +#define ISGLOW(ent) ((ent)->rendermode == TEX_GLOW && (ent)->renderamt > 0 && (ent)->renderamt <= 1) +#define ISSOLID(ent) ((ent)->rendermode == TEX_SOLID && (ent)->renderamt > 0 && (ent)->renderamt <= 1) +#define ISADDITIVE(ent) ((ent)->rendermode == TEX_ADDITIVE && (ent)->renderamt > 0 && (ent)->renderamt <= 1) + +#define ISLMPOINT(ent) ((ent)->rendermode == TEX_LMPOINT && ((ent)->rendercolor[0] <= 1|| \ + (ent)->rendercolor[1] <= 1|| \ + (ent)->rendercolor[2] <= 1)) +/* +--------------------------------- +//half-life Render Modes +--------------------------------- +*/ + +// r_local.h -- private refresh defs + +#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) + // normalizing factor so player model works out to about + // 1 pixel per triangle +#define MAX_LBM_HEIGHT 480 + +#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf + +#define SKYSHIFT 7 +#define SKYSIZE (1 << SKYSHIFT) +#define SKYMASK (SKYSIZE - 1) + +#define BACKFACE_EPSILON 0.01 + + +void R_TimeRefresh_f (void); +void R_ReadPointFile_f (void); +texture_t *R_TextureAnimation (texture_t *base); + +typedef struct surfcache_s +{ + struct surfcache_s *next; + struct surfcache_s **owner; // NULL is an empty chunk of memory + int lightadj[MAXLIGHTMAPS]; // checked for strobe flush + int dlight; + int size; // including header + unsigned width; + unsigned height; // DEBUG only needed for debug + float mipscale; + struct texture_s *texture; // checked for animating textures + byte data[4]; // width*height elements +} surfcache_t; + + +typedef struct +{ + pixel_t *surfdat; // destination for generated surface + int rowbytes; // destination logical width in bytes + msurface_t *surf; // description for surface to generate + fixed8_t lightadj[MAXLIGHTMAPS]; + // adjust for lightmap levels for dynamic lighting + texture_t *texture; // corrected for animating textures + int surfmip; // mipmapped ratio of surface texels / world pixels + int surfwidth; // in mipmapped texels + int surfheight; // in mipmapped texels +} drawsurf_t; + +typedef enum +{ + pm_classic, pm_qmb, pm_quake3, pm_mixed +} part_mode_t; + +typedef enum { + pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2 +} ptype_t; + +typedef byte col_t[4]; + +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +typedef struct particle2_s +{ +// driver-usable fields + vec3_t org; + float color; +// drivers never touch the following fields + struct particle2_s *next; + vec3_t vel; + float ramp; + float die; + ptype_t type; +} particle2_t; + + +//==================================================== + + +extern entity_t r_worldentity; +extern qboolean r_cache_thrash; // compatability +extern vec3_t modelorg, r_entorigin; +extern entity_t *currententity; +extern int r_visframecount; // ??? what difs? +extern int r_framecount; +extern mplane_t frustum[4]; +extern int c_brush_polys, c_alias_polys; + + +// +// view origin +// +extern vec3_t vup; +extern vec3_t vpn; +extern vec3_t vright; +extern vec3_t r_origin; + +// +// screen size info +// +extern refdef_t r_refdef; +extern mleaf_t *r_viewleaf, *r_oldviewleaf; +extern texture_t *r_notexture_mip; +extern int d_lightstylevalue[256]; // 8.8 fraction of base light value + +extern qboolean envmap; +extern int currenttexture0; +extern int currenttexture1; +extern int cnttextures[2]; +extern int particletexture; +extern int playertextures[MAX_SCOREBOARD]; + +extern int skytexturenum; // index in cl.loadmodel, not gl texture object + +extern cvar_t r_norefresh; +extern cvar_t r_drawentities; +extern cvar_t r_drawworld; +extern cvar_t r_drawviewmodel; +extern cvar_t r_speeds; +extern cvar_t r_waterwarp; +extern cvar_t r_fullbright; +extern cvar_t r_lightmap; +extern cvar_t r_shadows; +extern cvar_t r_mirroralpha; +extern cvar_t r_wateralpha; +extern cvar_t r_dynamic; +extern cvar_t r_novis; +extern cvar_t r_lerpmodels; +extern cvar_t r_lerpmove; +extern cvar_t r_farclip; +extern cvar_t r_skyfog; + +extern cvar_t gl_clear; +extern cvar_t gl_cull; +extern cvar_t gl_poly; +extern cvar_t gl_smoothmodels; +extern cvar_t gl_affinemodels; +extern cvar_t gl_polyblend; +extern cvar_t gl_fogblend; +extern cvar_t gl_keeptjunctions; +extern cvar_t gl_reporttjunctions; +extern cvar_t gl_nocolors; +extern cvar_t gl_doubleeyes; + +extern cvar_t r_laserpoint; +extern cvar_t r_particle_count; +extern cvar_t r_part_explosions; +extern cvar_t r_part_trails; +extern cvar_t r_part_sparks; +extern cvar_t r_part_spikes; +extern cvar_t r_part_gunshots; +extern cvar_t r_part_blood; +extern cvar_t r_part_telesplash; +extern cvar_t r_part_blobs; +extern cvar_t r_part_lavasplash; +extern cvar_t r_part_flames; +extern cvar_t r_part_lightning; +extern cvar_t r_part_flies; +extern cvar_t r_bounceparticles; +extern cvar_t r_explosiontype; +extern cvar_t r_part_muzzleflash; +extern cvar_t r_flametype; +extern cvar_t r_bounceparticles; +extern cvar_t r_decal_blood; +extern cvar_t r_decal_bullets; +extern cvar_t r_decal_sparks; +extern cvar_t r_decal_explosions; +extern cvar_t r_coronas; +extern cvar_t r_model_brightness; +extern cvar_t r_overbright; + +extern cvar_t gl_max_size; +extern cvar_t gl_playermip; + +extern cvar_t vid_tvborder; +extern cvar_t vid_retromode; + +extern cvar_t r_part_muzzleflash; + +extern int white_texturenum; + +extern int mirrortexturenum; +extern qboolean mirror; +extern mplane_t *mirror_plane; + +extern float r_world_matrix[16]; + +void GL_Bind0 (int texnum); + +extern vrect_t scr_vrect; + +extern Mtx44 perspective; +extern Mtx view, model, modelview; + +#define ZMIN3D 4.0f +#define ZMAX3D 16384.0f +#define ZMIN2D -9999.0f +#define ZMAX2D 9999.0f + +// Textures + +typedef struct +{ + int texnum; + GXTexObj gx_tex; + char identifier[64]; + int width, height; + qboolean mipmap; + unsigned *data; + int scaled_width, scaled_height; + + // ELUTODO: make sure textures loaded without an identifier are loaded only one time, if "keep" is on + // What about mid-game gamma changes? + qboolean type; // 0 = normal, 1 = lightmap + qboolean keep; + + qboolean used; + + qboolean islmp; + + int checksum; + + // Diabolicka TGA + int bytesperpixel; + int lhcsum; + // Diabolickal end +} gltexture_t; + +#define MAX_GLTEXTURES 1024 +extern int numgltextures; +extern gltexture_t gltextures[MAX_GLTEXTURES]; + +void QGX_ZMode(qboolean state); +void QGX_Alpha(qboolean state); +void QGX_Blend(qboolean state); +void QGX_BlendMap(qboolean state); + +int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, qboolean keep, int bytesperpixel); +int GL_LoadLightmapTexture (char *identifier, int width, int height, byte *data); +void GL_UpdateTexture (int pic_id, char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha); +void GL_UpdateLightmapTextureRegion (int pic_id, int width, int height, int xoffset, int yoffset, byte *data); +int GL_FindTexture (char *identifier); +void GL_SubdivideSurface (msurface_t *fa); +void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr); +int R_LightPoint (vec3_t p); +void CL_NewDlight (int key, vec3_t origin, float radius, float time, int type); +void R_DrawBrushModel (entity_t *e); +void R_AnimateLight (void); +void V_CalcBlend (void); +void R_DrawWorld (void); +void R_DrawParticles (void); +void R_DrawWaterSurfaces (void); +void R_InitParticles (void); +void GL_Update32 (gltexture_t *destination, u32 *data, int width, int height, qboolean mipmap, qboolean alpha); +void R_ClearParticles (void); +void GL_BuildLightmaps (void); +void EmitWaterPolys (msurface_t *fa); +void R_DrawSkyChain (msurface_t *s); +qboolean R_CullBox (vec3_t mins, vec3_t maxs); +void R_MarkLights (dlight_t *light, int bit, mnode_t *node); +void R_RotateForEntity (entity_t *e, unsigned char scale); +void R_StoreEfrags (efrag_t **ppefrag); +void GL_Set2D (void); + +void GL_DisableMultitexture(void); +void GL_EnableMultitexture(void); + +//johnfitz -- fog functions called from outside gx_fog.c +void Fog_ParseServerMessage (void); +GXColor Fog_GetColor (void); +float Fog_GetDensity (void); +void Fog_EnableGFog (void); +void Fog_DisableGFog (void); +void Fog_StartAdditive (void); +void Fog_StopAdditive (void); +void Fog_SetupFrame (void); +void Fog_NewMap (void); +void Fog_Init (void); +void Fog_SetupState (void); + +void GX_SetMinMag (int minfilt, int magfilt); +void GX_SetMaxAniso (int aniso); + +void GL_ClearTextureCache(void); + +void Clear_LoadingFill (void); + +// OSK +extern qboolean in_osk; +//void GX_DrawOSK(void); +//extern char *osk_set; +//extern int osk_selected; +//extern int osk_coords[2]; +//#define osk_charsize 8 +// ELUTODO: use glwidth/height or wiimote_ir_res_x/y? +//#define osk_num_lines 5 +//#define osk_line_size 16 +//#define osk_num_col 15 +//#define osk_col_size 16 +//#define OSK_XSTART (((glwidth) - ((glwidth) / (osk_col_size) * (osk_num_col))) / 2) +//#define OSK_YSTART (((glheight) - ((glheight) / (osk_line_size) * (osk_num_lines))) / 2) + +// Draw.c extensions +extern void Draw_TransAlphaPic (int x, int y, qpic_t *pic, float alpha); +extern void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha); +extern void Draw_AlphaTileClear (int x, int y, int w, int h, float alpha); +//extern qpic_t *conback; + +// input extensions +extern float in_pitchangle; +extern float in_yawangle; +extern float in_rollangle; + +// naievil -- fixme: none of these work +//----------------------------------------------------- +void QMB_InitParticles (void); +void QMB_ClearParticles (void); +void QMB_DrawParticles (void); +void QMB_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); +void QMB_RocketTrail (vec3_t start, vec3_t end, trail_type_t type); +void QMB_BlobExplosion (vec3_t org); +void QMB_ParticleExplosion (vec3_t org); +void QMB_LavaSplash (vec3_t org); +void QMB_TeleportSplash (vec3_t org); +void QMB_InfernoFlame (vec3_t org); +void QMB_StaticBubble (entity_t *ent); +void QMB_ColorMappedExplosion (vec3_t org, int colorStart, int colorLength); +void QMB_TorchFlame (vec3_t org); +void QMB_FlameGt (vec3_t org, float size, float time); +void QMB_BigTorchFlame (vec3_t org); +void QMB_ShamblerCharge (vec3_t org); +void QMB_LightningBeam (vec3_t start, vec3_t end); +//void QMB_GenSparks (vec3_t org, byte col[3], float count, float size, float life); +void QMB_EntityParticles (entity_t *ent); +void QMB_MuzzleFlash (vec3_t org); +void QMB_RayFlash (vec3_t org, float weapon); +void QMB_Q3Gunshot (vec3_t org, int skinnum, float alpha); +void QMB_Q3Teleport (vec3_t org, float alpha); +void QMB_Q3TorchFlame (vec3_t org, float size); + +void R_SpawnDecal (vec3_t center, vec3_t normal, vec3_t tangent, int tex, int size, int isbsp); +void R_SpawnDecalStatic (vec3_t org, int tex, int size); +void R_DrawDecals (void); +void R_InitDecals (void); +void R_ClearDecals (void); + +void Sky_LoadSkyBox(char* name); + +void Build_Gamma_Table (void); +void Sky_Init (void); +void Sky_NewMap (void); +void R_DrawSkyBox (void); +void R_ClearSkyBox (void); +void EmitBothSkyLayers (msurface_t *fa); +int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean keep); +byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight, int reverseRGBA); +int loadskyboximage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap); + +extern qboolean qmb_initialized; \ No newline at end of file diff --git a/source/wii/gx/video_gx.c b/source/wii/gx/video_gx.c new file mode 100644 index 0000000..34210be --- /dev/null +++ b/source/wii/gx/video_gx.c @@ -0,0 +1,341 @@ +/* +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +// ELUTODO: blank all the framebuffers to prevent artifacts before rendering takes place. Happens between the frontend ending and the quake console showing up + +#include "../../quakedef.h" + +extern void *framebuffer[2]; +extern u32 fb; +extern GXRModeObj *rmode; + +static void *gp_fifo; +static const size_t fifo_size = 1024 * 256; + +#define WARP_WIDTH 640 +#define WARP_HEIGHT 480 + +static int scr_width, scr_height; + +static bool vidmode_active = false; + +int texture_extension_number = 1; + +/*-----------------------------------------------------------------------*/ + +unsigned d_8to24table[256]; + +float gldepthmin, gldepthmax; + +static float vid_gamma = 1.0; + +/*-----------------------------------------------------------------------*/ + +Mtx44 perspective; +Mtx view, model, modelview; + +cvar_t vid_tvborder = {"vid_tvborder", "0", (qboolean)true}; +cvar_t vid_conmode = {"vid_conmode", "0", (qboolean)true}; + +void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ +} + +void D_EndDirectRect (int x, int y, int width, int height) +{ +} + +void VID_Shutdown(void) +{ + if (vidmode_active) + { + // Free the FIFO. + free(MEM_K1_TO_K0(gp_fifo)); + gp_fifo = 0; + + vidmode_active = false; + } +} + +void VID_ShiftPalette(unsigned char *p) +{ + VID_SetPalette(p); +} + +void VID_SetPalette (unsigned char *palette) +{ + byte *pal; + unsigned r,g,b; + unsigned v; + unsigned short i; + unsigned *table; + +// +// 8 8 8 encoding +// + pal = palette; + table = d_8to24table; + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + + v = (255<<24) + (r<<0) + (g<<8) + (b<<16); + *table++ = v; + } + //d_8to24table[255] &= 0xffffff; // 255 is transparent + d_8to24table[255] = 0; // ELUTODO: will look prettier until we solve the filtering issue +} + +void VID_ConModeUpdate(void) +{ + // update console resolution + /* + switch((int)vid_conmode.value) + { + default: + case 0: + vid.conwidth = 320; + vid.conheight = 240; + break; + case 1: + vid.conwidth = 400; + vid.conheight = 300; + break; + case 2: + vid.conwidth = 480; + vid.conheight = 360; + break; + case 3: + vid.conwidth = 560; + vid.conheight = 420; + break; + case 4: + vid.conwidth = 640; + vid.conheight = 480; + break; + } + */ + + vid.conwidth = vid.width; + vid.conheight = vid.height; + + if (vid.conheight > scr_height) + vid.conheight = scr_height; + if (vid.conwidth > scr_width) + vid.conwidth = scr_width; + + //conback->width = vid.conwidth; + //conback->height = vid.conheight; +} + +/* +=============== +GL_Init +=============== +*/ +void GL_Init (void) +{ + f32 yscale; + u32 xfbHeight; + + GXColor background = {0, 0, 0, 0xff}; + + // Initialise GX. + gp_fifo = memalign(32, fifo_size); + if (!gp_fifo) + Sys_Error("VID_Init: !gp_fifo\n"); + + gp_fifo = MEM_K0_TO_K1(gp_fifo); + memset(gp_fifo, 0, fifo_size); + GX_Init(gp_fifo, fifo_size); + + // clears the bg to color and clears the z buffer + GX_SetCopyClear(background, GX_MAX_Z24); + + // other gx setup + GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1); + yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight); + xfbHeight = GX_SetDispCopyYScale(yscale); + GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight); + GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight); + GX_SetDispCopyDst(rmode->fbWidth,xfbHeight); + GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter); + GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE)); + + if (rmode->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GX_CopyDisp(framebuffer[fb & 1],GX_TRUE); + GX_SetDispCopyGamma(GX_GM_1_0); + + GX_SetZCompLoc(false); // ELUTODO + + GL_DisableMultitexture(); + + // setup the vertex attribute table + // describes the data + // args: vat location 0-7, type of data, data format, size, scale + // so for ex. in the first call we are sending position data with + // 3 values X,Y,Z of size F32. scale sets the number of fractional + // bits for non float data. + + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + + GX_SetNumChans(1); + GX_SetNumTexGens(1); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + //GX_SetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY); + + GX_InvVtxCache(); + GX_InvalidateTexAll(); +} + +/* +================= +GL_BeginRendering + +================= +*/ +void GL_BeginRendering (int *x, int *y, int *width, int *height) +{ + // ELUTODO: lol at the * 2 on height + *x = 0; + *y = vid_tvborder.value * 200; + *width = scr_width; + *height = scr_height - (vid_tvborder.value * 400); + + GX_SetScissor(*x,*y,*width,*height); + + // ELUTODO: really necessary? + //GX_InvVtxCache(); + //GX_InvalidateTexAll(); +} + +void GL_EndRendering (void) +{ + GX_SetColorUpdate(GX_TRUE); + GX_SetAlphaUpdate(GX_TRUE); + + // Start copying the frame buffer every vsync. + GX_CopyDisp(framebuffer[fb], GX_TRUE); + + // Finish up any graphics operations. + GX_DrawDone(); + GX_Flush(); + + VIDEO_SetNextFramebuffer(framebuffer[fb]); + VIDEO_Flush(); + // Keep framerate + VIDEO_WaitVSync(); + + fb ^= 1; +} + +// This is not the "v_gamma/gamma" cvar +static void Check_Gamma (unsigned char *pal) +{ + float f, inf; + unsigned char palette[768]; + int i; + + if ((i = COM_CheckParm("-gamma")) == 0) { + vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware + } else + vid_gamma = atof(com_argv[i+1]); + + for (i=0 ; i<768 ; i++) + { + f = pow ( (pal[i]+1)/256.0 , vid_gamma ); + inf = f*255 + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + palette[i] = inf; + } + + memcpy (pal, palette, sizeof(palette)); + + Build_Gamma_Table (); +} + +// ELUTODO: proper widescreen support +// ELUTODO: one more mess to remove: glwidth is the VIEWAREA and scr_width is the WHOLE SCREEN (will have to clean this up if I want to implemented split-screen multiplayer +// ELUTODO: crosshair, osk are NOT right on higher 2d resolutions and split-screen setups (is the use of scr_vrect for cl_crossx/y right?) +// scr_width/height = 3D res, vid.conwidth/conheight = 2D res, vid.width/height = "natural" resolution (320x{200,240}) +// many things rely on a minimum resolution of 320x{200,240} +void VID_Init(unsigned char *palette) +{ + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + vid.colormap = host_colormap; + vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); + +// interpret command-line params + +// only multiples of eight, please +// set vid parameters + scr_width = rmode->fbWidth; + scr_height = rmode->efbHeight; + + vid.width = 640; //640 + vid.height = 480; //480 + + if (vid.height > scr_height) + vid.height = scr_height; + if (vid.width > scr_width) + vid.width = scr_width; + + vid.aspect = ((float)vid.height / (float)vid.width) * (640.0 / 480.0); //640.0/480.0 + vid.numpages = 2; + + //GL_Init(); + + Check_Gamma(palette); + VID_SetPalette(palette); + + Con_Printf ("Video mode %dx%d initialized.\n", scr_width, scr_height); + + vid.recalc_refdef = 1; // force a surface cache flush + + Cvar_RegisterVariable(&vid_tvborder); + Cvar_RegisterVariable(&vid_retromode); + Cvar_RegisterVariable(&vid_conmode); + + vidmode_active = true; +} diff --git a/source/wii/input.c b/source/wii/input.c new file mode 100644 index 0000000..1194045 --- /dev/null +++ b/source/wii/input.c @@ -0,0 +1,842 @@ +/* +Quake GameCube port. +Copyright (C) 2007 Peter Mackay +Copyright (C) 2008 Eluan Miranda +Copyright (C) 2015 Fabio Olimpieri + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +// ELUTODO: do something about lookspring and lookstrafe +// ELUTODO: keys to: nunchuk turn and nunchuk look up/down? +// ELUTODO: osk doesn't work if client disconnected + +#include "../quakedef.h" + +cvar_t nunchuk_stick_as_arrows = {"nunchuk_stick_as_arrows","0"}; +cvar_t rumble = {"rumble","1"}; + +// pass these values to whatever subsystem wants it +float in_pitchangle; +float in_yawangle; +float in_rollangle; + +#include +#include +#include +#include "input_wiimote.h" + +#define FORCE_KEY_BINDINGS 0 + +u32 wiimote_ir_res_x; +u32 wiimote_ir_res_y; + +// wiimote info +u32 wpad_previous_keys = 0x0000; +u32 wpad_keys = 0x0000; + +ir_t pointer; +orient_t orientation; +expansion_t expansion; +nunchuk_t nunchuk; //Shake +gforce_t gforce; + +bool wiimote_connected = true; +bool nunchuk_connected = false; +bool classic_connected = false; +bool keyboard_connected = false; + +typedef enum {LEFT, CENTER_X, RIGHT} stick_x_st_t; +typedef enum {UP, CENTER_Y, DOWN} stick_y_st_t; + +stick_x_st_t stick_x_st = CENTER_X; +stick_y_st_t stick_y_st = CENTER_Y; + +u16 pad_previous_keys = 0x0000; +u16 pad_keys = 0x0000; + +static float clamp(float value, float minimum, float maximum) +{ + if (value > maximum) + { + return maximum; + } + else if (value < minimum) + { + return minimum; + } + else + { + return value; + } +} +qboolean aimsnap = false; +static void apply_dead_zone(float* x, float* y, float dead_zone) +{ + if (aimsnap == true) + dead_zone = 0.15f; + + if ((fabsf(*x) >= dead_zone) || (fabsf(*y) >= dead_zone)) + { + // Nothing to do. + } + else + { + // Clamp to the dead zone. + *x = 0.0f; + *y = 0.0f; + } +} + +static s8 WPAD_StickX(u8 which) +{ + float mag = 0.0; + float ang = 0.0; + + switch (expansion.type) + { + case WPAD_EXP_NUNCHUK: + case WPAD_EXP_GUITARHERO3: + if (which == 0) + { + mag = expansion.nunchuk.js.mag; + ang = expansion.nunchuk.js.ang; + } + break; + + case WPAD_EXP_CLASSIC: + if (which == 0) + { + mag = expansion.classic.ljs.mag; + ang = expansion.classic.ljs.ang; + } + else + { + mag = expansion.classic.rjs.mag; + ang = expansion.classic.rjs.ang; + } + break; + + default: + break; + } + + /* calculate X value (angle needs to be converted into radians) */ + if (mag > 1.0) mag = 1.0; + else if (mag < -1.0) mag = -1.0; + double val = mag * sin(M_PI * ang/180.0f); + + return (s8)(val * 128.0f); +} + +static s8 WPAD_StickY(u8 which) +{ + float mag = 0.0; + float ang = 0.0; + + switch (expansion.type) + { + case WPAD_EXP_NUNCHUK: + case WPAD_EXP_GUITARHERO3: + if (which == 0) + { + mag = expansion.nunchuk.js.mag; + ang = expansion.nunchuk.js.ang; + } + break; + + case WPAD_EXP_CLASSIC: + if (which == 0) + { + mag = expansion.classic.ljs.mag; + ang = expansion.classic.ljs.ang; + } + else + { + mag = expansion.classic.rjs.mag; + ang = expansion.classic.rjs.ang; + } + break; + + default: + break; + } + + /* calculate X value (angle need to be converted into radian) */ + if (mag > 1.0) mag = 1.0; + else if (mag < -1.0) mag = -1.0; + double val = mag * cos(M_PI * ang/180.0f); + + return (s8)(val * 128.0f); +} + +void IN_Init (void) +{ + in_pitchangle = .0f; + in_yawangle = .0f; + in_rollangle = .0f; + + WPAD_SetDataFormat(WPAD_CHAN_ALL, WPAD_FMT_BTNS_ACC_IR); + WPAD_SetVRes(WPAD_CHAN_ALL, wiimote_ir_res_x, wiimote_ir_res_y); + + Cvar_RegisterVariable (&nunchuk_stick_as_arrows); + Cvar_RegisterVariable (&rumble); +} + +void IN_Shutdown (void) +{ +} + +void IN_Commands (void) +{ + // Fetch the pad state. + PAD_ScanPads(); + WPAD_ScanPads(); + + //It manages the nunchunk or classic controller connection + //It assigns the pressed buttons to wpad_keys and to pad_keys + + u32 exp_type; + if ( WPAD_Probe(WPAD_CHAN_0, &exp_type) != 0 ) + exp_type = WPAD_EXP_NONE; + + if(exp_type == WPAD_EXP_NUNCHUK) + { + if(!nunchuk_connected) + wpad_previous_keys = 0x0000; + + nunchuk_connected = true; + classic_connected = false; + wpad_keys = WPAD_ButtonsHeld(WPAD_CHAN_0); + pad_keys = 0x0000; + pad_previous_keys = 0x0000; + } + + else if(exp_type == WPAD_EXP_CLASSIC) + { + if(!classic_connected) + wpad_previous_keys = 0x0000; + + nunchuk_connected = false; + classic_connected = true; + wpad_keys = WPAD_ButtonsHeld(WPAD_CHAN_0); + pad_keys = 0x0000; + pad_previous_keys = 0x0000; + } + + else + //Here neither the classic controller nor the nuncunk are connected + { + if(classic_connected || nunchuk_connected) + wpad_previous_keys = 0x0000; + + nunchuk_connected = false; + classic_connected = false; + pad_keys = PAD_ButtonsHeld(PAD_CHAN0); + wpad_keys = WPAD_ButtonsHeld(WPAD_CHAN_0); + } + + WPAD_IR(WPAD_CHAN_0, &pointer); + WPAD_Orientation(WPAD_CHAN_0, &orientation); + WPAD_Expansion(WPAD_CHAN_0, &expansion); + WPAD_GForce(WPAD_CHAN_0, &gforce); //Shake to reload + +//Send the wireless classic controller buttons events + if(classic_connected) + { + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_LEFT) != (wpad_keys & WPAD_CLASSIC_BUTTON_LEFT)) + { + // Send a press event. + Key_Event(K_LEFTARROW, ((wpad_keys & WPAD_CLASSIC_BUTTON_LEFT) == WPAD_CLASSIC_BUTTON_LEFT)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_RIGHT) != (wpad_keys & WPAD_CLASSIC_BUTTON_RIGHT)) + { + // Send a press event. + Key_Event(K_RIGHTARROW, ((wpad_keys & WPAD_CLASSIC_BUTTON_RIGHT) == WPAD_CLASSIC_BUTTON_RIGHT)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_DOWN) != (wpad_keys & WPAD_CLASSIC_BUTTON_DOWN)) + { + // Send a press event. + Key_Event(K_DOWNARROW, ((wpad_keys & WPAD_CLASSIC_BUTTON_DOWN) == WPAD_CLASSIC_BUTTON_DOWN)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_UP) != (wpad_keys & WPAD_CLASSIC_BUTTON_UP)) + { + // Send a press event. + Key_Event(K_UPARROW, ((wpad_keys & WPAD_CLASSIC_BUTTON_UP) == WPAD_CLASSIC_BUTTON_UP)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_A) != (wpad_keys & WPAD_CLASSIC_BUTTON_A)) + { + // Send a press event. + Key_Event(K_JOY9, ((wpad_keys & WPAD_CLASSIC_BUTTON_A) == WPAD_CLASSIC_BUTTON_A)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_B) != (wpad_keys & WPAD_CLASSIC_BUTTON_B)) + { + // Send a press event. + Key_Event(K_JOY10, ((wpad_keys & WPAD_CLASSIC_BUTTON_B) == WPAD_CLASSIC_BUTTON_B)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_X) != (wpad_keys & WPAD_CLASSIC_BUTTON_X)) + { + // Send a press event. + Key_Event(K_JOY11, ((wpad_keys & WPAD_CLASSIC_BUTTON_X) == WPAD_CLASSIC_BUTTON_X)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_Y) != (wpad_keys & WPAD_CLASSIC_BUTTON_Y)) + { + // Send a press event. + Key_Event(K_JOY12, ((wpad_keys & WPAD_CLASSIC_BUTTON_Y) == WPAD_CLASSIC_BUTTON_Y)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_FULL_L) != (wpad_keys & WPAD_CLASSIC_BUTTON_FULL_L)) + { + // Send a press event. + Key_Event(K_JOY13, ((wpad_keys & WPAD_CLASSIC_BUTTON_FULL_L) == WPAD_CLASSIC_BUTTON_FULL_L)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_FULL_R) != (wpad_keys & WPAD_CLASSIC_BUTTON_FULL_R)) + { + // Send a press event. + Key_Event(K_JOY14, ((wpad_keys & WPAD_CLASSIC_BUTTON_FULL_R) == WPAD_CLASSIC_BUTTON_FULL_R)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_ZL) != (wpad_keys & WPAD_CLASSIC_BUTTON_ZL)) + { + // Send a press event. + Key_Event(K_JOY15, ((wpad_keys & WPAD_CLASSIC_BUTTON_ZL) == WPAD_CLASSIC_BUTTON_ZL)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_ZR) != (wpad_keys & WPAD_CLASSIC_BUTTON_ZR)) + { + // Send a press event. + Key_Event(K_JOY16, ((wpad_keys & WPAD_CLASSIC_BUTTON_ZR) == WPAD_CLASSIC_BUTTON_ZR)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_MINUS) != (wpad_keys & WPAD_CLASSIC_BUTTON_MINUS)) + { + // Send a press event. + Key_Event(K_JOY17, ((wpad_keys & WPAD_CLASSIC_BUTTON_MINUS) == WPAD_CLASSIC_BUTTON_MINUS)); + } + + if ((wpad_previous_keys & WPAD_CLASSIC_BUTTON_PLUS) != (wpad_keys & WPAD_CLASSIC_BUTTON_PLUS)) + { + // Send a press event. + Key_Event(K_JOY18, ((wpad_keys & WPAD_CLASSIC_BUTTON_PLUS) == WPAD_CLASSIC_BUTTON_PLUS)); + } + + } + + else +//Send the wiimote button events if the classic controller is not connected + + { + if ((wpad_previous_keys & WPAD_BUTTON_LEFT) != (wpad_keys & WPAD_BUTTON_LEFT)) + { + // Send a press event. + Key_Event(K_LEFTARROW, ((wpad_keys & WPAD_BUTTON_LEFT) == WPAD_BUTTON_LEFT)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_RIGHT) != (wpad_keys & WPAD_BUTTON_RIGHT)) + { + // Send a press event. + Key_Event(K_RIGHTARROW, ((wpad_keys & WPAD_BUTTON_RIGHT) == WPAD_BUTTON_RIGHT)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_DOWN) != (wpad_keys & WPAD_BUTTON_DOWN)) + { + // Send a press event. + Key_Event(K_DOWNARROW, ((wpad_keys & WPAD_BUTTON_DOWN) == WPAD_BUTTON_DOWN)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_UP) != (wpad_keys & WPAD_BUTTON_UP)) + { + // Send a press event. + Key_Event(K_UPARROW, ((wpad_keys & WPAD_BUTTON_UP) == WPAD_BUTTON_UP)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_A) != (wpad_keys & WPAD_BUTTON_A)) + { + // Send a press event. + Key_Event(K_JOY0, ((wpad_keys & WPAD_BUTTON_A) == WPAD_BUTTON_A)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_B) != (wpad_keys & WPAD_BUTTON_B)) + { + // Send a press event. + Key_Event(K_JOY1, ((wpad_keys & WPAD_BUTTON_B) == WPAD_BUTTON_B)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_1) != (wpad_keys & WPAD_BUTTON_1)) + { + // Send a press event. + Key_Event(K_JOY2, ((wpad_keys & WPAD_BUTTON_1) == WPAD_BUTTON_1)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_2) != (wpad_keys & WPAD_BUTTON_2)) + { + // Send a press event. + Key_Event(K_JOY3, ((wpad_keys & WPAD_BUTTON_2) == WPAD_BUTTON_2)); + } + + if ((wpad_previous_keys & WPAD_BUTTON_PLUS) != (wpad_keys & WPAD_BUTTON_PLUS)) + + { + // Send a press event. + Key_Event(K_JOY5, ((wpad_keys & WPAD_BUTTON_PLUS) == WPAD_BUTTON_PLUS)); + } + // select: + if ((wpad_previous_keys & WPAD_BUTTON_MINUS) != (wpad_keys & WPAD_BUTTON_MINUS)) + { + // Send a press event. + Key_Event(K_JOY17, ((wpad_keys & WPAD_BUTTON_MINUS) == WPAD_BUTTON_MINUS)); + } + +//Send nunchunk button events + if(nunchuk_connected) + { + if ((wpad_previous_keys & WPAD_NUNCHUK_BUTTON_Z) != (wpad_keys & WPAD_NUNCHUK_BUTTON_Z)) + { + // Send a press event. + Key_Event(K_JOY7, ((wpad_keys & WPAD_NUNCHUK_BUTTON_Z) == WPAD_NUNCHUK_BUTTON_Z)); + } + + if ((wpad_previous_keys & WPAD_NUNCHUK_BUTTON_C) != (wpad_keys & WPAD_NUNCHUK_BUTTON_C)) + { + // Send a press event. + Key_Event(K_JOY8, ((wpad_keys & WPAD_NUNCHUK_BUTTON_C) == WPAD_NUNCHUK_BUTTON_C)); + } + + //Con_Printf("oriy:%f, acy:%f\n", expansion.nunchuk.orient.pitch, expansion.nunchuk.gforce.y); + + if(expansion.nunchuk.orient.pitch <= 15 && expansion.nunchuk.gforce.y > 0.25) { + Key_Event(K_SHAKE, true); + } else { + Key_Event(K_SHAKE, false); + } + +//Emulation of the wimote arrows with the nunchuk stick + if(nunchuk_stick_as_arrows.value) + { + const s8 nunchuk_stick_x = WPAD_StickX(0); + const s8 nunchuk_stick_y = WPAD_StickY(0); + if (nunchuk_stick_x > 10) + { + switch (stick_x_st) + { + + case CENTER_X : Key_Event(K_RIGHTARROW, true);break; + default : break; + + } + stick_x_st = RIGHT; + } + + else if (nunchuk_stick_x < -10) + { + switch (stick_x_st) + { + case CENTER_X : Key_Event(K_LEFTARROW, true);break; + default: break; + + + } + stick_x_st = LEFT; + } + + else + { + switch (stick_x_st) + { + case LEFT : Key_Event(K_LEFTARROW, false);break; + case RIGHT: Key_Event(K_RIGHTARROW, false);break; + default: break; + } + stick_x_st = CENTER_X; + } + + if (nunchuk_stick_y > 10) + { + switch (stick_y_st) + { + case CENTER_Y : Key_Event(K_UPARROW, true); break; + default: break; + + } + stick_y_st = UP; + } + + else if (nunchuk_stick_y < -10) + { + switch (stick_y_st) + { + + case CENTER_Y : Key_Event(K_DOWNARROW, true);break; + default: break; + } + stick_y_st = DOWN; + } + + + else + { + switch (stick_y_st) + { + case DOWN : Key_Event(K_DOWNARROW, false);break; + case UP: Key_Event(K_UPARROW, false);break; + default: break; + } + stick_y_st = CENTER_Y; + } + + } + + } + } +//Send the gamecube controller button events in the case neither the nunchuk nor the classic controller is connected + if(!nunchuk_connected && !classic_connected) + { + if ((pad_previous_keys & PAD_BUTTON_LEFT) != (pad_keys & PAD_BUTTON_LEFT)) + { + // Send a press event. + Key_Event(K_LEFTARROW, ((pad_keys & PAD_BUTTON_LEFT) == PAD_BUTTON_LEFT)); + } + + if ((pad_previous_keys & PAD_BUTTON_RIGHT) != (pad_keys & PAD_BUTTON_RIGHT)) + { + // Send a press event. + Key_Event(K_RIGHTARROW, ((pad_keys & PAD_BUTTON_RIGHT) == PAD_BUTTON_RIGHT)); + } + + if ((pad_previous_keys & PAD_BUTTON_DOWN) != (pad_keys & PAD_BUTTON_DOWN)) + { + // Send a press event. + Key_Event(K_DOWNARROW, ((pad_keys & PAD_BUTTON_DOWN) == PAD_BUTTON_DOWN)); + } + if ((pad_previous_keys & PAD_BUTTON_UP) != (pad_keys & PAD_BUTTON_UP)) + { + // Send a press event. + Key_Event(K_UPARROW, ((pad_keys & PAD_BUTTON_UP) == PAD_BUTTON_UP)); + } + + if ((pad_previous_keys & PAD_BUTTON_A) != (pad_keys & PAD_BUTTON_A)) + { + // Send a press event. + Key_Event(K_JOY20, ((pad_keys & PAD_BUTTON_A) == PAD_BUTTON_A)); + } + + if ((pad_previous_keys & PAD_BUTTON_B) != (pad_keys & PAD_BUTTON_B)) + { + // Send a press event. + Key_Event(K_JOY21, ((pad_keys & PAD_BUTTON_B) == PAD_BUTTON_B)); + } + + if ((pad_previous_keys & PAD_BUTTON_X) != (pad_keys & PAD_BUTTON_X)) + { + // Send a press event. + Key_Event(K_JOY22, ((pad_keys & PAD_BUTTON_X) == PAD_BUTTON_X)); + } + + if ((pad_previous_keys & PAD_BUTTON_Y) != (pad_keys & PAD_BUTTON_Y)) + { + // Send a press event. + Key_Event(K_JOY23, ((pad_keys & PAD_BUTTON_Y) == PAD_BUTTON_Y)); + } + + if ((pad_previous_keys & PAD_TRIGGER_Z) != (pad_keys & PAD_TRIGGER_Z)) + { + // Send a press event. + Key_Event(K_JOY24, ((pad_keys & PAD_TRIGGER_Z) == PAD_TRIGGER_Z)); + } + + if ((pad_previous_keys & PAD_TRIGGER_R) != (pad_keys & PAD_TRIGGER_R)) + { + // Send a press event. + Key_Event(K_JOY25, ((pad_keys & PAD_TRIGGER_R) == PAD_TRIGGER_R)); + } + + if ((pad_previous_keys & PAD_TRIGGER_L) != (pad_keys & PAD_TRIGGER_L)) + { + // Send a press event. + Key_Event(K_JOY26, ((pad_keys & PAD_TRIGGER_L) == PAD_TRIGGER_L)); + } + + if ((pad_previous_keys & PAD_BUTTON_START) != (pad_keys & PAD_BUTTON_START)) + { + // Send a press event. + Key_Event(K_ESCAPE, ((pad_keys & PAD_BUTTON_START) == PAD_BUTTON_START)); + } + + pad_previous_keys = pad_keys; + } + + wpad_previous_keys = wpad_keys; +} + +extern float crosshair_opacity; +float centerdrift_offset_yaw, centerdrift_offset_pitch; +extern int zoom_snap; +extern kbutton_t in_forward, in_left, in_right; +extern qboolean croshhairmoving; +extern cvar_t ads_center; +extern cvar_t sniper_center; +// Some things here rely upon IN_Move always being called after IN_Commands on the same frame +void IN_Move (usercmd_t *cmd) +{ + const float dead_zone = 0.3f; + + float x1; + float y1; + float x2; + float y2; + + // TODO: sensor bar position correct? aspect ratio correctly set? etc... + // In "pointer" variable there are the IR values + int last_wiimote_ir_x = pointer.x; + int last_wiimote_ir_y = pointer.y; + int wiimote_ir_x = 0, wiimote_ir_y = 0; + + + if (pointer.x < 1 || (unsigned int)pointer.x > pointer.vres[0] - 1) + wiimote_ir_x = last_wiimote_ir_x; + else + wiimote_ir_x = pointer.x; + if (pointer.y < 1 || (unsigned int)pointer.y > pointer.vres[1] - 1) + wiimote_ir_y = last_wiimote_ir_y; + else + wiimote_ir_y = pointer.y; + + last_wiimote_ir_x = wiimote_ir_x; + last_wiimote_ir_y = wiimote_ir_y; + +// Movement management of nunchuk stick (x1/y1) and of IR (x2/y2) if the nunchuk is connected + if(nunchuk_connected && !nunchuk_stick_as_arrows.value) + { + const s8 nunchuk_stick_x = WPAD_StickX(0); + const s8 nunchuk_stick_y = WPAD_StickY(0); + + x1 = clamp(((float)nunchuk_stick_x / 128.0f) * 1.5, -1.0f, 1.0f); + y1 = clamp(((float)nunchuk_stick_y / (128.0f)) * 1.5, -1.0f, 1.0f); + + x2 = clamp((float)wiimote_ir_x / (pointer.vres[0] / 2.0f) - 1.0f, -1.0f, 1.0f); + y2 = clamp((float)wiimote_ir_y / (pointer.vres[1] / 2.0f) - 1.0f, -1.0f, 1.0f); + // Move the cross position + + // sB if sniper scope we want to aim in da middle + // Unless I can find a way to make the scope image + // move with pointer>>?? + // seems impossible in my mind + + if (aimsnap == true || (cl.stats[STAT_ZOOM] == 1 && ads_center.value) || (cl.stats[STAT_ZOOM] == 2 && sniper_center.value)) { + Cvar_SetValue("cl_crossx", vid.width / 2); + Cvar_SetValue("cl_crossy", vid.height / 2); + } else { + Cvar_SetValue("cl_crossx", vid.width / 2 * x2); + Cvar_SetValue("cl_crossy", vid.height / 2 * y2); + + //Con_Printf ("crossx: %f crossy %f\n", scr_vrect.width / 2 * x2, scr_vrect.height / 2 * y2); + } + } + +// Movement management of 2 classic controller sticks (x1/y1) and (y1/y2) if the cc is connected + + else if(classic_connected) + { + const s8 left_stick_x = WPAD_StickX(0); + const s8 left_stick_y = WPAD_StickY(0); + + const s8 right_stick_x = WPAD_StickX(1); + const s8 right_stick_y = WPAD_StickY(1); + + x1 = clamp(((float)left_stick_x / 128.0f) * 1.5, -1.0f, 1.0f); + y1 = clamp(((float)left_stick_y / (128.0f)) * 1.5, -1.0f, 1.0f); + + x2 = clamp(((float)right_stick_x / 128.0f) * 1.5, -1.0f, 1.0f); + Cvar_SetValue("cl_crossx", /*(in_vlock.state & 1) ? */scr_vrect.width / 2 * x2/* : 0*/); + y2 = clamp(((float)right_stick_y / (-128.0f)) * 1.5, -1.0f, 1.0f); + Cvar_SetValue("cl_crossy", /*(in_vlock.state & 1) ? */scr_vrect.height / 2 * y2/* : 0*/); + } +// Movement management of 2 gamecube controller sticks (x1/y1) e (y1/y2) if neither the cc nor nn is connected + else + { + const s8 stick_x = PAD_StickX(0); + const s8 stick_y = PAD_StickY(0); + + const s8 sub_stick_x = PAD_SubStickX(0); + const s8 sub_stick_y = PAD_SubStickY(0); + + x1 = clamp(stick_x / 90.0f, -1.0f, 1.0f); + y1 = clamp(stick_y / 90.0f, -1.0f, 1.0f); + + x2 = clamp(sub_stick_x / 80.0f, -1.0f, 1.0f); + Cvar_SetValue("cl_crossx", /*(in_vlock.state & 1) ? */scr_vrect.width / 2 * x2/* : 0*/); + + y2 = clamp(sub_stick_y / -80.0f, -1.0f, 1.0f); + Cvar_SetValue("cl_crossy", /*(in_vlock.state & 1) ? */scr_vrect.height / 2 * y2/* : 0*/); + } + + //non-linear sensitivity based on how + //far the IR pointer is from the + //center of the screen. + + /* + if (cl.stats[STAT_ZOOM] == 1 || cl.stats[STAT_ZOOM] == 2) { + centerdrift_offset_yaw = 1; //yaw + centerdrift_offset_pitch = 1; //pitch + } else {*/ + centerdrift_offset_yaw = fabsf(x2); //yaw + centerdrift_offset_pitch = fabsf(y2); //pitch + //} + + // Apply the dead zone. + apply_dead_zone(&x1, &y1, dead_zone); + apply_dead_zone(&x2, &y2, dead_zone); + + // Don't let the pitch drift back to centre if mouse look is on or the right stick is being used. + //if ((in_mlook.state & 1) || (fabsf(y2) >= dead_zone)) Disabled, always very convenient with a gamepad or wiimote + { + V_StopPitchDrift(); + } + + // Lock view? + if (in_vlock.state & 1) + { + x2 = 0; + y2 = 0; + } + + float yaw_rate; + float pitch_rate; + + yaw_rate = x2; + pitch_rate = y2; + + cl_backspeed = cl_forwardspeed = cl_sidespeed = sv_player->v.maxspeed; + cl_sidespeed *= 0.8; + cl_backspeed *= 0.7; + + // Move using the main stick. + //Send the stick movement commands + if (!(nunchuk_stick_as_arrows.value&&nunchuk_connected)) + { + cmd->sidemove += cl_sidespeed * x1; + if (y1>0) cmd->forwardmove += cl_forwardspeed * y1; /* TODO: use cl_backspeed when going backwards? */ + else cmd->forwardmove += cl_backspeed * y1; + + if (cmd->forwardmove == 0.0f && cmd->sidemove == 0.0f) + croshhairmoving = false; + else + croshhairmoving = true; + /* + //if the nunchuk c button is pressed it speeds up + if (in_speed.state & 1) + { + if (cl_forwardspeed > 200) + { + cmd->forwardmove /= cl_movespeedkey.value; + cmd->sidemove /= cl_movespeedkey.value; + } + else + { + cmd->forwardmove *= cl_movespeedkey.value; + cmd->sidemove *= cl_movespeedkey.value; // TODO: always seem to be at the max and I'm too sleepy now to figure out why + } + } + */ + } + + // TODO: Use yawspeed and pitchspeed + + // Adjust the yaw. + const float turn_rate = sensitivity.value * 40.0; + + float speed = 1; + + // cut look speed in half when facing enemy, unless mag is empty + if ((in_aimassist.value) && (sv_player->v.facingenemy == 1) && cl.stats[STAT_CURRENTMAG] > 0) + speed = 0.6; + else + speed = 1; + + // additionally, slice look speed when ADS/scopes + if (cl.stats[STAT_ZOOM] == 1) + speed = 0.5; + else if (cl.stats[STAT_ZOOM] == 2) + speed = 0.25; + else + speed = 1; + + // How fast to yaw? + float yaw_offset; + yaw_offset = ((turn_rate * yaw_rate * host_frametime) * speed) * centerdrift_offset_yaw; + cl.viewangles[YAW] -= yaw_offset; + + // How fast to pitch? + float pitch_offset; + pitch_offset = ((turn_rate * pitch_rate * host_frametime) * speed) * centerdrift_offset_pitch; + + // Do the pitch. + const bool invert_pitch = m_pitch.value < 0; + if (invert_pitch) + { + cl.viewangles[PITCH] -= pitch_offset; + } + else + { + cl.viewangles[PITCH] += pitch_offset; + } + + // Don't look too far up or down. + if (cl.viewangles[PITCH] > 60.0f) + { + cl.viewangles[PITCH] = 60.0f; + } + else if (cl.viewangles[PITCH] < -50.0f) + { + cl.viewangles[PITCH] = -50.0f; + } + + if (wiimote_connected && nunchuk_connected && !nunchuk_stick_as_arrows.value) + { + in_pitchangle = orientation.pitch; + in_yawangle = orientation.yaw; + in_rollangle = orientation.roll; + } + else + { + in_pitchangle = .0f; + in_yawangle = .0f; + in_rollangle = .0f; + } + +} + +extern double time_wpad_off; +extern int rumble_on; +void Wiimote_Rumble (int low_frequency, int high_frequency, int duration) { + if (!rumble.value) return; + double rumble_time; + rumble_time = duration / 1000.0; + //low frequency and high frequency not used for wiimote. read them anyways + + //it switches rumble on for rumble_time milliseconds + WPAD_Rumble(0, true); + rumble_on=1; + time_wpad_off = Sys_FloatTime() + rumble_time; +} diff --git a/source/wii/input_wiimote.h b/source/wii/input_wiimote.h new file mode 100644 index 0000000..dd303df --- /dev/null +++ b/source/wii/input_wiimote.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef __INPUT_WIIMOTE_H__ +#define __INPUT_WIIMOTE_H__ + +extern u32 wiimote_ir_res_x; +extern u32 wiimote_ir_res_y; + +#endif /* __INPUT_WIIMOTE_H__ */ diff --git a/source/wii/keys.c b/source/wii/keys.c new file mode 100644 index 0000000..1bc288c --- /dev/null +++ b/source/wii/keys.c @@ -0,0 +1,1023 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "../quakedef.h" +#include + +/* + +key up events are sent even if in console mode + +*/ + + +#define MAXCMDLINE 256 +char key_lines[64][MAXCMDLINE]; +int key_linepos; +int shift_down=false; +int key_lastpress; + +int edit_line=0; +int history_line=0; + +keydest_t key_dest; + +int key_count; // incremented every key event + +char *keybindings[256]; +char *dtbindings[256]; +qboolean consolekeys[256]; // if true, can't be rebound while in console +qboolean menubound[256]; // if true, can't be rebound while in menu +int keyshift[256]; // key to map to if shift held down in console +int key_repeats[256]; // if > 1, it is autorepeating +qboolean keydown[256]; + +qboolean keydown[KEY_COUNT]; + +extern bool nunchuk_connected; +extern u32 wpad_keys; + +typedef struct +{ + char *name; + key_id_t keynum; +} keyname_t; + +// Are we inside the on-screen keyboard? +qboolean in_osk = false; + +// \0 means not mapped... +// 5 * 15 +/* +char osk_normal[75] = +{ + '\'', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', ']', K_BACKSPACE, + 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 0, '[', K_ENTER, K_ENTER, + 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0, '~', '/', K_ENTER, K_ENTER, + 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', ';', K_ENTER, K_ENTER, K_ENTER, + 0 , 0, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, 0, 0 +}; + +char osk_shifted[75] = +{ + '\"', '!', '@', '#', '$', '%', 0, '&', '*', '(', ')', '_', '+', '}', K_BACKSPACE, + 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 0, '{', K_ENTER, K_ENTER, + 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0, '^', '?', K_ENTER, K_ENTER, + 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', ':', K_ENTER, K_ENTER, K_ENTER, + 0 , 0, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, K_SPACE, 0, 0 +}; + +char *osk_set; +int osk_selected; +int osk_last_selected; +int osk_coords[2]; + +float osk_last_press_time = 0.0f; +extern cvar_t osk_repeat_delay; +*/ +//int last_irx, last_iry; +/* +static float clampLine(float value, float minimum, float maximum) +{ + if (value > maximum) + { + return maximum; + } + else if (value < minimum) + { + return minimum; + } + else + { + return value; + } +} +*/ +static keyname_t keynames[] = +{ + {"TAB", K_TAB}, + {"ENTER", K_ENTER}, + {"ESCAPE", K_ESCAPE}, + {"SPACE", K_SPACE}, + {"BACKSPACE", K_BACKSPACE}, + {"UPARROW", K_UPARROW}, + {"DOWNARROW", K_DOWNARROW}, + {"LEFTARROW", K_LEFTARROW}, + {"RIGHTARROW", K_RIGHTARROW}, + + {"ALT", K_ALT}, + {"CTRL", K_CTRL}, + {"SHIFT", K_SHIFT}, + + {"F1", K_F1}, + {"F2", K_F2}, + {"F3", K_F3}, + {"F4", K_F4}, + {"F5", K_F5}, + {"F6", K_F6}, + {"F7", K_F7}, + {"F8", K_F8}, + {"F9", K_F9}, + {"F10", K_F10}, + {"F11", K_F11}, + {"F12", K_F12}, + + {"INS", K_INS}, + {"DEL", K_DEL}, + {"PGDN", K_PGDN}, + {"PGUP", K_PGUP}, + {"HOME", K_HOME}, + {"END", K_END}, + {"LSHIFT", K_LSHIFT}, + {"RSHIFT", K_RSHIFT}, + {"NUMLOCK", K_NUMLOCK}, + {"MENU", K_MENU}, + {"LMETA", K_LMETA}, + {"RMETA", K_RMETA}, + {"CAPSLOCK", K_CAPSLOCK}, + + {"MOUSE1", K_MOUSE1}, + {"MOUSE2", K_MOUSE2}, + {"MOUSE3", K_MOUSE3}, + + {"JOY0", K_JOY0}, + {"JOY1", K_JOY1}, + {"JOY2", K_JOY2}, + {"JOY3", K_JOY3}, + {"JOY4", K_JOY4}, + {"JOY5", K_JOY5}, + {"JOY6", K_JOY6}, + {"JOY7", K_JOY7}, + {"JOY8", K_JOY8}, + {"JOY9", K_JOY9}, + {"JOY10", K_JOY10}, + {"JOY11", K_JOY11}, + {"JOY12", K_JOY12}, + {"JOY13", K_JOY13}, + {"JOY14", K_JOY14}, + {"JOY15", K_JOY15}, + {"JOY16", K_JOY16}, + {"JOY17", K_JOY17}, + {"JOY18", K_JOY18}, + {"JOY19", K_JOY19}, + {"JOY20", K_JOY20}, + {"JOY21", K_JOY21}, + {"JOY22", K_JOY22}, + {"JOY23", K_JOY23}, + {"JOY24", K_JOY24}, + {"JOY25", K_JOY25}, + {"JOY26", K_JOY26}, + {"JOY27", K_JOY27}, + {"JOY28", K_JOY28}, + {"JOY29", K_JOY29}, + {"JOY30", K_JOY30}, + {"JOY31", K_JOY31}, + {"JOY32", K_JOY32}, + + {"PAUSE", K_PAUSE}, + + {"MWHEELUP", K_MWHEELUP}, + {"MWHEELDOWN", K_MWHEELDOWN}, + + {"SHAKENUN", K_SHAKE}, + + {"SEMICOLON", ';'}, // because a raw semicolon seperates commands + + {NULL,0} +}; + +/* +============================================================================== + + LINE TYPING INTO THE CONSOLE + +============================================================================== +*/ +//#define MAX_Y 8 +//#define MAX_X 12 +//#define MAX_CHAR_LINE 35 +#define MAX_Y 12 +#define MAX_X 18 +#define MAX_CHAR_LINE 54 + +extern int osk_pos_x; +extern int osk_pos_y; +extern char osk_buffer[128]; + +// naievil -- quick hack to make everything work properly +char *osk_text2 [] = +{ + " 1 2 3 4 5 6 7 8 9 0 - = ` ", + " q w e r t y u i o p [ ] ", + " a s d f g h j k l ; ' \\ ", + " z x c v b n m , . / ", + " ", + " ! @ # $ % ^ & * ( ) _ + ~ ", + " Q W E R T Y U I O P { } ", + " A S D F G H J K L : \" | ", + " Z X C V B N M < > ? " +}; +/* +==================== +Key_Console + +Interactive line editing and console scrollback +==================== +*/ +extern qboolean console_enabled; +qboolean Con_isSetOSKActive(void); +void Con_SetOSKActive(qboolean active); +void Key_Console (int key) +{ + char *cmd; + //static char current[MAXCMDLINE] = ""; + //int history_line_last; + //size_t len; + char *workline = key_lines[edit_line]; + + // minus is to open console + if (Con_isSetOSKActive()) + { + switch(key) { + case K_JOY0: + if (MAX_CHAR_LINE > strlen(osk_buffer)) { + char *selected_line = osk_text2[osk_pos_y]; + char selected_char[2]; + + selected_char[0] = selected_line[1+(2*osk_pos_x)]; + + if (selected_char[0] == '\t') + selected_char[0] = ' '; + + selected_char[1] = '\0'; + strcat(osk_buffer,selected_char); + } + break; + + case K_JOY17: + strncpy(workline,osk_buffer,MAX_CHAR_LINE); + //strcpy(key_lines[edit_line],workline); + Con_SetOSKActive(false); + break; + + case K_JOY1: + Con_SetOSKActive(false); + if (strlen(osk_buffer) > 1) { + osk_buffer[strlen(osk_buffer)-1] = '\0'; + } + break; + + case K_RIGHTARROW: + osk_pos_x++; + if (osk_pos_x > MAX_X) + osk_pos_x = 0;//MAX_X + break; + + case K_LEFTARROW: + osk_pos_x--; + if (osk_pos_x < 0) + osk_pos_x = MAX_X;//0 + break; + + case K_DOWNARROW: + osk_pos_y++; + if (osk_pos_y > MAX_Y) + osk_pos_y = 0;//MAX_Y + break; + case K_UPARROW: + osk_pos_y--; + if (osk_pos_y < 0) + osk_pos_y = MAX_Y;//0 + break; + + default: + break; + } + } else { + if (key == K_JOY0) + { + Cbuf_AddText (key_lines[edit_line]+1); // skip the > + Cbuf_AddText ("\n"); + Con_Printf ("%s\n",key_lines[edit_line]); + edit_line = (edit_line + 1) & 31; + history_line = edit_line; + key_lines[edit_line][0] = ']'; + key_linepos = 1; + if (cls.state == ca_disconnected) + SCR_UpdateScreen (); // force an update, because the command + // may take some time + return; + } + + if (key == K_TAB) + { // command completion + cmd = Cmd_CompleteCommand (key_lines[edit_line]+1); + if (!cmd) + cmd = Cvar_CompleteVariable (key_lines[edit_line]+1); + if (cmd) + { + strcpy (key_lines[edit_line]+1, cmd); + key_linepos = Q_strlen(cmd)+1; + key_lines[edit_line][key_linepos] = ' '; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + return; + } + } + + if (key == K_JOY17) { + Con_SetOSKActive(true); + //strcpy(osk_buffer, workline); + return; + } + + if (key == K_BACKSPACE) + { + if (key_linepos > 1) + key_linepos--; + return; + } + + if (key == K_UPARROW) + { + do + { + history_line = (history_line - 1) & 31; + } while (history_line != edit_line + && !key_lines[history_line][1]); + if (history_line == edit_line) + history_line = (edit_line+1)&31; + strcpy(key_lines[edit_line], key_lines[history_line]); + key_linepos = Q_strlen(key_lines[edit_line]); + return; + } + + if (key == K_DOWNARROW) + { + if (history_line == edit_line) return; + do + { + history_line = (history_line + 1) & 31; + } + while (history_line != edit_line + && !key_lines[history_line][1]); + if (history_line == edit_line) + { + key_lines[edit_line][0] = ']'; + key_linepos = 1; + } + else + { + strcpy(key_lines[edit_line], key_lines[history_line]); + key_linepos = Q_strlen(key_lines[edit_line]); + } + return; + } + + if (key == K_PGUP || key==K_MWHEELUP) + { + con_backscroll += 2; + if (con_backscroll > con_totallines - (vid.conheight>>3) - 1) + con_backscroll = con_totallines - (vid.conheight>>3) - 1; + return; + } + + if (key == K_PGDN || key==K_MWHEELDOWN) + { + con_backscroll -= 2; + if (con_backscroll < 0) + con_backscroll = 0; + return; + } + + if (key == K_HOME) + { + con_backscroll = con_totallines - (vid.conheight>>3) - 1; + return; + } + + if (key == K_END) + { + //console_enabled = false; + //con_backscroll = 0; + return; + } + + if (key < 32 || key > 127) + return; // non printable + + if (key_linepos < MAXCMDLINE-1) + { + key_lines[edit_line][key_linepos] = key; + key_linepos++; + key_lines[edit_line][key_linepos] = 0; + } + if (key == K_JOY1) { + //console_enabled = false; + //con_backscroll = 0; + return; + } + + } + +} + +//============================================================================ + +char chat_buffer[32]; +qboolean team_message = false; + +void Key_Message (key_id_t key) +{ + static int chat_bufferlen = 0; + + if (key == K_ENTER) + { + if (team_message) + Cbuf_AddText ("say_team \""); + else + Cbuf_AddText ("say \""); + Cbuf_AddText(chat_buffer); + Cbuf_AddText("\"\n"); + + key_dest = key_game; + chat_bufferlen = 0; + chat_buffer[0] = 0; + return; + } + + if (key == K_ESCAPE) + { + console_enabled = false; + key_dest = key_game; + chat_bufferlen = 0; + chat_buffer[0] = 0; + return; + } + + if (key < 32 || key > 127) + return; // non printable + + if (key == K_BACKSPACE) + { + if (chat_bufferlen) + { + chat_bufferlen--; + chat_buffer[chat_bufferlen] = 0; + } + return; + } + + if (chat_bufferlen == 31) + return; // all full + + chat_buffer[chat_bufferlen++] = key; + chat_buffer[chat_bufferlen] = 0; +} + +//============================================================================ + + +/* +=================== +Key_StringToKeynum + +Returns a key number to be used to index keybindings[] by looking at +the given string. Single ascii characters return themselves, while +the K_* names are matched up. +=================== +*/ +int Key_StringToKeynum (char *str) +{ + keyname_t *kn; + + if (!str || !str[0]) + return -1; + if (!str[1]) + return str[0]; + + for (kn=keynames ; kn->name ; kn++) + { + if (!Q_strcasecmp(str,kn->name)) + return kn->keynum; + } + return -1; +} + +/* +=================== +Key_KeynumToString + +Returns a string (either a single ascii char, or a K_* name) for the +given keynum. +FIXME: handle quote special (general escape sequence?) +=================== +*/ +char *Key_KeynumToString (int keynum) +{ + keyname_t *kn; + static char tinystr[2]; + + if (keynum == -1) + return ""; + if (keynum > 32 && keynum < 127) + { // printable ascii + tinystr[0] = keynum; + tinystr[1] = 0; + return tinystr; + } + + for (kn=keynames ; kn->name ; kn++) + if (keynum == kn->keynum) + return kn->name; + + return ""; +} + + +/* +=================== +Key_SetBinding +=================== +*/ +void Key_SetBinding (key_id_t keynum, char *binding) +{ + char *new; + int l; + + if (keynum == -1) + return; + +// free old bindings + if (keybindings[keynum]) + { + Z_Free (keybindings[keynum]); + keybindings[keynum] = NULL; + } + +// allocate memory for new binding + l = Q_strlen (binding); + new = Z_Malloc (l+1); + strcpy (new, binding); + new[l] = 0; + keybindings[keynum] = new; +} + +/* +=================== +Key_SetDTBinding +=================== +*/ +void Key_SetDTBinding (int keynum, char *binding) +{ + char *new; + int l; + + if (keynum == -1) + return; + +// free old bindings + if (dtbindings[keynum]) + { + Z_Free (dtbindings[keynum]); + dtbindings[keynum] = NULL; + } + +// allocate memory for new binding + l = strlen (binding); + new = Z_Malloc (l+1); + strcpy (new, binding); + new[l] = 0; + dtbindings[keynum] = new; +} + +/* +=================== +Key_Unbind_f +=================== +*/ +void Key_Unbind_f (void) +{ + int b; + + if (Cmd_Argc() != 2) + { + Con_Printf ("unbind : remove commands from a key\n"); + return; + } + + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + Key_SetBinding (b, ""); +} + +void Key_Unbindall_f (void) +{ + int i; + + for (i=0 ; i [command] : attach a command to a key\n"); + return; + } + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + if (c == 2) + { + if (keybindings[b]) + Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), keybindings[b] ); + else + Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); + return; + } + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i=2 ; i< c ; i++) + { + if (i > 2) + strcat (cmd, " "); + strcat (cmd, Cmd_Argv(i)); + } + + Key_SetBinding (b, cmd); +} + +/* +=================== +Key_Binddt_f +=================== +*/ +void Key_Binddt_f (void) +{ + int i, c, b; + char cmd[1024]; + + c = Cmd_Argc(); + + if (c != 2 && c != 3) + { + Con_Printf ("binddt [command] : attach a command to a double tap key\n"); + return; + } + b = Key_StringToKeynum (Cmd_Argv(1)); + if (b==-1) + { + Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1)); + return; + } + + if (c == 2) + { + if (dtbindings[b]) + Con_Printf ("\"%s\" = \"%s\"\n", Cmd_Argv(1), dtbindings[b] ); + else + Con_Printf ("\"%s\" is not bound\n", Cmd_Argv(1) ); + return; + } + +// copy the rest of the command line + cmd[0] = 0; // start out with a null string + for (i=2 ; i< c ; i++) + { + if (i > 2) + strcat (cmd, " "); + strcat (cmd, Cmd_Argv(i)); + } + + Key_SetDTBinding (b, cmd); +} + +/* +============ +Key_WriteBindings + +Writes lines containing "bind key value" +============ +*/ +void Key_WriteBindings (FILE *f) +{ + int i; + + for (i=0 ; i 1) + { + return; // ignore most autorepeats + } + + if (key >= K_BACKSPACE && !keybindings[key]) + Con_Printf ("%s is unbound, use the options screen to set.\n", Key_KeynumToString (key) ); + } + + if (key == K_SHIFT) + shift_down = down; + +// +// handle escape specialy, so the user can never unbind it +// + /* + if (key == K_JOY1) + { + if (!down) + return; + switch (key_dest) + { + case key_message: + Key_Message (key); + break; + case key_menu: + case key_menu_pause: + M_Keydown (key); + break; + case key_game: + break; + case key_console: + console_enabled = false; + M_ToggleMenu_f (); + break; + default: + Sys_Error ("Bad key_dest"); + } + return; + } + */ +// +// key up events only generate commands if the game key binding is +// a button command (leading + sign). These will occur even in console mode, +// to keep the character from continuing an action started before a console +// switch. Button commands include the kenum as a parameter, so multiple +// downs can be matched with ups +// + if (!down) + { + kb = keybindings[key]; + if (kb && kb[0] == '+') + { + sprintf (cmd, "-%s %i\n", kb+1, key); + Cbuf_AddText (cmd); + } + if (keyshift[key] != key) + { + kb = keybindings[keyshift[key]]; + if (kb && kb[0] == '+') + { + sprintf (cmd, "-%s %i\n", kb+1, key); + Cbuf_AddText (cmd); + } + } + return; + } + +// +// during demo playback, most keys bring up the main menu +// + if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) + { + M_ToggleMenu_f (); + return; + } + +// +// if not a consolekey, send to the interpreter no matter what mode is +// + if ((key_dest == key_menu && menubound[key]) || + (key_dest == key_console && !consolekeys[key]) || + (key_dest == key_game && (!con_forcedup || !consolekeys[key]))) + { + kb = keybindings[key]; + if (kb) + { + if (kb[0] == '+') + { // button commands add keynum as a parm + sprintf (cmd, "%s %i\n", kb, key); + Cbuf_AddText (cmd); + } + else + { + Cbuf_AddText (kb); + Cbuf_AddText ("\n"); + } + } + return; + } + + if (!down) + return; // other systems only care about key down events + + if (shift_down) + { + key = keyshift[key]; + } + switch (key_dest) + { + case key_message: + Key_Message (key); + break; + case key_menu: + case key_menu_pause: + M_Keydown (key); + break; + + case key_game: + case key_console: { + Key_Console (key); + break; + } + default: + Sys_Error ("Bad key_dest"); + } +} + + +/* +=================== +Key_ClearStates +=================== +*/ +void Key_ClearStates (void) +{ + int i; + + for (i=0 ; i +#include +#include +#include +#include +#include +#include +#include "input_wiimote.h" + +#if USBGECKO_DEBUG || WIFI_DEBUG +#include +#endif + +#include +#include +#include + +#include "../quakedef.h" + +//u32 MALLOC_MEM2 = 0; + +extern void Sys_Reset(void); +extern void Sys_Shutdown(void); + +// Video globals. +void *framebuffer[2] = {NULL, NULL}; +u32 fb = 0; +GXRModeObj *rmode = 0; + +int want_to_reset = 0; +int want_to_shutdown = 0; +double time_wpad_off = 0; +double current_time = 0; +int rumble_on = 0; + +// Set up the heap. +static size_t heap_size = 39 * 1024 * 1024; +static char *heap; +static u32 real_heap_size; +float sys_frame_length; + +// ELUTODO: ugly and beyond quake's limits, I think +int parms_number = 0; +char parms[1024]; +char *parms_ptr = parms; +char *parms_array[64]; + +void reset_system(void) +{ + want_to_reset = 1; +} + +void shutdown_system(void) +{ + want_to_shutdown = 1; +} + +inline void *align32 (void *p) +{ + return (void*)((((int)p + 31)) & 0xffffffe0); +} +void GL_Init (void); +static void init() +{ + // Initialise the video system. + VIDEO_Init(); + VIDEO_SetBlack(true); + rmode = VIDEO_GetPreferredMode(NULL); + + // Allocate the frame buffer. + framebuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + framebuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + + fb = 0; + + // 16:9 and 4:3 Screen Adjustment for Wii + if (CONF_GetAspectRatio() == CONF_ASPECT_16_9) { + rmode->viWidth = 672; + } else { // 4:3 + rmode->viWidth = 640; + } + + // This probably needs to consider PAL + rmode->viXOrigin = (VI_MAX_WIDTH_NTSC - rmode->viWidth) / 2; + + // Set up the video system with the chosen mode. + VIDEO_Configure(rmode); + + // Set the frame buffer. + VIDEO_SetNextFramebuffer(framebuffer[fb]); + + VIDEO_Flush(); + VIDEO_WaitVSync(); + if (rmode->viTVMode & VI_NON_INTERLACE) + { + VIDEO_WaitVSync(); + } + + fb++; + + // Initialise the debug console. + // ELUTODO: only one framebuffer with it? + console_init(framebuffer[fb & 1], 20, 20, rmode->fbWidth, rmode->xfbHeight, rmode->fbWidth * 2); + + GL_Init(); + + //VIDEO_SetBlack(false); + + // Initialise the controller library. + PAD_Init(); + // Initialise the keyboard library + KEYBOARD_Init(NULL); + + if(!fatInitDefault()) + printf("Error initializing filesystem\n"); + + Sys_Init_Logfile(); + +#ifndef DISABLE_WIIMOTE + if (WPAD_Init() != WPAD_ERR_NONE) + Sys_Error("WPAD_Init() failed.\n"); +#endif + + wiimote_ir_res_x = rmode->fbWidth; + wiimote_ir_res_y = rmode->xfbHeight; + + // hope the parms are all set by now + if (parms_number > 0 ) { + COM_InitArgv(parms_number, parms_array); + } + + // Initialise the Host module. + quakeparms_t parms; + memset(&parms, 0, sizeof(parms)); + parms.argc = com_argc; + parms.argv = com_argv; + parms.basedir = QUAKE_WII_BASEDIR; + parms.memsize = real_heap_size; + parms.membase = heap; + if (parms.membase == 0) + { + Sys_Error("Heap allocation failed"); + } + memset(parms.membase, 0, parms.memsize); + Host_Init(&parms); + +#if TEST_CONNECTION + Cbuf_AddText("connect 192.168.0.2"); +#endif + + SYS_SetResetCallback(reset_system); + SYS_SetPowerCallback(shutdown_system); +} + +int cstring_cmp(const void *p1, const void *p2) +{ + return strcmp(*(char * const *)p1, *(char * const *)p2); +} + +qboolean isDedicated = false; + +void alloc_main_heap (void) { + u32 level; + + _CPU_ISR_Disable(level); + heap = (char *)align32(SYS_GetArena2Lo()); + real_heap_size = heap_size - ((u32)heap - (u32)SYS_GetArena2Lo()); + if ((u32)heap + real_heap_size > (u32)SYS_GetArena2Hi()) + { + _CPU_ISR_Restore(level); + Sys_Error("heap + real_heap_size > (u32)SYS_GetArena2Hi()"); + } + else + { + SYS_SetArena2Lo(heap + real_heap_size); + _CPU_ISR_Restore(level); + } +} + +int main(int argc, char* argv[]) +{ + // is this safe to do? I'm not sure yet> + // could lock out iOS functionality temporarily? + L2Enhance(); // sB activate 64-byte fetches for the L2 cache + +#if USBGECKO_DEBUG + DEBUG_Init(GDBSTUB_DEVICE_USB, 1); // Slot B + _break(); +#endif + +#if WIFI_DEBUG + printf("Now waiting for WI-FI debugger\n"); + DEBUG_Init(GDBSTUB_DEVICE_WIFI, 8000); // Port 8000 (use whatever you want) + _break(); +#endif + + // Initialize. + alloc_main_heap (); + init(); + + // Run the main loop. + double current_time, last_time; + + last_time = Sys_FloatTime (); + + for (;;) + { + if (want_to_reset) + Sys_Reset(); + if (want_to_shutdown) + Sys_Shutdown(); + + // Get the frame time in ticks. + current_time = Sys_FloatTime (); + // Run the frame. + Host_Frame(current_time - last_time); + last_time = current_time; + + //Con_Printf ("time: %f \n", current_time_millisec); + //Con_Printf ("time off: %f \n", time_wpad_off_millisec); + + if (rumble_on&&(current_time > time_wpad_off)) + { + WPAD_Rumble(0, false); + rumble_on = 0; + } + }; + + exit(0); + return 0; +} diff --git a/source/wii/menu.c b/source/wii/menu.c new file mode 100644 index 0000000..37a7fd0 --- /dev/null +++ b/source/wii/menu.c @@ -0,0 +1,3597 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "../quakedef.h" + +enum +{ + m_none, + m_start, + m_main, + m_paused_menu, + m_singleplayer, + m_load, + m_save, + m_custommaps, + m_setup, + m_net, + m_options, + m_video, + m_keys, + m_options2, + m_help, + m_quit, + m_restart, + m_credits, + m_exit, + m_serialconfig, + m_modemconfig, + m_lanconfig, + m_gameoptions, + m_search, + m_slist, +} m_state; + + void M_Menu_Load_f (void); + void M_Menu_Save_f (void); + void M_Menu_MultiPlayer_f (void); + void M_Menu_Setup_f (void); + void M_Menu_Net_f (void); + void M_Menu_Options_f (void); + void M_Menu_Options2_f (void); + void M_Menu_Help_f (void); +void M_Menu_LanConfig_f (void); +void M_Menu_GameOptions_f (void); +void M_Menu_Search_f (void); +void M_Menu_ServerList_f (void); +void M_Paused_Menu_f (void); + + void M_Load_Draw (void); + void M_Save_Draw (void); + void M_MultiPlayer_Draw (void); + void M_Setup_Draw (void); + void M_Net_Draw (void); + void M_Options_Draw (void); + void M_Options2_Draw (void); + void M_Help_Draw (void); +void M_LanConfig_Draw (void); +void M_GameOptions_Draw (void); +void M_Search_Draw (void); +void M_ServerList_Draw (void); + + void M_Load_Key (int key); + void M_Save_Key (int key); + void M_MultiPlayer_Key (int key); + void M_Setup_Key (int key); + void M_Net_Key (int key); + void M_Options_Key (int key); + void M_Options2_Key (int key); + void M_Help_Key (int key); +void M_LanConfig_Key (int key); +void M_GameOptions_Key (int key); +void M_Search_Key (int key); +void M_ServerList_Key (int key); + + +void M_Menu_Main_f (void); + void M_Menu_SinglePlayer_f (void); + void M_Menu_CustomMaps_f (void); + void M_Menu_Options_f (void); + void M_Menu_Keys_f (void); + void M_Menu_Video_f (void); + void M_Menu_Credits_f (void); + void M_Menu_Quit_f (void); +void M_Menu_GameOptions_f (void); + +void M_Main_Draw (void); + void M_SinglePlayer_Draw (void); + void M_Menu_CustomMaps_Draw (void); + void M_Options_Draw (void); + void M_Keys_Draw (void); + void M_Video_Draw (void); + void M_Menu_Credits_Draw (void); + void M_Quit_Draw (void); + +void M_Main_Key (int key); + void M_SinglePlayer_Key (int key); + void M_Menu_CustomMaps_Key (int key); + void M_Options_Key (int key); + void M_Keys_Key (int key); + void M_Video_Key (int key); + void M_Menu_Credits_Key (int key); + void M_Quit_Key (int key); +void M_GameOptions_Key (int key); + +void M_Menu_Restart_f (void); +void M_Menu_Exit_f (void); + +qboolean m_entersound; // play after drawing a frame, so caching + // won't disrupt the sound +qboolean m_recursiveDraw; + +int m_return_state; +qboolean m_return_onerror; +char m_return_reason [32]; + +typedef struct +{ + int occupied; + int map_allow_game_settings; + int map_use_thumbnail; + char* map_name; + char* map_name_pretty; + char* map_desc_1; + char* map_desc_2; + char* map_desc_3; + char* map_desc_4; + char* map_desc_5; + char* map_desc_6; + char* map_desc_7; + char* map_desc_8; + char* map_author; + char* map_thumbnail_path; +} usermap_t; + +usermap_t custom_maps[50]; + +// Backgrounds +qpic_t *menu_bk; + +// Map screens +qpic_t *menu_ndu; +qpic_t *menu_wh; +qpic_t *menu_wh2; +//qpic_t *menu_kn; +qpic_t *menu_ch; +//qpic_t *menu_wn; +qpic_t *menu_custom; +qpic_t *menu_cuthum; + +extern cvar_t waypoint_mode; + +extern int loadingScreen; +extern char* loadname2; +extern char* loadnamespec; +extern qboolean loadscreeninit; + +char* game_build_date; + +#define StartingGame (m_multiplayer_cursor == 1) +#define JoiningGame (m_multiplayer_cursor == 0) +#define TCPIPConfig (m_net_cursor == 3) + +void M_ConfigureNetSubsystem(void); + +/* +================ +M_DrawCharacter + +Draws one solid graphics character +================ +*/ +void M_DrawCharacter (int cx, int line, int num) +{ + Draw_Character ( cx + ((vid.conwidth - 320)>>1), line, num); +} + +void M_Print (int cx, int cy, char *str) +{ + while (*str) + { + M_DrawCharacter (cx, cy, (*str)+128); + str++; + cx += 8; + } +} + +void M_PrintWhite (int cx, int cy, char *str) +{ + while (*str) + { + M_DrawCharacter (cx, cy, *str); + str++; + cx += 8; + } +} + +void M_DrawTransPic (int x, int y, qpic_t *pic) +{ + Draw_TransPic (x + ((vid.conwidth - 320)>>1), y, pic); +} + +void M_DrawPic (int x, int y, qpic_t *pic) +{ + Draw_Pic (x + ((vid.conwidth - 320)>>1), y, pic); +} + +byte identityTable[256]; +byte translationTable[256]; + +void M_BuildTranslationTable(int top, int bottom) +{ + int j; + byte *dest, *source; + + for (j = 0; j < 256; j++) + identityTable[j] = j; + dest = translationTable; + source = identityTable; + memcpy (dest, source, 256); + + if (top < 128) // the artists made some backwards ranges. sigh. + memcpy (dest + TOP_RANGE, source + top, 16); + else + for (j=0 ; j<16 ; j++) + dest[TOP_RANGE+j] = source[top+15-j]; + + if (bottom < 128) + memcpy (dest + BOTTOM_RANGE, source + bottom, 16); + else + for (j=0 ; j<16 ; j++) + dest[BOTTOM_RANGE+j] = source[bottom+15-j]; +} + + +void M_DrawTransPicTranslate (int x, int y, qpic_t *pic) +{ + Draw_TransPicTranslate (x + ((vid.conwidth - 320)>>1), y, pic, translationTable); +} + +void M_DrawTextBox (int x, int y, int width, int lines) +{ + + qpic_t *p; + int cx, cy; + int n; + + // draw left side + cx = x; + cy = y; + p = Draw_LMP ("gfx/box_tl.lmp"); + M_DrawTransPic (cx, cy, p); + p = Draw_LMP ("gfx/box_ml.lmp"); + for (n = 0; n < lines; n++) + { + cy += 8; + M_DrawTransPic (cx, cy, p); + } + p = Draw_LMP ("gfx/box_bl.lmp"); + M_DrawTransPic (cx, cy+8, p); + + // draw middle + cx += 8; + while (width > 0) + { + cy = y; + p = Draw_LMP ("gfx/box_tm.lmp"); + M_DrawTransPic (cx, cy, p); + p = Draw_LMP ("gfx/box_mm.lmp"); + for (n = 0; n < lines; n++) + { + cy += 8; + if (n == 1) + p = Draw_LMP ("gfx/box_mm2.lmp"); + M_DrawTransPic (cx, cy, p); + } + p = Draw_LMP ("gfx/box_bm.lmp"); + M_DrawTransPic (cx, cy+8, p); + width -= 2; + cx += 16; + } + + // draw right side + cy = y; + p = Draw_LMP ("gfx/box_tr.lmp"); + M_DrawTransPic (cx, cy, p); + p = Draw_LMP ("gfx/box_mr.lmp"); + for (n = 0; n < lines; n++) + { + cy += 8; + M_DrawTransPic (cx, cy, p); + } + p = Draw_LMP ("gfx/box_br.lmp"); + M_DrawTransPic (cx, cy+8, p); + + return; +} + +//============================================================================= + +void M_Load_Menu_Pics () +{ + menu_bk = Draw_CachePic("gfx/menu/menu_background"); + menu_ndu = Draw_CachePic("gfx/menu/nacht_der_untoten"); + //menu_kn = Draw_CachePic("gfx/menu/kino_der_toten"); + menu_wh = Draw_CachePic("gfx/menu/nzp_warehouse"); + menu_wh2 = Draw_CachePic("gfx/menu/nzp_warehouse2"); + //menu_wn = Draw_CachePic("gfx/menu/wahnsinn"); + menu_ch = Draw_CachePic("gfx/menu/christmas_special"); + menu_custom = Draw_CachePic("gfx/menu/custom"); +} + +int m_save_demonum; + +/* +================ +M_ToggleMenu_f +================ +*/ +void M_ToggleMenu_f (void) +{ + m_entersound = true; + + if (key_dest == key_menu || key_dest == key_menu_pause) + { + if (m_state != m_main && m_state != m_paused_menu) + { + M_Menu_Main_f (); + return; + } + key_dest = key_game; + m_state = m_none; + return; + } + if (key_dest == key_console) + { + Con_ToggleConsole_f (); + } + else if (sv.active && (svs.maxclients > 1 || key_dest == key_game)) + { + M_Paused_Menu_f(); + } + else + { + M_Menu_Main_f (); + } +} + +int M_Paused_Cusor; +#define Max_Paused_Iteams 5 + +void M_Paused_Menu_f () +{ + key_dest = key_menu_pause; + m_state = m_paused_menu; + m_entersound = true; + loadingScreen = 0; + loadscreeninit = false; + M_Paused_Cusor = 0; +} + +static void M_Paused_Menu_Draw () +{ + // Fill black to make everything easier to see + Draw_FillByColor(0, 0, 680, 340, 0, 0, 0, 80); + + // Header + Draw_ColoredString(30, 20, "PAUSED", 255, 255, 255, 255, 3); + + if ((M_Paused_Cusor == 0)) + Draw_ColoredString(30, 200, "Resume", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(30, 200, "Resume", 255, 255, 255, 255, 1.5); + + if ((M_Paused_Cusor == 1)) + Draw_ColoredString(30, 220, "Restart", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(30, 220, "Restart", 255, 255, 255, 255, 1.5); + + if ((M_Paused_Cusor == 2)) + Draw_ColoredString(30, 240, "Settings", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(30, 240, "Settings", 255, 255, 255, 255, 1.5); + + if (waypoint_mode.value) { + if ((M_Paused_Cusor == 3)) + Draw_ColoredString(30, 260, "Save Waypoints", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(30, 260, "Save Waypoints", 255, 255, 255, 255, 1.5); + } else { + if ((M_Paused_Cusor == 3)) + Draw_ColoredString(30, 260, "Achievements", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(30, 260, "Achievements", 255, 255, 255, 255, 1.5); + } + + if ((M_Paused_Cusor == 4)) + Draw_ColoredString(30, 280, "Main Menu", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(30, 280, "Main Menu", 255, 255, 255, 255, 1.5); +} + +static void M_Paused_Menu_Key (int key) +{ + switch (key) + { + case K_BACKSPACE: + case K_ESCAPE: + case K_JOY1: + S_LocalSound ("sounds/menu/enter.wav"); + Cbuf_AddText("togglemenu\n"); + break; + + case K_DOWNARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + if (++M_Paused_Cusor >= Max_Paused_Iteams) + M_Paused_Cusor = 0; + break; + + case K_UPARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + if (--M_Paused_Cusor < 0) + M_Paused_Cusor = Max_Paused_Iteams - 1; + break; + + case K_ENTER: + case K_JOY0: + m_entersound = true; + + switch (M_Paused_Cusor) + { + case 0: + key_dest = key_game; + m_state = m_none; + break; + case 1: + M_Menu_Restart_f(); + break; + case 2: + M_Menu_Options_f(); + key_dest = key_menu_pause; + break; + case 3: + if (waypoint_mode.value) { + Cbuf_AddText("impulse 101\n"); + } + /*else + M_Menu_Achievement_f(); + */ // naievil -- fixme: do not have achievements + key_dest = key_menu_pause; + break; + case 4: + M_Menu_Exit_f(); + break; + } + } +} + +//============================================================================= +/* CREDITS MENU */ + + +void M_Menu_Credits_f (void) +{ + key_dest = key_menu; + m_state = m_credits; + m_entersound = true; +} + +void M_Credits_Draw (void) +{ + // Background + menu_bk = Draw_CachePic("gfx/menu/menu_background"); + Draw_StretchPic(0, 0, menu_bk, vid.width, vid.height); + + // Fill black to make everything easier to see + Draw_FillByColor(0, 0, 400, 240, 0, 0, 0, 102); + + // Header + Draw_ColoredString(5, 5, "CREDITS", 255, 255, 255, 255, 3); + + Draw_ColoredString(5, 30, "Programming:", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 40, "Blubs, Jukki, DR_Mabuse1981, Naievil", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 50, "Cypress, ScatterBox", 255, 255, 255, 255, 1.5); + + Draw_ColoredString(5, 70, "Models:", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 80, "Blubs, Ju[s]tice, Derped_Crusader", 255, 255, 255, 255, 1.5); + + Draw_ColoredString(5, 100, "GFX:", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 110, "Blubs, Ju[s]tice, Cypress, Derped_Crusader", 255, 255, 255, 255, 1.5); + + Draw_ColoredString(5, 130, "Sounds/Music:", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 140, "Blubs, Biodude, Cypress, Marty P.", 255, 255, 255, 255, 1.5); + + Draw_ColoredString(5, 160, "Special Thanks:", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 170, "- Spike, Eukara: FTEQW", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 180, "- Shpuld: CleanQC4FTE", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 190, "- Crow_Bar, st1x51: dQuake(plus)", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 200, "- fgsfdsfgs: Quakespasm-NX", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 210, "- MasterFeizz: ctrQuake", 255, 255, 255, 255, 1.5); + Draw_ColoredString(5, 220, "- Rinnegatamante: Initial VITA Port & Updater", 255, 255, 255, 255, 1.5); + + Draw_ColoredString(5, 230, "Back", 255, 0, 0, 255, 1.5); +} + + +void M_Credits_Key (int key) +{ + switch (key) + { + case K_ENTER: + case K_JOY0: + case K_JOY1: + M_Menu_Main_f (); + break; + } +} + +//============================================================================= +/* RESTART MENU */ + +qboolean wasInMenus; + + +char *restartMessage [] = +{ + + " Are you sure you want", + " to restart this game? ", //msg:0 + " ", + " A :Yes B : No " +}; + + +void M_Menu_Restart_f (void) +{ + wasInMenus = (key_dest == key_menu_pause); + key_dest = key_menu_pause; + m_state = m_restart; + m_entersound = true; +} + + +void M_Restart_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case 'n': + case 'N': + m_state = m_paused_menu; + m_entersound = true; + break; + + case 'Y': + case 'y': + case K_ENTER: + case K_JOY0: + key_dest = key_game; + m_state = m_none; + // Cbuf_AddText ("restart\n"); // nai -- old, now do soft reset + PR_ExecuteProgram (pr_global_struct->Soft_Restart); + break; + + default: + break; + } + +} + + +void M_Restart_Draw (void) +{ + m_state = m_paused_menu; + m_recursiveDraw = true; + M_Draw (); + m_state = m_restart; + + M_Print (64, 84, restartMessage[0]); + M_Print (64, 92, restartMessage[1]); + M_Print (64, 100, restartMessage[2]); + M_Print (64, 108, restartMessage[3]); +} + + +//============================================================================= +/* EXIT MENU */ + + +char *exitMessage [] = +{ + + " Are you sure you want ", + "to quit to the Main Menu?", //msg:0 + " ", + " A :Yes B : No " +}; + + +void M_Menu_Exit_f (void) +{ + wasInMenus = (key_dest == key_menu_pause); + key_dest = key_menu_pause; + m_state = m_exit; + m_entersound = true; +} + + +void M_Exit_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case 'n': + case 'N': + m_state = m_paused_menu; + m_entersound = true; + break; + + case 'Y': + case 'y': + case K_ENTER: + case K_JOY0: + Cbuf_AddText("disconnect\n"); + CL_ClearState (); + M_Menu_Main_f(); + break; + + default: + break; + } + +} + + +void M_Exit_Draw (void) +{ + m_state = m_paused_menu; + m_recursiveDraw = true; + M_Draw (); + m_state = m_exit; + + M_Print (64, 84, exitMessage[0]); + M_Print (64, 92, exitMessage[1]); + M_Print (64, 100, exitMessage[2]); + M_Print (64, 108, exitMessage[3]); +} + + + +//============================================================================= +/* MAIN MENU */ + +void M_Start_Menu_f () +{ + key_dest = key_menu; + m_state = m_start; + m_entersound = true; + //CDAudio_Play("tracks/tensioned_by_the_damned.mp3", false); +} + +static void M_Start_Menu_Draw () +{ + char *str = "Press 'A'"; + + // Fill black to make everything easier to see + Draw_FillByColor(0, 0, vid.width, vid.height, 0, 0, 0, 255); + + // Background + menu_bk = Draw_CachePic("gfx/menu/menu_background"); + Draw_StretchPic(0, 0, menu_bk, vid.width, vid.height); + + Draw_ColoredString((vid.width/2) - 64, (vid.height - 64), str, 255, 0, 0, 185, 2); +} + +void M_Start_Key (int key) +{ + switch (key) + { + case K_JOY0: + case K_JOY5: + S_LocalSound ("sounds/menu/enter.wav"); + Cbuf_AddText("togglemenu\n"); + break; + } +} + +int m_main_cursor; +#define MAIN_ITEMS 4 + + +void M_Menu_Main_f (void) +{ + if (key_dest != key_menu) + { + m_save_demonum = cls.demonum; + cls.demonum = -1; + } + key_dest = key_menu; + m_state = m_main; + m_entersound = true; +} + + +void M_Main_Draw (void) +{ + int y = 60; + + // Background + menu_bk = Draw_CachePic("gfx/menu/menu_background"); + Draw_StretchPic(0, 0, menu_bk, vid.width, vid.height); + + // Fill black to make everything easier to see + Draw_FillByColor(0, 0, vid.width, vid.height, 0, 0, 0, 102); + + // Version String + Draw_ColoredString((vid.width - (strlen(game_build_date) * 12)), 6, game_build_date, 255, 255, 255, 255, 1.5); + + // Header + Draw_ColoredString(6, 6, "MAIN MENU", 255, 255, 255, 255, 3.5); + + // Solo + if (m_main_cursor == 0) + Draw_ColoredString(5, y, "Solo", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Solo", 255, 255, 255, 255, 1.5); + + y+=20; + + // Co-Op (Unfinished, so non-selectable) + Draw_ColoredString(5, y, "Co-Op (Coming Soon!)", 128, 128, 128, 255, 1.5); + + y+=20; + + // Divider + Draw_FillByColor(5, y, 160, 2, 130, 130, 130, 255); + + y+=10; + + if (m_main_cursor == 1) + Draw_ColoredString(5, y, "Settings", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Settings", 255, 255, 255, 255, 1.5); + + y+=20; + + Draw_ColoredString(5, y, "Achievements", 128, 128, 128, 255, 1.5); + + y+=20; + + // Divider + Draw_FillByColor(5, y, 160, 2, 130, 130, 130, 255); + + y+=10; + + if (m_main_cursor == 2) + Draw_ColoredString(5, y, "Credits", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Credits", 255, 255, 255, 255, 1.5); + + y+=20; + + // Divider + Draw_FillByColor(5, y, 160, 2, 130, 130, 130, 255); + + y+=10; + + if (m_main_cursor == 3) + Draw_ColoredString(5, y, "Exit", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Exit", 255, 255, 255, 255, 1.5); + + // Descriptions + switch(m_main_cursor) { + case 0: // Solo + Draw_ColoredString(12, 455, "Take on the Hordes by yourself.", 255, 255, 255, 255, 1.5); + break; + case 1: // Settings + Draw_ColoredString(12, 455, "Adjust your Settings to Optimize your Experience.", 255, 255, 255, 255, 1.5); + break; + case 2: // Credits + Draw_ColoredString(12, 455, "See who made NZ:P possible.", 255, 255, 255, 255, 1.5); + break; + case 3: // Exit + Draw_ColoredString(12, 455, "Return to Home Menu.", 255, 255, 255, 255, 1.5); + break; + } +} + + +void M_Main_Key (int key) +{ + switch (key) + { + case K_DOWNARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + if (++m_main_cursor >= MAIN_ITEMS) + m_main_cursor = 0; + break; + + case K_UPARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + if (--m_main_cursor < 0) + m_main_cursor = MAIN_ITEMS - 1; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + m_entersound = true; + + switch (m_main_cursor) + { + case 0: + M_Menu_SinglePlayer_f (); + break; + + case 1: + M_Menu_Options_f (); + break; + + case 2: + M_Menu_Credits_f (); + break; + + case 3: + M_Menu_Quit_f (); + break; + } + } +} + +//============================================================================= +/* SINGLE PLAYER MENU */ + +int m_singleplayer_cursor; +#define SINGLEPLAYER_ITEMS 6 //6 + + +void M_Menu_SinglePlayer_f (void) +{ + key_dest = key_menu; + m_state = m_singleplayer; + m_entersound = true; +} + + +void M_SinglePlayer_Draw (void) +{ + int y = 60; + + // Background + menu_bk = Draw_CachePic("gfx/menu/menu_background"); + Draw_StretchPic(0, 0, menu_bk, vid.width, vid.height); + + // Fill black to make everything easier to see + Draw_FillByColor(0, 0, vid.width, vid.height, 0, 0, 0, 102); + + // Header + Draw_ColoredString(6, 6, "SOLO", 255, 255, 255, 255, 3); + + // Version String + Draw_ColoredString((vid.width - (strlen(game_build_date) * 12)), 6, game_build_date, 255, 255, 255, 255, 1.5); + + // Nacht der Untoten + if (m_singleplayer_cursor == 0) + Draw_ColoredString(5, y, "Nacht der Untoten", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Nacht der Untoten", 255, 255, 255, 255, 1.5); + + y+=20; + + // Divider + Draw_FillByColor(5, y, 160, 2, 130, 130, 130, 255); + + y+=10; + + // Warehouse + if (m_singleplayer_cursor == 1) + Draw_ColoredString(5, y, "Warehouse", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Warehouse", 255, 255, 255, 255, 1.5); + + y+=20; + + // Warehouse (Classic) + if (m_singleplayer_cursor == 2) + Draw_ColoredString(5, y, "Warehouse (Classic)", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Warehouse (Classic)", 255, 255, 255, 255, 1.5); + + y+=20; + + // Christmas Special + if (m_singleplayer_cursor == 3) + Draw_ColoredString(5, y, "Christmas Special", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Christmas Special", 255, 255, 255, 255, 1.5); + + y+=20; + + // Divider + Draw_FillByColor(5, y, 160, 2, 130, 130, 130, 255); + + y+=10; + + // Custom Maps + if (m_singleplayer_cursor == 4) + Draw_ColoredString(5, y, "Custom Maps", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, y, "Custom Maps", 255, 255, 255, 255, 1.5); + + y+=22; + + // Back + if (m_singleplayer_cursor == 5) + Draw_ColoredString(5, y, "Back", 255, 0, 0, 255, 1.4); + else + Draw_ColoredString(5, y, "Back", 255, 255, 255, 255, 1.4); + + // Map description & pic + switch(m_singleplayer_cursor) { + case 0: + menu_ndu = Draw_CachePic("gfx/menu/nacht_der_untoten"); + Draw_StretchPic(265, 55, menu_ndu, 320, 200); + Draw_ColoredString(235, 275, "Desolate bunker located on a Ge-", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 290, "rman airfield, stranded after a", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 305, "brutal plane crash surrounded by", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 320, "hordes of undead. Exploit myste-", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 335, "rious forces at play and hold o-", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 350, "ut against relentless waves. Der", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 365, "Anstieg ist jetzt. Will you fall", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 380, "to the overwhelming onslaught?", 255, 255, 255, 255, 1.5); + break; + case 1: + menu_wh2 = Draw_CachePic("gfx/menu/nzp_warehouse2"); + Draw_StretchPic(265, 55, menu_wh2, 320, 200); + Draw_ColoredString(235, 275, "Four nameless marines find them-", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 290, "selves at a forsaken warehouse,", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 305, "or is it something more? Fight", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 320, "your way to uncovering its sec-", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 335, "rets, though you may not like", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 350, "what you find..", 255, 255, 255, 255, 1.5); + break; + case 2: + menu_wh = Draw_CachePic("gfx/menu/nzp_warehouse"); + Draw_StretchPic(265, 55, menu_wh, 320, 200); + Draw_ColoredString(235, 275, "Old Warehouse full of Zombies!", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 290, "Fight your way to the Power", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 305, "Switch through the Hordes!", 255, 255, 255, 255, 1.5); + break; + case 3: + menu_ch = Draw_CachePic("gfx/menu/christmas_special"); + Draw_StretchPic(265, 55, menu_ch, 320, 200); + Draw_ColoredString(235, 275, "No Santa this year. Though we're", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 290, "sure you will get presents from", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 305, "the undead! Will you accept them?", 255, 255, 255, 255, 1.5); + break; + case 4: + menu_custom = Draw_CachePic("gfx/menu/custom"); + Draw_StretchPic(265, 55, menu_custom, 320, 200); + Draw_ColoredString(235, 275, "Custom Maps made by Community", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 290, "Members on GitHub and on the", 255, 255, 255, 255, 1.5); + Draw_ColoredString(235, 305, "NZ:P Forum!", 255, 255, 255, 255, 1.5); + break; + } +} + + +void M_SinglePlayer_Key (int key) +{ + switch (key) + { + case K_DOWNARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + if (++m_singleplayer_cursor >= SINGLEPLAYER_ITEMS) + m_singleplayer_cursor = 0; + break; + + case K_UPARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + if (--m_singleplayer_cursor < 0) + m_singleplayer_cursor = SINGLEPLAYER_ITEMS - 1; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + m_entersound = true; + + switch (m_singleplayer_cursor) + { + case 0: + key_dest = key_game; + if (sv.active) + Cbuf_AddText ("disconnect\n"); + Cbuf_AddText ("maxplayers 1\n"); + Cbuf_AddText ("map ndu\n"); + loadingScreen = 1; + loadname2 = "ndu"; + loadnamespec = "Nacht der Untoten"; + break; + + case 1: + key_dest = key_game; + if (sv.active) + Cbuf_AddText ("disconnect\n"); + Cbuf_AddText ("maxplayers 1\n"); + Cbuf_AddText ("map nzp_warehouse2\n"); + loadingScreen = 1; + loadname2 = "nzp_warehouse2"; + loadnamespec = "Warehouse"; + break; + + case 2: + key_dest = key_game; + if (sv.active) + Cbuf_AddText ("disconnect\n"); + Cbuf_AddText ("maxplayers 1\n"); + Cbuf_AddText ("map nzp_warehouse\n"); + loadingScreen = 1; + loadname2 = "nzp_warehouse"; + loadnamespec = "Warehouse (Classic)"; + break; + + case 3: + key_dest = key_game; + if (sv.active) + Cbuf_AddText ("disconnect\n"); + Cbuf_AddText ("maxplayers 1\n"); + Cbuf_AddText ("map christmas_special\n"); + loadingScreen = 1; + loadname2 = "christmas_special"; + loadnamespec = "Christmas Special"; + break; + + case 4: + M_Menu_CustomMaps_f (); + break; + case 5: + M_Menu_Main_f (); + break; + } + break; + + // b button + case K_BACKSPACE: + case K_ESCAPE: + case K_JOY1: + M_Menu_Main_f(); + break; + } +} + +//============================================================================= +/* SINGLE PLAYER MENU */ + +int m_map_cursor; +int MAP_ITEMS; +int user_maps_num = 0; +int current_custom_map_page; +int custom_map_pages; +int multiplier; +char user_levels[256][MAX_QPATH]; + +// UGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH +// fuck windows +char* remove_windows_newlines(const char* line) +{ + const char* p = line; + size_t len = strlen(line); + char* result = (char*)malloc(len + 1); + + if (result == NULL) { + return NULL; + } + + char* q = result; + + for (size_t i = 0; i < len; i++) { + if (p[i] == '\r') { + continue; + } + *q++ = p[i]; + } + + *q = '\0'; + + return result; +} +#include +#include +char *COM_FileExtension (char *in); +void Map_Finder(void) +{ + struct dirent *dp; + DIR *dir = opendir(va("%s/maps", com_gamedir)); // Open the directory - dir contains a pointer to manage the dir + + if(dir < 0) + { + Sys_Error ("Map_Finder"); + return; + } + + for (int i = 0; i < 50; i++) { + custom_maps[i].occupied = false; + } + + while(dp=readdir(dir)) + { + + if(dp->d_name[0] == '.') + { + continue; + } + + if(!strcmp(COM_FileExtension(dp->d_name),"bsp")|| !strcmp(COM_FileExtension(dp->d_name),"BSP")) + { + char ntype[32]; + + COM_StripExtension(dp->d_name, ntype); + custom_maps[user_maps_num].occupied = true; + custom_maps[user_maps_num].map_name = malloc(sizeof(char)*32); + sprintf(custom_maps[user_maps_num].map_name, "%s", ntype); + + char* setting_path; + + setting_path = malloc(sizeof(char)*64); + custom_maps[user_maps_num].map_thumbnail_path = malloc(sizeof(char)*64); + strcpy(setting_path, va("%s/maps/", com_gamedir)); + strcpy(custom_maps[user_maps_num].map_thumbnail_path, "gfx/menu/custom/"); + strcat(setting_path, custom_maps[user_maps_num].map_name); + strcat(custom_maps[user_maps_num].map_thumbnail_path, custom_maps[user_maps_num].map_name); + strcat(setting_path, ".txt"); + + FILE *setting_file; + setting_file = fopen(setting_path, "rb"); + if (setting_file != NULL) { + + fseek(setting_file, 0L, SEEK_END); + size_t sz = ftell(setting_file); + fseek(setting_file, 0L, SEEK_SET); + + int state; + state = 0; + int value; + + custom_maps[user_maps_num].map_name_pretty = malloc(sizeof(char)*32); + custom_maps[user_maps_num].map_desc_1 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_2 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_3 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_4 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_5 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_6 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_7 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_desc_8 = malloc(sizeof(char)*40); + custom_maps[user_maps_num].map_author = malloc(sizeof(char)*40); + + char* buffer = (char*)calloc(sz+1, sizeof(char)); + fread(buffer, sz, 1, setting_file); + + strtok(buffer, "\n"); + while(buffer != NULL) { + switch(state) { + case 0: strcpy(custom_maps[user_maps_num].map_name_pretty, remove_windows_newlines(buffer)); break; + case 1: strcpy(custom_maps[user_maps_num].map_desc_1, remove_windows_newlines(buffer)); break; + case 2: strcpy(custom_maps[user_maps_num].map_desc_2, remove_windows_newlines(buffer)); break; + case 3: strcpy(custom_maps[user_maps_num].map_desc_3, remove_windows_newlines(buffer)); break; + case 4: strcpy(custom_maps[user_maps_num].map_desc_4, remove_windows_newlines(buffer)); break; + case 5: strcpy(custom_maps[user_maps_num].map_desc_5, remove_windows_newlines(buffer)); break; + case 6: strcpy(custom_maps[user_maps_num].map_desc_6, remove_windows_newlines(buffer)); break; + case 7: strcpy(custom_maps[user_maps_num].map_desc_7, remove_windows_newlines(buffer)); break; + case 8: strcpy(custom_maps[user_maps_num].map_desc_8, remove_windows_newlines(buffer)); break; + case 9: strcpy(custom_maps[user_maps_num].map_author, remove_windows_newlines(buffer)); break; + case 10: value = 0; sscanf(remove_windows_newlines(buffer), "%d", &value); custom_maps[user_maps_num].map_use_thumbnail = value; break; + case 11: value = 0; sscanf(remove_windows_newlines(buffer), "%d", &value); custom_maps[user_maps_num].map_allow_game_settings = value; break; + default: break; + } + state++; + buffer = strtok(NULL, "\n"); + } + free(buffer); + buffer = 0; + fclose(setting_file); + } + user_maps_num++; + } + } + closedir(dir); // close the handle (pointer) + custom_map_pages = (int)ceil((double)(user_maps_num)/15); +} + +void M_Menu_CustomMaps_f (void) +{ + key_dest = key_menu; + m_state = m_custommaps; + m_entersound = true; + MAP_ITEMS = 13; + current_custom_map_page = 1; +} + + +void M_Menu_CustomMaps_Draw (void) +{ + // Background + menu_bk = Draw_CachePic("gfx/menu/menu_background"); + Draw_StretchPic(0, 0, menu_bk, vid.width, vid.height); + + // Fill black to make everything easier to see + Draw_FillByColor(0, 0, vid.width, vid.height, 0, 0, 0, 102); + + // Header + Draw_ColoredString(6, 6, "CUSTOM MAPS", 255, 255, 255, 255, 3); + + // Version String + Draw_ColoredString((vid.width - (strlen(game_build_date) * 12)), 6, game_build_date, 255, 255, 255, 255, 1.5); + + int line_increment; + line_increment = 0; + + if (current_custom_map_page > 1) + multiplier = (current_custom_map_page - 1) * 15; + else + multiplier = 0; + + for (int i = 0; i < 15; i++) { + if (custom_maps[i + multiplier].occupied == false) + continue; + + if (m_map_cursor == i) { + + if (custom_maps[i + multiplier].map_use_thumbnail == 1) { + menu_cuthum = Draw_CachePic(custom_maps[i + multiplier].map_thumbnail_path); + if (menu_cuthum != NULL) { + Draw_StretchPic(265, 55, menu_cuthum, 320, 200); + } + } + + if (custom_maps[i + multiplier].map_name_pretty != 0) + Draw_ColoredString(5, 60 + (15 * i), custom_maps[i + multiplier].map_name_pretty, 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(5, 60 + (15 * i), custom_maps[i + multiplier].map_name, 255, 0, 0, 255, 1.5); + + if (custom_maps[i + multiplier].map_desc_1 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_1, " ") != 0) { + Draw_ColoredString(235, 275, custom_maps[i + multiplier].map_desc_1, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_2 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_2, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 290, custom_maps[i + multiplier].map_desc_2, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_3 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_3, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 305, custom_maps[i + multiplier].map_desc_3, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_4 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_4, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 320, custom_maps[i + multiplier].map_desc_4, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_5 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_5, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 335, custom_maps[i + multiplier].map_desc_5, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_6 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_6, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 350, custom_maps[i + multiplier].map_desc_6, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_7 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_7, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 365, custom_maps[i + multiplier].map_desc_7, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_desc_8 != 0) { + if (strcmp(custom_maps[i + multiplier].map_desc_8, " ") != 0) { + line_increment++; + Draw_ColoredString(235, 380, custom_maps[i + multiplier].map_desc_8, 255, 255, 255, 255, 1.5); + } + } + if (custom_maps[i + multiplier].map_author != 0) { + if (strcmp(custom_maps[i + multiplier].map_author, " ") != 0) { + int y = 238; + Draw_ColoredString(270, y, custom_maps[i + multiplier].map_author, 255, 255, 0, 255, 1.5); + } + } + } else { + if (custom_maps[i + multiplier].map_name_pretty != 0) + Draw_ColoredString(6, 60 + (15 * i), custom_maps[i + multiplier].map_name_pretty, 255, 255, 255, 255, 1.5); + else + Draw_ColoredString(6, 60 + (15 * i), custom_maps[i + multiplier].map_name, 255, 255, 255, 255, 1.5); + } + } + + if (current_custom_map_page != custom_map_pages) { + if (m_map_cursor == 15) + Draw_ColoredString(6, 315, "Next Page", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(6, 315, "Next Page", 255, 255, 255, 255, 1.5); + } else { + Draw_ColoredString(6, 315, "Next Page", 128, 128, 128, 255, 1.5); + } + + if (current_custom_map_page != 1) { + if (m_map_cursor == 16) + Draw_ColoredString(6, 330, "Previous Page", 255, 0, 0, 255, 1.5); + else + Draw_ColoredString(6, 330, "Previous Page", 255, 255, 255, 255, 1.5); + } else { + Draw_ColoredString(6, 330, "Previous Page", 128, 128, 128, 255, 1.5); + } + + + + if (m_map_cursor == 17) + Draw_ColoredString(6, 348, "Back", 255, 0, 0, 255, 1.4); + else + Draw_ColoredString(6, 348, "Back", 255, 255, 255, 255, 1.4); +} + + +void M_Menu_CustomMaps_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + M_Menu_SinglePlayer_f (); + break; + case K_DOWNARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + + m_map_cursor++; + + if (m_map_cursor < 14 && custom_maps[m_map_cursor + multiplier].occupied == false) { + m_map_cursor = 15; + } + + if (m_map_cursor == 15 && current_custom_map_page == custom_map_pages) + m_map_cursor = 16; + + if (m_map_cursor == 16 && current_custom_map_page == 1) + m_map_cursor = 17; + + if (m_map_cursor >= 18) + m_map_cursor = 0; + break; + case K_UPARROW: + S_LocalSound ("sounds/menu/navigate.wav"); + + m_map_cursor--; + + if (m_map_cursor < 0) + m_map_cursor = 17; + + if (m_map_cursor == 16 && current_custom_map_page == 1) + m_map_cursor = 15; + + if (m_map_cursor == 15 && current_custom_map_page == custom_map_pages) + m_map_cursor = 14; + + if (m_map_cursor <= 14 && custom_maps[m_map_cursor + multiplier].occupied == false) { + for (int i = 14; i > -1; i--) { + if (custom_maps[i + multiplier].occupied == true) { + m_map_cursor = i; + break; + } + } + } + break; + case K_ENTER: + case K_JOY0: + m_entersound = true; + if (m_map_cursor == 17) { + M_Menu_SinglePlayer_f (); + } else if (m_map_cursor == 16) { + current_custom_map_page--; + m_map_cursor = 0; + } else if (m_map_cursor == 15) { + current_custom_map_page++; + m_map_cursor = 0; + } else + { + key_dest = key_game; + if (sv.active) + Cbuf_AddText ("disconnect\n"); + Cbuf_AddText ("maxplayers 1\n"); + Cbuf_AddText (va("map %s\n", custom_maps[m_map_cursor + multiplier].map_name)); + loadingScreen = 1; + loadname2 = custom_maps[m_map_cursor + multiplier].map_name; + if (custom_maps[m_map_cursor + multiplier].map_name_pretty != 0) + loadnamespec = custom_maps[m_map_cursor + multiplier].map_name_pretty; + else + loadnamespec = custom_maps[m_map_cursor + multiplier].map_name; + } + break; + } +} + +//============================================================================= +/* MULTIPLAYER MENU */ + +int m_multiplayer_cursor; +#define MULTIPLAYER_ITEMS 3 + + +void M_Menu_MultiPlayer_f (void) +{ + key_dest = key_menu; + //m_state = m_multiplayer; + m_entersound = true; +} + + +void M_MultiPlayer_Draw (void) +{ + //int f; + //qpic_t *p; + /* + M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); + p = Draw_CachePic ("gfx/p_multi.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mp_menu.lmp") ); + + f = (int)(host_time * 10)%6; + + M_DrawTransPic (54, 32 + m_multiplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) ); + + if (tcpipAvailable) + return; + M_PrintWhite ((320/2) - ((27*8)/2), 148, "No Communications Available"); + */ +} + + +void M_MultiPlayer_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_Main_f (); + break; + + case K_DOWNARROW: + //S_LocalSound ("misc/menu1.wav"); + if (++m_multiplayer_cursor >= MULTIPLAYER_ITEMS) + m_multiplayer_cursor = 0; + break; + + case K_UPARROW: + //S_LocalSound ("misc/menu1.wav"); + if (--m_multiplayer_cursor < 0) + m_multiplayer_cursor = MULTIPLAYER_ITEMS - 1; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + m_entersound = true; + switch (m_multiplayer_cursor) + { + case 0: + if (tcpipAvailable) + M_Menu_Net_f (); + break; + + case 1: + if (tcpipAvailable) + M_Menu_Net_f (); + break; + + case 2: + M_Menu_Setup_f (); + break; + } + } +} + +//============================================================================= +/* SETUP MENU */ + +int setup_cursor = 4; +int setup_cursor_table[] = {40, 56, 80, 104, 140}; + +char setup_hostname[16]; +char setup_myname[16]; +int setup_oldtop; +int setup_oldbottom; +int setup_top; +int setup_bottom; + +#define NUM_SETUP_CMDS 5 + +void M_Menu_Setup_f (void) +{ + key_dest = key_menu; + m_state = m_setup; + m_entersound = true; + strcpy(setup_myname, cl_name.string); + strcpy(setup_hostname, hostname.string); + setup_top = setup_oldtop = 4; + setup_bottom = setup_oldbottom = 15; +} + + +void M_Setup_Draw (void) +{ + /* + qpic_t *p; + + M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); + p = Draw_CachePic ("gfx/p_multi.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + + M_Print (64, 40, "Hostname"); + M_Print (168, 40, setup_hostname); + + M_Print (64, 56, "Your name"); + M_Print (168, 56, setup_myname); + + M_Print (64, 80, "Shirt color"); + M_Print (64, 104, "Pants color"); + + M_Print (72, 140, "Accept Changes"); + + p = Draw_CachePic ("gfx/bigbox.lmp"); + M_DrawTransPic (160, 64, p); + p = Draw_CachePic ("gfx/menuplyr.lmp"); + M_BuildTranslationTable(setup_top*16, setup_bottom*16); + M_DrawTransPicTranslate (172, 72, p); + + M_DrawCharacter (56, setup_cursor_table [setup_cursor], 12+((int)(realtime*4)&1)); + + if (setup_cursor == 0) + M_DrawCharacter (168 + 8*strlen(setup_hostname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1)); + + if (setup_cursor == 1) + M_DrawCharacter (168 + 8*strlen(setup_myname), setup_cursor_table [setup_cursor], 10+((int)(realtime*4)&1)); + */ +} + + +void M_Setup_Key (int k) +{ + int l; + + switch (k) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_MultiPlayer_f (); + break; + + case K_UPARROW: + //S_LocalSound ("misc/menu1.wav"); + setup_cursor--; + if (setup_cursor < 0) + setup_cursor = NUM_SETUP_CMDS-1; + break; + + case K_DOWNARROW: + //S_LocalSound ("misc/menu1.wav"); + setup_cursor++; + if (setup_cursor >= NUM_SETUP_CMDS) + setup_cursor = 0; + break; + + case K_LEFTARROW: + if (setup_cursor < 2) + return; + //S_LocalSound ("misc/menu3.wav"); + if (setup_cursor == 2) + setup_top = setup_top - 1; + if (setup_cursor == 3) + setup_bottom = setup_bottom - 1; + break; + case K_RIGHTARROW: + if (setup_cursor < 2) + return; +forward: + //S_LocalSound ("misc/menu3.wav"); + if (setup_cursor == 2) + setup_top = setup_top + 1; + if (setup_cursor == 3) + setup_bottom = setup_bottom + 1; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + if (setup_cursor == 0 || setup_cursor == 1) + return; + + if (setup_cursor == 2 || setup_cursor == 3) + goto forward; + + // setup_cursor == 4 (OK) + if (strcmp(cl_name.string, setup_myname) != 0) + Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) ); + if (strcmp(hostname.string, setup_hostname) != 0) + Cvar_Set("hostname", setup_hostname); + if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom) + Cbuf_AddText( va ("color %i %i\n", setup_top, setup_bottom) ); + m_entersound = true; + M_Menu_MultiPlayer_f (); + break; + + case K_BACKSPACE: + if (setup_cursor == 0) + { + if (strlen(setup_hostname)) + setup_hostname[strlen(setup_hostname)-1] = 0; + } + + if (setup_cursor == 1) + { + if (strlen(setup_myname)) + setup_myname[strlen(setup_myname)-1] = 0; + } + break; + + default: + if (k < 32 || k > 127) + break; + if (setup_cursor == 0) + { + l = strlen(setup_hostname); + if (l < 15) + { + setup_hostname[l+1] = 0; + setup_hostname[l] = k; + } + } + if (setup_cursor == 1) + { + l = strlen(setup_myname); + if (l < 15) + { + setup_myname[l+1] = 0; + setup_myname[l] = k; + } + } + } + + if (setup_top > 13) + setup_top = 0; + if (setup_top < 0) + setup_top = 13; + if (setup_bottom > 13) + setup_bottom = 0; + if (setup_bottom < 0) + setup_bottom = 13; +} + +//============================================================================= +/* NET MENU */ + +int m_net_cursor; +int m_net_items; +int m_net_saveHeight; + +char *net_helpMessage [] = +{ +/* .........1.........2.... */ + " ", + " Two computers connected", + " through two modems. ", + " ", + + " ", + " Two computers connected", + " by a null-modem cable. ", + " ", + + " Novell network LANs ", + " or Windows 95 DOS-box. ", + " ", + "(LAN=Local Area Network)", + + " Commonly used to play ", + " over the Internet, but ", + " also used on a Local ", + " Area Network. " +}; + +void M_Menu_Net_f (void) +{ + key_dest = key_menu; + m_state = m_net; + m_entersound = true; + m_net_items = 4; + + if (m_net_cursor >= m_net_items) + m_net_cursor = 0; + m_net_cursor--; + M_Net_Key (K_DOWNARROW); +} + + +void M_Net_Draw (void) +{ + /* + int f; + qpic_t *p; + + M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); + p = Draw_CachePic ("gfx/p_multi.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + + f = 32; + + p = Draw_CachePic ("gfx/dim_modm.lmp"); + + if (p) + M_DrawTransPic (72, f, p); + + f += 19; + + p = Draw_CachePic ("gfx/dim_drct.lmp"); + + if (p) + M_DrawTransPic (72, f, p); + + f += 19; + p = Draw_CachePic ("gfx/dim_ipx.lmp"); + M_DrawTransPic (72, f, p); + + f += 19; + if (tcpipAvailable) + p = Draw_CachePic ("gfx/netmen4.lmp"); + else + p = Draw_CachePic ("gfx/dim_tcp.lmp"); + M_DrawTransPic (72, f, p); + + if (m_net_items == 5) // JDC, could just be removed + { + f += 19; + p = Draw_CachePic ("gfx/netmen5.lmp"); + M_DrawTransPic (72, f, p); + } + + f = (320-26*8)/2; + f += 8; + M_Print (f, 142, net_helpMessage[m_net_cursor*4+0]); + M_Print (f, 150, net_helpMessage[m_net_cursor*4+1]); + M_Print (f, 158, net_helpMessage[m_net_cursor*4+2]); + M_Print (f, 166, net_helpMessage[m_net_cursor*4+3]); + + f = (int)(host_time * 10)%6; + M_DrawTransPic (54, 32 + m_net_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) ); + */ +} + + +void M_Net_Key (int k) +{ +again: + switch (k) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_MultiPlayer_f (); + break; + + case K_DOWNARROW: + //S_LocalSound ("misc/menu1.wav"); + if (++m_net_cursor >= m_net_items) + m_net_cursor = 0; + break; + + case K_UPARROW: + //S_LocalSound ("misc/menu1.wav"); + if (--m_net_cursor < 0) + m_net_cursor = m_net_items - 1; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + m_entersound = true; + + switch (m_net_cursor) + { + case 0: + break; + + case 1: + break; + + case 2: + break; + + case 3: + M_Menu_LanConfig_f (); + break; + + case 4: +// multiprotocol + break; + } + } + + if (m_net_cursor == 0) + goto again; + if (m_net_cursor == 1) + goto again; + if (m_net_cursor == 2) + goto again; + if (m_net_cursor == 3 && !tcpipAvailable) + goto again; +} + +//============================================================================= +/* OPTIONS MENU */ + +#define OPTIONS_ITEMS 15 + +#define SLIDER_RANGE 10 + +extern cvar_t nunchuk_stick_as_arrows; +extern cvar_t cl_weapon_inrollangle; +int options_cursor; + +void M_Menu_Options_f (void) +{ + if (key_dest != key_menu_pause) + key_dest = key_menu; + + m_state = m_options; + + m_entersound = true; +} + +void M_AdjustSliders (int dir) +{ + //S_LocalSound ("misc/menu3.wav"); + + switch (options_cursor) + { + case 3: // screen size + scr_viewsize.value += dir * 10; + if (scr_viewsize.value < 100) + scr_viewsize.value = 100; + if (scr_viewsize.value > 120) + scr_viewsize.value = 120; + Cvar_SetValue ("viewsize", scr_viewsize.value); + break; + case 4: // gamma + v_gamma.value -= dir * 0.05; + if (v_gamma.value < 0.5f) + v_gamma.value = 0.5f; + if (v_gamma.value > 1) + v_gamma.value = 1; + Cvar_SetValue ("gamma", v_gamma.value); + break; + case 5: // mouse speed + sensitivity.value += dir * 0.5f; + if (sensitivity.value < 1) + sensitivity.value = 1; + if (sensitivity.value > 11) + sensitivity.value = 11; + Cvar_SetValue ("sensitivity", sensitivity.value); + break; + case 6: // music volume + bgmvolume.value += dir * 0.1f; + if (bgmvolume.value < 0) + bgmvolume.value = 0; + if (bgmvolume.value > 1) + bgmvolume.value = 1; + Cvar_SetValue ("bgmvolume", bgmvolume.value); + break; + case 7: // sfx volume + volume.value += dir * 0.1f; + if (volume.value < 0) + volume.value = 0; + if (volume.value > 1) + volume.value = 1; + Cvar_SetValue ("volume", volume.value); + break; + + case 8: // Nunchuk stick as arrows + Cvar_SetValue ("nunchuk_stick_as_arrows", !nunchuk_stick_as_arrows.value); + break; + + case 9: // Aim assist + Cvar_SetValue ("in_aimassist", !in_aimassist.value); + break; + case 10: // ADS Always Centered + Cvar_SetValue ("ads_center", !ads_center.value); + break; + case 11: // Sniper Scope Always Centered + Cvar_SetValue ("sniper_center", !sniper_center.value); + break; + case 12: // weapon roll by input + Cvar_SetValue ("cl_weapon_inrollangle", !cl_weapon_inrollangle.value); + break; + case 13: // tv border + vid_tvborder.value += dir * 0.005f; + if (vid_tvborder.value < 0) + vid_tvborder.value = 0; + if (vid_tvborder.value > 0.2) + vid_tvborder.value = 0.2; + Cvar_SetValue ("vid_tvborder", vid_tvborder.value); + break; + case 14: // retro mode + Cvar_SetValue ("vid_retromode", !vid_retromode.value); + break; + } +} + + +void M_DrawSlider (int x, int y, float range) +{ + int i; + + if (range < 0) + range = 0; + if (range > 1) + range = 1; + M_DrawCharacter (x-8, y, 128); + for (i=0 ; i= OPTIONS_ITEMS) + options_cursor = 0; + break; + + case K_ESCAPE: + case K_JOY1: + if (key_dest == key_menu_pause) + M_Paused_Menu_f(); + else + M_Menu_Main_f (); + break; + + case K_LEFTARROW: + M_AdjustSliders (-1); + break; + + case K_RIGHTARROW: + M_AdjustSliders (1); + break; + } +} + +//============================================================================= +/* KEYS MENU */ + +char *bindnames[][2] = +{ +{"+attack", "Attack"}, +{"+switch", "Change Weapon"}, +{"+reload", "Reload"}, +{"impulse 23", "Sprint"}, +{"+aim", "Aim Down Sight"}, +{"+knife", "Knife"}, +{"+grenade", "Grenade"}, +{"+jump", "Jump"}, +{"impulse 30", "Change Stance"}, +{"impulse 33", "Place Betty"}, +{"showscores", "Show Scoreboard"}, +{"+forward", "Walk Forward"}, +{"+back", "Walk Backward"}, +{"+moveleft", "Step Left"}, +{"+moveright", "Step Right"}, +}; + +#define NUMCOMMANDS (sizeof(bindnames)/sizeof(bindnames[0])) + +int keys_cursor; +int bind_grab; + +void M_Menu_Keys_f (void) +{ + if (key_dest != key_menu_pause) + key_dest = key_menu; + + m_state = m_keys; + m_entersound = true; +} + + +void M_FindKeysForCommand (char *command, int *twokeys) +{ + int count; + int j; + int l; + char *b; + + twokeys[0] = twokeys[1] = -1; + l = strlen(command); + count = 0; + + for (j=0 ; j<256 ; j++) + { + b = keybindings[j]; + if (!b) + continue; + if (!strncmp (b, command, l) ) + { + twokeys[count] = j; + count++; + if (count == 2) + break; + } + } +} + +void M_UnbindCommand (char *command) +{ + int j; + int l; + char *b; + + l = strlen(command); + + for (j=0 ; j<256 ; j++) + { + b = keybindings[j]; + if (!b) + continue; + if (!strncmp (b, command, l) ) + Key_SetBinding (j, ""); + } +} + + +void M_Keys_Draw (void) +{ + int i/*, l*/; + int keys[2]; + char *name; + int x, y; + //qpic_t *p; + + //p = Draw_CachePic ("gfx/ttl_cstm.lmp"); + //M_DrawPic ( (320-p->width)/2, 4, p); + + if (bind_grab) + M_Print (12, 32, "Press a key or button for this action"); + else + M_Print (18, 32, "Enter to change, backspace to clear"); + +// search for known bindings + for (i=0 ; i= NUMCOMMANDS) + keys_cursor = 0; + break; + + case K_ENTER: // go into bind mode + case K_JOY0: + case K_JOY9: + case K_JOY20: + M_FindKeysForCommand (bindnames[keys_cursor][0], keys); + //S_LocalSound ("misc/menu2.wav"); + if (keys[1] != -1) + M_UnbindCommand (bindnames[keys_cursor][0]); + bind_grab = true; + break; + + case K_BACKSPACE: // delete bindings + case K_DEL: // delete bindings + //S_LocalSound ("misc/menu2.wav"); + M_UnbindCommand (bindnames[keys_cursor][0]); + break; + } +} + +//============================================================================= +/* CONSOLE OSK */ + +#define CHAR_SIZE 8 +#define MAX_Y 8 +#define MAX_X 12 + +#define MAX_CHAR_LINE 36 +#define MAX_CHAR 72 + +int osk_pos_x = 0; +int osk_pos_y = 0; +int max_len = 0; +int m_old_state = 0; + +char* osk_out_buff = NULL; +char osk_buffer[128]; + +char *osk_help [] = +{ + "ADD: ", + "A ", + " ", + "DELETE:", + "B ", + " ", + "CLOSE: ", + "MINUS ", + " " +}; + +char *osk_text [] = +{ + " 1 2 3 4 5 6 7 8 9 0 - = ` ", + " q w e r t y u i o p [ ] ", + " a s d f g h j k l ; ' \\ ", + " z x c v b n m , . / ", + " ", + " ! @ # $ % ^ & * ( ) _ + ~ ", + " Q W E R T Y U I O P { } ", + " A S D F G H J K L : \" | ", + " Z X C V B N M < > ? " +}; + +void M_OSK_Draw (void) { + + int x,y; + int i; + + char *selected_line = osk_text[osk_pos_y]; + char selected_char[2]; + + //GL_SetCanvas(CANVAS_MENU); + + selected_char[0] = selected_line[1+(2*osk_pos_x)]; + selected_char[1] = '\0'; + if (selected_char[0] == ' ' || selected_char[0] == '\t') + selected_char[0] = 'X'; + + y = 150; + x = 150; + + M_DrawTextBox (x-3, y-10, 26, 10); + M_DrawTextBox ((x-3)+(26*CHAR_SIZE), y-10, 10, 10); + M_DrawTextBox (x-3, (y-10)+(10*CHAR_SIZE),36, 3); + + for(i=0;i<=MAX_Y;i++) + { + M_PrintWhite (x, y+(CHAR_SIZE*i), osk_text[i]); + if (i == 1 || i == 4 || i == 7) + M_Print (x+(27*CHAR_SIZE), y+(CHAR_SIZE*i), osk_help[i]); + else + M_PrintWhite (x+(27*CHAR_SIZE), y+(CHAR_SIZE*i), osk_help[i]); + } + + int text_len = strlen(osk_buffer); + if (text_len > MAX_CHAR_LINE) { + + char oneline[MAX_CHAR_LINE+1]; + strncpy(oneline,osk_buffer,MAX_CHAR_LINE); + oneline[MAX_CHAR_LINE] = '\0'; + + M_Print (x+4, y+4+(CHAR_SIZE*(MAX_Y+2)), oneline ); + + strncpy(oneline,osk_buffer+MAX_CHAR_LINE, text_len - MAX_CHAR_LINE); + oneline[text_len - MAX_CHAR_LINE] = '\0'; + + M_Print (x+4, y+4+(CHAR_SIZE*(MAX_Y+3)), oneline ); + M_PrintWhite (x+4+(CHAR_SIZE*(text_len - MAX_CHAR_LINE)), y+4+(CHAR_SIZE*(MAX_Y+3)),"_"); + } + else { + M_Print (x+4, y+4+(CHAR_SIZE*(MAX_Y+2)), osk_buffer ); + M_PrintWhite (x+4+(CHAR_SIZE*(text_len)), y+4+(CHAR_SIZE*(MAX_Y+2)),"_"); + } + M_Print (x+((((osk_pos_x)*2)+1)*CHAR_SIZE), y+(osk_pos_y*CHAR_SIZE), selected_char); +} + + +//============================================================================= +/* HELP MENU */ + +int help_page; +#define NUM_HELP_PAGES 6 + + +void M_Menu_Help_f (void) +{ + key_dest = key_menu; + m_state = m_help; + m_entersound = true; + help_page = 0; +} + + + +void M_Help_Draw (void) +{ + //M_DrawPic (0, 0, Draw_CachePic ( va("gfx/help%i.lmp", help_page)) ); +} + + +void M_Help_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_Main_f (); + break; + + case K_UPARROW: + case K_RIGHTARROW: + m_entersound = true; + if (++help_page >= NUM_HELP_PAGES) + help_page = 0; + break; + + case K_DOWNARROW: + case K_LEFTARROW: + m_entersound = true; + if (--help_page < 0) + help_page = NUM_HELP_PAGES-1; + break; + } + +} + +//============================================================================= +/* QUIT MENU */ + +int m_quit_prevstate; +qboolean wasInMenus; + + +void M_Menu_Quit_f (void) +{ + if (m_state == m_quit) + return; + wasInMenus = (key_dest == key_menu); + key_dest = key_menu; + m_quit_prevstate = m_state; + m_state = m_quit; + m_entersound = true; +} + + +void M_Quit_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + case 'n': + case 'N': + if (wasInMenus) + { + m_state = m_quit_prevstate; + m_entersound = true; + } + else + { + key_dest = key_game; + m_state = m_none; + } + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + case 'Y': + case 'y': + key_dest = key_console; + Host_Quit_f (); + break; + + default: + break; + } + +} + + +void M_Quit_Draw (void) +{ + char yes[32]; + char no[32]; + + if (wasInMenus) + { + m_state = m_quit_prevstate; + m_recursiveDraw = true; + M_Draw (); + m_state = m_quit; + } + + sprintf(yes, "Y or A button: Yes"); + sprintf(no, "N or B button: No"); + + M_Print (64, 84, "Really quit?"); + M_Print (64, 92, ""); + M_Print (64, 100, yes); + M_Print (64, 108, no); +} + +//============================================================================= +/* LAN CONFIG MENU */ + +int lanConfig_cursor = -1; +int lanConfig_cursor_table [] = {72, 92, 124}; +#define NUM_LANCONFIG_CMDS 3 + +int lanConfig_port; +char lanConfig_portname[6]; +char lanConfig_joinname[22]; + +void M_Menu_LanConfig_f (void) +{ + key_dest = key_menu; + m_state = m_lanconfig; + m_entersound = true; + if (lanConfig_cursor == -1) + { + if (JoiningGame && TCPIPConfig) + lanConfig_cursor = 2; + else + lanConfig_cursor = 1; + } + if (StartingGame && lanConfig_cursor == 2) + lanConfig_cursor = 1; + lanConfig_port = DEFAULTnet_hostport; + sprintf(lanConfig_portname, "%u", lanConfig_port); + + m_return_onerror = false; + m_return_reason[0] = 0; +} + + +void M_LanConfig_Draw (void) +{ + /* + qpic_t *p; + int basex; + char *startJoin; + char *protocol; + + M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); + p = Draw_CachePic ("gfx/p_multi.lmp"); + basex = (320-p->width)/2; + M_DrawPic (basex, 4, p); + + if (StartingGame) + startJoin = "New Game"; + else + startJoin = "Join Game"; + protocol = "TCP/IP"; + M_Print (basex, 32, va ("%s - %s", startJoin, protocol)); + basex += 8; + + M_Print (basex, 52, "Address:"); + M_Print (basex+9*8, 52, my_tcpip_address); + + M_Print (basex, lanConfig_cursor_table[0], "Port"); + M_Print (basex+9*8, lanConfig_cursor_table[0], lanConfig_portname); + + if (JoiningGame) + { + M_Print (basex, lanConfig_cursor_table[1], "Search for local games..."); + M_Print (basex, 108, "Join game at:"); + M_Print (basex+16, lanConfig_cursor_table[2], lanConfig_joinname); + } + else + { + M_Print (basex+8, lanConfig_cursor_table[1], "OK"); + } + + M_DrawCharacter (basex-8, lanConfig_cursor_table [lanConfig_cursor], 12+((int)(realtime*4)&1)); + + if (lanConfig_cursor == 0) + M_DrawCharacter (basex+9*8 + 8*strlen(lanConfig_portname), lanConfig_cursor_table [0], 10+((int)(realtime*4)&1)); + + if (lanConfig_cursor == 2) + M_DrawCharacter (basex+16 + 8*strlen(lanConfig_joinname), lanConfig_cursor_table [2], 10+((int)(realtime*4)&1)); + + if (*m_return_reason) + M_PrintWhite (basex, 148, m_return_reason); + */ +} + + +void M_LanConfig_Key (int key) +{ + int l; + + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_Net_f (); + break; + + case K_UPARROW: + //S_LocalSound ("misc/menu1.wav"); + lanConfig_cursor--; + if (lanConfig_cursor < 0) + lanConfig_cursor = NUM_LANCONFIG_CMDS-1; + break; + + case K_DOWNARROW: + //S_LocalSound ("misc/menu1.wav"); + lanConfig_cursor++; + if (lanConfig_cursor >= NUM_LANCONFIG_CMDS) + lanConfig_cursor = 0; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + if (lanConfig_cursor == 0) + break; + + m_entersound = true; + + M_ConfigureNetSubsystem (); + + if (lanConfig_cursor == 1) + { + if (StartingGame) + { + M_Menu_GameOptions_f (); + break; + } + M_Menu_Search_f(); + break; + } + + if (lanConfig_cursor == 2) + { + m_return_state = m_state; + m_return_onerror = true; + key_dest = key_game; + m_state = m_none; + Cbuf_AddText ( va ("connect \"%s\"\n", lanConfig_joinname) ); + break; + } + + break; + + case K_BACKSPACE: + if (lanConfig_cursor == 0) + { + if (strlen(lanConfig_portname)) + lanConfig_portname[strlen(lanConfig_portname)-1] = 0; + } + + if (lanConfig_cursor == 2) + { + if (strlen(lanConfig_joinname)) + lanConfig_joinname[strlen(lanConfig_joinname)-1] = 0; + } + break; + + default: + if (key < 32 || key > 127) + break; + + if (lanConfig_cursor == 2) + { + l = strlen(lanConfig_joinname); + if (l < 21) + { + lanConfig_joinname[l+1] = 0; + lanConfig_joinname[l] = key; + } + } + + if (key < '0' || key > '9') + break; + if (lanConfig_cursor == 0) + { + l = strlen(lanConfig_portname); + if (l < 5) + { + lanConfig_portname[l+1] = 0; + lanConfig_portname[l] = key; + } + } + } + + if (StartingGame && lanConfig_cursor == 2) + { + if (key == K_UPARROW) + lanConfig_cursor = 1; + else + lanConfig_cursor = 0; + } + + l = atoi(lanConfig_portname); + if (l > 65535) + l = lanConfig_port; + else + lanConfig_port = l; + sprintf(lanConfig_portname, "%u", lanConfig_port); +} + +//============================================================================= +/* GAME OPTIONS MENU */ + +typedef struct +{ + char *name; + char *description; +} level_t; + +level_t levels[] = +{ + {"start", "Entrance"}, // 0 + + {"e1m1", "Slipgate Complex"}, // 1 + {"e1m2", "Castle of the Damned"}, + {"e1m3", "The Necropolis"}, + {"e1m4", "The Grisly Grotto"}, + {"e1m5", "Gloom Keep"}, + {"e1m6", "The Door To Chthon"}, + {"e1m7", "The House of Chthon"}, + {"e1m8", "Ziggurat Vertigo"}, + + {"e2m1", "The Installation"}, // 9 + {"e2m2", "Ogre Citadel"}, + {"e2m3", "Crypt of Decay"}, + {"e2m4", "The Ebon Fortress"}, + {"e2m5", "The Wizard's Manse"}, + {"e2m6", "The Dismal Oubliette"}, + {"e2m7", "Underearth"}, + + {"e3m1", "Termination Central"}, // 16 + {"e3m2", "The Vaults of Zin"}, + {"e3m3", "The Tomb of Terror"}, + {"e3m4", "Satan's Dark Delight"}, + {"e3m5", "Wind Tunnels"}, + {"e3m6", "Chambers of Torment"}, + {"e3m7", "The Haunted Halls"}, + + {"e4m1", "The Sewage System"}, // 23 + {"e4m2", "The Tower of Despair"}, + {"e4m3", "The Elder God Shrine"}, + {"e4m4", "The Palace of Hate"}, + {"e4m5", "Hell's Atrium"}, + {"e4m6", "The Pain Maze"}, + {"e4m7", "Azure Agony"}, + {"e4m8", "The Nameless City"}, + + {"end", "Shub-Niggurath's Pit"}, // 31 + + {"dm1", "Place of Two Deaths"}, // 32 + {"dm2", "Claustrophobopolis"}, + {"dm3", "The Abandoned Base"}, + {"dm4", "The Bad Place"}, + {"dm5", "The Cistern"}, + {"dm6", "The Dark Zone"} +}; + +//MED 01/06/97 added hipnotic levels +level_t hipnoticlevels[] = +{ + {"start", "Command HQ"}, // 0 + + {"hip1m1", "The Pumping Station"}, // 1 + {"hip1m2", "Storage Facility"}, + {"hip1m3", "The Lost Mine"}, + {"hip1m4", "Research Facility"}, + {"hip1m5", "Military Complex"}, + + {"hip2m1", "Ancient Realms"}, // 6 + {"hip2m2", "The Black Cathedral"}, + {"hip2m3", "The Catacombs"}, + {"hip2m4", "The Crypt"}, + {"hip2m5", "Mortum's Keep"}, + {"hip2m6", "The Gremlin's Domain"}, + + {"hip3m1", "Tur Torment"}, // 12 + {"hip3m2", "Pandemonium"}, + {"hip3m3", "Limbo"}, + {"hip3m4", "The Gauntlet"}, + + {"hipend", "Armagon's Lair"}, // 16 + + {"hipdm1", "The Edge of Oblivion"} // 17 +}; + +//PGM 01/07/97 added rogue levels +//PGM 03/02/97 added dmatch level +level_t roguelevels[] = +{ + {"start", "Split Decision"}, + {"r1m1", "Deviant's Domain"}, + {"r1m2", "Dread Portal"}, + {"r1m3", "Judgement Call"}, + {"r1m4", "Cave of Death"}, + {"r1m5", "Towers of Wrath"}, + {"r1m6", "Temple of Pain"}, + {"r1m7", "Tomb of the Overlord"}, + {"r2m1", "Tempus Fugit"}, + {"r2m2", "Elemental Fury I"}, + {"r2m3", "Elemental Fury II"}, + {"r2m4", "Curse of Osiris"}, + {"r2m5", "Wizard's Keep"}, + {"r2m6", "Blood Sacrifice"}, + {"r2m7", "Last Bastion"}, + {"r2m8", "Source of Evil"}, + {"ctf1", "Division of Change"} +}; + +typedef struct +{ + char *description; + int firstLevel; + int levels; +} episode_t; + +episode_t episodes[] = +{ + {"Welcome to Quake", 0, 1}, + {"Doomed Dimension", 1, 8}, + {"Realm of Black Magic", 9, 7}, + {"Netherworld", 16, 7}, + {"The Elder World", 23, 8}, + {"Final Level", 31, 1}, + {"Deathmatch Arena", 32, 6} +}; + +//MED 01/06/97 added hipnotic episodes +episode_t hipnoticepisodes[] = +{ + {"Scourge of Armagon", 0, 1}, + {"Fortress of the Dead", 1, 5}, + {"Dominion of Darkness", 6, 6}, + {"The Rift", 12, 4}, + {"Final Level", 16, 1}, + {"Deathmatch Arena", 17, 1} +}; + +//PGM 01/07/97 added rogue episodes +//PGM 03/02/97 added dmatch episode +episode_t rogueepisodes[] = +{ + {"Introduction", 0, 1}, + {"Hell's Fortress", 1, 7}, + {"Corridors of Time", 8, 8}, + {"Deathmatch Arena", 16, 1} +}; + +int startepisode; +int startlevel; +int maxplayers; +qboolean m_serverInfoMessage = false; +double m_serverInfoMessageTime; + +void M_Menu_GameOptions_f (void) +{ + key_dest = key_menu; + m_state = m_gameoptions; + m_entersound = true; + if (maxplayers == 0) + maxplayers = svs.maxclients; + if (maxplayers < 2) + maxplayers = svs.maxclientslimit; +} + + +int gameoptions_cursor_table[] = {40, 56, 64, 72, 80, 88, 96, 112, 120}; +#define NUM_GAMEOPTIONS 9 +int gameoptions_cursor; + +void M_GameOptions_Draw (void) +{ + /* + qpic_t *p; + int x; + + M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") ); + p = Draw_CachePic ("gfx/p_multi.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + + M_Print (160, 40, "begin game"); + + M_Print (0, 56, " Max players"); + M_Print (160, 56, va("%i", maxplayers) ); + + M_Print (0, 64, " Game Type"); + if (coop.value) + M_Print (160, 64, "Cooperative"); + else + M_Print (160, 64, "Deathmatch"); + + M_Print (0, 72, " Teamplay"); + if (rogue) + { + char *msg; + + switch((int)teamplay.value) + { + case 1: msg = "No Friendly Fire"; break; + case 2: msg = "Friendly Fire"; break; + case 3: msg = "Tag"; break; + case 4: msg = "Capture the Flag"; break; + case 5: msg = "One Flag CTF"; break; + case 6: msg = "Three Team CTF"; break; + default: msg = "Off"; break; + } + M_Print (160, 72, msg); + } + else + { + char *msg; + + switch((int)teamplay.value) + { + case 1: msg = "No Friendly Fire"; break; + case 2: msg = "Friendly Fire"; break; + default: msg = "Off"; break; + } + M_Print (160, 72, msg); + } + + M_Print (0, 80, " Skill"); + if (skill.value == 0) + M_Print (160, 80, "Easy difficulty"); + else if (skill.value == 1) + M_Print (160, 80, "Normal difficulty"); + else if (skill.value == 2) + M_Print (160, 80, "Hard difficulty"); + else + M_Print (160, 80, "Nightmare difficulty"); + + M_Print (0, 88, " Frag Limit"); + if (fraglimit.value == 0) + M_Print (160, 88, "none"); + else + M_Print (160, 88, va("%i frags", (int)fraglimit.value)); + + M_Print (0, 96, " Time Limit"); + if (timelimit.value == 0) + M_Print (160, 96, "none"); + else + M_Print (160, 96, va("%i minutes", (int)timelimit.value)); + + M_Print (0, 112, " Episode"); + //MED 01/06/97 added hipnotic episodes + if (hipnotic) + M_Print (160, 112, hipnoticepisodes[startepisode].description); + //PGM 01/07/97 added rogue episodes + else if (rogue) + M_Print (160, 112, rogueepisodes[startepisode].description); + else + M_Print (160, 112, episodes[startepisode].description); + + M_Print (0, 120, " Level"); + //MED 01/06/97 added hipnotic episodes + if (hipnotic) + { + M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name); + } + //PGM 01/07/97 added rogue episodes + else if (rogue) + { + M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name); + } + else + { + M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name); + } + +// line cursor + M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1)); + + if (m_serverInfoMessage) + { + if ((realtime - m_serverInfoMessageTime) < 5.0) + { + x = (320-26*8)/2; + x += 8; + M_Print (x, 146, " More than 4 players "); + M_Print (x, 154, " requires using command "); + M_Print (x, 162, "line parameters; please "); + M_Print (x, 170, " see techinfo.txt. "); + } + else + { + m_serverInfoMessage = false; + } + } + */ +} + + +void M_NetStart_Change (int dir) +{ + int count; + + switch (gameoptions_cursor) + { + case 1: + maxplayers += dir; + if (maxplayers > svs.maxclientslimit) + { + maxplayers = svs.maxclientslimit; + m_serverInfoMessage = true; + m_serverInfoMessageTime = realtime; + } + if (maxplayers < 2) + maxplayers = 2; + break; + + case 2: + Cvar_SetValue ("coop", coop.value ? 0 : 1); + break; + + case 3: + if (rogue) + count = 6; + else + count = 2; + + Cvar_SetValue ("teamplay", teamplay.value + dir); + if (teamplay.value > count) + Cvar_SetValue ("teamplay", 0); + else if (teamplay.value < 0) + Cvar_SetValue ("teamplay", count); + break; + + case 4: + Cvar_SetValue ("skill", skill.value + dir); + if (skill.value > 3) + Cvar_SetValue ("skill", 0); + if (skill.value < 0) + Cvar_SetValue ("skill", 3); + break; + + case 5: + Cvar_SetValue ("fraglimit", fraglimit.value + dir*10); + if (fraglimit.value > 100) + Cvar_SetValue ("fraglimit", 0); + if (fraglimit.value < 0) + Cvar_SetValue ("fraglimit", 100); + break; + + case 6: + Cvar_SetValue ("timelimit", timelimit.value + dir*5); + if (timelimit.value > 60) + Cvar_SetValue ("timelimit", 0); + if (timelimit.value < 0) + Cvar_SetValue ("timelimit", 60); + break; + + case 7: + startepisode += dir; + //MED 01/06/97 added hipnotic count + if (hipnotic) + count = 6; + //PGM 01/07/97 added rogue count + //PGM 03/02/97 added 1 for dmatch episode + else if (rogue) + count = 4; + else if (registered.value) + count = 7; + else + count = 2; + + if (startepisode < 0) + startepisode = count - 1; + + if (startepisode >= count) + startepisode = 0; + + startlevel = 0; + break; + + case 8: + startlevel += dir; + //MED 01/06/97 added hipnotic episodes + if (hipnotic) + count = hipnoticepisodes[startepisode].levels; + //PGM 01/06/97 added hipnotic episodes + else if (rogue) + count = rogueepisodes[startepisode].levels; + else + count = episodes[startepisode].levels; + + if (startlevel < 0) + startlevel = count - 1; + + if (startlevel >= count) + startlevel = 0; + break; + } +} + +void M_GameOptions_Key (int key) +{ + switch (key) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_Net_f (); + break; + + case K_UPARROW: + //S_LocalSound ("misc/menu1.wav"); + gameoptions_cursor--; + if (gameoptions_cursor < 0) + gameoptions_cursor = NUM_GAMEOPTIONS-1; + break; + + case K_DOWNARROW: + //S_LocalSound ("misc/menu1.wav"); + gameoptions_cursor++; + if (gameoptions_cursor >= NUM_GAMEOPTIONS) + gameoptions_cursor = 0; + break; + + case K_LEFTARROW: + if (gameoptions_cursor == 0) + break; + //S_LocalSound ("misc/menu3.wav"); + M_NetStart_Change (-1); + break; + + case K_RIGHTARROW: + if (gameoptions_cursor == 0) + break; + //S_LocalSound ("misc/menu3.wav"); + M_NetStart_Change (1); + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + //S_LocalSound ("misc/menu2.wav"); + if (gameoptions_cursor == 0) + { + if (sv.active) + Cbuf_AddText ("disconnect\n"); + Cbuf_AddText ("listen 0\n"); // so host_netport will be re-examined + Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) ); + SCR_BeginLoadingPlaque (); + + if (hipnotic) + Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) ); + else if (rogue) + Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) ); + else + Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) ); + + return; + } + + M_NetStart_Change (1); + break; + } +} + +//============================================================================= +/* SEARCH MENU */ + +qboolean searchComplete = false; +double searchCompleteTime; + +void M_Menu_Search_f (void) +{ + key_dest = key_menu; + m_state = m_search; + m_entersound = false; + slistSilent = true; + slistLocal = false; + searchComplete = false; + NET_Slist_f(); + +} + + +void M_Search_Draw (void) +{ + /* + qpic_t *p; + int x; + + p = Draw_CachePic ("gfx/p_multi.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + x = (320/2) - ((12*8)/2) + 4; + M_Print (x, 40, "Searching..."); + + if(slistInProgress) + { + NET_Poll(); + return; + } + + if (! searchComplete) + { + searchComplete = true; + searchCompleteTime = realtime; + } + + if (hostCacheCount) + { + M_Menu_ServerList_f (); + return; + } + + M_PrintWhite ((320/2) - ((22*8)/2), 64, "No Quake servers found"); + if ((realtime - searchCompleteTime) < 3.0) + return; + + M_Menu_LanConfig_f (); + */ +} + + +void M_Search_Key (int key) +{ +} + +//============================================================================= +/* SLIST MENU */ + +int slist_cursor; +qboolean slist_sorted; + +void M_Menu_ServerList_f (void) +{ + key_dest = key_menu; + m_state = m_slist; + m_entersound = true; + slist_cursor = 0; + m_return_onerror = false; + m_return_reason[0] = 0; + slist_sorted = false; +} + + +void M_ServerList_Draw (void) +{ + /* + int n; + char string [64]; + qpic_t *p; + + if (!slist_sorted) + { + if (hostCacheCount > 1) + { + int i,j; + hostcache_t temp; + for (i = 0; i < hostCacheCount; i++) + for (j = i+1; j < hostCacheCount; j++) + if (strcmp(hostcache[j].name, hostcache[i].name) < 0) + { + memcpy(&temp, &hostcache[j], sizeof(hostcache_t)); + memcpy(&hostcache[j], &hostcache[i], sizeof(hostcache_t)); + memcpy(&hostcache[i], &temp, sizeof(hostcache_t)); + } + } + slist_sorted = true; + } + + p = Draw_CachePic ("gfx/p_multi.lmp"); + M_DrawPic ( (320-p->width)/2, 4, p); + for (n = 0; n < hostCacheCount; n++) + { + if (hostcache[n].maxusers) + sprintf(string, "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); + else + sprintf(string, "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map); + M_Print (16, 32 + 8*n, string); + } + M_DrawCharacter (0, 32 + slist_cursor*8, 12+((int)(realtime*4)&1)); + + if (*m_return_reason) + M_PrintWhite (16, 148, m_return_reason); + */ +} + + +void M_ServerList_Key (int k) +{ + switch (k) + { + case K_ESCAPE: + case K_JOY1: + case K_JOY10: + case K_JOY21: + M_Menu_LanConfig_f (); + break; + + case K_SPACE: + M_Menu_Search_f (); + break; + + case K_UPARROW: + case K_LEFTARROW: + //S_LocalSound ("misc/menu1.wav"); + slist_cursor--; + if (slist_cursor < 0) + slist_cursor = hostCacheCount - 1; + break; + + case K_DOWNARROW: + case K_RIGHTARROW: + //S_LocalSound ("misc/menu1.wav"); + slist_cursor++; + if (slist_cursor >= hostCacheCount) + slist_cursor = 0; + break; + + case K_ENTER: + case K_JOY0: + case K_JOY9: + case K_JOY20: + //S_LocalSound ("misc/menu2.wav"); + m_return_state = m_state; + m_return_onerror = true; + slist_sorted = false; + key_dest = key_game; + m_state = m_none; + Cbuf_AddText ( va ("connect \"%s\"\n", hostcache[slist_cursor].cname) ); + break; + + default: + break; + } + +} + +//============================================================================= +/* VIDEO MENU */ + +void M_Menu_Video_f (void) +{ + key_dest = key_menu; + m_state = m_video; + m_entersound = true; +} + + +void M_Video_Draw (void) +{ + //(*vid_menudrawfn) (); +} + + +void M_Video_Key (int key) +{ + //(*vid_menukeyfn) (key); +} + +//============================================================================= +/* Menu Subsystem */ + + +void M_Init (void) +{ + Cmd_AddCommand ("togglemenu", M_ToggleMenu_f); + Cmd_AddCommand ("menu_main", M_Menu_Main_f); + Cmd_AddCommand ("menu_singleplayer", M_Menu_SinglePlayer_f); + Cmd_AddCommand ("menu_options", M_Menu_Options_f); + Cmd_AddCommand ("menu_keys", M_Menu_Keys_f); + Cmd_AddCommand ("menu_video", M_Menu_Video_f); + Cmd_AddCommand ("menu_quit", M_Menu_Quit_f); + + // Snag the game version + long length; + FILE* f = fopen(va("%s/version.txt", com_gamedir), "rb"); + + if (f) + { + fseek (f, 0, SEEK_END); + length = ftell (f); + fseek (f, 0, SEEK_SET); + game_build_date = malloc(length); + + if (game_build_date) + fread (game_build_date, 1, length, f); + + fclose (f); + } else { + game_build_date = "version.txt not found."; + } + + //M_Load_Menu_Pics(); + Map_Finder(); +} + + +void M_Draw (void) +{ + if (m_state == m_none || (key_dest != key_menu && key_dest != key_menu_pause)) + return; + + if (!m_recursiveDraw) + { + scr_copyeverything = 1; + + if (scr_con_current) + { + Draw_ConsoleBackground (vid.conheight); + VID_UnlockBuffer (); + S_ExtraUpdate (); + VID_LockBuffer (); + } + else + Draw_FadeScreen (); + + scr_fullupdate = 0; + } + else + { + m_recursiveDraw = false; + } + + switch (m_state) + { + case m_none: + break; + + case m_start: + M_Start_Menu_Draw(); + break; + + case m_paused_menu: + M_Paused_Menu_Draw(); + break; + + case m_main: + M_Main_Draw (); + break; + + case m_singleplayer: + M_SinglePlayer_Draw (); + break; + + case m_options: + M_Options_Draw (); + break; + + case m_keys: + M_Keys_Draw (); + break; + + case m_video: + //M_Video_Draw (); + break; + + case m_quit: + M_Quit_Draw (); + break; + + case m_restart: + M_Restart_Draw (); + break; + + case m_credits: + M_Credits_Draw (); + break; + + case m_exit: + M_Exit_Draw (); + break; + + case m_gameoptions: + M_GameOptions_Draw (); + break; + + case m_custommaps: + M_Menu_CustomMaps_Draw (); + return; + + default: + Con_Printf("Cannot identify menu for case %d\n", m_state); + } + + if (m_entersound) + { + S_LocalSound ("sounds/menu/enter.wav"); + m_entersound = false; + } + + VID_UnlockBuffer (); + S_ExtraUpdate (); + VID_LockBuffer (); +} + + +void M_Keydown (int key) +{ + switch (m_state) + { + case m_none: + return; + + case m_paused_menu: + M_Paused_Menu_Key (key); + break; + + case m_start: + M_Start_Key (key); + break; + + case m_main: + M_Main_Key (key); + return; + + case m_singleplayer: + M_SinglePlayer_Key (key); + return; + + case m_options: + M_Options_Key (key); + return; + + case m_keys: + M_Keys_Key (key); + return; + + case m_restart: + M_Restart_Key (key); + return; + + case m_credits: + M_Credits_Key (key); + return; + + case m_video: + //M_Video_Key (key); + return; + + case m_quit: + M_Quit_Key (key); + return; + + case m_exit: + M_Exit_Key (key); + return; + + case m_gameoptions: + M_GameOptions_Key (key); + return; + + case m_custommaps: + M_Menu_CustomMaps_Key (key); + return; + + default: + Con_Printf("Cannot identify menu for case %d\n", m_state); + } +} + + +void M_ConfigureNetSubsystem(void) +{ +// enable/disable net systems to match desired config + + Cbuf_AddText ("stopdemo\n"); + + if (TCPIPConfig) + net_hostport = lanConfig_port; +} \ No newline at end of file diff --git a/source/wii/menu.h b/source/wii/menu.h new file mode 100644 index 0000000..e645ce2 --- /dev/null +++ b/source/wii/menu.h @@ -0,0 +1,37 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// +// the net drivers should just set the apropriate bits in m_activenet, +// instead of having the menu code look through their internal tables +// +#define MNET_TCP 2 + +extern int m_activenet; + +// +// menus +// +void M_Init (void); +void M_Keydown (int key); +void M_Draw (void); +void M_ToggleMenu_f (void); + + diff --git a/source/wii/modelgen.h b/source/wii/modelgen.h new file mode 100644 index 0000000..3acbb89 --- /dev/null +++ b/source/wii/modelgen.h @@ -0,0 +1,134 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// modelgen.h: header file for model generation program +// + +// ********************************************************* +// * This file must be identical in the modelgen directory * +// * and in the Quake directory, because it's used to * +// * pass data from one to the other via model files. * +// ********************************************************* + +#ifdef INCLUDELIBS + +#include +#include +#include +#include + +#include "cmdlib.h" +#include "scriplib.h" +#include "trilib.h" +#include "lbmlib.h" +#include "mathlib.h" + +#endif + +#define ALIAS_VERSION 6 + +#define ALIAS_ONSEAM 0x0020 + +// must match definition in spritegn.h +#ifndef SYNCTYPE_T +#define SYNCTYPE_T +typedef enum {ST_SYNC=0, ST_RAND } synctype_t; +#endif + +typedef enum { ALIAS_SINGLE=0, ALIAS_GROUP } aliasframetype_t; + +typedef enum { ALIAS_SKIN_SINGLE=0, ALIAS_SKIN_GROUP } aliasskintype_t; + +typedef struct { + int ident; + int version; + vec3_t scale; + vec3_t scale_origin; + float boundingradius; + vec3_t eyeposition; + int numskins; + int skinwidth; + int skinheight; + int numverts; + int numtris; + int numframes; + synctype_t synctype; + int flags; + float size; +} mdl_t; + +// TODO: could be shorts + +typedef struct { + int onseam; + int s; + int t; +} stvert_t; + +typedef struct dtriangle_s { + int facesfront; + int vertindex[3]; +} dtriangle_t; + +#define DT_FACES_FRONT 0x0010 + +// This mirrors trivert_t in trilib.h, is present so Quake knows how to +// load this data + +typedef struct { + byte v[3]; + byte lightnormalindex; +} trivertx_t; + +typedef struct { + trivertx_t bboxmin; // lightnormal isn't used + trivertx_t bboxmax; // lightnormal isn't used + char name[16]; // frame name from grabbing +} daliasframe_t; + +typedef struct { + int numframes; + trivertx_t bboxmin; // lightnormal isn't used + trivertx_t bboxmax; // lightnormal isn't used +} daliasgroup_t; + +typedef struct { + int numskins; +} daliasskingroup_t; + +typedef struct { + float interval; +} daliasinterval_t; + +typedef struct { + float interval; +} daliasskininterval_t; + +typedef struct { + int type; +} daliasframetype_t; + +typedef struct { + int type; +} daliasskintype_t; + +#define IDPOLYHEADER (('O'<<24)+('P'<<16)+('D'<<8)+'I') + // little-endian "IDPO" + diff --git a/source/wii/net.h b/source/wii/net.h new file mode 100644 index 0000000..4fab00a --- /dev/null +++ b/source/wii/net.h @@ -0,0 +1,317 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net.h -- quake's interface to the networking layer + +struct qsockaddr +{ + short sa_family; + unsigned char sa_data[14]; +}; + + +#define NET_NAMELEN 64 + +#define NET_MAXMESSAGE 16384 //sB doubled for nzp i guess +#define NET_HEADERSIZE (2 * sizeof(unsigned int)) +#define NET_DATAGRAMSIZE (MAX_DATAGRAM + NET_HEADERSIZE) + +// NetHeader flags +#define NETFLAG_LENGTH_MASK 0x0000ffff +#define NETFLAG_DATA 0x00010000 +#define NETFLAG_ACK 0x00020000 +#define NETFLAG_NAK 0x00040000 +#define NETFLAG_EOM 0x00080000 +#define NETFLAG_UNRELIABLE 0x00100000 +#define NETFLAG_CTL 0x80000000 + + +#define NET_PROTOCOL_VERSION 3 + +// This is the network info/connection protocol. It is used to find Quake +// servers, get info about them, and connect to them. Once connected, the +// Quake game protocol (documented elsewhere) is used. +// +// +// General notes: +// game_name is currently always "QUAKE", but is there so this same protocol +// can be used for future games as well; can you say Quake2? +// +// CCREQ_CONNECT +// string game_name "QUAKE" +// byte net_protocol_version NET_PROTOCOL_VERSION +// +// CCREQ_SERVER_INFO +// string game_name "QUAKE" +// byte net_protocol_version NET_PROTOCOL_VERSION +// +// CCREQ_PLAYER_INFO +// byte player_number +// +// CCREQ_RULE_INFO +// string rule +// +// +// +// CCREP_ACCEPT +// long port +// +// CCREP_REJECT +// string reason +// +// CCREP_SERVER_INFO +// string server_address +// string host_name +// string level_name +// byte current_players +// byte max_players +// byte protocol_version NET_PROTOCOL_VERSION +// +// CCREP_PLAYER_INFO +// byte player_number +// string name +// long colors +// long frags +// long connect_time +// string address +// +// CCREP_RULE_INFO +// string rule +// string value + +// note: +// There are two address forms used above. The short form is just a +// port number. The address that goes along with the port is defined as +// "whatever address you receive this reponse from". This lets us use +// the host OS to solve the problem of multiple host addresses (possibly +// with no routing between them); the host will use the right address +// when we reply to the inbound connection request. The long from is +// a full address and port in a string. It is used for returning the +// address of a server that is not running locally. + +#define CCREQ_CONNECT 0x01 +#define CCREQ_SERVER_INFO 0x02 +#define CCREQ_PLAYER_INFO 0x03 +#define CCREQ_RULE_INFO 0x04 + +#define CCREP_ACCEPT 0x81 +#define CCREP_REJECT 0x82 +#define CCREP_SERVER_INFO 0x83 +#define CCREP_PLAYER_INFO 0x84 +#define CCREP_RULE_INFO 0x85 + +typedef struct qsocket_s +{ + struct qsocket_s *next; + double connecttime; + double lastMessageTime; + double lastSendTime; + + qboolean disconnected; + qboolean canSend; + qboolean sendNext; + + int driver; + int landriver; + int socket; + void *driverdata; + + unsigned int ackSequence; + unsigned int sendSequence; + unsigned int unreliableSendSequence; + int sendMessageLength; + byte sendMessage [NET_MAXMESSAGE]; + + unsigned int receiveSequence; + unsigned int unreliableReceiveSequence; + int receiveMessageLength; + byte receiveMessage [NET_MAXMESSAGE]; + + struct qsockaddr addr; + char address[NET_NAMELEN]; + +} qsocket_t; + +extern qsocket_t *net_activeSockets; +extern qsocket_t *net_freeSockets; +extern int net_numsockets; + +typedef struct +{ + char *name; + qboolean initialized; + int controlSock; + int (*Init) (void); + void (*Shutdown) (void); + void (*Listen) (qboolean state); + int (*OpenSocket) (int port); + int (*CloseSocket) (int socket); + int (*Connect) (int socket, struct qsockaddr *addr); + int (*CheckNewConnections) (void); + int (*Read) (int socket, byte *buf, int len, struct qsockaddr *addr); + int (*Write) (int socket, byte *buf, int len, struct qsockaddr *addr); + int (*Broadcast) (int socket, byte *buf, int len); + char * (*AddrToString) (struct qsockaddr *addr); + int (*StringToAddr) (char *string, struct qsockaddr *addr); + int (*GetSocketAddr) (int socket, struct qsockaddr *addr); + int (*GetNameFromAddr) (struct qsockaddr *addr, char *name); + int (*GetAddrFromName) (char *name, struct qsockaddr *addr); + int (*AddrCompare) (struct qsockaddr *addr1, struct qsockaddr *addr2); + int (*GetSocketPort) (struct qsockaddr *addr); + int (*SetSocketPort) (struct qsockaddr *addr, int port); +} net_landriver_t; + +#define MAX_NET_DRIVERS 8 +extern int net_numlandrivers; +extern net_landriver_t net_landrivers[MAX_NET_DRIVERS]; + +typedef struct +{ + char *name; + qboolean initialized; + int (*Init) (void); + void (*Listen) (qboolean state); + void (*SearchForHosts) (qboolean xmit); + qsocket_t *(*Connect) (char *host); + qsocket_t *(*CheckNewConnections) (void); + int (*QGetMessage) (qsocket_t *sock); + int (*QSendMessage) (qsocket_t *sock, sizebuf_t *data); + int (*SendUnreliableMessage) (qsocket_t *sock, sizebuf_t *data); + qboolean (*CanSendMessage) (qsocket_t *sock); + qboolean (*CanSendUnreliableMessage) (qsocket_t *sock); + void (*Close) (qsocket_t *sock); + void (*Shutdown) (void); + int controlSock; +} net_driver_t; + +extern int net_numdrivers; +extern net_driver_t net_drivers[MAX_NET_DRIVERS]; + +extern int DEFAULTnet_hostport; +extern int net_hostport; + +extern int net_driverlevel; +extern cvar_t hostname; +extern char playername[]; +extern int playercolor; + +extern int messagesSent; +extern int messagesReceived; +extern int unreliableMessagesSent; +extern int unreliableMessagesReceived; + +qsocket_t *NET_NewQSocket (void); +void NET_FreeQSocket(qsocket_t *); +double SetNetTime(void); + + +#define HOSTCACHESIZE 8 + +typedef struct +{ + char name[16]; + char map[16]; + char cname[32]; + int users; + int maxusers; + int driver; + int ldriver; + struct qsockaddr addr; +} hostcache_t; + +extern int hostCacheCount; +extern hostcache_t hostcache[HOSTCACHESIZE]; + +#ifdef IDGODS +qboolean IsID(struct qsockaddr *addr); +#endif + +//============================================================================ +// +// public network functions +// +//============================================================================ + +extern double net_time; +extern sizebuf_t net_message; +extern int net_activeconnections; + +void NET_Init (void); +void NET_Shutdown (void); + +struct qsocket_s *NET_CheckNewConnections (void); +// returns a new connection number if there is one pending, else -1 + +struct qsocket_s *NET_Connect (char *host); +// called by client to connect to a host. Returns -1 if not able to + +qboolean NET_CanSendMessage (qsocket_t *sock); +// Returns true or false if the given qsocket can currently accept a +// message to be transmitted. + +int NET_GetMessage (struct qsocket_s *sock); +// returns data in net_message sizebuf +// returns 0 if no data is waiting +// returns 1 if a message was received +// returns 2 if an unreliable message was received +// returns -1 if the connection died + +int NET_SendMessage (struct qsocket_s *sock, sizebuf_t *data); +int NET_SendUnreliableMessage (struct qsocket_s *sock, sizebuf_t *data); +// returns 0 if the message connot be delivered reliably, but the connection +// is still considered valid +// returns 1 if the message was sent properly +// returns -1 if the connection died + +int NET_SendToAll(sizebuf_t *data, int blocktime); +// This is a reliable *blocking* send to all attached clients. + + +void NET_Close (struct qsocket_s *sock); +// if a dead connection is returned by a get or send function, this function +// should be called when it is convenient + +// Server calls when a client is kicked off for a game related misbehavior +// like an illegal protocal conversation. Client calls when disconnecting +// from a server. +// A netcon_t number will not be reused until this function is called for it + +void NET_Poll(void); + + +typedef struct _PollProcedure +{ + struct _PollProcedure *next; + double nextTime; + void (*procedure)(); + void *arg; +} PollProcedure; + +void SchedulePollProcedure(PollProcedure *pp, double timeOffset); + +extern qboolean tcpipAvailable; +extern qboolean ipxAvailable; +extern char my_tcpip_address[NET_NAMELEN]; +extern char my_ipx_address[NET_NAMELEN]; + +extern qboolean slistInProgress; +extern qboolean slistSilent; +extern qboolean slistLocal; + +void NET_Slist_f (void); diff --git a/source/wii/net_dgrm.c b/source/wii/net_dgrm.c new file mode 100644 index 0000000..875b095 --- /dev/null +++ b/source/wii/net_dgrm.c @@ -0,0 +1,1373 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_dgrm.c + +// This is enables a simple IP banning mechanism +#define BAN_TEST + +#ifdef BAN_TEST +#if defined(_WIN32) +#include +#elif defined (NeXT) +#include +#include +#else +#define AF_INET 2 /* internet */ +struct in_addr +{ + union + { + struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { unsigned short s_w1,s_w2; } S_un_w; + unsigned long S_addr; + } S_un; +}; +#define s_addr S_un.S_addr /* can be used for most tcp & ip code */ +struct sockaddr_in +{ + short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; +char *inet_ntoa(struct in_addr in); +unsigned long inet_addr(const char *cp); +#endif +#endif // BAN_TEST + +#include "../quakedef.h" +#include "net_dgrm.h" + +// these two macros are to make the code more readable +#define sfunc net_landrivers[sock->landriver] +#define dfunc net_landrivers[net_landriverlevel] + +static int net_landriverlevel; + +/* statistic counters */ +int packetsSent = 0; +int packetsReSent = 0; +int packetsReceived = 0; +int receivedDuplicateCount = 0; +int shortPacketCount = 0; +int droppedDatagrams; + +static int myDriverLevel; + +struct +{ + unsigned int length; + unsigned int sequence; + byte data[MAX_DATAGRAM]; +} packetBuffer; + +extern int m_return_state; +extern int m_state; +extern qboolean m_return_onerror; +extern char m_return_reason[32]; + + +#ifdef DEBUG +char *StrAddr (struct qsockaddr *addr) +{ + static char buf[34]; + byte *p = (byte *)addr; + int n; + + for (n = 0; n < 16; n++) + sprintf (buf + n * 2, "%02x", *p++); + return buf; +} +#endif + + +#ifdef BAN_TEST +unsigned long banAddr = 0x00000000; +unsigned long banMask = 0xffffffff; + +void NET_Ban_f (void) +{ + char addrStr [32]; + char maskStr [32]; + void (*print) (char *fmt, ...); + + if (cmd_source == src_command) + { + if (!sv.active) + { + Cmd_ForwardToServer (); + return; + } + print = Con_Printf; + } + else + { + if (pr_global_struct->deathmatch && !host_client->privileged) + return; + print = SV_ClientPrintf; + } + + switch (Cmd_Argc ()) + { + case 1: + if (((struct in_addr *)&banAddr)->s_addr) + { + strcpy(addrStr, inet_ntoa(*(struct in_addr *)&banAddr)); + strcpy(maskStr, inet_ntoa(*(struct in_addr *)&banMask)); + print("Banning %s [%s]\n", addrStr, maskStr); + } + else + print("Banning not active\n"); + break; + + case 2: + if (strcasecmp(Cmd_Argv(1), "off") == 0) + banAddr = 0x00000000; + else + banAddr = inet_addr(Cmd_Argv(1)); + banMask = 0xffffffff; + break; + + case 3: + banAddr = inet_addr(Cmd_Argv(1)); + banMask = inet_addr(Cmd_Argv(2)); + break; + + default: + print("BAN ip_address [mask]\n"); + break; + } +} +#endif + + +int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) +{ + unsigned int packetLen; + unsigned int dataLen; + unsigned int eom; + +#ifdef DEBUG + if (data->cursize == 0) + Sys_Error("Datagram_SendMessage: zero length message\n"); + + if (data->cursize > NET_MAXMESSAGE) + Sys_Error("Datagram_SendMessage: message too big %u\n", data->cursize); + + if (sock->canSend == false) + Sys_Error("SendMessage: called with canSend == false\n"); +#endif + + memcpy(sock->sendMessage, data->data, data->cursize); + sock->sendMessageLength = data->cursize; + + if (data->cursize <= MAX_DATAGRAM) + { + dataLen = data->cursize; + eom = NETFLAG_EOM; + } + else + { + dataLen = MAX_DATAGRAM; + eom = 0; + } + packetLen = NET_HEADERSIZE + dataLen; + + packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); + packetBuffer.sequence = BigLong(sock->sendSequence++); + memcpy (packetBuffer.data, sock->sendMessage, dataLen); + + sock->canSend = false; + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + sock->lastSendTime = net_time; + packetsSent++; + return 1; +} + + +int SendMessageNext (qsocket_t *sock) +{ + unsigned int packetLen; + unsigned int dataLen; + unsigned int eom; + + if (sock->sendMessageLength <= MAX_DATAGRAM) + { + dataLen = sock->sendMessageLength; + eom = NETFLAG_EOM; + } + else + { + dataLen = MAX_DATAGRAM; + eom = 0; + } + packetLen = NET_HEADERSIZE + dataLen; + + packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); + packetBuffer.sequence = BigLong(sock->sendSequence++); + memcpy (packetBuffer.data, sock->sendMessage, dataLen); + + sock->sendNext = false; + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + sock->lastSendTime = net_time; + packetsSent++; + return 1; +} + + +int ReSendMessage (qsocket_t *sock) +{ + unsigned int packetLen; + unsigned int dataLen; + unsigned int eom; + + if (sock->sendMessageLength <= MAX_DATAGRAM) + { + dataLen = sock->sendMessageLength; + eom = NETFLAG_EOM; + } + else + { + dataLen = MAX_DATAGRAM; + eom = 0; + } + packetLen = NET_HEADERSIZE + dataLen; + + packetBuffer.length = BigLong(packetLen | (NETFLAG_DATA | eom)); + packetBuffer.sequence = BigLong(sock->sendSequence - 1); + memcpy (packetBuffer.data, sock->sendMessage, dataLen); + + sock->sendNext = false; + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + sock->lastSendTime = net_time; + packetsReSent++; + return 1; +} + + +qboolean Datagram_CanSendMessage (qsocket_t *sock) +{ + if (sock->sendNext) + SendMessageNext (sock); + + return sock->canSend; +} + + +qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock) +{ + return true; +} + + +int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) +{ + int packetLen; + +#ifdef DEBUG + if (data->cursize == 0) + Sys_Error("Datagram_SendUnreliableMessage: zero length message\n"); + + if (data->cursize > MAX_DATAGRAM) + Sys_Error("Datagram_SendUnreliableMessage: message too big %u\n", data->cursize); +#endif + + packetLen = NET_HEADERSIZE + data->cursize; + + packetBuffer.length = BigLong(packetLen | NETFLAG_UNRELIABLE); + packetBuffer.sequence = BigLong(sock->unreliableSendSequence++); + memcpy (packetBuffer.data, data->data, data->cursize); + + if (sfunc.Write (sock->socket, (byte *)&packetBuffer, packetLen, &sock->addr) == -1) + return -1; + + packetsSent++; + return 1; +} + + +int Datagram_GetMessage (qsocket_t *sock) +{ + unsigned int length; + unsigned int flags; + int ret = 0; + struct qsockaddr readaddr; + unsigned int sequence; + unsigned int count; + + if (!sock->canSend) + if ((net_time - sock->lastSendTime) > 1.0) + ReSendMessage (sock); + + while(1) + { + length = sfunc.Read (sock->socket, (byte *)&packetBuffer, NET_DATAGRAMSIZE, &readaddr); + +// if ((rand() & 255) > 220) +// continue; + + if (length == 0) + break; + + if (length == -1) + { + Con_Printf("Read error\n"); + return -1; + } + + if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0) + { +#ifdef DEBUG + Con_DPrintf("Forged packet received\n"); + Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr)); + Con_DPrintf("Received: %s\n", StrAddr (&readaddr)); +#endif + continue; + } + + if (length < NET_HEADERSIZE) + { + shortPacketCount++; + continue; + } + + length = BigLong(packetBuffer.length); + flags = length & (~NETFLAG_LENGTH_MASK); + length &= NETFLAG_LENGTH_MASK; + + if (flags & NETFLAG_CTL) + continue; + + sequence = BigLong(packetBuffer.sequence); + packetsReceived++; + + if (flags & NETFLAG_UNRELIABLE) + { + if (sequence < sock->unreliableReceiveSequence) + { + Con_DPrintf("Got a stale datagram\n"); + ret = 0; + break; + } + if (sequence != sock->unreliableReceiveSequence) + { + count = sequence - sock->unreliableReceiveSequence; + droppedDatagrams += count; + Con_DPrintf("Dropped %u datagram(s)\n", count); + } + sock->unreliableReceiveSequence = sequence + 1; + + length -= NET_HEADERSIZE; + + SZ_Clear (&net_message); + SZ_Write (&net_message, packetBuffer.data, length); + + ret = 2; + break; + } + + if (flags & NETFLAG_ACK) + { + if (sequence != (sock->sendSequence - 1)) + { + Con_DPrintf("Stale ACK received\n"); + continue; + } + if (sequence == sock->ackSequence) + { + sock->ackSequence++; + if (sock->ackSequence != sock->sendSequence) + Con_DPrintf("ack sequencing error\n"); + } + else + { + Con_DPrintf("Duplicate ACK received\n"); + continue; + } + sock->sendMessageLength -= MAX_DATAGRAM; + if (sock->sendMessageLength > 0) + { + memcpy(sock->sendMessage, sock->sendMessage+MAX_DATAGRAM, sock->sendMessageLength); + sock->sendNext = true; + } + else + { + sock->sendMessageLength = 0; + sock->canSend = true; + } + continue; + } + + if (flags & NETFLAG_DATA) + { + packetBuffer.length = BigLong(NET_HEADERSIZE | NETFLAG_ACK); + packetBuffer.sequence = BigLong(sequence); + sfunc.Write (sock->socket, (byte *)&packetBuffer, NET_HEADERSIZE, &readaddr); + + if (sequence != sock->receiveSequence) + { + receivedDuplicateCount++; + continue; + } + sock->receiveSequence++; + + length -= NET_HEADERSIZE; + + if (flags & NETFLAG_EOM) + { + SZ_Clear(&net_message); + SZ_Write(&net_message, sock->receiveMessage, sock->receiveMessageLength); + SZ_Write(&net_message, packetBuffer.data, length); + sock->receiveMessageLength = 0; + + ret = 1; + break; + } + + memcpy(sock->receiveMessage + sock->receiveMessageLength, packetBuffer.data, length); + sock->receiveMessageLength += length; + continue; + } + } + + if (sock->sendNext) + SendMessageNext (sock); + + return ret; +} + + +void PrintStats(qsocket_t *s) +{ + Con_Printf("canSend = %4u \n", s->canSend); + Con_Printf("sendSeq = %4u ", s->sendSequence); + Con_Printf("recvSeq = %4u \n", s->receiveSequence); + Con_Printf("\n"); +} + +void NET_Stats_f (void) +{ + qsocket_t *s; + + if (Cmd_Argc () == 1) + { + Con_Printf("unreliable messages sent = %i\n", unreliableMessagesSent); + Con_Printf("unreliable messages recv = %i\n", unreliableMessagesReceived); + Con_Printf("reliable messages sent = %i\n", messagesSent); + Con_Printf("reliable messages received = %i\n", messagesReceived); + Con_Printf("packetsSent = %i\n", packetsSent); + Con_Printf("packetsReSent = %i\n", packetsReSent); + Con_Printf("packetsReceived = %i\n", packetsReceived); + Con_Printf("receivedDuplicateCount = %i\n", receivedDuplicateCount); + Con_Printf("shortPacketCount = %i\n", shortPacketCount); + Con_Printf("droppedDatagrams = %i\n", droppedDatagrams); + } + else if (strcmp(Cmd_Argv(1), "*") == 0) + { + for (s = net_activeSockets; s; s = s->next) + PrintStats(s); + for (s = net_freeSockets; s; s = s->next) + PrintStats(s); + } + else + { + for (s = net_activeSockets; s; s = s->next) + if (strcasecmp(Cmd_Argv(1), s->address) == 0) + break; + if (s == NULL) + for (s = net_freeSockets; s; s = s->next) + if (strcasecmp(Cmd_Argv(1), s->address) == 0) + break; + if (s == NULL) + return; + PrintStats(s); + } +} + + +static qboolean testInProgress = false; +static int testPollCount; +static int testDriver; +static int testSocket; + +static void Test_Poll(void); +PollProcedure testPollProcedure = {NULL, 0.0, Test_Poll}; + +static void Test_Poll(void) +{ + struct qsockaddr clientaddr; + int control; + int len; + char name[32]; + char address[64]; + int colors; + int frags; + int connectTime; + byte playerNumber; + + net_landriverlevel = testDriver; + + while (1) + { + len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr); + if (len < sizeof(int)) + break; + + net_message.cursize = len; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + break; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + break; + if ((control & NETFLAG_LENGTH_MASK) != len) + break; + + if (MSG_ReadByte() != CCREP_PLAYER_INFO) + Sys_Error("Unexpected repsonse to Player Info request\n"); + + playerNumber = MSG_ReadByte(); + strcpy(name, MSG_ReadString()); + colors = MSG_ReadLong(); + frags = MSG_ReadLong(); + connectTime = MSG_ReadLong(); + strcpy(address, MSG_ReadString()); + + Con_Printf("%s\n frags:%3i colors:%u %u time:%u\n %s\n", name, frags, colors >> 4, colors & 0x0f, connectTime / 60, address); + } + + testPollCount--; + if (testPollCount) + { + SchedulePollProcedure(&testPollProcedure, 0.1); + } + else + { + dfunc.CloseSocket(testSocket); + testInProgress = false; + } +} + +static void Test_f (void) +{ + char *host; + int n; + int max = MAX_SCOREBOARD; + struct qsockaddr sendaddr; + + if (testInProgress) + return; + + host = Cmd_Argv (1); + + if (host && hostCacheCount) + { + for (n = 0; n < hostCacheCount; n++) + if (strcasecmp (host, hostcache[n].name) == 0) + { + if (hostcache[n].driver != myDriverLevel) + continue; + net_landriverlevel = hostcache[n].ldriver; + max = hostcache[n].maxusers; + memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); + break; + } + if (n < hostCacheCount) + goto JustDoIt; + } + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + { + if (!net_landrivers[net_landriverlevel].initialized) + continue; + + // see if we can resolve the host name + if (dfunc.GetAddrFromName(host, &sendaddr) != -1) + break; + } + if (net_landriverlevel == net_numlandrivers) + return; + +JustDoIt: + testSocket = dfunc.OpenSocket(0); + if (testSocket == -1) + return; + + testInProgress = true; + testPollCount = 20; + testDriver = net_landriverlevel; + + for (n = 0; n < max; n++) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO); + MSG_WriteByte(&net_message, n); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (testSocket, net_message.data, net_message.cursize, &sendaddr); + } + SZ_Clear(&net_message); + SchedulePollProcedure(&testPollProcedure, 0.1); +} + + +static qboolean test2InProgress = false; +static int test2Driver; +static int test2Socket; + +static void Test2_Poll(void); +PollProcedure test2PollProcedure = {NULL, 0.0, Test2_Poll}; + +static void Test2_Poll(void) +{ + struct qsockaddr clientaddr; + int control; + int len; + char name[256]; + char value[256]; + + net_landriverlevel = test2Driver; + name[0] = 0; + + len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr); + if (len < sizeof(int)) + goto Reschedule; + + net_message.cursize = len; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + goto Error; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + goto Error; + if ((control & NETFLAG_LENGTH_MASK) != len) + goto Error; + + if (MSG_ReadByte() != CCREP_RULE_INFO) + goto Error; + + strcpy(name, MSG_ReadString()); + if (name[0] == 0) + goto Done; + strcpy(value, MSG_ReadString()); + + Con_Printf("%-16.16s %-16.16s\n", name, value); + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_RULE_INFO); + MSG_WriteString(&net_message, name); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (test2Socket, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + +Reschedule: + SchedulePollProcedure(&test2PollProcedure, 0.05); + return; + +Error: + Con_Printf("Unexpected repsonse to Rule Info request\n"); +Done: + dfunc.CloseSocket(test2Socket); + test2InProgress = false; + return; +} + +static void Test2_f (void) +{ + char *host; + int n; + struct qsockaddr sendaddr; + + if (test2InProgress) + return; + + host = Cmd_Argv (1); + + if (host && hostCacheCount) + { + for (n = 0; n < hostCacheCount; n++) + if (strcasecmp (host, hostcache[n].name) == 0) + { + if (hostcache[n].driver != myDriverLevel) + continue; + net_landriverlevel = hostcache[n].ldriver; + memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr)); + break; + } + if (n < hostCacheCount) + goto JustDoIt; + } + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + { + if (!net_landrivers[net_landriverlevel].initialized) + continue; + + // see if we can resolve the host name + if (dfunc.GetAddrFromName(host, &sendaddr) != -1) + break; + } + if (net_landriverlevel == net_numlandrivers) + return; + +JustDoIt: + test2Socket = dfunc.OpenSocket(0); + if (test2Socket == -1) + return; + + test2InProgress = true; + test2Driver = net_landriverlevel; + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_RULE_INFO); + MSG_WriteString(&net_message, ""); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (test2Socket, net_message.data, net_message.cursize, &sendaddr); + SZ_Clear(&net_message); + SchedulePollProcedure(&test2PollProcedure, 0.05); +} + + +int Datagram_Init (void) +{ + int i; + int csock; + + myDriverLevel = net_driverlevel; + Cmd_AddCommand ("net_stats", NET_Stats_f); + + if (COM_CheckParm("-nolan")) + return -1; + + for (i = 0; i < net_numlandrivers; i++) + { + csock = net_landrivers[i].Init (); + if (csock == -1) + continue; + net_landrivers[i].initialized = true; + net_landrivers[i].controlSock = csock; + } + +#ifdef BAN_TEST + Cmd_AddCommand ("ban", NET_Ban_f); +#endif + Cmd_AddCommand ("test", Test_f); + Cmd_AddCommand ("test2", Test2_f); + + return 0; +} + + +void Datagram_Shutdown (void) +{ + int i; + +// +// shutdown the lan drivers +// + for (i = 0; i < net_numlandrivers; i++) + { + if (net_landrivers[i].initialized) + { + net_landrivers[i].Shutdown (); + net_landrivers[i].initialized = false; + } + } +} + + +void Datagram_Close (qsocket_t *sock) +{ + sfunc.CloseSocket(sock->socket); +} + + +void Datagram_Listen (qboolean state) +{ + int i; + + for (i = 0; i < net_numlandrivers; i++) + if (net_landrivers[i].initialized) + net_landrivers[i].Listen (state); +} + + +static qsocket_t *_Datagram_CheckNewConnections (void) +{ + struct qsockaddr clientaddr; + struct qsockaddr newaddr; + int newsock; + int acceptsock; + qsocket_t *sock; + qsocket_t *s; + int len; + int command; + int control; + int ret; + + acceptsock = dfunc.CheckNewConnections(); + if (acceptsock == -1) + return NULL; + + SZ_Clear(&net_message); + + len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr); + if (len < sizeof(int)) + return NULL; + net_message.cursize = len; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + return NULL; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + return NULL; + if ((control & NETFLAG_LENGTH_MASK) != len) + return NULL; + + command = MSG_ReadByte(); + if (command == CCREQ_SERVER_INFO) + { + if (strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_SERVER_INFO); + dfunc.GetSocketAddr(acceptsock, &newaddr); + MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); + MSG_WriteString(&net_message, hostname.string); + MSG_WriteString(&net_message, sv.name); + MSG_WriteByte(&net_message, net_activeconnections); + MSG_WriteByte(&net_message, svs.maxclients); + MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + + if (command == CCREQ_PLAYER_INFO) + { + int playerNumber; + int activeNumber; + int clientNumber; + client_t *client; + + playerNumber = MSG_ReadByte(); + activeNumber = -1; + for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) + { + if (client->active) + { + activeNumber++; + if (activeNumber == playerNumber) + break; + } + } + if (clientNumber == svs.maxclients) + return NULL; + + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_PLAYER_INFO); + MSG_WriteByte(&net_message, playerNumber); + MSG_WriteString(&net_message, client->name); + MSG_WriteLong(&net_message, client->colors); + MSG_WriteLong(&net_message, 0); + MSG_WriteLong(&net_message, (int)(net_time - client->netconnection->connecttime)); + MSG_WriteString(&net_message, client->netconnection->address); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + + return NULL; + } + + if (command == CCREQ_RULE_INFO) + { + const char *prevCvarName; + cvar_t *var; + + // find the search start location + prevCvarName = MSG_ReadString(); + var = Cvar_FindVarAfter (prevCvarName, CVAR_SERVERINFO); + + // send the response + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_RULE_INFO); + if (var) + { + MSG_WriteString(&net_message, var->name); + MSG_WriteString(&net_message, var->string); + } + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + + return NULL; + } + + if (command != CCREQ_CONNECT) + return NULL; + + if (strcmp(MSG_ReadString(), "QUAKE") != 0) + return NULL; + + if (MSG_ReadByte() != NET_PROTOCOL_VERSION) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_REJECT); + MSG_WriteString(&net_message, "Incompatible version.\n"); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + +#ifdef BAN_TEST + // check for a ban + if (clientaddr.sa_family == AF_INET) + { + unsigned long testAddr; + testAddr = ((struct sockaddr_in *)&clientaddr)->sin_addr.s_addr; + if ((testAddr & banMask) == banAddr) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_REJECT); + MSG_WriteString(&net_message, "You have been banned.\n"); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + } +#endif + + // see if this guy is already connected + for (s = net_activeSockets; s; s = s->next) + { + if (s->driver != net_driverlevel) + continue; + ret = dfunc.AddrCompare(&clientaddr, &s->addr); + if (ret >= 0) + { + // is this a duplicate connection reqeust? + if (ret == 0 && net_time - s->connecttime < 2.0) + { + // yes, so send a duplicate reply + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_ACCEPT); + dfunc.GetSocketAddr(s->socket, &newaddr); + MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + // it's somebody coming back in from a crash/disconnect + // so close the old qsocket and let their retry get them back in + NET_Close(s); + return NULL; + } + } + + // allocate a QSocket + sock = NET_NewQSocket (); + if (sock == NULL) + { + // no room; try to let him know + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_REJECT); + MSG_WriteString(&net_message, "Server is full.\n"); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + return NULL; + } + + // allocate a network socket + newsock = dfunc.OpenSocket(0); + if (newsock == -1) + { + NET_FreeQSocket(sock); + return NULL; + } + + // connect to the client + if (dfunc.Connect (newsock, &clientaddr) == -1) + { + dfunc.CloseSocket(newsock); + NET_FreeQSocket(sock); + return NULL; + } + + // everything is allocated, just fill in the details + sock->socket = newsock; + sock->landriver = net_landriverlevel; + sock->addr = clientaddr; + strcpy(sock->address, dfunc.AddrToString(&clientaddr)); + + // send him back the info about the server connection he has been allocated + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREP_ACCEPT); + dfunc.GetSocketAddr(newsock, &newaddr); + MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr)); +// MSG_WriteString(&net_message, dfunc.AddrToString(&newaddr)); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr); + SZ_Clear(&net_message); + + return sock; +} + +qsocket_t *Datagram_CheckNewConnections (void) +{ + qsocket_t *ret = NULL; + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + if (net_landrivers[net_landriverlevel].initialized) + if ((ret = _Datagram_CheckNewConnections ()) != NULL) + break; + return ret; +} + + +static void _Datagram_SearchForHosts (qboolean xmit) +{ + int ret; + int n; + int i; + struct qsockaddr readaddr; + struct qsockaddr myaddr; + int control; + + dfunc.GetSocketAddr (dfunc.controlSock, &myaddr); + if (xmit) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); + MSG_WriteString(&net_message, "QUAKE"); + MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize); + SZ_Clear(&net_message); + } + + while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) + { + if (ret < sizeof(int)) + continue; + net_message.cursize = ret; + + // don't answer our own query + if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0) + continue; + + // is the cache full? + if (hostCacheCount == HOSTCACHESIZE) + continue; + + MSG_BeginReading (); + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + continue; + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + continue; + if ((control & NETFLAG_LENGTH_MASK) != ret) + continue; + + if (MSG_ReadByte() != CCREP_SERVER_INFO) + continue; + + dfunc.GetAddrFromName(MSG_ReadString(), &readaddr); + // search the cache for this server + for (n = 0; n < hostCacheCount; n++) + if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0) + break; + + // is it already there? + if (n < hostCacheCount) + continue; + + // add it + hostCacheCount++; + strcpy(hostcache[n].name, MSG_ReadString()); + strcpy(hostcache[n].map, MSG_ReadString()); + hostcache[n].users = MSG_ReadByte(); + hostcache[n].maxusers = MSG_ReadByte(); + if (MSG_ReadByte() != NET_PROTOCOL_VERSION) + { + strcpy(hostcache[n].cname, hostcache[n].name); + hostcache[n].cname[14] = 0; + strcpy(hostcache[n].name, "*"); + strcat(hostcache[n].name, hostcache[n].cname); + } + memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr)); + hostcache[n].driver = net_driverlevel; + hostcache[n].ldriver = net_landriverlevel; + strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr)); + + // check for a name conflict + for (i = 0; i < hostCacheCount; i++) + { + if (i == n) + continue; + if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0) + { + i = strlen(hostcache[n].name); + if (i < 15 && hostcache[n].name[i-1] > '8') + { + hostcache[n].name[i] = '0'; + hostcache[n].name[i+1] = 0; + } + else + hostcache[n].name[i-1]++; + i = -1; + } + } + } +} + +void Datagram_SearchForHosts (qboolean xmit) +{ + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + { + if (hostCacheCount == HOSTCACHESIZE) + break; + if (net_landrivers[net_landriverlevel].initialized) + _Datagram_SearchForHosts (xmit); + } +} + + +static qsocket_t *_Datagram_Connect (char *host) +{ + struct qsockaddr sendaddr; + struct qsockaddr readaddr; + qsocket_t *sock; + int newsock; + int ret; + int reps; + double start_time; + int control; + char *reason; + + // see if we can resolve the host name + if (dfunc.GetAddrFromName(host, &sendaddr) == -1) + return NULL; + + newsock = dfunc.OpenSocket (0); + if (newsock == -1) + return NULL; + + sock = NET_NewQSocket (); + if (sock == NULL) + goto ErrorReturn2; + sock->socket = newsock; + sock->landriver = net_landriverlevel; + + // connect to the host + if (dfunc.Connect (newsock, &sendaddr) == -1) + goto ErrorReturn; + + // send the connection request + Con_Printf("trying...\n"); SCR_UpdateScreen (); + start_time = net_time; + + for (reps = 0; reps < 3; reps++) + { + SZ_Clear(&net_message); + // save space for the header, filled in later + MSG_WriteLong(&net_message, 0); + MSG_WriteByte(&net_message, CCREQ_CONNECT); + MSG_WriteString(&net_message, "QUAKE"); + MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); + *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + dfunc.Write (newsock, net_message.data, net_message.cursize, &sendaddr); + SZ_Clear(&net_message); + do + { + ret = dfunc.Read (newsock, net_message.data, net_message.maxsize, &readaddr); + // if we got something, validate it + if (ret > 0) + { + // is it from the right place? + if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0) + { +#ifdef DEBUG + Con_Printf("wrong reply address\n"); + Con_Printf("Expected: %s\n", StrAddr (&sendaddr)); + Con_Printf("Received: %s\n", StrAddr (&readaddr)); + SCR_UpdateScreen (); +#endif + ret = 0; + continue; + } + + if (ret < sizeof(int)) + { + ret = 0; + continue; + } + + net_message.cursize = ret; + MSG_BeginReading (); + + control = BigLong(*((int *)net_message.data)); + MSG_ReadLong(); + if (control == -1) + { + ret = 0; + continue; + } + if ((control & (~NETFLAG_LENGTH_MASK)) != NETFLAG_CTL) + { + ret = 0; + continue; + } + if ((control & NETFLAG_LENGTH_MASK) != ret) + { + ret = 0; + continue; + } + } + } + while (ret == 0 && (SetNetTime() - start_time) < 2.5); + if (ret) + break; + Con_Printf("still trying...\n"); SCR_UpdateScreen (); + start_time = SetNetTime(); + } + + if (ret == 0) + { + reason = "No Response"; + Con_Printf("%s\n", reason); + strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + if (ret == -1) + { + reason = "Network Error"; + Con_Printf("%s\n", reason); + strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + ret = MSG_ReadByte(); + if (ret == CCREP_REJECT) + { + reason = MSG_ReadString(); + Con_Printf(reason); + strncpy(m_return_reason, reason, 31); + goto ErrorReturn; + } + + if (ret == CCREP_ACCEPT) + { + memcpy(&sock->addr, &sendaddr, sizeof(struct qsockaddr)); + dfunc.SetSocketPort (&sock->addr, MSG_ReadLong()); + } + else + { + reason = "Bad Response"; + Con_Printf("%s\n", reason); + strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + dfunc.GetNameFromAddr (&sendaddr, sock->address); + + Con_Printf ("Connection accepted\n"); + sock->lastMessageTime = SetNetTime(); + + // switch the connection to the specified address + if (dfunc.Connect (newsock, &sock->addr) == -1) + { + reason = "Connect to Game failed"; + Con_Printf("%s\n", reason); + strcpy(m_return_reason, reason); + goto ErrorReturn; + } + + m_return_onerror = false; + return sock; + +ErrorReturn: + NET_FreeQSocket(sock); +ErrorReturn2: + dfunc.CloseSocket(newsock); + if (m_return_onerror) + { + key_dest = key_menu; + m_state = m_return_state; + m_return_onerror = false; + } + return NULL; +} + +qsocket_t *Datagram_Connect (char *host) +{ + qsocket_t *ret = NULL; + + for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) + if (net_landrivers[net_landriverlevel].initialized) + if ((ret = _Datagram_Connect (host)) != NULL) + break; + return ret; +} diff --git a/source/wii/net_dgrm.h b/source/wii/net_dgrm.h new file mode 100644 index 0000000..da052e7 --- /dev/null +++ b/source/wii/net_dgrm.h @@ -0,0 +1,34 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_dgrm.h + + +int Datagram_Init (void); +void Datagram_Listen (qboolean state); +void Datagram_SearchForHosts (qboolean xmit); +qsocket_t *Datagram_Connect (char *host); +qsocket_t *Datagram_CheckNewConnections (void); +int Datagram_GetMessage (qsocket_t *sock); +int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data); +int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); +qboolean Datagram_CanSendMessage (qsocket_t *sock); +qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock); +void Datagram_Close (qsocket_t *sock); +void Datagram_Shutdown (void); diff --git a/source/wii/net_main.c b/source/wii/net_main.c new file mode 100644 index 0000000..69a10a9 --- /dev/null +++ b/source/wii/net_main.c @@ -0,0 +1,997 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_main.c + +#include "../quakedef.h" +#include "../net_vcr.h" + +qsocket_t *net_activeSockets = NULL; +qsocket_t *net_freeSockets = NULL; +int net_numsockets = 0; + +qboolean serialAvailable = false; +qboolean ipxAvailable = false; +qboolean tcpipAvailable = false; + +int net_hostport; +int DEFAULTnet_hostport = 26000; + +char my_ipx_address[NET_NAMELEN]; +char my_tcpip_address[NET_NAMELEN]; + +void (*GetComPortConfig) (int portNumber, int *port, int *irq, int *baud, qboolean *useModem); +void (*SetComPortConfig) (int portNumber, int port, int irq, int baud, qboolean useModem); +void (*GetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); +void (*SetModemConfig) (int portNumber, char *dialType, char *clear, char *init, char *hangup); + +static qboolean listening = false; + +qboolean slistInProgress = false; +qboolean slistSilent = false; +qboolean slistLocal = true; +static double slistStartTime; +static int slistLastShown; + +static void Slist_Send(void); +static void Slist_Poll(void); +PollProcedure slistSendProcedure = {NULL, 0.0f, Slist_Send}; +PollProcedure slistPollProcedure = {NULL, 0.0f, Slist_Poll}; + + +sizebuf_t net_message; +int net_activeconnections = 0; + +int messagesSent = 0; +int messagesReceived = 0; +int unreliableMessagesSent = 0; +int unreliableMessagesReceived = 0; + +cvar_t net_messagetimeout = {"net_messagetimeout","300"}; +cvar_t hostname = {"hostname", "UNNAMED"}; + +qboolean configRestored = false; +cvar_t config_com_port = {"_config_com_port", "0x3f8", true}; +cvar_t config_com_irq = {"_config_com_irq", "4", true}; +cvar_t config_com_baud = {"_config_com_baud", "57600", true}; +cvar_t config_com_modem = {"_config_com_modem", "1", true}; +cvar_t config_modem_dialtype = {"_config_modem_dialtype", "T", true}; +cvar_t config_modem_clear = {"_config_modem_clear", "ATZ", true}; +cvar_t config_modem_init = {"_config_modem_init", "", true}; +cvar_t config_modem_hangup = {"_config_modem_hangup", "AT H", true}; + +#ifdef IDGODS +cvar_t idgods = {"idgods", "0"}; +#endif + +int vcrFile = -1; +qboolean recording = false; + +// these two macros are to make the code more readable +#define sfunc net_drivers[sock->driver] +#define dfunc net_drivers[net_driverlevel] + +int net_driverlevel; + + +double net_time; + +double SetNetTime(void) +{ + net_time = Sys_FloatTime(); + return net_time; +} + + +/* +=================== +NET_NewQSocket + +Called by drivers when a new communications endpoint is required +The sequence and buffer fields will be filled in properly +=================== +*/ +qsocket_t *NET_NewQSocket (void) +{ + qsocket_t *sock; + + if (net_freeSockets == NULL) + return NULL; + + if (net_activeconnections >= svs.maxclients) + return NULL; + + // get one from free list + sock = net_freeSockets; + net_freeSockets = sock->next; + + // add it to active list + sock->next = net_activeSockets; + net_activeSockets = sock; + + sock->disconnected = false; + sock->connecttime = net_time; + strcpy (sock->address,"UNSET ADDRESS"); + sock->driver = net_driverlevel; + sock->socket = 0; + sock->driverdata = NULL; + sock->canSend = true; + sock->sendNext = false; + sock->lastMessageTime = net_time; + sock->ackSequence = 0; + sock->sendSequence = 0; + sock->unreliableSendSequence = 0; + sock->sendMessageLength = 0; + sock->receiveSequence = 0; + sock->unreliableReceiveSequence = 0; + sock->receiveMessageLength = 0; + + return sock; +} + + +void NET_FreeQSocket(qsocket_t *sock) +{ + qsocket_t *s; + + // remove it from active list + if (sock == net_activeSockets) + net_activeSockets = net_activeSockets->next; + else + { + for (s = net_activeSockets; s; s = s->next) + if (s->next == sock) + { + s->next = sock->next; + break; + } + if (!s) + Sys_Error ("NET_FreeQSocket: not active\n"); + } + + // add it to free list + sock->next = net_freeSockets; + net_freeSockets = sock; + sock->disconnected = true; +} + + +static void NET_Listen_f (void) +{ + if (Cmd_Argc () != 2) + { + Con_Printf ("\"listen\" is \"%u\"\n", listening ? 1 : 0); + return; + } + + listening = atoi(Cmd_Argv(1)) ? true : false; + + for (net_driverlevel=0 ; net_driverlevel svs.maxclientslimit) + { + n = svs.maxclientslimit; + Con_Printf ("\"maxplayers\" set to \"%u\"\n", n); + } + + if ((n == 1) && listening) + Cbuf_AddText ("listen 0\n"); + + if ((n > 1) && (!listening)) + Cbuf_AddText ("listen 1\n"); + + svs.maxclients = n; + if (n == 1) + Cvar_Set ("deathmatch", "0"); + else + Cvar_Set ("deathmatch", "1"); +} + + +static void NET_Port_f (void) +{ + int n; + + if (Cmd_Argc () != 2) + { + Con_Printf ("\"port\" is \"%u\"\n", net_hostport); + return; + } + + n = atoi(Cmd_Argv(1)); + if (n < 1 || n > 65534) + { + Con_Printf ("Bad value, must be between 1 and 65534\n"); + return; + } + + DEFAULTnet_hostport = n; + net_hostport = n; + + if (listening) + { + // force a change to the new port + Cbuf_AddText ("listen 0\n"); + Cbuf_AddText ("listen 1\n"); + } +} + + +static void PrintSlistHeader(void) +{ + Con_Printf("Server Map Users\n"); + Con_Printf("--------------- --------------- -----\n"); + slistLastShown = 0; +} + + +static void PrintSlist(void) +{ + int n; + + for (n = slistLastShown; n < hostCacheCount; n++) + { + if (hostcache[n].maxusers) + Con_Printf("%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); + else + Con_Printf("%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map); + } + slistLastShown = n; +} + + +static void PrintSlistTrailer(void) +{ + if (hostCacheCount) + Con_Printf("== end list ==\n\n"); + else + Con_Printf("No Quake servers found.\n\n"); +} + + +void NET_Slist_f (void) +{ + if (slistInProgress) + return; + + if (! slistSilent) + { + Con_Printf("Looking for Quake servers...\n"); + PrintSlistHeader(); + } + + slistInProgress = true; + slistStartTime = Sys_FloatTime(); + + SchedulePollProcedure(&slistSendProcedure, 0.0f); + SchedulePollProcedure(&slistPollProcedure, 0.1f); + + hostCacheCount = 0; +} + + +static void Slist_Send(void) +{ + for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) + { + if (!slistLocal && net_driverlevel == 0) + continue; + if (net_drivers[net_driverlevel].initialized == false) + continue; + dfunc.SearchForHosts (true); + } + + if ((Sys_FloatTime() - slistStartTime) < 0.5f) + SchedulePollProcedure(&slistSendProcedure, 0.75); +} + + +static void Slist_Poll(void) +{ + for (net_driverlevel=0; net_driverlevel < net_numdrivers; net_driverlevel++) + { + if (!slistLocal && net_driverlevel == 0) + continue; + if (net_drivers[net_driverlevel].initialized == false) + continue; + dfunc.SearchForHosts (false); + } + + if (! slistSilent) + PrintSlist(); + + if ((Sys_FloatTime() - slistStartTime) < 1.5) + { + SchedulePollProcedure(&slistPollProcedure, 0.1f); + return; + } + + if (! slistSilent) + PrintSlistTrailer(); + slistInProgress = false; + slistSilent = false; + slistLocal = true; +} + + +/* +=================== +NET_Connect +=================== +*/ + +int hostCacheCount = 0; +hostcache_t hostcache[HOSTCACHESIZE]; + +qsocket_t *NET_Connect (char *host) +{ + qsocket_t *ret; + int n; + int numdrivers = net_numdrivers; + + SetNetTime(); + + if (host && *host == 0) + host = NULL; + + if (host) + { + if (strcasecmp (host, "local") == 0) + { + numdrivers = 1; + goto JustDoIt; + } + + if (hostCacheCount) + { + for (n = 0; n < hostCacheCount; n++) + if (strcasecmp (host, hostcache[n].name) == 0) + { + host = hostcache[n].cname; + break; + } + if (n < hostCacheCount) + goto JustDoIt; + } + } + + slistSilent = host ? true : false; + NET_Slist_f (); + + while(slistInProgress) + NET_Poll(); + + if (host == NULL) + { + if (hostCacheCount != 1) + return NULL; + host = hostcache[0].cname; + Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host); + } + + if (hostCacheCount) + for (n = 0; n < hostCacheCount; n++) + if (strcasecmp (host, hostcache[n].name) == 0) + { + host = hostcache[n].cname; + break; + } + +JustDoIt: + for (net_driverlevel=0 ; net_driverleveladdress, NET_NAMELEN); + } + return ret; + } + } + + if (recording) + { + vcrConnect.time = host_time; + vcrConnect.op = VCR_OP_CONNECT; + vcrConnect.session = 0; + Sys_FileWrite (vcrFile, &vcrConnect, sizeof(vcrConnect)); + } + + return NULL; +} + +/* +=================== +NET_Close +=================== +*/ +void NET_Close (qsocket_t *sock) +{ + if (!sock) + return; + + if (sock->disconnected) + return; + + SetNetTime(); + + // call the driver_Close function + sfunc.Close (sock); + + NET_FreeQSocket(sock); +} + + +/* +================= +NET_GetMessage + +If there is a complete message, return it in net_message + +returns 0 if no data is waiting +returns 1 if a message was received +returns -1 if connection is invalid +================= +*/ + +struct +{ + double time; + int op; + long session; + int ret; + int len; +} vcrGetMessage; + +extern void PrintStats(qsocket_t *s); + +int NET_GetMessage (qsocket_t *sock) +{ + int ret; + + if (!sock) + return -1; + + if (sock->disconnected) + { + Con_Printf("NET_GetMessage: disconnected socket\n"); + return -1; + } + + SetNetTime(); + + ret = sfunc.QGetMessage(sock); + + // see if this connection has timed out + if (ret == 0 && sock->driver) + { + if (net_time - sock->lastMessageTime > net_messagetimeout.value) + { + NET_Close(sock); + return -1; + } + } + + + if (ret > 0) + { + if (sock->driver) + { + sock->lastMessageTime = net_time; + if (ret == 1) + messagesReceived++; + else if (ret == 2) + unreliableMessagesReceived++; + } + + if (recording) + { + vcrGetMessage.time = host_time; + vcrGetMessage.op = VCR_OP_GETMESSAGE; + vcrGetMessage.session = (long)sock; + vcrGetMessage.ret = ret; + vcrGetMessage.len = net_message.cursize; + Sys_FileWrite (vcrFile, &vcrGetMessage, 24); + Sys_FileWrite (vcrFile, net_message.data, net_message.cursize); + } + } + else + { + if (recording) + { + vcrGetMessage.time = host_time; + vcrGetMessage.op = VCR_OP_GETMESSAGE; + vcrGetMessage.session = (long)sock; + vcrGetMessage.ret = ret; + Sys_FileWrite (vcrFile, &vcrGetMessage, 20); + } + } + + return ret; +} + + +/* +================== +NET_SendMessage + +Try to send a complete length+message unit over the reliable stream. +returns 0 if the message cannot be delivered reliably, but the connection + is still considered valid +returns 1 if the message was sent properly +returns -1 if the connection died +================== +*/ +struct +{ + double time; + int op; + long session; + int r; +} vcrSendMessage; + +int NET_SendMessage (qsocket_t *sock, sizebuf_t *data) +{ + int r; + + if (!sock) + return -1; + + if (sock->disconnected) + { + Con_Printf("NET_SendMessage: disconnected socket\n"); + return -1; + } + + SetNetTime(); + r = sfunc.QSendMessage(sock, data); + if (r == 1 && sock->driver) + messagesSent++; + + if (recording) + { + vcrSendMessage.time = host_time; + vcrSendMessage.op = VCR_OP_SENDMESSAGE; + vcrSendMessage.session = (long)sock; + vcrSendMessage.r = r; + Sys_FileWrite (vcrFile, &vcrSendMessage, 20); + } + + return r; +} + + +int NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) +{ + int r; + + if (!sock) + return -1; + + if (sock->disconnected) + { + Con_Printf("NET_SendMessage: disconnected socket\n"); + return -1; + } + + SetNetTime(); + r = sfunc.SendUnreliableMessage(sock, data); + if (r == 1 && sock->driver) + unreliableMessagesSent++; + + if (recording) + { + vcrSendMessage.time = host_time; + vcrSendMessage.op = VCR_OP_SENDMESSAGE; + vcrSendMessage.session = (long)sock; + vcrSendMessage.r = r; + Sys_FileWrite (vcrFile, &vcrSendMessage, 20); + } + + return r; +} + + +/* +================== +NET_CanSendMessage + +Returns true or false if the given qsocket can currently accept a +message to be transmitted. +================== +*/ +qboolean NET_CanSendMessage (qsocket_t *sock) +{ + int r; + + if (!sock) + return false; + + if (sock->disconnected) + return false; + + SetNetTime(); + + r = sfunc.CanSendMessage(sock); + + if (recording) + { + vcrSendMessage.time = host_time; + vcrSendMessage.op = VCR_OP_CANSENDMESSAGE; + vcrSendMessage.session = (long)sock; + vcrSendMessage.r = r; + Sys_FileWrite (vcrFile, &vcrSendMessage, 20); + } + + return r; +} + + +int NET_SendToAll(sizebuf_t *data, int blocktime) +{ + double start; + int i; + int count = 0; + qboolean state1 [MAX_SCOREBOARD]; + qboolean state2 [MAX_SCOREBOARD]; + + for (i=0, host_client = svs.clients ; inetconnection) + continue; + if (host_client->active) + { + if (host_client->netconnection->driver == 0) + { + NET_SendMessage(host_client->netconnection, data); + state1[i] = true; + state2[i] = true; + continue; + } + count++; + state1[i] = false; + state2[i] = false; + } + else + { + state1[i] = true; + state2[i] = true; + } + } + + start = Sys_FloatTime(); + while (count) + { + count = 0; + for (i=0, host_client = svs.clients ; inetconnection)) + { + state1[i] = true; + NET_SendMessage(host_client->netconnection, data); + } + else + { + NET_GetMessage (host_client->netconnection); + } + count++; + continue; + } + + if (! state2[i]) + { + if (NET_CanSendMessage (host_client->netconnection)) + { + state2[i] = true; + } + else + { + NET_GetMessage (host_client->netconnection); + } + count++; + continue; + } + } + if ((Sys_FloatTime() - start) > blocktime) + break; + } + return count; +} + + +//============================================================================= + +/* +==================== +NET_Init +==================== +*/ + +void NET_Init (void) +{ + int i; + int controlSocket; + qsocket_t *s; + + if (COM_CheckParm("-playback")) + { + net_numdrivers = 1; + net_drivers[0].Init = VCR_Init; + } + + if (COM_CheckParm("-record")) + recording = true; + + i = COM_CheckParm ("-port"); + if (!i) + i = COM_CheckParm ("-udpport"); + if (!i) + i = COM_CheckParm ("-ipxport"); + + if (i) + { + if (i < com_argc-1) + DEFAULTnet_hostport = atoi (com_argv[i+1]); + else + Sys_Error ("NET_Init: you must specify a number after -port"); + } + net_hostport = DEFAULTnet_hostport; + + if (COM_CheckParm("-listen") || cls.state == ca_dedicated) + listening = true; + net_numsockets = svs.maxclientslimit; + if (cls.state != ca_dedicated) + net_numsockets++; + + SetNetTime(); + + for (i = 0; i < net_numsockets; i++) + { + s = (qsocket_t *)Hunk_AllocName(sizeof(qsocket_t), "qsocket"); + s->next = net_freeSockets; + net_freeSockets = s; + s->disconnected = true; + } + + // allocate space for network message buffer + SZ_Alloc (&net_message, NET_MAXMESSAGE); + + Cvar_RegisterVariable (&net_messagetimeout); + Cvar_RegisterVariable (&hostname); + Cvar_RegisterVariable (&config_com_port); + Cvar_RegisterVariable (&config_com_irq); + Cvar_RegisterVariable (&config_com_baud); + Cvar_RegisterVariable (&config_com_modem); + Cvar_RegisterVariable (&config_modem_dialtype); + Cvar_RegisterVariable (&config_modem_clear); + Cvar_RegisterVariable (&config_modem_init); + Cvar_RegisterVariable (&config_modem_hangup); +#ifdef IDGODS + Cvar_RegisterVariable (&idgods); +#endif + + Cmd_AddCommand ("slist", NET_Slist_f); + Cmd_AddCommand ("listen", NET_Listen_f); + Cmd_AddCommand ("maxplayers", MaxPlayers_f); + Cmd_AddCommand ("port", NET_Port_f); + + // initialize all the drivers + for (net_driverlevel=0 ; net_driverlevelnext) + NET_Close(sock); + +// +// shutdown the drivers +// + for (net_driverlevel = 0; net_driverlevel < net_numdrivers; net_driverlevel++) + { + if (net_drivers[net_driverlevel].initialized == true) + { + net_drivers[net_driverlevel].Shutdown (); + net_drivers[net_driverlevel].initialized = false; + } + } + + if (vcrFile != -1) + { + Con_Printf ("Closing vcrfile.\n"); + Sys_FileClose(vcrFile); + } +} + + +static PollProcedure *pollProcedureList = NULL; + +void NET_Poll(void) +{ + PollProcedure *pp; + qboolean useModem; + + if (!configRestored) + { + if (serialAvailable) + { + if (config_com_modem.value == 1.0f) + useModem = true; + else + useModem = false; + SetComPortConfig (0, (int)config_com_port.value, (int)config_com_irq.value, (int)config_com_baud.value, useModem); + SetModemConfig (0, config_modem_dialtype.string, config_modem_clear.string, config_modem_init.string, config_modem_hangup.string); + } + configRestored = true; + } + + SetNetTime(); + + for (pp = pollProcedureList; pp; pp = pp->next) + { + if (pp->nextTime > net_time) + break; + pollProcedureList = pp->next; + pp->procedure(pp->arg); + } +} + + +void SchedulePollProcedure(PollProcedure *proc, double timeOffset) +{ + PollProcedure *pp, *prev; + + proc->nextTime = Sys_FloatTime() + timeOffset; + for (pp = pollProcedureList, prev = NULL; pp; pp = pp->next) + { + if (pp->nextTime >= proc->nextTime) + break; + prev = pp; + } + + if (prev == NULL) + { + proc->next = pollProcedureList; + pollProcedureList = proc; + return; + } + + proc->next = pp; + prev->next = proc; +} + + +#ifdef IDGODS +#define IDNET 0xc0f62800 + +qboolean IsID(struct qsockaddr *addr) +{ + if (idgods.value == 0.0f) + return false; + + if (addr->sa_family != 2) + return false; + + if ((BigLong(*(int *)&addr->sa_data[2]) & 0xffffff00) == IDNET) + return true; + return false; +} +#endif diff --git a/source/wii/net_udp_wii.c b/source/wii/net_udp_wii.c new file mode 100644 index 0000000..2c0ee38 --- /dev/null +++ b/source/wii/net_udp_wii.c @@ -0,0 +1,532 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_udp.c + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Including the device-specific network layer header: +#include +// <<< FIX + +#include "../quakedef.h" + +#include +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Removing non-present headers: +//#include +//#include +//#include +// <<< FIX +#include +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Removing non-present headers: +//#include +// <<< FIX +#include + +#ifdef __sun__ +#include +#endif + +#ifdef NeXT +#include +#endif + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Adding stuff supposed to be present on the previously removed headers: +#define MAXHOSTNAMELEN 256 +// <<< FIX + +extern int gethostname (char *, int); +extern int close (int); + +extern cvar_t hostname; + +static int net_acceptsocket = -1; // socket for fielding new connections +static int net_controlsocket; +static int net_broadcastsocket = 0; +static struct qsockaddr broadcastaddr; + +static unsigned long myAddr; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// New variable to signal if_config() error: +int netinit_error; +// <<< FIX + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// New variable containing the current IP address of the device: +char ipaddress_text[16]; +// <<< FIX + +#include "net_udp_wii.h" + +//============================================================================= + +int UDP_Init (void) +{ +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// This variable is not needed in the current implementation: + //struct hostent *local; +// <<< FIX + char buff[MAXHOSTNAMELEN]; +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// This variable is not needed in the current implementation: + //struct qsockaddr addr; +// <<< FIX + char *colon; + + if (COM_CheckParm ("-noudp")) + return -1; + + do + { + netinit_error = if_config(ipaddress_text, NULL, NULL, true, 1); + } while(netinit_error == -EAGAIN); + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Signal as uninitialized if if_config() failed previously: + if(netinit_error < 0) + { + Con_Printf("UDP_Init: if_config() failed with %i", netinit_error); + return -1; + }; +// <<< FIX + + // determine my name & address +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Since we don't currently have a gethostname(), or equivalent, function, let's just paste the IP address of the device: + //gethostname(buff, MAXHOSTNAMELEN); + //local = gethostbyname(buff); + //myAddr = *(int *)local->h_addr_list[0]; + strcpy(buff, ipaddress_text); +// <<< FIX + + // if the quake hostname isn't set, set it to the machine name + if (strcmp(hostname.string, "UNNAMED") == 0) + { + buff[15] = 0; + Cvar_Set ("hostname", buff); + } + + if ((net_controlsocket = UDP_OpenSocket (0)) == -1) + Sys_Error("UDP_Init: Unable to open control socket\n"); + + ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; + ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; + ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport); + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Since we can't bind anything to port 0, the following line does not work. Replacing: + //UDP_GetSocketAddr (net_controlsocket, &addr); + //strcpy(my_tcpip_address, UDP_AddrToString (&addr)); + strcpy(my_tcpip_address, buff); +// <<< FIX + colon = strrchr (my_tcpip_address, ':'); + if (colon) + *colon = 0; + + Con_Printf("UDP Initialized\n"); + tcpipAvailable = true; + + return net_controlsocket; +} + +//============================================================================= + +void UDP_Shutdown (void) +{ + UDP_Listen (false); + UDP_CloseSocket (net_controlsocket); +} + +//============================================================================= + +void UDP_Listen (qboolean state) +{ + // enable listening + if (state) + { + if (net_acceptsocket != -1) + return; + if ((net_acceptsocket = UDP_OpenSocket (net_hostport)) == -1) + Sys_Error ("UDP_Listen: Unable to open accept socket\n"); + return; + } + + // disable listening + if (net_acceptsocket == -1) + return; + UDP_CloseSocket (net_acceptsocket); + net_acceptsocket = -1; +} + +//============================================================================= + +int UDP_OpenSocket (int port) +{ + int newsocket; + struct sockaddr_in address; + qboolean _TRUE = true; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function in the library (and using supported parameters): + //if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + if ((newsocket = net_socket (PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) +// <<< FIX + return -1; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function in the library: + //if (ioctl (newsocket, FIONBIO, (char *)&_TRUE) == -1) + if (net_ioctl (newsocket, FIONBIO, (char *)&_TRUE) < 0) +// <<< FIX + goto ErrorReturn; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Do not bind the socket if port == 0 (part 1): + if(port > 0) + { +// <<< FIX + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(port); +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function in the library: + //if( bind (newsocket, (void *)&address, sizeof(address)) == -1) + if( net_bind (newsocket, (void *)&address, sizeof(address)) < 0) +// <<< FIX + goto ErrorReturn; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Do not bind the socket if port == 0 (part 2): + } +// <<< FIX + return newsocket; + +ErrorReturn: + close (newsocket); + return -1; +} + +//============================================================================= + +int UDP_CloseSocket (int socket) +{ + if (socket == net_broadcastsocket) + net_broadcastsocket = 0; + return close (socket); +} + + +//============================================================================= +/* +============ +PartialIPAddress + +this lets you type only as much of the net address as required, using +the local network components to fill in the rest +============ +*/ +static int PartialIPAddress (char *in, struct qsockaddr *hostaddr) +{ + char buff[256]; + char *b; + int addr; + int num; + int mask; + int run; + int port; + + buff[0] = '.'; + b = buff; + strcpy(buff+1, in); + if (buff[1] == '.') + b++; + + addr = 0; + mask=-1; + while (*b == '.') + { + b++; + num = 0; + run = 0; + while (!( *b < '0' || *b > '9')) + { + num = num*10 + *b++ - '0'; + if (++run > 3) + return -1; + } + if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) + return -1; + if (num < 0 || num > 255) + return -1; + mask<<=8; + addr = (addr<<8) + num; + } + + if (*b++ == ':') + port = atoi(b); + else + port = net_hostport; + + hostaddr->sa_family = AF_INET; + ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port); + ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr); + + return 0; +} +//============================================================================= + +int UDP_Connect (int socket, struct qsockaddr *addr) +{ + return 0; +} + +//============================================================================= + +int UDP_CheckNewConnections (void) +{ + unsigned long available; + + if (net_acceptsocket == -1) + return -1; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function in the library: + //if (ioctl (net_acceptsocket, FIONREAD, &available) == -1) + if (net_ioctl (net_acceptsocket, FIONREAD, &available) < 0) +// <<< FIX + Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n"); + if (available) + return net_acceptsocket; + return -1; +} + +//============================================================================= + +int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int addrlen = sizeof (struct qsockaddr); + int ret; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function (and data structures) in the library: + //ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen); + //if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED)) + struct sockaddr_in torecv; + socklen_t torecvlen; + + memset(&torecv, 0, sizeof(torecv)); + torecvlen = addrlen; + ret = net_recvfrom(socket, buf, len > 4096 ? 4096 : len, 0, (struct sockaddr *)&torecv, &torecvlen); + addr->sa_family = torecv.sin_family; + ((struct sockaddr_in *)addr)->sin_port = torecv.sin_port; + ((struct sockaddr_in *)addr)->sin_addr = torecv.sin_addr; + if((ret == -EWOULDBLOCK) || (ret == -ECONNREFUSED)) +// <<< FIX + return 0; + return ret; +} + +//============================================================================= + +int UDP_MakeSocketBroadcastCapable (int socket) +{ + int i = 1; + + // make this socket broadcast capable +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function in the library: + //if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) + if (net_setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0) +// <<< FIX + return -1; + net_broadcastsocket = socket; + + return 0; +} + +//============================================================================= + +int UDP_Broadcast (int socket, byte *buf, int len) +{ + int ret; + + if (socket != net_broadcastsocket) + { + if (net_broadcastsocket != 0) + Sys_Error("Attempted to use multiple broadcasts sockets\n"); + ret = UDP_MakeSocketBroadcastCapable (socket); + if (ret == -1) + { + Con_Printf("Unable to make socket broadcast capable\n"); + return ret; + } + } + + return UDP_Write (socket, buf, len, &broadcastaddr); +} + +//============================================================================= + +int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr) +{ + int ret; + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function (and data structures) in the library: + //ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr)); + //if (ret == -1 && errno == EWOULDBLOCK) + struct sockaddr_in tosend; + + memset(&tosend, 0, sizeof(struct sockaddr_in)); + tosend.sin_family = ((struct sockaddr_in *)addr)->sin_family; + tosend.sin_port = ((struct sockaddr_in *)addr)->sin_port; + tosend.sin_addr = ((struct sockaddr_in *)addr)->sin_addr; + tosend.sin_len = 8; + ret = net_sendto (socket, buf, len, 0, (struct sockaddr *)&tosend, 8); + if(ret == -EWOULDBLOCK) +// <<< FIX + return 0; + return ret; +} + +//============================================================================= + +char *UDP_AddrToString (struct qsockaddr *addr) +{ + static char buffer[22]; + int haddr; + + haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr); + sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port)); + return buffer; +} + +//============================================================================= + +int UDP_StringToAddr (char *string, struct qsockaddr *addr) +{ + int ha1, ha2, ha3, ha4, hp; + int ipaddr; + + sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); + ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr); + ((struct sockaddr_in *)addr)->sin_port = htons(hp); + return 0; +} + +//============================================================================= + +int UDP_GetSocketAddr (int socket, struct qsockaddr *addr) +{ +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Since there's no getsockname(), or equivalent, function in the library, just assign it myAddr: + //int addrlen = sizeof(struct qsockaddr); + //unsigned int a; + + //memset(addr, 0, sizeof(struct qsockaddr)); + //getsockname(socket, (struct sockaddr *)addr, &addrlen); + //a = ((struct sockaddr_in *)addr)->sin_addr.s_addr; + //if (a == 0 || a == inet_addr("127.0.0.1")) +// <<< FIX + ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr; + + return 0; +} + +//============================================================================= + +int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name) +{ +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Since there's no gethostbyaddr(), or equivalent, function in the library, just copy addr to name: + //struct hostent *hostentry; + + //hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET); + //if (hostentry) + //{ + // strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1); + // return 0; + //} +// <<< FIX + + strcpy (name, UDP_AddrToString (addr)); + return 0; +} + +//============================================================================= + +int UDP_GetAddrFromName(char *name, struct qsockaddr *addr) +{ + struct hostent *hostentry; + + if (name[0] >= '0' && name[0] <= '9') + return PartialIPAddress (name, addr); + +// >>> FIX: For Nintendo Wii using devkitPPC / libogc +// Switching to the equivalent function in the library: + //hostentry = gethostbyname (name); + hostentry = net_gethostbyname (name); +// <<< FIX + if (!hostentry) + return -1; + + addr->sa_family = AF_INET; + ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport); + ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; + + return 0; +} + +//============================================================================= + +int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2) +{ + if (addr1->sa_family != addr2->sa_family) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr) + return -1; + + if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port) + return 1; + + return 0; +} + +//============================================================================= + +int UDP_GetSocketPort (struct qsockaddr *addr) +{ + return ntohs(((struct sockaddr_in *)addr)->sin_port); +} + + +int UDP_SetSocketPort (struct qsockaddr *addr, int port) +{ + ((struct sockaddr_in *)addr)->sin_port = htons(port); + return 0; +} + +//============================================================================= diff --git a/source/wii/net_udp_wii.h b/source/wii/net_udp_wii.h new file mode 100644 index 0000000..7530301 --- /dev/null +++ b/source/wii/net_udp_wii.h @@ -0,0 +1,39 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// net_udp.h + +int UDP_Init (void); +void UDP_Shutdown (void); +void UDP_Listen (qboolean state); +int UDP_OpenSocket (int port); +int UDP_CloseSocket (int socket); +int UDP_Connect (int socket, struct qsockaddr *addr); +int UDP_CheckNewConnections (void); +int UDP_Read (int socket, byte *buf, int len, struct qsockaddr *addr); +int UDP_Write (int socket, byte *buf, int len, struct qsockaddr *addr); +int UDP_Broadcast (int socket, byte *buf, int len); +char *UDP_AddrToString (struct qsockaddr *addr); +int UDP_StringToAddr (char *string, struct qsockaddr *addr); +int UDP_GetSocketAddr (int socket, struct qsockaddr *addr); +int UDP_GetNameFromAddr (struct qsockaddr *addr, char *name); +int UDP_GetAddrFromName (char *name, struct qsockaddr *addr); +int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2); +int UDP_GetSocketPort (struct qsockaddr *addr); +int UDP_SetSocketPort (struct qsockaddr *addr, int port); diff --git a/source/wii/net_wii.c b/source/wii/net_wii.c new file mode 100644 index 0000000..c5d82cf --- /dev/null +++ b/source/wii/net_wii.c @@ -0,0 +1,94 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "../quakedef.h" + +#include "../net_loop.h" +#include "net_dgrm.h" + +net_driver_t net_drivers[MAX_NET_DRIVERS] = +{ + { + "Loopback", + false, + Loop_Init, + Loop_Listen, + Loop_SearchForHosts, + Loop_Connect, + Loop_CheckNewConnections, + Loop_GetMessage, + Loop_SendMessage, + Loop_SendUnreliableMessage, + Loop_CanSendMessage, + Loop_CanSendUnreliableMessage, + Loop_Close, + Loop_Shutdown + } + , + { + "Datagram", + false, + Datagram_Init, + Datagram_Listen, + Datagram_SearchForHosts, + Datagram_Connect, + Datagram_CheckNewConnections, + Datagram_GetMessage, + Datagram_SendMessage, + Datagram_SendUnreliableMessage, + Datagram_CanSendMessage, + Datagram_CanSendUnreliableMessage, + Datagram_Close, + Datagram_Shutdown + } +}; + +int net_numdrivers = 2; + +#include "net_udp_wii.h" + +net_landriver_t net_landrivers[MAX_NET_DRIVERS] = +{ + { + "UDP", + false, + 0, + UDP_Init, + UDP_Shutdown, + UDP_Listen, + UDP_OpenSocket, + UDP_CloseSocket, + UDP_Connect, + UDP_CheckNewConnections, + UDP_Read, + UDP_Write, + UDP_Broadcast, + UDP_AddrToString, + UDP_StringToAddr, + UDP_GetSocketAddr, + UDP_GetNameFromAddr, + UDP_GetAddrFromName, + UDP_AddrCompare, + UDP_GetSocketPort, + UDP_SetSocketPort + } +}; + +int net_numlandrivers = 1; diff --git a/source/wii/render.h b/source/wii/render.h new file mode 100644 index 0000000..4839535 --- /dev/null +++ b/source/wii/render.h @@ -0,0 +1,211 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// refresh.h -- public interface to refresh functions + +#define MAXCLIPPLANES 11 + +#define TOP_RANGE 16 // soldier uniform colors +#define BOTTOM_RANGE 96 + +//============================================================================= + +typedef struct efrag_s +{ + struct mleaf_s *leaf; + struct efrag_s *leafnext; + struct entity_s *entity; + struct efrag_s *entnext; +} efrag_t; + +//johnfitz -- for lerping +#define LERP_MOVESTEP (1<<0) //this is a MOVETYPE_STEP entity, enable movement lerp +#define LERP_RESETANIM (1<<1) //disable anim lerping until next anim frame +#define LERP_RESETANIM2 (1<<2) //set this and previous flag to disable anim lerping for two anim frames +#define LERP_RESETMOVE (1<<3) //disable movement lerping until next origin/angles change +#define LERP_FINISH (1<<4) //use lerpfinish time from server update instead of assuming interval of 0.1 +//johnfitz + +typedef struct entity_s +{ + qboolean forcelink; // model changed + + int update_type; + + entity_state_t baseline; // to fill in defaults in updates + + double msgtime; // time of last update + vec3_t msg_origins[2]; // last two updates (0 is newest) + vec3_t origin; + vec3_t msg_angles[2]; // last two updates (0 is newest) + vec3_t angles; + + + // Tomaz - QC Alpha Scale Glow Begin + float renderamt; + float rendermode; + float rendercolor[3]; + //Crow_bar + + + unsigned char scale; + struct model_s *model; // NULL = no model + struct efrag_s *efrag; // linked list of efrags + int frame; + float syncbase; // for client-side animations + byte *colormap; + int effects; // light, particals, etc + int skinnum; // for Alias models + int visframe; // last frame this entity was + // found in an active leaf + + int dlightframe; // dynamic lighting + int dlightbits; + +// FIXME: could turn these into a union + int trivial_accept; + struct mnode_s *topnode; // for bmodels, first world node + // that splits bmodel, or NULL if + // not split + + byte lerpflags; //johnfitz -- lerping + float lerpstart; //johnfitz -- animation lerping + float lerptime; //johnfitz -- animation lerping + float lerpfinish; //johnfitz -- lerping -- server sent us a more accurate interval, use it instead of 0.1 + short previouspose; //johnfitz -- animation lerping + short currentpose; //johnfitz -- animation lerping +// short futurepose; //johnfitz -- animation lerping + float movelerpstart; //johnfitz -- transform lerping + vec3_t previousorigin; //johnfitz -- transform lerping + vec3_t currentorigin; //johnfitz -- transform lerping + vec3_t previousangles; //johnfitz -- transform lerping + vec3_t currentangles; //johnfitz -- transform lerping + + int modelindex; + + // sBTODO come back and change lerping to match vril + float frame_start_time; + float rotate_start_time; + float translate_start_time; + + int z_head; + int z_larm; + int z_rarm; +} entity_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct +{ + vrect_t vrect; // subwindow in video for refresh + // FIXME: not need vrect next field here? + vrect_t aliasvrect; // scaled Alias version + int vrectright, vrectbottom; // right & bottom screen coords + int aliasvrectright, aliasvrectbottom; // scaled Alias versions + float vrectrightedge; // rightmost right edge we care about, + // for use in edge list + float fvrectx, fvrecty; // for floating-point compares + float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping + int vrect_x_adj_shift20; // (vrect.x + 0.5f - epsilon) << 20 + int vrectright_adj_shift20; // (vrectright + 0.5f - epsilon) << 20 + float fvrectright_adj, fvrectbottom_adj; + // right and bottom edges, for clamping + float fvrectright; // rightmost edge, for Alias clamping + float fvrectbottom; // bottommost edge, for Alias clamping + float horizontalFieldOfView; // at Z = 1.0f, this many X is visible + // 2.0f = 90 degrees + float xOrigin; // should probably allways be 0.5f + float yOrigin; // between be around 0.3f to 0.5f + + vec3_t vieworg; + vec3_t viewangles; + + float fov_x, fov_y; + + int ambientlight; + + float fog_start; + float fog_end; + float fog_red; + float fog_green; + float fog_blue; +} refdef_t; + + +// +// refresh +// +extern int reinit_surfcache; + + +extern refdef_t r_refdef; +extern vec3_t r_origin, vpn, vright, vup; + +extern struct texture_s *r_notexture_mip; + + +void R_Init (void); +void R_InitTextures (void); +void R_InitEfrags (void); +void R_RenderView (void); // must set r_refdef first +void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); + // called whenever r_refdef or vid change +void R_InitSky (struct miptex_s *mt); // called at level load + +void R_AddEfrags (entity_t *ent); +void R_RemoveEfrags (entity_t *ent); + +void R_NewMap (void); + +typedef enum trail_type_s +{ + ROCKET_TRAIL, GRENADE_TRAIL, BLOOD_TRAIL, TRACER1_TRAIL, SLIGHT_BLOOD_TRAIL,NAIL_TRAIL, + TRACER2_TRAIL, VOOR_TRAIL, ALT_ROCKET_TRAIL, LAVA_TRAIL, BUBBLE_TRAIL, NEHAHRA_SMOKE, + RAYGREEN_TRAIL, RAYRED_TRAIL +} trail_type_t; + +void R_ParseParticleEffect (void); +void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); +void R_RocketTrail (vec3_t start, vec3_t end, int type); + +#ifdef QUAKE2 +void R_DarkFieldParticles (entity_t *ent); +#endif +void R_EntityParticles (entity_t *ent); +void R_BlobExplosion (vec3_t org); +void R_ParticleExplosion (vec3_t org); +void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength); +void R_LavaSplash (vec3_t org); +void R_TeleportSplash (vec3_t org); + +void R_PushDlights (void); + + +// +// surface cache related +// +extern int reinit_surfcache; // if 1, surface cache is currently empty and +extern qboolean r_cache_thrash; // set if thrashing the surface cache + +int D_SurfaceCacheForRes (int width, int height); +void D_DeleteSurfaceCache (void); +void D_InitCaches (void *buffer, int size); +void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj); + +void R_TranslatePlayerSkin (int playernum); diff --git a/source/wii/sbar.c b/source/wii/sbar.c new file mode 100644 index 0000000..a6ed347 --- /dev/null +++ b/source/wii/sbar.c @@ -0,0 +1,402 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sbar.c -- status bar code + +#include "../quakedef.h" + +cvar_t sbar_alpha = {"sbar_alpha", "0.3", true}; + +int sb_updates; // if >= vid.numpages, no update needed + +#define STAT_MINUS 10 // num frame for '-' stats digit +qpic_t *sb_nums[2][11]; +qpic_t *sb_colon, *sb_slash; +qpic_t *sb_ibar; +qpic_t *sb_sbar; +qpic_t *sb_scorebar; + +qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes +qpic_t *sb_ammo[4]; +qpic_t *sb_sigil[4]; +qpic_t *sb_armor[3]; +qpic_t *sb_items[32]; + +qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive + // 0 is static, 1 is temporary animation +qpic_t *sb_face_invis; +qpic_t *sb_face_quad; +qpic_t *sb_face_invuln; +qpic_t *sb_face_invis_invuln; + +extern int sb_lines; // scan lines to draw + +qpic_t *rsb_invbar[2]; +qpic_t *rsb_weapons[5]; +qpic_t *rsb_items[2]; +qpic_t *rsb_ammo[3]; +qpic_t *rsb_teambord; // PGM 01/19/97 - team color border + +void Sbar_MiniDeathmatchOverlay (void); +void Sbar_DeathmatchOverlay (void); +void M_DrawPic (int x, int y, qpic_t *pic); + +/* +=============== +Sbar_ShowScores + +Tab key down +=============== +*/ +void Sbar_ShowScores (void) +{ + +} + +/* +=============== +Sbar_DontShowScores + +Tab key up +=============== +*/ +void Sbar_DontShowScores (void) +{ + +} + +/* +=============== +Sbar_Changed +=============== +*/ +void Sbar_Changed (void) +{ + +} + +/* +=============== +Sbar_Init +=============== +*/ +void Sbar_Init (void) +{ + +} + + +//============================================================================= + +// drawing routines are relative to the status bar location + +/* +============= +Sbar_DrawAlphaPic +============= +*/ +void Sbar_DrawAlphaPic (int x, int y, qpic_t *pic, float alpha) +{ + +} + +/* +============= +Sbar_DrawPic +============= +*/ +void Sbar_DrawPic (int x, int y, qpic_t *pic) +{ + +} + +/* +============= +Sbar_DrawTransPic +============= +*/ +void Sbar_DrawTransPic (int x, int y, qpic_t *pic) +{ + +} + +/* +================ +Sbar_DrawCharacter + +Draws one solid graphics character +================ +*/ +void Sbar_DrawCharacter (int x, int y, int num) +{ + +} + +/* +================ +Sbar_DrawString +================ +*/ +void Sbar_DrawString (int x, int y, char *str) +{ + +} + +/* +============= +Sbar_itoa +============= +*/ +int Sbar_itoa (int num, char *buf) +{ + char *str; + int pow10; + int dig; + + str = buf; + + if (num < 0) + { + *str++ = '-'; + num = -num; + } + + for (pow10 = 10 ; num >= pow10 ; pow10 *= 10) + ; + + do + { + pow10 /= 10; + dig = num/pow10; + *str++ = '0'+dig; + num -= dig*pow10; + } while (pow10 != 1); + + *str = 0; + + return str-buf; +} + + +/* +============= +Sbar_DrawNum +============= +*/ +void Sbar_DrawNum (int x, int y, int num, int digits, int color) +{ + char str[12]; + char *ptr; + int l, frame; + + l = Sbar_itoa (num, str); + ptr = str; + if (l > digits) + ptr += (l-digits); + if (l < digits) + x += (digits-l)*24; + + while (*ptr) + { + if (*ptr == '-') + frame = STAT_MINUS; + else + frame = *ptr -'0'; + + Sbar_DrawTransPic (x,y,sb_nums[color][frame]); + x += 24; + ptr++; + } +} + +//============================================================================= + +/* +=============== +Sbar_SortFrags +=============== +*/ +void Sbar_SortFrags (void) +{ + /* + int i, j, k; + +// sort by frags + scoreboardlines = 0; + for (i=0 ; i.bsp, for model_precache[0] + struct model_s *worldmodel; + char *model_precache[MAX_MODELS]; // NULL terminated + struct model_s *models[MAX_MODELS]; + char *sound_precache[MAX_SOUNDS]; // NULL terminated + char *lightstyles[MAX_LIGHTSTYLES]; + int num_edicts; + int max_edicts; + edict_t *edicts; // can NOT be array indexed, because + // edict_t is variable sized, but can + // be used to reference the world ent + server_state_t state; // some actions are only valid during load + + sizebuf_t datagram; + byte datagram_buf[MAX_DATAGRAM]; + + sizebuf_t reliable_datagram; // copied to all clients at end of frame + byte reliable_datagram_buf[MAX_DATAGRAM]; + + sizebuf_t signon; + byte signon_buf[8192]; +} server_t; + + +#define NUM_PING_TIMES 16 +#define NUM_SPAWN_PARMS 16 + +typedef struct client_s +{ + qboolean active; // false = client is free + qboolean spawned; // false = don't send datagrams + qboolean dropasap; // has been told to go to another level + qboolean privileged; // can execute any host command + qboolean sendsignon; // only valid before spawned + + double last_message; // reliable messages must be sent + // periodically + + struct qsocket_s *netconnection; // communications handle + + usercmd_t cmd; // movement + vec3_t wishdir; // intended motion calced from cmd + + sizebuf_t message; // can be added to at any time, + // copied and clear once per frame + byte msgbuf[MAX_MSGLEN]; + edict_t *edict; // EDICT_NUM(clientnum+1) + char name[32]; // for printing to other people + int colors; + + float ping_times[NUM_PING_TIMES]; + int num_pings; // ping_times[num_pings%NUM_PING_TIMES] + +// spawn parms are carried from level to level + float spawn_parms[NUM_SPAWN_PARMS]; + +// client known data for deltas + //int old_frags; + int old_points; + int old_kills; +// joe, from ProQuake: allow clients to connect if they don't have the map + qboolean nomap; +} client_t; + + +//============================================================================= + +// edict->movetype values +#define MOVETYPE_NONE 0 // never moves +#define MOVETYPE_ANGLENOCLIP 1 +#define MOVETYPE_ANGLECLIP 2 +#define MOVETYPE_WALK 3 // gravity +#define MOVETYPE_STEP 4 // gravity, special edge handling +#define MOVETYPE_FLY 5 +#define MOVETYPE_TOSS 6 // gravity +#define MOVETYPE_PUSH 7 // no clip to world, push and crush +#define MOVETYPE_NOCLIP 8 +#define MOVETYPE_FLYMISSILE 9 // extra size to monsters +#define MOVETYPE_BOUNCE 10 +#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity +#define MOVETYPE_FOLLOW 12 // track movement of aiment +#define MOVETYPE_HEAD 13 // track movement of head +#define MOVETYPE_LARM 14 // track movement of larm +#define MOVETYPE_RARM 15 // track movement of rarm + +// edict->solid values +#define SOLID_NOT 0 // no interaction with other objects +#define SOLID_TRIGGER 1 // touch on edge, but not blocking +#define SOLID_BBOX 2 // touch on edge, block +#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground +#define SOLID_BSP 4 // bsp clip, touch on edge, block +#define SOLID_CORPSE 5 // bsp clip, touch on edge, block + +// edict->deadflag values +#define DEAD_NO 0 +#define DEAD_DYING 1 +#define DEAD_DEAD 2 + +#define DAMAGE_NO 0 +#define DAMAGE_YES 1 +#define DAMAGE_AIM 2 + +// edict->flags +#define FL_FLY 1 +#define FL_SWIM 2 +//#define FL_GLIMPSE 4 +#define FL_CONVEYOR 4 +#define FL_CLIENT 8 +#define FL_INWATER 16 +#define FL_MONSTER 32 +#define FL_GODMODE 64 +#define FL_NOTARGET 128 +#define FL_ITEM 256 +#define FL_ONGROUND 512 +#define FL_PARTIALGROUND 1024 // not all corners are valid +#define FL_WATERJUMP 2048 // player jumping out of water +#define FL_JUMPRELEASED 4096 // for jump debouncing +#ifdef QUAKE2 +#define FL_FLASHLIGHT 8192 +#define FL_ARCHIVE_OVERRIDE 1048576 +#endif + +// entity effects + +#define EF_BLUELIGHT 1 +#define EF_MUZZLEFLASH 2 +#define EF_BRIGHTLIGHT 4 +#define EF_REDLIGHT 8 +#define EF_ORANGELIGHT 16 +#define EF_GREENLIGHT 32 +#define EF_PINKLIGHT 64 // formerly EF_LIGHT +#define EF_NODRAW 128 +#define EF_LIMELIGHT 256 // formerly EF_BRIGHTFIELD +#define EF_FULLBRIGHT 512 +#define EF_CYANLIGHT 1024 // formerly EF_DARKLIGHT +#define EF_YELLOWLIGHT 2048 // formerly EF_DARKFIELD +#define EF_PURPLELIGHT 4096 +#define EF_RAYRED 8196 // red trail for porter x2 +#define EF_RAYGREEN 16384 // green trail for ray gun + +#define SPAWNFLAG_NOT_EASY 256 +#define SPAWNFLAG_NOT_MEDIUM 512 +#define SPAWNFLAG_NOT_HARD 1024 +#define SPAWNFLAG_NOT_DEATHMATCH 2048 + +#ifdef QUAKE2 +// server flags +#define SFL_EPISODE_1 1 +#define SFL_EPISODE_2 2 +#define SFL_EPISODE_3 4 +#define SFL_EPISODE_4 8 +#define SFL_NEW_UNIT 16 +#define SFL_NEW_EPISODE 32 +#define SFL_CROSS_TRIGGERS 65280 +#endif + +//============================================================================ + +extern cvar_t teamplay; +extern cvar_t skill; +extern cvar_t deathmatch; +extern cvar_t coop; +extern cvar_t fraglimit; +extern cvar_t timelimit; + +extern server_static_t svs; // persistant server info +extern server_t sv; // local server + +extern client_t *host_client; + +extern jmp_buf host_abortserver; + +extern double host_time; + +extern edict_t *sv_player; + +//=========================================================== + +void SV_Init (void); + +void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count); +void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, + float attenuation); + +void SV_DropClient (qboolean crash); + +void SV_SendClientMessages (void); +void SV_ClearDatagram (void); + +int SV_ModelIndex (char *name); + +void SV_SetIdealPitch (void); + +void SV_AddUpdates (void); + +void SV_ClientThink (void); +void SV_AddClientToServer (struct qsocket_s *ret); + +void SV_ClientPrintf (char *fmt, ...); +void SV_BroadcastPrintf (char *fmt, ...); + +void SV_Physics (void); + +qboolean SV_CheckBottom (edict_t *ent); +qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink); + +void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); + +void SV_MoveToGoal (void); +void SV_MoveToOrigin (void); + +void SV_CheckForNewClients (void); +void SV_RunClients (void); +void SV_SaveSpawnparms (); +#ifdef QUAKE2 +void SV_SpawnServer (char *server, char *startspot); +#else +void SV_SpawnServer (char *server); +#endif diff --git a/source/wii/sound.c b/source/wii/sound.c new file mode 100644 index 0000000..d59f69c --- /dev/null +++ b/source/wii/sound.c @@ -0,0 +1,117 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. +Copyright (C) 2007 Peter Mackay + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +// ELUTODO: go to 48khz once we have hi-res sound packs + +#include +#include + +#include "../quakedef.h" + +// Represents a single sound sample. +typedef u32 sample; + +// We copy Quake's audio into double buffered DMA buffers while it is +// being transferred to the GameCube's audio system. +static const size_t samples_per_dma_buffer = 2048; +static sample dma_buffers[2][2048] __attribute__((aligned(32))); +static size_t current_dma_buffer = 0; + +// Quake writes its audio into this mix buffer. +static const size_t samples_per_mix_buffer = 32768; //65536 +static sample mix_buffer[32768]; +static volatile size_t mix_buffer_pointer = 0; + +// Called whenever more audio data is required. +static void play_more_audio() +{ + // Copy from mix buffer to DMA buffer. + sample* const src_begin = &mix_buffer[mix_buffer_pointer]; + sample* const dst_begin = &dma_buffers[current_dma_buffer][0]; + const sample* const dst_end = dst_begin + samples_per_dma_buffer; + sample* src = src_begin; + sample* dst = dst_begin; + while (dst != dst_end) + { + // We have to swap the channels, because Quake stores the left + // channel first, whereas the GameCube expects right first. + const u32 mix_sample = *src; + *src++ = 0; + *dst++ = (mix_sample >> 16) | ((mix_sample & 0x0000ffff) << 16); + } + + // Set up the DMA. + const u32 dma_src_address = (u32)(dst_begin); + const size_t bytes = samples_per_dma_buffer * sizeof(sample); + AUDIO_InitDMA(dma_src_address, bytes); + + // Flush the data cache. + DCFlushRange(dst_begin, bytes); + + // Start the DMA. + AUDIO_StartDMA(); + + // Move the mix buffer pointer. + mix_buffer_pointer = (mix_buffer_pointer + samples_per_dma_buffer) % samples_per_mix_buffer; + + // Use the other DMA buffer next time. + current_dma_buffer = 1 - current_dma_buffer; +} + +qboolean SNDDMA_Init(void) +{ + // Set up Quake's audio. + shm = &sn; + shm->channels = 2; + shm->samplebits = 16; + shm->speed = 32000; + shm->soundalive = true; + shm->splitbuffer = false; + shm->samples = samples_per_mix_buffer * shm->channels; + shm->samplepos = 0; + shm->submission_chunk = 1; + shm->buffer = (unsigned char*)(&mix_buffer[0]); + + // Initialise the audio system. + AUDIO_Init(0); + AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ); + AUDIO_RegisterDMACallback(play_more_audio); + + // Start the first chunk of audio playing. + play_more_audio(); + + return true; +} + +void SNDDMA_Shutdown(void) +{ + // Stop streaming. + AUDIO_RegisterDMACallback(0); + AUDIO_StopDMA(); +} + +int SNDDMA_GetDMAPos(void) +{ + return mix_buffer_pointer * shm->channels; +} + +void SNDDMA_Submit(void) +{ +} diff --git a/source/wii/sys.h b/source/wii/sys.h new file mode 100644 index 0000000..c6ad5d7 --- /dev/null +++ b/source/wii/sys.h @@ -0,0 +1,74 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// sys.h -- non-portable functions + +// +// file IO +// + +// returns the file size +// return -1 if file is not present +// the file should be in BINARY mode for stupid OSs that care +int Sys_FileOpenRead (char *path, int *hndl); + +int Sys_FileOpenWrite (char *path); +void Sys_FileClose (int handle); +void Sys_FileSeek (int handle, int position); +int Sys_FileRead (int handle, void *dest, int count); +int Sys_FileWrite (int handle, void *data, int count); +int Sys_FileTime (char *path); +void Sys_mkdir (char *path); + +// +// memory protection +// +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length); + +// +// system IO +// +void Sys_DebugLog(const char *file, char *fmt, ...); + +void Sys_Error (char *error, ...); +// an error will cause the entire program to exit + +void Sys_Printf (const char *fmt, ...); +// send text to the console + +void Sys_Quit (void); + +double Sys_FloatTime (void); + +char *Sys_ConsoleInput (void); + +void Sys_Sleep (void); +// called to yield for a little bit so as +// not to hog cpu when paused or debugging + +void Sys_SendKeyEvents (void); +// Perform Key_Event () callbacks until the input que is empty + +void Sys_LowFPPrecision (void); +void Sys_HighFPPrecision (void); +void Sys_SetFPCW (void); + +void Sys_Shutdown (void); + +void Sys_Init_Logfile(void); diff --git a/source/wii/system.c b/source/wii/system.c new file mode 100644 index 0000000..f59c360 --- /dev/null +++ b/source/wii/system.c @@ -0,0 +1,307 @@ +/* +Quake GameCube port. +Copyright (C) 2007 Peter Mackay +Copyright (C) 2008 Eluan Miranda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../quakedef.h" + +FILE *logfile; + +void Sys_Error (char *error, ...) +{ + // Clear the sound buffer. + S_ClearBuffer(); + + // Put the error message in a buffer. + va_list args; + va_start(args, error); + char buffer[1024]; + memset(buffer, 0, sizeof(buffer)); + vsnprintf(buffer, sizeof(buffer) - 1, error, args); + va_end(args); + + // Print the error message to the debug screen. + printf("\n\n\nThe following error occurred:\n"); + printf("%s\n\n", buffer); + + int i = 0; + + while(i < 60) + { + VIDEO_WaitVSync(); + i++; + }; + printf("Press A to quit.\n"); + + // Wait for the user to release the button. + do + { + VIDEO_WaitVSync(); + PAD_ScanPads(); + WPAD_ScanPads(); + } + while (PAD_ButtonsHeld(0) & PAD_BUTTON_A || WPAD_ButtonsHeld(WPAD_CHAN_0) & WPAD_BUTTON_A); + + // Wait for the user to press the button. + do + { + VIDEO_WaitVSync(); + PAD_ScanPads(); + WPAD_ScanPads(); + } + while (((PAD_ButtonsHeld(0) & PAD_BUTTON_A) == 0) && ((WPAD_ButtonsHeld(WPAD_CHAN_0) & WPAD_BUTTON_A) == 0)); + + printf("Sys_Quit();\n"); + + // Quit. + Sys_Quit(); +} + +void Sys_Init_Logfile(void) +{ + +//#ifdef LOGFILE + logfile= fopen("/apps/nzportable/logfile.txt", "w"); +//#endif +} + +void Sys_Finish_Logfile(void) +{ +//#ifdef LOGFILE + if (logfile) fclose(logfile); +//#endif +} + +void Sys_Printf (const char *fmt, ...) +{ +//#ifdef LOGFILE + va_list args; + va_start(args, fmt); + if (logfile) vfprintf(logfile, fmt, args); + va_end(args); +//#endif +} + +void Sys_Quit (void) +{ + Sys_Printf("%s", "Returning to loader...\n"); + + // Shut down the host system. + if (host_initialized > 0) + { + Host_Shutdown(); + } + + VIDEO_SetBlack(true); + + Sys_Finish_Logfile(); + + // Exit. + exit(0); +} + +void Sys_Reset (void) +{ + Sys_Printf("%s", "Resetting...\n"); + + // Shut down the host system. + if (host_initialized > 0) + { + Host_Shutdown(); + } + + VIDEO_SetBlack(true); + + Sys_Finish_Logfile(); + + // Exit. + //SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + exit(0); +} + +void Sys_Shutdown (void) +{ + Sys_Printf("%s", "Shutting down...\n"); + + // Shut down the host system. + if (host_initialized > 0) + { + Host_Shutdown(); + } + + VIDEO_SetBlack(true); + + Sys_Finish_Logfile(); + + // Exit. + SYS_ResetSystem(SYS_POWEROFF, 0, 0); +} +//Current time in seconds +//Current time in seconds +double Sys_FloatTime (void) +{ + static u64 base; + static qboolean initialized = FALSE; + u64 ms; + + ms = ticks_to_millisecs(gettime()); + if (!initialized) + { + base = ms; + initialized = TRUE; + } + return ((double)(ms - base)) / 1000.0; +} + +char *Sys_ConsoleInput (void) +{ + return 0; +} + +void Sys_SendKeyEvents (void) +{ +} + +void Sys_LowFPPrecision (void) +{ +} + +void Sys_HighFPPrecision (void) +{ +} + +/* +=============================================================================== + +FILE IO + +=============================================================================== +*/ + +#define MAX_HANDLES 16 +FILE *sys_handles[MAX_HANDLES]; + +int findhandle (void) +{ + int i; + + for (i=1 ; i width if displayed in a window + unsigned width; + unsigned height; + float aspect; // width / height -- < 0 is taller than wide + int numpages; + int recalc_refdef; // if true, recalc vid-based stuff + pixel_t *conbuffer; + int conrowbytes; + unsigned conwidth; + unsigned conheight; + int maxwarpwidth; + int maxwarpheight; + pixel_t *direct; // direct drawing to framebuffer, if not + // NULL +} viddef_t; + +extern viddef_t vid; // global video state +extern unsigned short d_8to16table[256]; +extern unsigned d_8to24table[256]; +extern void (*vid_menudrawfn)(void); +extern void (*vid_menukeyfn)(int key); + +void VID_SetPalette (unsigned char *palette); +// called at startup and after any gamma correction + +void VID_ShiftPalette (unsigned char *palette); +// called for bonus and pain flashes, and for underwater color changes + +void VID_Init (unsigned char *palette); +// Called at startup to set up translation tables, takes 256 8 bit RGB values +// the palette data will go away after the call, so it must be copied off if +// the video driver will need it again + +void VID_Shutdown (void); +// Called at shutdown + +void VID_Update (vrect_t *rects); +// flushes the given rectangles from the view buffer to the screen From e7179c130a9a4ba6618a4830083cac1284b13878 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Mon, 7 Oct 2024 16:10:01 -0400 Subject: [PATCH 18/20] Remove duplicate file --- source/wii/gx/anorm_dots.h | 37 ------------------------------------- source/wii/gx/gx_rmain.c | 2 +- 2 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 source/wii/gx/anorm_dots.h diff --git a/source/wii/gx/anorm_dots.h b/source/wii/gx/anorm_dots.h deleted file mode 100644 index 2845fa2..0000000 --- a/source/wii/gx/anorm_dots.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -{ -{1.23,1.30,1.47,1.35,1.56,1.71,1.37,1.38,1.59,1.60,1.79,1.97,1.88,1.92,1.79,1.02,0.93,1.07,0.82,0.87,0.88,0.94,0.96,1.14,1.11,0.82,0.83,0.89,0.89,0.86,0.94,0.91,1.00,1.21,0.98,1.48,1.30,1.57,0.96,1.07,1.14,1.60,1.61,1.40,1.37,1.72,1.78,1.79,1.93,1.99,1.90,1.68,1.71,1.86,1.60,1.68,1.78,1.86,1.93,1.99,1.97,1.44,1.22,1.49,0.93,0.99,0.99,1.23,1.22,1.44,1.49,0.89,0.89,0.97,0.91,0.98,1.19,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.19,0.98,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.87,0.93,0.94,1.02,1.30,1.07,1.35,1.38,1.11,1.56,1.92,1.79,1.79,1.59,1.60,1.72,1.90,1.79,0.80,0.85,0.79,0.93,0.80,0.85,0.77,0.74,0.72,0.77,0.74,0.72,0.70,0.70,0.71,0.76,0.73,0.79,0.79,0.73,0.76,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.26,1.26,1.48,1.23,1.50,1.71,1.14,1.19,1.38,1.46,1.64,1.94,1.87,1.84,1.71,1.02,0.92,1.00,0.79,0.85,0.84,0.91,0.90,0.98,0.99,0.77,0.77,0.83,0.82,0.79,0.86,0.84,0.92,0.99,0.91,1.24,1.03,1.33,0.88,0.94,0.97,1.41,1.39,1.18,1.11,1.51,1.61,1.59,1.80,1.91,1.76,1.54,1.65,1.76,1.70,1.70,1.85,1.85,1.97,1.99,1.93,1.28,1.09,1.39,0.92,0.97,0.99,1.18,1.26,1.52,1.48,0.83,0.85,0.90,0.88,0.93,1.00,0.77,0.73,0.78,0.72,0.71,0.74,0.75,0.79,0.86,0.81,0.75,0.81,0.79,0.96,0.88,0.94,0.86,0.93,0.92,0.85,1.08,1.33,1.05,1.55,1.31,1.01,1.05,1.27,1.31,1.60,1.47,1.70,1.54,1.76,1.76,1.57,0.93,0.90,0.99,0.88,0.88,0.95,0.97,1.11,1.39,1.20,0.92,0.97,1.01,1.10,1.39,1.22,1.51,1.58,1.32,1.64,1.97,1.85,1.91,1.77,1.74,1.88,1.99,1.91,0.79,0.86,0.80,0.94,0.84,0.88,0.74,0.74,0.71,0.82,0.77,0.76,0.70,0.73,0.72,0.73,0.70,0.74,0.85,0.77,0.82,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.34,1.27,1.53,1.17,1.46,1.71,0.98,1.05,1.20,1.34,1.48,1.86,1.82,1.71,1.62,1.09,0.94,0.99,0.79,0.85,0.82,0.90,0.87,0.93,0.96,0.76,0.74,0.79,0.76,0.74,0.79,0.78,0.85,0.92,0.85,1.00,0.93,1.06,0.81,0.86,0.89,1.16,1.12,0.97,0.95,1.28,1.38,1.35,1.60,1.77,1.57,1.33,1.50,1.58,1.69,1.63,1.82,1.74,1.91,1.92,1.80,1.04,0.97,1.21,0.90,0.93,0.97,1.05,1.21,1.48,1.37,0.77,0.80,0.84,0.85,0.88,0.92,0.73,0.71,0.74,0.74,0.71,0.75,0.73,0.79,0.84,0.78,0.79,0.86,0.81,1.05,0.94,0.99,0.90,0.95,0.92,0.86,1.24,1.44,1.14,1.59,1.34,1.02,1.27,1.50,1.49,1.80,1.69,1.86,1.72,1.87,1.80,1.69,1.00,0.98,1.23,0.95,0.96,1.09,1.16,1.37,1.63,1.46,0.99,1.10,1.25,1.24,1.51,1.41,1.67,1.77,1.55,1.72,1.95,1.89,1.98,1.91,1.86,1.97,1.99,1.94,0.81,0.89,0.85,0.98,0.90,0.94,0.75,0.78,0.73,0.89,0.83,0.82,0.72,0.77,0.76,0.72,0.70,0.71,0.91,0.83,0.89,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.46,1.34,1.60,1.16,1.46,1.71,0.94,0.99,1.05,1.26,1.33,1.74,1.76,1.57,1.54,1.23,0.98,1.05,0.83,0.89,0.84,0.92,0.87,0.91,0.96,0.78,0.74,0.79,0.72,0.72,0.75,0.76,0.80,0.88,0.83,0.94,0.87,0.95,0.76,0.80,0.82,0.97,0.96,0.89,0.88,1.08,1.11,1.10,1.37,1.59,1.37,1.07,1.27,1.34,1.57,1.45,1.69,1.55,1.77,1.79,1.60,0.93,0.90,0.99,0.86,0.87,0.93,0.96,1.07,1.35,1.18,0.73,0.76,0.77,0.81,0.82,0.85,0.70,0.71,0.72,0.78,0.73,0.77,0.73,0.79,0.82,0.76,0.83,0.90,0.84,1.18,0.98,1.03,0.92,0.95,0.90,0.86,1.32,1.45,1.15,1.53,1.27,0.99,1.42,1.65,1.58,1.93,1.83,1.94,1.81,1.88,1.74,1.70,1.19,1.17,1.44,1.11,1.15,1.36,1.41,1.61,1.81,1.67,1.22,1.34,1.50,1.42,1.65,1.61,1.82,1.91,1.75,1.80,1.89,1.89,1.98,1.99,1.94,1.98,1.92,1.87,0.86,0.95,0.92,1.14,0.98,1.03,0.79,0.84,0.77,0.97,0.90,0.89,0.76,0.82,0.82,0.74,0.72,0.71,0.98,0.89,0.97,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.60,1.44,1.68,1.22,1.49,1.71,0.93,0.99,0.99,1.23,1.22,1.60,1.68,1.44,1.49,1.40,1.14,1.19,0.89,0.96,0.89,0.97,0.89,0.91,0.98,0.82,0.76,0.82,0.71,0.72,0.73,0.76,0.79,0.86,0.83,0.91,0.83,0.89,0.72,0.76,0.76,0.89,0.89,0.82,0.82,0.98,0.96,0.97,1.14,1.40,1.19,0.94,1.00,1.07,1.37,1.21,1.48,1.30,1.57,1.61,1.37,0.86,0.83,0.91,0.82,0.82,0.88,0.89,0.96,1.14,0.98,0.70,0.72,0.73,0.77,0.76,0.79,0.70,0.72,0.71,0.82,0.77,0.80,0.74,0.79,0.80,0.74,0.87,0.93,0.85,1.23,1.02,1.02,0.93,0.93,0.87,0.85,1.30,1.35,1.07,1.38,1.11,0.94,1.47,1.71,1.56,1.97,1.88,1.92,1.79,1.79,1.59,1.60,1.30,1.35,1.56,1.37,1.38,1.59,1.60,1.79,1.92,1.79,1.48,1.57,1.72,1.61,1.78,1.79,1.93,1.99,1.90,1.86,1.78,1.86,1.93,1.99,1.97,1.90,1.79,1.72,0.94,1.07,1.00,1.37,1.21,1.30,0.86,0.91,0.83,1.14,0.98,0.96,0.82,0.88,0.89,0.79,0.76,0.73,1.07,0.94,1.11,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.74,1.57,1.76,1.33,1.54,1.71,0.94,1.05,0.99,1.26,1.16,1.46,1.60,1.34,1.46,1.59,1.37,1.37,0.97,1.11,0.96,1.10,0.95,0.94,1.08,0.89,0.82,0.88,0.72,0.76,0.75,0.80,0.80,0.88,0.87,0.91,0.83,0.87,0.72,0.76,0.74,0.83,0.84,0.78,0.79,0.96,0.89,0.92,0.98,1.23,1.05,0.86,0.92,0.95,1.11,0.98,1.22,1.03,1.34,1.42,1.14,0.79,0.77,0.84,0.78,0.76,0.82,0.82,0.89,0.97,0.90,0.70,0.71,0.71,0.73,0.72,0.74,0.73,0.76,0.72,0.86,0.81,0.82,0.76,0.79,0.77,0.73,0.90,0.95,0.86,1.18,1.03,0.98,0.92,0.90,0.83,0.84,1.19,1.17,0.98,1.15,0.97,0.89,1.42,1.65,1.44,1.93,1.83,1.81,1.67,1.61,1.36,1.41,1.32,1.45,1.58,1.57,1.53,1.74,1.70,1.88,1.94,1.81,1.69,1.77,1.87,1.79,1.89,1.92,1.98,1.99,1.98,1.89,1.65,1.80,1.82,1.91,1.94,1.75,1.61,1.50,1.07,1.34,1.27,1.60,1.45,1.55,0.93,0.99,0.90,1.35,1.18,1.07,0.87,0.93,0.96,0.85,0.82,0.77,1.15,0.99,1.27,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.86,1.71,1.82,1.48,1.62,1.71,0.98,1.20,1.05,1.34,1.17,1.34,1.53,1.27,1.46,1.77,1.60,1.57,1.16,1.38,1.12,1.35,1.06,1.00,1.28,0.97,0.89,0.95,0.76,0.81,0.79,0.86,0.85,0.92,0.93,0.93,0.85,0.87,0.74,0.78,0.74,0.79,0.82,0.76,0.79,0.96,0.85,0.90,0.94,1.09,0.99,0.81,0.85,0.89,0.95,0.90,0.99,0.94,1.10,1.24,0.98,0.75,0.73,0.78,0.74,0.72,0.77,0.76,0.82,0.89,0.83,0.73,0.71,0.71,0.71,0.70,0.72,0.77,0.80,0.74,0.90,0.85,0.84,0.78,0.79,0.75,0.73,0.92,0.95,0.86,1.05,0.99,0.94,0.90,0.86,0.79,0.81,1.00,0.98,0.91,0.96,0.89,0.83,1.27,1.50,1.23,1.80,1.69,1.63,1.46,1.37,1.09,1.16,1.24,1.44,1.49,1.69,1.59,1.80,1.69,1.87,1.86,1.72,1.82,1.91,1.94,1.92,1.95,1.99,1.98,1.91,1.97,1.89,1.51,1.72,1.67,1.77,1.86,1.55,1.41,1.25,1.33,1.58,1.50,1.80,1.63,1.74,1.04,1.21,0.97,1.48,1.37,1.21,0.93,0.97,1.05,0.92,0.88,0.84,1.14,1.02,1.34,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.94,1.84,1.87,1.64,1.71,1.71,1.14,1.38,1.19,1.46,1.23,1.26,1.48,1.26,1.50,1.91,1.80,1.76,1.41,1.61,1.39,1.59,1.33,1.24,1.51,1.18,0.97,1.11,0.82,0.88,0.86,0.94,0.92,0.99,1.03,0.98,0.91,0.90,0.79,0.84,0.77,0.79,0.84,0.77,0.83,0.99,0.85,0.91,0.92,1.02,1.00,0.79,0.80,0.86,0.88,0.84,0.92,0.88,0.97,1.10,0.94,0.74,0.71,0.74,0.72,0.70,0.73,0.72,0.76,0.82,0.77,0.77,0.73,0.74,0.71,0.70,0.73,0.83,0.85,0.78,0.92,0.88,0.86,0.81,0.79,0.74,0.75,0.92,0.93,0.85,0.96,0.94,0.88,0.86,0.81,0.75,0.79,0.93,0.90,0.85,0.88,0.82,0.77,1.05,1.27,0.99,1.60,1.47,1.39,1.20,1.11,0.95,0.97,1.08,1.33,1.31,1.70,1.55,1.76,1.57,1.76,1.70,1.54,1.85,1.97,1.91,1.99,1.97,1.99,1.91,1.77,1.88,1.85,1.39,1.64,1.51,1.58,1.74,1.32,1.22,1.01,1.54,1.76,1.65,1.93,1.70,1.85,1.28,1.39,1.09,1.52,1.48,1.26,0.97,0.99,1.18,1.00,0.93,0.90,1.05,1.01,1.31,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.97,1.92,1.88,1.79,1.79,1.71,1.37,1.59,1.38,1.60,1.35,1.23,1.47,1.30,1.56,1.99,1.93,1.90,1.60,1.78,1.61,1.79,1.57,1.48,1.72,1.40,1.14,1.37,0.89,0.96,0.94,1.07,1.00,1.21,1.30,1.14,0.98,0.96,0.86,0.91,0.83,0.82,0.88,0.82,0.89,1.11,0.87,0.94,0.93,1.02,1.07,0.80,0.79,0.85,0.82,0.80,0.87,0.85,0.93,1.02,0.93,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.82,0.76,0.79,0.72,0.73,0.76,0.89,0.89,0.82,0.93,0.91,0.86,0.83,0.79,0.73,0.76,0.91,0.89,0.83,0.89,0.89,0.82,0.82,0.76,0.72,0.76,0.86,0.83,0.79,0.82,0.76,0.73,0.94,1.00,0.91,1.37,1.21,1.14,0.98,0.96,0.88,0.89,0.96,1.14,1.07,1.60,1.40,1.61,1.37,1.57,1.48,1.30,1.78,1.93,1.79,1.99,1.92,1.90,1.79,1.59,1.72,1.79,1.30,1.56,1.35,1.38,1.60,1.11,1.07,0.94,1.68,1.86,1.71,1.97,1.68,1.86,1.44,1.49,1.22,1.44,1.49,1.22,0.99,0.99,1.23,1.19,0.98,0.97,0.97,0.98,1.19,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.94,1.97,1.87,1.91,1.85,1.71,1.60,1.77,1.58,1.74,1.51,1.26,1.48,1.39,1.64,1.99,1.97,1.99,1.70,1.85,1.76,1.91,1.76,1.70,1.88,1.55,1.33,1.57,0.96,1.08,1.05,1.31,1.27,1.47,1.54,1.39,1.20,1.11,0.93,0.99,0.90,0.88,0.95,0.88,0.97,1.32,0.92,1.01,0.97,1.10,1.22,0.84,0.80,0.88,0.79,0.79,0.85,0.86,0.92,1.02,0.94,0.82,0.76,0.77,0.72,0.73,0.70,0.72,0.71,0.74,0.74,0.88,0.81,0.85,0.75,0.77,0.82,0.94,0.93,0.86,0.92,0.92,0.86,0.85,0.79,0.74,0.79,0.88,0.85,0.81,0.82,0.83,0.77,0.78,0.73,0.71,0.75,0.79,0.77,0.74,0.77,0.73,0.70,0.86,0.92,0.84,1.14,0.99,0.98,0.91,0.90,0.84,0.83,0.88,0.97,0.94,1.41,1.18,1.39,1.11,1.33,1.24,1.03,1.61,1.80,1.59,1.91,1.84,1.76,1.64,1.38,1.51,1.71,1.26,1.50,1.23,1.19,1.46,0.99,1.00,0.91,1.70,1.85,1.65,1.93,1.54,1.76,1.52,1.48,1.26,1.28,1.39,1.09,0.99,0.97,1.18,1.31,1.01,1.05,0.90,0.93,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.86,1.95,1.82,1.98,1.89,1.71,1.80,1.91,1.77,1.86,1.67,1.34,1.53,1.51,1.72,1.92,1.91,1.99,1.69,1.82,1.80,1.94,1.87,1.86,1.97,1.59,1.44,1.69,1.05,1.24,1.27,1.49,1.50,1.69,1.72,1.63,1.46,1.37,1.00,1.23,0.98,0.95,1.09,0.96,1.16,1.55,0.99,1.25,1.10,1.24,1.41,0.90,0.85,0.94,0.79,0.81,0.85,0.89,0.94,1.09,0.98,0.89,0.82,0.83,0.74,0.77,0.72,0.76,0.73,0.75,0.78,0.94,0.86,0.91,0.79,0.83,0.89,0.99,0.95,0.90,0.90,0.92,0.84,0.86,0.79,0.75,0.81,0.85,0.80,0.78,0.76,0.77,0.73,0.74,0.71,0.71,0.73,0.74,0.74,0.71,0.76,0.72,0.70,0.79,0.85,0.78,0.98,0.92,0.93,0.85,0.87,0.82,0.79,0.81,0.89,0.86,1.16,0.97,1.12,0.95,1.06,1.00,0.93,1.38,1.60,1.35,1.77,1.71,1.57,1.48,1.20,1.28,1.62,1.27,1.46,1.17,1.05,1.34,0.96,0.99,0.90,1.63,1.74,1.50,1.80,1.33,1.58,1.48,1.37,1.21,1.04,1.21,0.97,0.97,0.93,1.05,1.34,1.02,1.14,0.84,0.88,0.92,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.74,1.89,1.76,1.98,1.89,1.71,1.93,1.99,1.91,1.94,1.82,1.46,1.60,1.65,1.80,1.79,1.77,1.92,1.57,1.69,1.74,1.87,1.88,1.94,1.98,1.53,1.45,1.70,1.18,1.32,1.42,1.58,1.65,1.83,1.81,1.81,1.67,1.61,1.19,1.44,1.17,1.11,1.36,1.15,1.41,1.75,1.22,1.50,1.34,1.42,1.61,0.98,0.92,1.03,0.83,0.86,0.89,0.95,0.98,1.23,1.14,0.97,0.89,0.90,0.78,0.82,0.76,0.82,0.77,0.79,0.84,0.98,0.90,0.98,0.83,0.89,0.97,1.03,0.95,0.92,0.86,0.90,0.82,0.86,0.79,0.77,0.84,0.81,0.76,0.76,0.72,0.73,0.70,0.72,0.71,0.73,0.73,0.72,0.74,0.71,0.78,0.74,0.72,0.75,0.80,0.76,0.94,0.88,0.91,0.83,0.87,0.84,0.79,0.76,0.82,0.80,0.97,0.89,0.96,0.88,0.95,0.94,0.87,1.11,1.37,1.10,1.59,1.57,1.37,1.33,1.05,1.08,1.54,1.34,1.46,1.16,0.99,1.26,0.96,1.05,0.92,1.45,1.55,1.27,1.60,1.07,1.34,1.35,1.18,1.07,0.93,0.99,0.90,0.93,0.87,0.96,1.27,0.99,1.15,0.77,0.82,0.85,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.60,1.78,1.68,1.93,1.86,1.71,1.97,1.99,1.99,1.97,1.93,1.60,1.68,1.78,1.86,1.61,1.57,1.79,1.37,1.48,1.59,1.72,1.79,1.92,1.90,1.38,1.35,1.60,1.23,1.30,1.47,1.56,1.71,1.88,1.79,1.92,1.79,1.79,1.30,1.56,1.35,1.37,1.59,1.38,1.60,1.90,1.48,1.72,1.57,1.61,1.79,1.21,1.00,1.30,0.89,0.94,0.96,1.07,1.14,1.40,1.37,1.14,0.96,0.98,0.82,0.88,0.82,0.89,0.83,0.86,0.91,1.02,0.93,1.07,0.87,0.94,1.11,1.02,0.93,0.93,0.82,0.87,0.80,0.85,0.79,0.80,0.85,0.77,0.72,0.74,0.71,0.70,0.70,0.71,0.72,0.77,0.74,0.72,0.76,0.73,0.82,0.79,0.76,0.73,0.79,0.76,0.93,0.86,0.91,0.83,0.89,0.89,0.82,0.72,0.76,0.76,0.89,0.82,0.89,0.82,0.89,0.91,0.83,0.96,1.14,0.97,1.40,1.44,1.19,1.22,0.99,0.98,1.49,1.44,1.49,1.22,0.99,1.23,0.98,1.19,0.97,1.21,1.30,1.00,1.37,0.94,1.07,1.14,0.98,0.96,0.86,0.91,0.83,0.88,0.82,0.89,1.11,0.94,1.07,0.73,0.76,0.79,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.46,1.65,1.60,1.82,1.80,1.71,1.93,1.91,1.99,1.94,1.98,1.74,1.76,1.89,1.89,1.42,1.34,1.61,1.11,1.22,1.36,1.50,1.61,1.81,1.75,1.15,1.17,1.41,1.18,1.19,1.42,1.44,1.65,1.83,1.67,1.94,1.81,1.88,1.32,1.58,1.45,1.57,1.74,1.53,1.70,1.98,1.69,1.87,1.77,1.79,1.92,1.45,1.27,1.55,0.97,1.07,1.11,1.34,1.37,1.59,1.60,1.35,1.07,1.18,0.86,0.93,0.87,0.96,0.90,0.93,0.99,1.03,0.95,1.15,0.90,0.99,1.27,0.98,0.90,0.92,0.78,0.83,0.77,0.84,0.79,0.82,0.86,0.73,0.71,0.73,0.72,0.70,0.73,0.72,0.76,0.81,0.76,0.76,0.82,0.77,0.89,0.85,0.82,0.75,0.80,0.80,0.94,0.88,0.94,0.87,0.95,0.96,0.88,0.72,0.74,0.76,0.83,0.78,0.84,0.79,0.87,0.91,0.83,0.89,0.98,0.92,1.23,1.34,1.05,1.16,0.99,0.96,1.46,1.57,1.54,1.33,1.05,1.26,1.08,1.37,1.10,0.98,1.03,0.92,1.14,0.86,0.95,0.97,0.90,0.89,0.79,0.84,0.77,0.82,0.76,0.82,0.97,0.89,0.98,0.71,0.72,0.74,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.34,1.51,1.53,1.67,1.72,1.71,1.80,1.77,1.91,1.86,1.98,1.86,1.82,1.95,1.89,1.24,1.10,1.41,0.95,0.99,1.09,1.25,1.37,1.63,1.55,0.96,0.98,1.16,1.05,1.00,1.27,1.23,1.50,1.69,1.46,1.86,1.72,1.87,1.24,1.49,1.44,1.69,1.80,1.59,1.69,1.97,1.82,1.94,1.91,1.92,1.99,1.63,1.50,1.74,1.16,1.33,1.38,1.58,1.60,1.77,1.80,1.48,1.21,1.37,0.90,0.97,0.93,1.05,0.97,1.04,1.21,0.99,0.95,1.14,0.92,1.02,1.34,0.94,0.86,0.90,0.74,0.79,0.75,0.81,0.79,0.84,0.86,0.71,0.71,0.73,0.76,0.73,0.77,0.74,0.80,0.85,0.78,0.81,0.89,0.84,0.97,0.92,0.88,0.79,0.85,0.86,0.98,0.92,1.00,0.93,1.06,1.12,0.95,0.74,0.74,0.78,0.79,0.76,0.82,0.79,0.87,0.93,0.85,0.85,0.94,0.90,1.09,1.27,0.99,1.17,1.05,0.96,1.46,1.71,1.62,1.48,1.20,1.34,1.28,1.57,1.35,0.90,0.94,0.85,0.98,0.81,0.89,0.89,0.83,0.82,0.75,0.78,0.73,0.77,0.72,0.76,0.89,0.83,0.91,0.71,0.70,0.72,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00}, -{1.26,1.39,1.48,1.51,1.64,1.71,1.60,1.58,1.77,1.74,1.91,1.94,1.87,1.97,1.85,1.10,0.97,1.22,0.88,0.92,0.95,1.01,1.11,1.39,1.32,0.88,0.90,0.97,0.96,0.93,1.05,0.99,1.27,1.47,1.20,1.70,1.54,1.76,1.08,1.31,1.33,1.70,1.76,1.55,1.57,1.88,1.85,1.91,1.97,1.99,1.99,1.70,1.65,1.85,1.41,1.54,1.61,1.76,1.80,1.91,1.93,1.52,1.26,1.48,0.92,0.99,0.97,1.18,1.09,1.28,1.39,0.94,0.93,1.05,0.92,1.01,1.31,0.88,0.81,0.86,0.72,0.75,0.74,0.79,0.79,0.86,0.85,0.71,0.73,0.75,0.82,0.77,0.83,0.78,0.85,0.88,0.81,0.88,0.97,0.90,1.18,1.00,0.93,0.86,0.92,0.94,1.14,0.99,1.24,1.03,1.33,1.39,1.11,0.79,0.77,0.84,0.79,0.77,0.84,0.83,0.90,0.98,0.91,0.85,0.92,0.91,1.02,1.26,1.00,1.23,1.19,0.99,1.50,1.84,1.71,1.64,1.38,1.46,1.51,1.76,1.59,0.84,0.88,0.80,0.94,0.79,0.86,0.82,0.77,0.76,0.74,0.74,0.71,0.73,0.70,0.72,0.82,0.77,0.85,0.74,0.70,0.73,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00} -} diff --git a/source/wii/gx/gx_rmain.c b/source/wii/gx/gx_rmain.c index 5f7f6fc..d29eece 100644 --- a/source/wii/gx/gx_rmain.c +++ b/source/wii/gx/gx_rmain.c @@ -353,7 +353,7 @@ float shadelight, ambientlight; // precalculated dot products for quantized angles #define SHADEDOT_QUANT 16 float r_avertexnormal_dots[SHADEDOT_QUANT][256] = -#include "anorm_dots.h" +#include "../../anorm_dots.h" ; float *shadedots = r_avertexnormal_dots[0]; From b7e01e547d58d46f27a78ddfa457d7c25dffca14 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 15 Dec 2024 21:40:29 -0500 Subject: [PATCH 19/20] Upload Makefile.wii and fix ctr/psp compile errors --- Makefile.wii | 130 ++++++++++++++++++++++++++++++++++++++++++++++ source/cl_input.c | 5 +- 2 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 Makefile.wii diff --git a/Makefile.wii b/Makefile.wii new file mode 100644 index 0000000..f053c20 --- /dev/null +++ b/Makefile.wii @@ -0,0 +1,130 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := boot +TARGETDIR := dist/wii/apps/nzportable +BUILD := obj +SOURCES := source/wii\ + source/wii/gx\ + source\ + +INCLUDES := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +# Note that we MUST USE -fno-merge-constants, because the compiler generates crap otherwise. + +CFLAGS = $(MACHDEP) $(INCLUDE) \ + -g -Wall -O2 -Wcast-align -fno-merge-constants -fstrict-aliasing -fsingle-precision-constant -fno-aggressive-loop-optimizations \ + -DGXQUAKE -DNQ_HACK -Wtrigraphs -D__WII__ + +CXXFLAGS = $(CFLAGS) + +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lasnd -lmad -lwiiuse -lbte -lfat -ldb -lwiikeyboard -logc -lm +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := -I$(DEVKITPPC)/libogc/include \ + -I$(DEVKITPRO)/libogc/include/ogc \ + -I$(DEVKITPRO)/libogc/include + + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR) + @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +run: + wiiload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +reload: + wiiload -r $(OUTPUT).dol + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/source/cl_input.c b/source/cl_input.c index 186f204..125ce3b 100644 --- a/source/cl_input.c +++ b/source/cl_input.c @@ -328,9 +328,9 @@ void CL_AdjustAngles (void) speed *= 0.25; #ifdef __PSP__ - cl_sensitivity = in_sensitivity.value + cl_sensitivity = in_sensitivity.value; #elif _3DS - cl_sensitivity = sensitivity.value + cl_sensitivity = sensitivity.value; #else cl_sensitivity = 1.0f; #endif @@ -590,6 +590,7 @@ void CL_SendMove (usercmd_t *cmd) buf.maxsize = 128; buf.cursize = 0; buf.data = data; + int i; cl.cmd = *cmd; From dc0b5f86bc7907f5ade24e9f56b1e8a12d575af0 Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Sun, 15 Dec 2024 21:41:36 -0500 Subject: [PATCH 20/20] Update Makefile to use the same build folder as other systems --- Makefile.wii | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.wii b/Makefile.wii index f053c20..8b35bf8 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -16,7 +16,7 @@ include $(DEVKITPPC)/wii_rules # INCLUDES is a list of directories containing extra header files #--------------------------------------------------------------------------------- TARGET := boot -TARGETDIR := dist/wii/apps/nzportable +TARGETDIR := build/wii/apps/nzportable BUILD := obj SOURCES := source/wii\ source/wii/gx\