This is by design. Several state structures in citro3d like C3D_TexEnv are supposed to be independent of the current GPU state. The current design allows users to make their own C3D_TexEnv structures separate from the ones that are internally managed in the GPU context and configure them - to upload them the user can use C3D_SetTexEnv. Adding the dirty flag to any of the functions that configure a TexEnv structure would not make sense. Moreover, the return value of C3D_GetTexEnv is not supposed to be stored in a persistent variable - every time you want to modify the state of a TexEnv stage directly, you are supposed to call C3D_GetTexEnv and call the appropriate functions using its return value right away.
This is by design. Several state structures in citro3d like C3D_TexEnv are supposed to be independent of the current GPU state. The current design allows users to make their own C3D_TexEnv structures separate from the ones that are internally managed in the GPU context and configure them - to upload them the user can use C3D_SetTexEnv. Adding the dirty flag to any of the functions that configure a TexEnv structure would not make sense. Moreover, the return value of C3D_GetTexEnv is not supposed to be stored in a persistent variable - every time you want to modify the state of a TexEnv stage directly, you are supposed to call C3D_GetTexEnv and call the appropriate functions using its return value right away.