Download crates/openwa-core/src/render/queue.rs from nmarshall/wormz-a: direct link, hf CLI and curl.
- Browser
- Download file 3.96 kB
-
https://huggingface.co/nmarshall/wormz-a/resolve/main/crates/openwa-core/src/render/queue.rs
- Command line
-
hf download hf://nmarshall/wormz-a/crates/openwa-core/src/render/queue.rs
-
curl -L -o queue.rs https://huggingface.co/nmarshall/wormz-a/resolve/main/crates/openwa-core/src/render/queue.rs
3.96 kB
| use super::message::{RenderMessage, TypedRenderCmd, COMMAND_TYPE_TYPED}; | |
| /// Render queue — manages a downward-growing arena buffer of draw commands. | |
| /// | |
| /// Passed as `this` (ECX) to the original DrawSprite*/DrawRect/etc. enqueue | |
| /// functions. The buffer area sits between offset 0x04 and the entry metadata | |
| /// at 0x10000+. Entries are allocated from the end of the buffer downward. | |
| /// | |
| /// Max 0x800 (2048) entries per frame. | |
| pub struct RenderQueue { | |
| /// 0x00000: Buffer write offset (i32, decrements per allocation) | |
| pub buffer_offset: i32, | |
| /// 0x00004 - 0x10003: Buffer area for command entries (64KB) | |
| pub _buffer: [u8; 0x10000], | |
| /// 0x10004: Number of enqueued entries (max 0x800) | |
| pub entry_count: u32, | |
| /// 0x10008: Pointer array — entry_ptrs[N] points to the N-th command | |
| pub entry_ptrs: [*mut u8; 0x800], | |
| } | |
| impl RenderQueue { | |
| /// Allocate a command of type `T` from the downward-growing buffer. | |
| /// | |
| /// Returns `None` if the queue is full (>= 0x800 entries or buffer exhausted). | |
| /// The returned reference is registered in `entry_ptrs` and `entry_count` is incremented. | |
| pub unsafe fn alloc<T>(&mut self) -> Option<&mut T> { | |
| if self.entry_count >= 0x800 { | |
| return None; | |
| } | |
| let new_offset = self.buffer_offset - core::mem::size_of::<T>() as i32; | |
| if new_offset < 0 { | |
| return None; | |
| } | |
| self.buffer_offset = new_offset; | |
| let entry = &mut *(self._buffer.as_mut_ptr().add(new_offset as usize) as *mut T); | |
| self.entry_ptrs[self.entry_count as usize] = entry as *mut T as *mut u8; | |
| self.entry_count += 1; | |
| Some(entry) | |
| } | |
| /// Allocate `size` bytes from the buffer WITHOUT registering an entry pointer. | |
| /// | |
| /// Used for auxiliary data (vertex arrays, etc.) that will be referenced | |
| /// from a typed command via an explicit pointer. Both the aux data and | |
| /// the subsequent `push_typed()` command live in the same arena, freed | |
| /// together on frame reset. | |
| /// | |
| /// Unlike `alloc_raw()`, this does NOT consume an `entry_ptrs` slot or | |
| /// increment `entry_count`. | |
| pub unsafe fn alloc_aux(&mut self, size: usize) -> Option<*mut u8> { | |
| let new_offset = self.buffer_offset - size as i32; | |
| if new_offset < 0 { | |
| return None; | |
| } | |
| self.buffer_offset = new_offset; | |
| Some(self._buffer.as_mut_ptr().add(new_offset as usize)) | |
| } | |
| /// Allocate `size` bytes from the downward-growing buffer. | |
| /// | |
| /// Like `alloc<T>()` but for variable-size entries (e.g. legacy commands | |
| /// still enqueued by unported WA.exe code). | |
| /// Returns `None` if the queue is full or buffer exhausted. | |
| pub unsafe fn alloc_raw(&mut self, size: usize) -> Option<*mut u8> { | |
| if self.entry_count >= 0x800 { | |
| return None; | |
| } | |
| let new_offset = self.buffer_offset - size as i32; | |
| if new_offset < 0 { | |
| return None; | |
| } | |
| self.buffer_offset = new_offset; | |
| let ptr = self._buffer.as_mut_ptr().add(new_offset as usize); | |
| self.entry_ptrs[self.entry_count as usize] = ptr; | |
| self.entry_count += 1; | |
| Some(ptr) | |
| } | |
| /// Enqueue a typed render message. Constant-time, zero allocation — | |
| /// the message is stored inline in the existing per-frame buffer. | |
| /// | |
| /// Returns `false` if the per-frame queue is full. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The caller must ensure `self` points to a valid, live `RenderQueue`. | |
| pub unsafe fn push_typed(&mut self, layer: u32, message: RenderMessage) -> bool { | |
| match self.alloc::<TypedRenderCmd>() { | |
| Some(slot) => { | |
| *slot = TypedRenderCmd { | |
| command_type: COMMAND_TYPE_TYPED, | |
| layer, | |
| message, | |
| }; | |
| true | |
| } | |
| None => false, | |
| } | |
| } | |
| } | |