Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gdi32 palette functions #49

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified win32/dll/gdi32.dll
Binary file not shown.
40 changes: 39 additions & 1 deletion win32/src/winapi/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,11 @@ pub mod gdi32 {
)
.to_raw()
}
pub unsafe fn CreatePalette(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let plpal = <u32>::from_stack(mem, esp + 4u32);
winapi::gdi32::CreatePalette(machine, plpal).to_raw()
}
pub unsafe fn CreatePen(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let iStyle = <Result<PS, u32>>::from_stack(mem, esp + 4u32);
Expand Down Expand Up @@ -1661,12 +1666,24 @@ pub mod gdi32 {
let y = <i32>::from_stack(mem, esp + 12u32);
winapi::gdi32::PtVisible(machine, hdc, x, y).to_raw()
}
pub unsafe fn RealizePalette(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hdc = <HDC>::from_stack(mem, esp + 4u32);
winapi::gdi32::RealizePalette(machine, hdc).to_raw()
}
pub unsafe fn SelectObject(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hdc = <HDC>::from_stack(mem, esp + 4u32);
let hGdiObj = <HGDIOBJ>::from_stack(mem, esp + 8u32);
winapi::gdi32::SelectObject(machine, hdc, hGdiObj).to_raw()
}
pub unsafe fn SelectPalette(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hdc = <HDC>::from_stack(mem, esp + 4u32);
let hpal = <HGDIOBJ>::from_stack(mem, esp + 8u32);
let bForceBackground = <bool>::from_stack(mem, esp + 12u32);
winapi::gdi32::SelectPalette(machine, hdc, hpal, bForceBackground).to_raw()
}
pub unsafe fn SetBkColor(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hdc = <HDC>::from_stack(mem, esp + 4u32);
Expand Down Expand Up @@ -1822,6 +1839,12 @@ pub mod gdi32 {
stack_consumed: 56u32,
is_async: false,
};
pub const CreatePalette: Shim = Shim {
name: "CreatePalette",
func: impls::CreatePalette,
stack_consumed: 4u32,
is_async: false,
};
pub const CreatePen: Shim = Shim {
name: "CreatePen",
func: impls::CreatePen,
Expand Down Expand Up @@ -1936,12 +1959,24 @@ pub mod gdi32 {
stack_consumed: 12u32,
is_async: false,
};
pub const RealizePalette: Shim = Shim {
name: "RealizePalette",
func: impls::RealizePalette,
stack_consumed: 4u32,
is_async: false,
};
pub const SelectObject: Shim = Shim {
name: "SelectObject",
func: impls::SelectObject,
stack_consumed: 8u32,
is_async: false,
};
pub const SelectPalette: Shim = Shim {
name: "SelectPalette",
func: impls::SelectPalette,
stack_consumed: 12u32,
is_async: false,
};
pub const SetBkColor: Shim = Shim {
name: "SetBkColor",
func: impls::SetBkColor,
Expand Down Expand Up @@ -2009,13 +2044,14 @@ pub mod gdi32 {
is_async: false,
};
}
const SHIMS: [Shim; 37usize] = [
const SHIMS: [Shim; 40usize] = [
shims::BitBlt,
shims::CreateBitmap,
shims::CreateCompatibleBitmap,
shims::CreateCompatibleDC,
shims::CreateDIBSection,
shims::CreateFontA,
shims::CreatePalette,
shims::CreatePen,
shims::CreateSolidBrush,
shims::DeleteDC,
Expand All @@ -2035,7 +2071,9 @@ pub mod gdi32 {
shims::MoveToEx,
shims::PatBlt,
shims::PtVisible,
shims::RealizePalette,
shims::SelectObject,
shims::SelectPalette,
shims::SetBkColor,
shims::SetBkMode,
shims::SetBrushOrgEx,
Expand Down
5 changes: 4 additions & 1 deletion win32/src/winapi/gdi32/dc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub struct DC {
// per object type.
pub brush: HGDIOBJ,
pub pen: HGDIOBJ,
pub palette: HGDIOBJ,
}

impl DC {
Expand All @@ -48,6 +49,7 @@ impl DC {
y: 0,
brush: Default::default(),
pen: Default::default(),
palette: Default::default(),
}
}

Expand Down Expand Up @@ -134,7 +136,8 @@ pub fn GetDeviceCaps(
GetDeviceCapsArg::NUMCOLORS => -1i32 as u32, // true color
GetDeviceCapsArg::HORZRES => 640,
GetDeviceCapsArg::VERTRES => 480,
_ => unimplemented!(),
GetDeviceCapsArg::RASTERCAPS => 0x100, // RC_PALETTE
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to depend on the underlying device? I think this is making this function say that all our DCs support palettes, when I think in practice none (?) of them do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure here, but what I assumed when I wrote it was that the palettes would be handled by some code that I will write soon. But with that said, I'm not really sure what these paletts do, and how they are used at the moment 😅

Maybe it's better to hold of on this one until I have gotten more of it to work...

index => unimplemented!("GetDeviceCaps index={:?}", index),
}
}

Expand Down
2 changes: 2 additions & 0 deletions win32/src/winapi/gdi32/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ mod bitmap;
mod dc;
mod draw;
mod object;
mod palette;
mod state;
mod text;
pub use bitmap::*;
pub use dc::*;
pub use draw::*;
pub use object::*;
pub use palette::*;
pub use state::*;
pub use text::*;

Expand Down
5 changes: 4 additions & 1 deletion win32/src/winapi/gdi32/object.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Brush, DCTarget, Pen, BITMAP, COLORREF, HDC};
use super::{Brush, DCTarget, Palette, Pen, BITMAP, COLORREF, HDC};
use crate::{
winapi::{
bitmap::{Bitmap, BitmapMono, BitmapRGBA32},
Expand Down Expand Up @@ -29,6 +29,7 @@ impl BitmapType {
pub enum Object {
Brush(Brush),
Bitmap(BitmapType),
Palette(Palette),
Pen(Pen),
}

Expand Down Expand Up @@ -98,6 +99,7 @@ pub fn SelectObject(machine: &mut Machine, hdc: HDC, hGdiObj: HGDIOBJ) -> HGDIOB
DCTarget::DirectDrawSurface(_) => todo!(),
},
Object::Brush(_) => std::mem::replace(&mut dc.brush, hGdiObj),
Object::Palette(_) => panic!("SelectObject called with a palette (use SelectPalette)"),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the author of the exe is unlikely to see this recommendation :)

(The panic is fine, but if a program ends up going down this codepath we'll need to eventually figure out what behavior they expected)

Object::Pen(_) => std::mem::replace(&mut dc.pen, hGdiObj),
}
}
Expand Down Expand Up @@ -126,6 +128,7 @@ pub fn GetObjectA(machine: &mut Machine, handle: HGDIOBJ, bytes: u32, out: u32)
};
bytes
}
Object::Palette(_) => todo!(),
Object::Pen(_) => todo!(),
}
}
Expand Down
74 changes: 74 additions & 0 deletions win32/src/winapi/gdi32/palette.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::{winapi::{gdi32::{Object, HDC, HGDIOBJ}, types::WORD}, Machine};

