dxlib 0.5.1

dxlib dll for Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
//! typ demo dx bridge for DxLib
//!

use std::error::Error;
use std::path::PathBuf;

use crate::{dx::*, ext::*, ext::tdx::*, demo};

/// for DX11
pub fn proc_cb(t: &str, b_cb: &[FLOAT4]) {
  println!("{}", t);
  for f4 in b_cb {
    println!("{:?}", f4);
  }
}

/// for DX9
pub fn proc_sh(sh: &impl Ts, ns: &[&str]) {
  for n in ns {
    let cnt = sh.get_const_count_to_shader(n);
    let arr = sh.get_const_default_param_f_to_shader(n);
    let idx = sh.get_const_index_to_shader(n);
    println!("sh [{:?}] {}, {:?}, {}", n, cnt, arr, idx);
  }
}

pub fn screen(p: &str) -> Result<(), Box<dyn Error>> {
  let wf = false; // true: wire frame, false: surface
  let tex_mode = true; // true: texture color, false: vertex color
  let vert = demo::gen_vert();
  let vgl = from_vts_gl(&demo::gen_vert_gl(),
    &POS::new(0.0, 64.0, 0.0, 1.0), 128.0, tex_mode);
  let pgl = from_vts_gl(&demo::gen_poly_gl(5),
    &POS::new(0.0, -64.0, -224.0, 1.0), 64.0, tex_mode);
  let agl = from_vec_vts_gl(&demo::gen_any_face(),
    &POS::new(128.0, 96.0, 96.0, 1.0), 64.0, false); // always vertex color
  let vss = from_vec_vts_gl(&demo::gen_vec_vts_gl(),
    &POS::new(0.0, 0.0, 0.0, 1.0), 128.0, tex_mode);
  let c6f = from_vec_vts_gl(&demo::gen_c6f_gl(),
    &POS::new(160.0, 160.0, -128.0, 1.0), 40.0, tex_mode)
    .into_iter().flat_map(|v| v).collect(); // cube 6 faces on the one texture

  let tf = false; // true: on the one texture, false: texture each face
  let icosa = from_vec_vec_vts_gl(&demo::gen_icosahedron(tf),
    &POS::new(192.0, 32.0, -96.0, 1.0), 32.0, tex_mode);
  let dodeca = from_vec_vec_vts_gl(&demo::gen_dodecahedron(tf),
    &POS::new(192.0, -80.0, -96.0, 1.0), 32.0, tex_mode);
  let dodeca_center = from_vec_vec_vts_gl(&demo::gen_dodecahedron_center(tf),
    &POS::new(128.0, -80.0, -192.0, 1.0), 32.0, tex_mode);
  let c60 = from_vec_vec_vts_gl(&demo::gen_c60(tf),
    &POS::new(192.0, -192.0, -96.0, 1.0), 32.0, tex_mode);
  let c60_center = from_vec_vec_vts_gl(&demo::gen_c60_center(tf),
    &POS::new(128.0, -192.0, -192.0, 1.0), 32.0, tex_mode);

  let col = [
    get_color(0, 0, 0),
    get_color(255, 0, 0),
    get_color(0, 255, 0),
    get_color(255, 255, 0),
    get_color(0, 0, 255),
    get_color(255, 0, 255),
    get_color(0, 255, 255),
    get_color(255, 255, 255)];
  let amb = COLOR_F::get(&[0.33, 0.33, 0.33, 0.33]);

  let base = PathBuf::from(p);
  let res: Vec<String> = vec![
    "Fantasie_Impromptu_op66.mid\0",
    "onestop.mid\0",
    "ringout.wav\0", // "_SoranoCanvas_HiiragiHanon_loop.mp3\0",
    "_decision3_.wav\0",
    "_img_320x240_0000.png\0",
    "_texture_128x128_0000.bmp\0",
    "shader_VS.vso\0",
    "shader_PS.pso\0",
    "shader_GS.gso\0",
    "_font_32_u8_0000.dft\0", // pre convert by CreateDXFontData.exe
    "_img_256x256_16x64x64.png\0", // 12 scenes
    "_img_64x64_64x8x8.png\0", // 64 scenes
    "_img_256x256_6x64x64.png\0" // 6 faces on the one texture
  ].into_iter().map(|p|
    base.join(p).to_str().expect("str").to_string()).collect();

  set_out_application_log_valid_flag(FALSE);
  change_window_mode(TRUE); // not full screen
  set_graph_mode(640, 480, 32, 60); // 32 bit 60 fps
  // set_window_style_mode(2); // no frame
  // set_use_back_buffer_trans_color_flag(TRUE); // transparent
  let u8t: &[u8] = &[0x83, 0x65, 0x83, 0x58, 0x83, 0x67, 0x00]; // in cp932
  set_main_window_text_bytes(u8t);

  let mut dx = Tdx::new()?;
  init_music_mem();
  let bgm = dx.load_music_mem(&res[0]);
  let lps = dx.load_sound_mem(&res[2]);
  let snd = dx.load_sound_mem(&res[3]);
  let grp = dx.load_graph(&res[4]);
  let tex = dx.load_graph(&res[5]);
  println!("bgm: {:08x} lps: {:08x} snd: {:08x} grp: {:08x} tex: {:08x}",
    bgm.handle(), lps.handle(), snd.handle(), grp.handle(), tex.handle());
  init_shader();
  let shv = dx.load_vertex_shader(&res[6]);
  let shp = dx.load_pixel_shader(&res[7]);
  let shg = dx.load_geometry_shader(&res[8]);
  println!("shv: {:08x} shp: {:08x} shg: {:08x}",
    shv.handle(), shp.handle(), shg.handle());

  // DX11 constant buffer
  // cbv slot 4 cb_Test(f4 g_Test, f4[4] g_Arr)
  // cbp slot 4 cb_Test(f4 g_Test, f4[4] g_Arr)
  // cbg slot none
  // cb5 slot 5 cb_5(f4 cb_cam_pos4)
  // cb6 slot 6 cb_6(f4 cb_a, f4 cb_b)
  // cb7 slot 7 cb_7(f4 cb_c)
  // cb8 slot 8 cb_CamLight(CamLight g_CL(f4 cam_pos4, f4 cam_lat4, f4[2] r))
  init_shader_constant_buffer(); // DX11
  let cbv = dx.create_constant_buffer(5, 4);
  let cbp = dx.create_constant_buffer(5, 4);
  let cbg = dx.create_constant_buffer(0, 0);
  let cb5 = dx.create_constant_buffer(1, 5);
  let cb6 = dx.create_constant_buffer(2, 6);
  let cb7 = dx.create_constant_buffer(1, 7);
  let cb8 = dx.create_constant_buffer(4, 8);
  println!("cbv: {:08x}, cbp: {:08x} cbg: {:08x}",
    cbv.handle(), cbp.handle(), cbg.handle());
  println!("cb5: {:08x}, cb6: {:08x} cb7: {:08x} cb8: {:08x}",
    cb5.handle(), cb6.handle(), cb7.handle(), cb8.handle());

  let lights = vec![
    light::LightParamSub::new(DX_LIGHTTYPE_DIRECTIONAL, // default light
      COLOR_F::from_u32(col[7]), COLOR_F::from_u32(col[7]), amb.clone(),
      VECTOR::get(&[-1.0, 1.0, -1.0]), VECTOR::get(&[1.0, -1.0, 1.0])),
    light::LightParamSub::new(DX_LIGHTTYPE_DIRECTIONAL,
      COLOR_F::from_u32(col[2]), COLOR_F::from_u32(col[2]), amb.clone(),
      VECTOR::get(&[0.0, -512.0, 512.0]), VECTOR::new(0.0, 1.0, -1.0)),
    light::LightParamSub::new(DX_LIGHTTYPE_DIRECTIONAL,
      COLOR_F::from_u32(col[6]), COLOR_F::from_u32(col[6]), amb.clone(),
      VECTOR::get(&[512.0, -512.0, 0.0]), VECTOR::new(-1.0, 1.0, 0.0)),
    light::LightParamSub::new(DX_LIGHTTYPE_DIRECTIONAL,
      COLOR_F::from_u32(col[5]), COLOR_F::from_u32(col[5]), amb.clone(),
      VECTOR::get(&[0.0, 512.0, 0.0]), VECTOR::new(0.0, -1.0, 0.0))];
  let ls = (1..lights.len()).into_iter().map(|k| { // starts from 1 (0 default)
    // if lights[k].light_type == DX_LIGHTTYPE_DIRECTIONAL {} // TODO: skip
    let lt = dx.create_dir_light(lights[k].direction.clone()); // change later
    println!("light[{}]: {:08x}", k, lt.handle());
    lt.set_enable(TRUE);
    lt.set_dif_color(lights[k].diffuse.clone());
    lt.set_spc_color(lights[k].specular.clone());
    lt.set_amb_color(lights[k].ambient.clone());
    lt.set_position(lights[k].position.clone()); // not direction
    lt.set_direction(lights[k].direction.clone()); // after construct
    lt
  }).collect::<Vec<_>>();
  println!("lights: {} + 1", ls.len());

  init_font_to_handle();
  let fsys = dx.create_font("Arial\0", 32, 1, -1, -1, -1, TRUE); // italic
  let fdat = dx.load_font(&res[9]);
  println!("fsys: {:08x} fdat: {:08x}", fsys.handle(), fdat.handle());
  let ani = dx.load_div_graph(&res[10], 12, 4, 3, 64, 64, FALSE, 0, 0);
  // for a in ani.iter() { println!("ani: {:08x}", a.handle()); }
  let blk = dx.load_div_graph(&res[11], 8, 1, 8, 8, 8, FALSE, 8, 0);
  // for b in blk.iter() { println!("blk: {:08x}", b.handle()); }
  let bls = dx.make_graphs_from_div_graph(&blk, TRUE, TRUE, FALSE); // shader
  let t6f = dx.load_graph(&res[12]); // shader 6 faces on the one texture
  let gds = dx.make_graph(64, 64, FALSE); // empty for clipping
  let twh = dx.make_graph_color(64, 64, get_color(255, 255, 255),
    TRUE, TRUE, FALSE); // white texture (through vertex color)

  select_midi_mode(DX_MIDIMODE_MCI);
  bgm.volume(96);
  bgm.play(DX_PLAYTYPE_BACK);

  set_main_window_text("loop sound\0");
  lps.volume(96);
  lps.play(DX_PLAYTYPE_LOOP, TRUE);

  set_draw_screen(DX_SCREEN_WORK);
  clear_draw_screen(NULL);
  fsys.draw_string(40, 400, &format!("waiting...\0"),
    get_color(255, 192, 32), get_color(255, 0, 0), FALSE);
  fdat.draw_string(40, 440, &format!("waiting...\0"),
    get_color(32, 192, 255), get_color(0, 0, 255), FALSE);
  screen_flip();
  wait_key();

  set_draw_screen(DX_SCREEN_BACK);
  let m_pi = std::f32::consts::PI;
  let n = 360i32;
  let m = 4;
  for tick in 0..n * m {
    if process_message() != 0 { break; }
    if check_hit_key(0x01) != 0 { break; } // KEY_INPUT_ESCAPE
    if check_hit_key(0x10) != 0 { break; } // KEY_INPUT_Q
    clear_draw_screen(NULL);
    set_use_z_buffer_3d(TRUE);
    set_write_z_buffer_3d(TRUE);
    // set_use_z_buffer_flag(TRUE);
    // set_write_z_buffer_flag(TRUE);
    // set_draw_z(0.2);
    set_draw_blend_mode(DX_BLENDMODE_NOBLEND, 0); // not for shader
    // loss time test draw many pixel
    for r in 0..360 {
      for c in 0..480 {
        draw_pixel(80 + c, 60 + r, get_color(255 - c / 2, 192 - r / 2, 32));
      }
    }
    let i = tick * 640 / (n * m);
    let anim = (tick >> 6) as usize;
    [&grp, &tex][anim % 2].draw(i * 4 / 8, i * 3 / 8, TRUE); // transparent
    let anim = (tick >> 3) as usize % (2 * ani.len());
    let left = 80;
    let top = 420 - 64 - 13 * anim as i32;
    ani[anim % ani.len()].draw(left, top, TRUE);
    gds.get_draw_screen(left, top, left + 64, top + 64, TRUE); // clipping

    let g = dx.make_graph(480, 360, FALSE); // must unreg inner allocation
    g.get_draw_screen(80, 60, 560, 420, TRUE);
    g.draw_rota(0, 0, 0.5, 0.0, TRUE, TRUE, TRUE);
    dx.unreg(Box::new(g));

    let g = dx.get_graph(80, 60, 64, 64, TRUE, FALSE); // unreg inner
    g.draw(160, 0, TRUE);
    dx.unreg(Box::new(g));

    set_draw_screen(DX_SCREEN_WORK);
    set_use_lighting(TRUE); // default TRUE
    set_use_specular(TRUE); // default TRUE
    set_global_ambient_light(COLOR_F::from_u32(col[5]));
    set_use_light_angle_attenuation(TRUE); // default TRUE
    set_light_enable(TRUE); // default TRUE
    set_light_dif_color(lights[0].diffuse.clone());
    set_light_spc_color(lights[0].specular.clone());
    set_light_amb_color(lights[0].ambient.clone());
    // set_light_position(lights[0].position.clone()); // not direction
    set_light_direction(lights[0].direction.clone());
    // set_light_range_atten(1000.0, 1.0, 0.5, 0.25);
    // set_light_angle(2.0 * pi / 3.0, pi / 2.0);
    // set_light_use_shadow_map(ssi, TRUE);
    set_use_back_culling(TRUE); // small true is not same as 1 or TRUE
    // tex.set_to_shader(0); // single texture
    // [&grp, &tex][anim % 2].set_to_shader(0); // changing texture
    // ani[anim % ani.len()].set_to_shader(0); // transparent (black on black)
    // gds.set_to_shader(0); // clipped rect of 2d screen
    shv.set_shader();
    shp.set_shader();
    // shg.set_shader();

    // for DX11 (may be constant address in the loop)
    let b_cbv = cbv.as_slice_mut();
    let b_cbp = cbp.as_slice_mut();
    let b_cbg = cbg.as_slice_mut();
    let b_cb5 = cb5.as_slice_mut();
    let b_cb6 = cb6.as_slice_mut();
    let b_cb7 = cb7.as_slice_mut();
    let b_cb8 = cb8.as_slice_mut();
    if tick == 0 {
      let nl = dx.get_enable_light_handle_num();
      for l in 0..nl {
        let lh = dx.get_enable_light_handle(l);
        println!("lh[{}] = {:08x}", l, lh);
      }
      // for DX11 (may be constant address in the loop)
      println!("cbv buffer: {:?}", cbv.ptr_mut());
      println!("cbp buffer: {:?}", cbp.ptr_mut());
      println!("cbg buffer: {:?}", cbg.ptr_mut());
      println!("cb5 buffer: {:?}", cb5.ptr_mut());
      println!("cb6 buffer: {:?}", cb6.ptr_mut());
      println!("cb7 buffer: {:?}", cb7.ptr_mut());
      println!("cb8 buffer: {:?}", cb8.ptr_mut());
/*
      // for DX9
      proc_sh(&shv, &["g_Reg0\0", "g_Reg1\0", "g_Test\0", "g_Arr\0",
        "g_Common\0", "g_Base\0", "g_OtherMatrix\0", "g_LocalWorldMatrix\0"]);
      proc_sh(&shp, &["g_Reg0\0", "g_Reg1\0", "g_Test\0", "g_Arr\0",
        "g_Common\0", "g_Base\0", "g_ShadowMap\0", "g_Filter", "g_CL\0"]);
*/
    }

    // after set_draw_screen
    let r = 512.0f32;
    let t = tick as f32 * m_pi / 180.0;
    let c = t.cos();
    let s = t.sin();
    let p = (((tick / 4) % 91) - 45) as f32 * m_pi / 180.0;
    let rc = r * p.cos();
    let rs = r * p.sin();
    let cam_pos = VECTOR::new(rc * c, rc * s, rs);
    let cam_lookat = VECTOR::new(0.0, 0.0, 0.0);
    let cam_z = VECTOR::new(0.0, 0.0, 1.0); // 0 0 1
    let mut mv_cam = MATRIX::identity();
    create_look_at_matrix(&mut mv_cam, &cam_pos, &cam_lookat, &cam_z);
    // set_camera_near_far(0.1, 10000.0);
    set_camera_view_matrix(mv_cam); // MTranspose (GL<->DX)
    let mp_cam = get_camera_projection_matrix();
    set_transform_to_projection(&mp_cam);
    // let mut mp = MATRIX::identity();
    // get_transform_to_projection_matrix(&mut mp);
    // create_perspective_fov_matrix(&mut mp, fov, zn, zf, aspect);
    // set_transform_to_projection(&mp);
    // let mut mv = MATRIX::identity();
    // create_viewport_matrix(&mut mv, cx, cy, w, h);
    // set_transform_to_viewport(&mv);

    // for DX11
    if tick <= 1 {
      proc_cb("b_cbv", b_cbv);
      proc_cb("b_cbp", b_cbp);
      proc_cb("b_cbg", b_cbg);
      proc_cb("b_cb5", b_cb5);
      proc_cb("b_cb6", b_cb6);
      proc_cb("b_cb7", b_cb7);
      proc_cb("b_cb8", b_cb8);
    }
    cbv.update();
    shv.set_const(&cbv);
    cbp.update();
    shp.set_const(&cbp);
    cbg.update();
    shg.set_const(&cbg);
    b_cb5[0] = FLOAT4::new(0.0, 0.0, 0.0, 1.0); // cb_cam_pos4
    cb5.update();
    shp.set_const(&cb5);
    b_cb6[0] = FLOAT4::new(0.8, 0.8, 0.8, 0.8); // cb_a
    b_cb6[1] = FLOAT4::new(0.0, 0.0, 0.0, 0.0); // cb_b
    cb6.update();
    shp.set_const(&cb6);
    b_cb7[0] = FLOAT4::new(0.0, 0.0, 0.0, 0.0); // cb_c
    cb7.update();
    shp.set_const(&cb7);
    b_cb8[0] = FLOAT4::new(rc * c, rc * s, rs, 1.0); // g_CL.cam_pos4
    b_cb8[1] = FLOAT4::new(0.0, 0.0, 0.0, 1.0); // g_CL.cam_lat4
    b_cb8[2] = FLOAT4::new(0.8, 0.8, 0.8, 0.8); // g_CL.r[0] (light ratio)
    b_cb8[3] = FLOAT4::new(0.0, 0.0, 0.0, 1.0); // g_CL.r[1] (w: camera angle)
    cb8.update();
    shp.set_const(&cb8);
/*
    // for DX9
    set_ps_const_f(VecL0, COLOR_F::get(&[1.0, 1.0, 1.0, 1.0]).as_float4());
    set_ps_const_f(PosL0, COLOR_F::get(&[0.0, 0.0, 0.0, 1.0]).as_float4());
*/

    draw_line_3d(VECTOR::zeros(), VECTOR::new(-512.0, 0.0, 0.0), col[7]);
    draw_line_3d(VECTOR::zeros(), VECTOR::new(0.0, -512.0, 0.0), col[7]);
    draw_line_3d(VECTOR::zeros(), VECTOR::new(0.0, 0.0, -512.0), col[7]);
    draw_line_3d(VECTOR::zeros(), VECTOR::new(512.0, 0.0, 0.0), col[1]);
    draw_line_3d(VECTOR::zeros(), VECTOR::new(0.0, 512.0, 0.0), col[2]);
    draw_line_3d(VECTOR::zeros(), VECTOR::new(0.0, 0.0, 512.0), col[4]);

    if tex_mode {
      gds.set_to_shader(0); // clipped rect of 2d screen
    } else {
      twh.set_to_shader(0); // white texture (through vertex color)
    }
    draw_polygon_3d_to_shader_or_wire(&vert, wf);
    draw_polygon_3d_to_shader_or_wire(&vgl, wf);
    draw_polygon_3d_to_shader_or_wire(&pgl, wf);
    for (i, vs) in agl.iter().enumerate() {
      if (tex_mode && i == agl.len() - 1) || tick & 0x00000080 != 0 {
        gds.set_to_shader(0); // clipped rect of 2d screen
      } else {
        twh.set_to_shader(0); // white texture (through vertex color)
      }
      draw_polygon_3d_to_shader_or_wire(vs, wf);
    }
    for (i, vs) in vss.iter().enumerate() {
      if tex_mode {
        if i == 0 {
          gds.set_to_shader(0); // clipped rect of 2d screen
        } else {
          bls[i % bls.len()].set_to_shader(0); // transparent
        }
      } else {
        twh.set_to_shader(0); // white texture (through vertex color)
      }
      draw_polygon_3d_to_shader_or_wire(vs, wf);
    }
    if tex_mode {
      t6f.set_to_shader(0); // 6 faces on the one texture
    } else {
      twh.set_to_shader(0); // white texture (through vertex color)
    }
    draw_polygon_3d_to_shader_or_wire(&c6f, wf);

    for p in [&icosa, &dodeca, &dodeca_center, &c60, &c60_center] {
      for (i, f) in p.iter().enumerate() {
        if tex_mode {
          bls[i % bls.len()].set_to_shader(0); // transparent
        } else {
          twh.set_to_shader(0); // white texture (through vertex color)
        }
        for vs in f.iter() {
          draw_polygon_3d_to_shader_or_wire(vs, wf);
        }
      }
    }

    let ff = if wf { 0 } else { 1 }; // fill flag
    draw_cone_3d(
      VECTOR::new(-192.0, 0.0, -16.0), VECTOR::new(-255.0, 0.0, -16.0),
      32.0, 16, col[3], col[4], ff);
    draw_capsule_3d(
      VECTOR::new(-192.0, -64.0, -16.0), VECTOR::new(-255.0, -64.0, -16.0),
      32.0, 16, col[3], col[4], ff);
    draw_sphere_3d(
      VECTOR::new(-192.0, -128.0, -16.0), 32.0, 16, col[3], col[4], ff);
    draw_cube_3d(
      VECTOR::new(-255.0, -224.0, -48.0), VECTOR::new(-192.0, -160.0, 16.0),
      col[3], col[4], ff);
    let ca = (0..3).into_iter().flat_map(|k|
      (0..3).into_iter().flat_map(|j|
        (0..3).into_iter().map(|i| {
          let r = 8.0;
          let x = -160.0 - i as f32 * r * 3.0;
          let y = -256.0 - j as f32 * r * 3.0;
          let z = 16.0 - k as f32 * r * 3.0;
          CUBEDATA{
            p0: VECTOR::new(x - r, y - r, z - r),
            p1: VECTOR::new(x + r, y + r, z + r),
            dif: COLOR_U8::from_u32(col[3]),
            spc: COLOR_U8::from_u32(col[4])}
        }).collect::<Vec<_>>()).collect::<Vec<_>>()).collect::<Vec<_>>();
    draw_cube_set_3d(&ca, ff);

    grp.draw_turn(320, 0, TRUE);
    grp.draw_extend(0, 480 - 60, 80, 480, TRUE);
    tex.draw_rota(320, 0, 0.5, -m_pi as f64 / 4.0, TRUE, FALSE, FALSE);
    tex.draw_modi(640 - 160, 240 - 60, 640 - 40, 240 - 60,
      640, 240, 640 - 80, 240, TRUE);
    tex.draw_rect(640 - 160, 240 - 120, 32, 32, 64, 64, TRUE, TRUE, TRUE);
    tex.draw_rect_extend(640 - 240, 240 - 180, 640 - 160, 240 - 120,
      32, 32, 64, 64, TRUE);

    screen_flip();
  }

  set_main_window_text("sound\0");
  snd.volume(128);
  snd.play(DX_PLAYTYPE_NORMAL, TRUE);
  wait_timer(2000);
  set_main_window_text("sound end\0");
  snd.stop();

  Ok(())
}