use crate::core::*;
use crate::w32a::*;
use std::{ffi, mem};
use std::{result::Result, error::Error, ptr::null_mut};
use windows::{
core::*,
Win32::Graphics::Gdi::*,
Win32::Graphics::{Direct3D9 as D3D9, Direct3D9::*},
Win32::{Foundation::*}
};
pub const MARKER_DX9C: &[u8; 4] = b"DX9c";
#[macro_export]
macro_rules! as_dx9c {
($o:expr) => {
unsafe {
assert_ne!($o, null_mut());
let owner = &*($o as *const Dx9);
assert_eq!(owner.mk, *MARKER_DX9C);
owner
}
};
}
pub use as_dx9c;
#[macro_export]
macro_rules! as_dx9c_mut {
($o:expr) => {
unsafe {
assert_ne!($o, null_mut());
let owner = &mut *($o as *mut Dx9);
assert_eq!(owner.mk, *MARKER_DX9C);
owner
}
};
}
pub use as_dx9c_mut;
pub struct ResourceManager {
pub sa: Csa,
pub vs: Vec<usize>,
pub pvs: Vec<Pvec>
}
impl ResourceManager {
pub fn new(xd: *mut Cxd, sza: &[usize]) -> Result<Self, Box<dyn Error>> {
let n_pvec = unsafe { manage_resource_n_pvec(xd) };
let vs = sza.to_vec(); assert_eq!(n_pvec, vs.len());
let pvs = (0..n_pvec).into_iter().map(|i|
Pvec::new(vec![null_mut(); vs[i]])).collect::<Vec<_>>();
let sa = Csa{a: &vs[0], n: vs.len()}; Ok(ResourceManager{sa, vs, pvs})
}
pub fn probe(&self) -> u64 {
println!("n_pvecs: {}", self.pvs.len());
self.pvs.iter().enumerate().for_each(|(i, pv)|
println!("{:3}{:3}{}", i, pv.v.len(), pv));
1
}
#[unsafe(no_mangle)]
pub extern "C" fn mr_probe(o: VoidpMut) -> ffi::c_ulonglong {
if o == null_mut() { 0 } else { as_dx9c_mut!(o).rm.probe() }
}
}
pub struct Dx9 {
mk: [u8; 4],
rm: ResourceManager,
sz: [i32; 2],
xd: *mut Cxd
}
impl Drop for Dx9 {
fn drop(&mut self) {
unsafe {
destroyD3D(&mut self.xd);
}
}
}
impl Dx9 {
pub fn new(sz: [i32; 2], sa: &[usize]) -> Result<Self, Box<dyn Error>> {
if sa[1] < 32 { return Err("sa[1] must be >= 32".into()); }
if sa[6] < 32 { return Err("sa[6] must be >= 32".into()); }
let xd = unsafe { createD3D() };
let rm = ResourceManager::new(xd, sa)?;
if xd == null_mut() {
Err("null Cxd".into())
}else{
Ok(Dx9{mk: *MARKER_DX9C, rm, sz, xd})
}
}
pub fn size(&self) -> &[i32; 2] {
&self.sz
}
pub fn finish_d3d(&self) {
unsafe {
finishD3D(self.xd);
}
}
pub fn init_d3d(&mut self, wnd: HWND) -> HRESULT { unsafe {
HRESULT(initD3D(self.xd, voidp_mut(wnd)))
}
}
pub fn dispose_manage_resource_elements(&mut self) -> HRESULT {
unsafe {
HRESULT(disposeManageResourceElements(self.xd))
}
}
pub fn dispose_manage_resource(&mut self) -> HRESULT {
self.rm.probe();
if failed!(self.dispose_manage_resource_elements()) { return E_FAIL; }
unsafe {
let n = manage_resource_n_pvec(self.xd);
std::slice::from_raw_parts_mut(manage_resource_ptr_mut(self.xd), n)
.iter_mut().for_each(|q| *q = null_mut());
}
S_OK
}
#[unsafe(no_mangle)]
pub extern "C" fn disposer(xd: *mut Cxd, o: VoidpMut) -> ffi::c_long {
let owner = as_dx9c_mut!(o);
assert_eq!(xd, owner.xd);
unsafe {
cast_any!(ffi::c_long, HRESULT, owner.dispose_manage_resource())
}
}
pub fn init_manage_resource(&mut self,
d: unsafe extern "C" fn (xd: *mut Cxd, o: VoidpMut) -> ffi::c_long) ->
HRESULT {
unsafe {
let o = self as *mut Self as VoidpMut; manage_resource_set_disposer(self.xd, o, Some(d), &self.rm.sa);
let n = manage_resource_n_pvec(self.xd);
std::slice::from_raw_parts_mut(manage_resource_ptr_mut(self.xd), n)
.iter_mut().enumerate().for_each(|(i, q)| {
let pv = &mut self.rm.pvs[i];
*q = if pv.v.len() == 0 { null_mut() } else { pv.v.as_mut_ptr() }});
}
S_OK
}
pub fn init_font(&mut self) -> HRESULT {
unsafe {
HRESULT(initFont(self.xd))
}
}
pub fn init_texture(&mut self) -> HRESULT {
unsafe {
HRESULT(initTexture(self.xd))
}
}
pub fn init_texture_indirect(&mut self,
n: usize, w: u32, h: u32, q: &mut u32) -> HRESULT {
unsafe {
HRESULT(initTextureIndirect(self.xd, n, w, h, q as *mut u32))
}
}
pub fn read_texture(&mut self,
n: usize, w: u32, h: u32, q: &mut u32) -> HRESULT {
unsafe {
HRESULT(readTexture(self.xd, n, w, h, q as *mut u32))
}
}
pub fn alpha_texture(&mut self,
n: usize, w: u32, h: u32, mask: u32) -> HRESULT {
unsafe {
HRESULT(alphaTexture(self.xd, n, w, h, mask))
}
}
pub fn prepare_vertex_buffer(&mut self,
n: u32, vtx: *mut Cvtx, sz: u32, fvf: u32) -> HRESULT {
unsafe {
HRESULT(prepareVertexBuffer(self.xd, n, vtx, sz, fvf))
}
}
pub fn prep_rect_fan(&mut self, vtx: *mut Cvtx, c: *mut u32, s: *mut u32,
u: f32, v: f32, w: f32, h: f32,
x: f32, y: f32, z: f32, a: f32, b: f32, cg: *mut D3DXVECTOR3) -> HRESULT {
unsafe {
HRESULT(prepRectFAN(self.xd, vtx, c, s, u, v, w, h, x, y, z, a, b, cg))
}
}
pub fn prep_rect_strip(&mut self, vtx: *mut Cvtx, c: *mut u32, s: *mut u32,
u: f32, v: f32, w: f32, h: f32,
x: f32, y: f32, z: f32, a: f32, b: f32, cg: *mut D3DXVECTOR3) -> HRESULT {
unsafe {
HRESULT(prepRectSTRIP(self.xd, vtx, c, s, u, v, w, h, x, y, z, a, b, cg))
}
}
pub fn draw_vt(&mut self, t: u32, v: u32, vtx: *mut Cvtx, sz: u32, fvf: u32,
ptype: D3D9::D3DPRIMITIVETYPE, st: u32, pc: u32) -> HRESULT {
unsafe {
HRESULT(drawVT(self.xd, t, v, vtx, sz, fvf,
cast_any!(crate::core::D3DPRIMITIVETYPE, D3D9::D3DPRIMITIVETYPE, ptype),
st, pc))
}
}
pub fn draw_chars(&mut self, c: *mut u32, s: *mut u32,
t: u32, cw: i32, ch: i32, sw: i32, sh: i32, x: f32, y: f32, z: f32,
w: &str) -> HRESULT {
unsafe {
let sz = w.len() as u32;
HRESULT(drawChars(self.xd, c, s, t, cw, ch, sw, sh, x, y, z, &l(w)[0], sz))
}
}
pub fn draw_2d_text(&mut self,
c: u32, f: u32, x: i32, y: i32, t: &str) -> HRESULT {
unsafe {
HRESULT(draw2DText(self.xd, c, f, x, y, &l(t)[0]))
}
}
pub fn set_light(&mut self, n: u32, typ: D3D9::D3DLIGHTTYPE,
dif: &[f32; 4], spc: &[f32; 4], amb: &[f32; 4],
pos: &[f32; 4], dir: &[f32; 4], range: f32) -> HRESULT {
unsafe {
HRESULT(setLight(self.xd, n,
cast_any!(crate::core::D3DLIGHTTYPE, D3D9::D3DLIGHTTYPE, typ),
&dif[0], &spc[0], &amb[0], &pos[0], &dir[0], range))
}
}
pub fn set_camera(&mut self, tss: &mut TransScreen) -> HRESULT {
unsafe {
HRESULT(setCamera(self.xd, tss as *mut TransScreen as *mut Cts))
}
}
pub fn draw_d3d(&mut self, tss: &mut TransScreen) -> HRESULT {
unsafe {
HRESULT(drawD3D(self.xd, tss as *mut TransScreen as *mut Cts))
}
}
pub fn update_d3d(&mut self) -> HRESULT {
unsafe {
HRESULT(updateD3D(self.xd))
}
}
}
pub fn test_dx9c() {
assert_eq!(mem::size_of::<*mut ffi::c_void>(), 8);
assert_eq!(mem::size_of::<HWND>(), 8);
assert_eq!(mem::size_of::<HANDLE>(), 8);
assert_eq!(mem::size_of::<HGDIOBJ>(), 8);
assert_eq!(mem::size_of::<HBRUSH>(), 8);
assert_eq!(mem::size_of::<HRESULT>(), 4);
assert_eq!(format!("{:08x}", unsafe { cast_any!(i32, HRESULT, E_FAIL) }),
"80004005");
assert_eq!(format!("{:08x}", unsafe { cast_any!(i32, HRESULT, S_OK) }),
"00000000");
assert_eq!(mem::size_of::<Cxd>(), 0); assert_eq!(mem::size_of::<Cvtx>(), 28);
assert_eq!(format!("{:08x}", unsafe { FVF_CVTX }), "000001c2");
assert_eq!(mem::size_of::<D3DVERTEXELEMENT9>(), 8);
assert_eq!(mem::size_of::<timespec>(), 16);
}