const TRACE_CONTEXT: &'static str = "gdi32/palette";

#[repr(C)]
#[derive(Clone, Debug)]
pub struct LOGPALETTE_HEADER {
palVersion: WORD,
palNumEntries: WORD,
}
unsafe impl memory::Pod for LOGPALETTE_HEADER {}

#[repr(C)]
#[derive(Clone, Debug)]
pub struct PALETTEENTRY {
pub peRed: u8,
pub peGreen: u8,
pub peBlue: u8,
pub peFlags: u8,
}
unsafe impl memory::Pod for PALETTEENTRY {}

#[derive(Debug)]
pub struct Palette(LOGPALETTE_HEADER, Vec<PALETTEENTRY>);

#[win32_derive::dllexport]
pub fn CreatePalette(machine: &mut Machine, plpal: u32) -> HGDIOBJ {
let header = machine.mem().view::<LOGPALETTE_HEADER>(plpal).clone();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better as:

let header = machine.mem().get_pod::<LOGPALETTE_HEADER>(plpal);

(Ultimately I think I might need to remove the .view() methods, because Rust is unhappy if the underlying pointers aren't aligned)


let entries = plpal + size_of::<LOGPALETTE_HEADER>() as u32;
let entries = machine.mem().view_n::<PALETTEENTRY>(entries, header.palNumEntries as u32).to_vec();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(...but don't worry about changing view_n, I will need to revisit this API...)


machine.state.gdi32.objects.add(Object::Palette(Palette(header, entries)))
}

#[win32_derive::dllexport]
pub fn SelectPalette(machine: &mut Machine, hdc: HDC, hpal: HGDIOBJ, bForceBackground: bool) -> HGDIOBJ {
let dc = match machine.state.gdi32.dcs.get_mut(hdc) {
None => return HGDIOBJ::null(), // TODO: HGDI_ERROR
Some(dc) => dc,
};

let pal = match machine.state.gdi32.objects.get(hpal) {
None => return HGDIOBJ::null(), // TODO: HGDI_ERROR
Some(pal) => pal,
};

match pal {
Object::Bitmap(_) => panic!("SelectPalette called with a bitmap (use SelectObject)"),
Object::Brush(_) => panic!("SelectPalette called with a brush (use SelectObject)"),
Object::Palette(_) => std::mem::replace(&mut dc.palette, hpal),
Object::Pen(_) => panic!("SelectPalette called with a pen (use SelectObject)"),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same comment here about the panic!()s, they might be better expressed as todo()s given that if they're ever called we will need to figure what to do

}
}

#[win32_derive::dllexport]
pub fn RealizePalette(machine: &mut Machine, hdc: HDC) -> u32 {
let dc = match machine.state.gdi32.dcs.get_mut(hdc) {
None => return !0,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...oh interesting, I think this is basically saying the palette supports 2^32 entries?

Could you put a module-level comment about how you are thinking about this? I guess returning RC_PALETTE above is correct if this is a legal value here (?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the value of GDI_ERROR is !0, my intention was to return GDI_ERROR. I should have made it a constant though 😅

Some(dc) => dc,
};

let pal = match machine.state.gdi32.objects.get(dc.palette) {
None => return !0,
Some(pal) => pal,
};

match pal {
Object::Bitmap(_) => panic!("RealizePalette called with a bitmap"),
Object::Brush(_) => panic!("RealizePalette called with a brush"),
Object::Palette(palette) => palette.1.len() as u32,
Object::Pen(_) => panic!("RealizePalette called with a pen"),
Comment on lines +69 to +72
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could perhaps just handle the Palette case and add a _ => todo! branch otherwise, unless you think it's common

}
}