Add base.PIXEL_FORMAT__ETC constants
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index 340c3e6..1847f45 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -32,6 +32,46 @@
 	{"XMP ", "Extensible Metadata Platform"},
 }
 
+var Consts = [...]struct {
+	Type  t.ID
+	Value string
+	Name  string
+}{
+	{t.IDU32, "0x02000008", "PIXEL_FORMAT__A"},
+
+	{t.IDU32, "0x20000008", "PIXEL_FORMAT__Y"},
+	{t.IDU32, "0x21000008", "PIXEL_FORMAT__YA_NONPREMUL"},
+	{t.IDU32, "0x22000008", "PIXEL_FORMAT__YA_PREMUL"},
+
+	{t.IDU32, "0x40020888", "PIXEL_FORMAT__YCBCR"},
+	{t.IDU32, "0x41038888", "PIXEL_FORMAT__YCBCRA_NONPREMUL"},
+	{t.IDU32, "0x50038888", "PIXEL_FORMAT__YCBCRK"},
+
+	{t.IDU32, "0x60020888", "PIXEL_FORMAT__YCOCG"},
+	{t.IDU32, "0x61038888", "PIXEL_FORMAT__YCOCGA_NONPREMUL"},
+	{t.IDU32, "0x70038888", "PIXEL_FORMAT__YCOCGK"},
+
+	{t.IDU32, "0x81040008", "PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL"},
+	{t.IDU32, "0x82040008", "PIXEL_FORMAT__INDEXED__BGRA_PREMUL"},
+	{t.IDU32, "0x83040008", "PIXEL_FORMAT__INDEXED__BGRA_BINARY"},
+
+	{t.IDU32, "0x80000565", "PIXEL_FORMAT__BGR_565"},
+	{t.IDU32, "0x80000888", "PIXEL_FORMAT__BGR"},
+	{t.IDU32, "0x81008888", "PIXEL_FORMAT__BGRA_NONPREMUL"},
+	{t.IDU32, "0x82008888", "PIXEL_FORMAT__BGRA_PREMUL"},
+	{t.IDU32, "0x83008888", "PIXEL_FORMAT__BGRA_BINARY"},
+	{t.IDU32, "0x90008888", "PIXEL_FORMAT__BGRX"},
+
+	{t.IDU32, "0xA0000888", "PIXEL_FORMAT__RGB"},
+	{t.IDU32, "0xA1008888", "PIXEL_FORMAT__RGBA_NONPREMUL"},
+	{t.IDU32, "0xA2008888", "PIXEL_FORMAT__RGBA_PREMUL"},
+	{t.IDU32, "0xA3008888", "PIXEL_FORMAT__RGBA_BINARY"},
+	{t.IDU32, "0xB0008888", "PIXEL_FORMAT__RGBX"},
+
+	{t.IDU32, "0xC0020888", "PIXEL_FORMAT__CMY"},
+	{t.IDU32, "0xD0038888", "PIXEL_FORMAT__CMYK"},
+}
+
 var Statuses = [...]string{
 	// Notes.
 	`"@I/O redirect"`,
diff --git a/lang/check/bounds.go b/lang/check/bounds.go
index 8771cef..d2bdc9f 100644
--- a/lang/check/bounds.go
+++ b/lang/check/bounds.go
@@ -731,7 +731,7 @@
 		return b, nil
 	}
 	if n.ConstValue() != nil {
-		return bcheckExprConstValue(n), nil
+		return bcheckExprConstValue(n)
 	}
 
 	nb, err := q.bcheckExpr1(n, depth)
@@ -756,23 +756,34 @@
 	return nb, nil
 }
 
-func bcheckExprConstValue(n *a.Expr) bounds {
+func bcheckExprConstValue(n *a.Expr) (bounds, error) {
 	if o := n.LHS(); o != nil {
-		bcheckExprConstValue(o.AsExpr())
+		if _, err := bcheckExprConstValue(o.AsExpr()); err != nil {
+			return bounds{}, err
+		}
 	}
 	if o := n.MHS(); o != nil {
-		bcheckExprConstValue(o.AsExpr())
+		if _, err := bcheckExprConstValue(o.AsExpr()); err != nil {
+			return bounds{}, err
+		}
 	}
 	if o := n.RHS(); o != nil && n.Operator() != t.IDXBinaryAs {
-		bcheckExprConstValue(o.AsExpr())
+		if _, err := bcheckExprConstValue(o.AsExpr()); err != nil {
+			return bounds{}, err
+		}
 	}
 	for _, o := range n.Args() {
-		bcheckExprConstValue(o.AsExpr())
+		if _, err := bcheckExprConstValue(o.AsExpr()); err != nil {
+			return bounds{}, err
+		}
 	}
 	cv := n.ConstValue()
+	if cv == nil {
+		return bounds{}, fmt.Errorf("check: constant expression has nil ConstValue")
+	}
 	b := bounds{cv, cv}
 	n.SetMBounds(b)
-	return b
+	return b, nil
 }
 
 func (q *checker) bcheckExpr1(n *a.Expr, depth uint32) (bounds, error) {
diff --git a/lang/check/check.go b/lang/check/check.go
index f2c1713..be1c892 100644
--- a/lang/check/check.go
+++ b/lang/check/check.go
@@ -94,7 +94,9 @@
 		statuses:  map[t.QID]*a.Status{},
 		structs:   map[t.QID]*a.Struct{},
 
-		useBaseNames: map[t.ID]struct{}{},
+		useBaseNames: map[t.ID]struct{}{
+			t.IDBase: struct{}{},
+		},
 
 		builtInSliceFuncs: map[t.QQID]*a.Func{},
 		builtInTableFuncs: map[t.QQID]*a.Func{},
@@ -127,6 +129,31 @@
 		})
 	}
 
+	for _, z := range builtin.Consts {
+		name, err := tm.Insert(z.Name)
+		if err != nil {
+			return nil, err
+		}
+		xType := (*a.TypeExpr)(nil)
+		switch z.Type {
+		case t.IDU32:
+			xType = typeExprU32
+		case t.IDU64:
+			xType = typeExprU64
+		default:
+			return nil, fmt.Errorf("check: unsupported built-in const type %q", z.Type.Str(tm))
+		}
+		value, err := tm.Insert(z.Value)
+		if err != nil {
+			return nil, err
+		}
+		cNode := a.NewConst(0, "", 0, name, xType, a.NewExpr(0, 0, 0, value, nil, nil, nil, nil))
+		if err := c.checkConst(cNode.AsNode()); err != nil {
+			return nil, err
+		}
+		c.consts[t.QID{t.IDBase, name}] = cNode
+	}
+
 	for _, z := range builtin.Statuses {
 		id, err := tm.Insert(z)
 		if err != nil {
diff --git a/lang/check/resolve.go b/lang/check/resolve.go
index 9ac289e..09cfcfa 100644
--- a/lang/check/resolve.go
+++ b/lang/check/resolve.go
@@ -35,6 +35,7 @@
 	typeExprIdeal       = a.NewTypeExpr(0, t.IDBase, t.IDQIdeal, nil, nil, nil)
 	typeExprList        = a.NewTypeExpr(0, t.IDBase, t.IDComma, nil, nil, nil)
 	typeExprNullptr     = a.NewTypeExpr(0, t.IDBase, t.IDQNullptr, nil, nil, nil)
+	typeExprPackage     = a.NewTypeExpr(0, t.IDBase, t.IDQPackage, nil, nil, nil)
 	typeExprPlaceholder = a.NewTypeExpr(0, t.IDBase, t.IDQPlaceholder, nil, nil, nil)
 	typeExprTypeExpr    = a.NewTypeExpr(0, t.IDBase, t.IDQTypeExpr, nil, nil, nil)
 
diff --git a/lang/check/type.go b/lang/check/type.go
index b2cdbac..a3f8824 100644
--- a/lang/check/type.go
+++ b/lang/check/type.go
@@ -366,17 +366,12 @@
 					return nil
 				}
 			}
-			if c, ok := q.c.consts[t.QID{0, id1}]; ok {
-				// TODO: check somewhere that a global ident (i.e. a const) is
-				// not directly in the LHS of an assignment.
-				n.SetGlobalIdent()
-				n.SetConstValue(c.Value().ConstValue())
-				n.SetMType(c.XType())
+			if _, ok := q.c.useBaseNames[id1]; ok {
+				n.SetConstValue(zero)
+				n.SetMType(typeExprPackage)
 				return nil
 			}
-			// TODO: look for other (global) names: consts, funcs, statuses,
-			// structs from used packages.
-			return fmt.Errorf("check: unrecognized identifier %q", id1.Str(q.tm))
+			return q.tcheckExprXDotY(n, 0, id1)
 		}
 
 		switch id1 {
@@ -491,6 +486,21 @@
 		n.Operator(), n.Str(q.tm))
 }
 
+func (q *checker) tcheckExprXDotY(n *a.Expr, x t.ID, y t.ID) error {
+	qid := t.QID{x, y}
+	if c, ok := q.c.consts[qid]; ok {
+		// TODO: check somewhere that a global ident (i.e. a const) is
+		// not directly in the LHS of an assignment.
+		n.SetGlobalIdent()
+		n.SetConstValue(c.Value().ConstValue())
+		n.SetMType(c.XType())
+		return nil
+	}
+	// TODO: look for other (global) names: consts, funcs, statuses,
+	// structs from used packages.
+	return fmt.Errorf("check: unrecognized identifier %q", qid.Str(q.tm))
+}
+
 func (q *checker) tcheckExprCall(n *a.Expr, depth uint32) error {
 	lhs := n.LHS().AsExpr()
 	if err := q.tcheckExpr(lhs, depth); err != nil {
@@ -569,6 +579,9 @@
 	if err := q.tcheckExpr(lhs, depth); err != nil {
 		return err
 	}
+	if lhs.MType() == typeExprPackage {
+		return q.tcheckExprXDotY(n, lhs.Ident(), n.Ident())
+	}
 	lTyp := lhs.MType().Pointee()
 	lQID := lTyp.QID()
 	qqid := t.QQID{lQID[0], lQID[1], n.Ident()}
diff --git a/lang/token/list.go b/lang/token/list.go
index 705b970..4e87626 100644
--- a/lang/token/list.go
+++ b/lang/token/list.go
@@ -450,12 +450,13 @@
 	IDCoroutineResumed = ID(0x101)
 	IDThis             = ID(0x102)
 
-	IDT1      = ID(0x108)
-	IDT2      = ID(0x109)
-	IDDagger1 = ID(0x10A)
-	IDDagger2 = ID(0x10B)
+	IDT1      = ID(0x104)
+	IDT2      = ID(0x105)
+	IDDagger1 = ID(0x106)
+	IDDagger2 = ID(0x107)
 
-	IDQNullptr     = ID(0x10C)
+	IDQNullptr     = ID(0x10B)
+	IDQPackage     = ID(0x10C)
 	IDQPlaceholder = ID(0x10D)
 	IDQTypeExpr    = ID(0x10E)
 
@@ -809,6 +810,10 @@
 	// the nullptr literal.
 	IDQNullptr: "«Nullptr»",
 
+	// IDQPackage is used by the type checker to build an artificial MType for
+	// used (imported) packages.
+	IDQPackage: "«Package»",
+
 	// IDQPlaceholder is used by the type checker to build an artificial MType
 	// for AST nodes that aren't expression nodes or type expression nodes,
 	// such as struct definition nodes and statement nodes. Its presence means
diff --git a/std/bmp/decode_bmp.wuffs b/std/bmp/decode_bmp.wuffs
index f237744..5a28511 100644
--- a/std/bmp/decode_bmp.wuffs
+++ b/std/bmp/decode_bmp.wuffs
@@ -137,15 +137,11 @@
 		// The "((x + 3) >> 2) << 2" dance rounds x up.
 		this.bytes_per_row = ((((this.width as base.u64) * 3) + 3) >> 2) << 2
 		this.pad_per_row = this.width & 3
-		// TODO: a Wuffs (not just C) name for the
-		// WUFFS_BASE__PIXEL_FORMAT__BGR magic pixfmt constant.
-		this.pixfmt = this.util.make_pixel_format(repr: 0x8000_0888)
+		this.pixfmt = this.util.make_pixel_format(repr: base.PIXEL_FORMAT__BGR)
 	} else if bits_per_pixel == 32 {
 		this.bytes_per_row = (this.width as base.u64) * 4
 		this.pad_per_row = 0
-		// TODO: a Wuffs (not just C) name for the
-		// WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL magic pixfmt constant.
-		this.pixfmt = this.util.make_pixel_format(repr: 0x8100_8888)
+		this.pixfmt = this.util.make_pixel_format(repr: base.PIXEL_FORMAT__BGRA_NONPREMUL)
 	} else {
 		// TODO: support other bits_per_pixel's.
 		return "#unsupported BMP file"
@@ -185,10 +181,8 @@
 	this.frame_config_io_position = args.src.position()
 
 	if args.dst <> nullptr {
-		// TODO: a Wuffs (not just C) name for the
-		// WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL magic pixfmt constant.
 		args.dst.set!(
-			pixfmt: 0x8100_8888,  // TODO: this.pixfmt instead?
+			pixfmt: base.PIXEL_FORMAT__BGRA_NONPREMUL,  // TODO: this.pixfmt instead?
 			pixsub: 0,
 			width: this.width,
 			height: this.height,
diff --git a/std/gif/decode_config.wuffs b/std/gif/decode_config.wuffs
index 8e773dd..f05e201 100644
--- a/std/gif/decode_config.wuffs
+++ b/std/gif/decode_config.wuffs
@@ -147,10 +147,8 @@
 	}
 
 	if args.dst <> nullptr {
-		// TODO: a Wuffs (not just C) name for the
-		// WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY magic pixfmt constant.
 		args.dst.set!(
-			pixfmt: 0x8304_0008,
+			pixfmt: base.PIXEL_FORMAT__INDEXED__BGRA_BINARY,
 			pixsub: 0,
 			width: this.width,
 			height: this.height,
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 600d6a9..0dd4d40 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -186,10 +186,8 @@
 	}
 
 	if args.dst <> nullptr {
-		// TODO: a Wuffs (not just C) name for the
-		// WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY magic pixfmt constant.
 		args.dst.set!(
-			pixfmt: 0x8304_0008,
+			pixfmt: base.PIXEL_FORMAT__INDEXED__BGRA_BINARY,
 			pixsub: 0,
 			width: this.width,
 			height: this.height,
@@ -878,12 +876,10 @@
 		dst_palette = this.dst_palette[..]
 	}
 
-	// TODO: a Wuffs (not just C) name for the
-	// WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY magic pixfmt constant.
 	status = this.swizzler.prepare!(
 		dst_pixfmt: args.dst.pixel_format(),
 		dst_palette: dst_palette,
-		src_pixfmt: this.util.make_pixel_format(repr: 0x8304_0008),
+		src_pixfmt: this.util.make_pixel_format(repr: base.PIXEL_FORMAT__INDEXED__BGRA_BINARY),
 		src_palette: this.palettes[which_palette][..],
 		blend: args.blend)
 	if not status.is_ok() {
diff --git a/std/wbmp/decode_wbmp.wuffs b/std/wbmp/decode_wbmp.wuffs
index c27e52c..070bb57 100644
--- a/std/wbmp/decode_wbmp.wuffs
+++ b/std/wbmp/decode_wbmp.wuffs
@@ -82,10 +82,8 @@
 	this.frame_config_io_position = args.src.position()
 
 	if args.dst <> nullptr {
-		// TODO: a Wuffs (not just C) name for the
-		// WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY magic pixfmt constant.
 		args.dst.set!(
-			pixfmt: 0x8304_0008,
+			pixfmt: base.PIXEL_FORMAT__INDEXED__BGRA_BINARY,
 			pixsub: 0,
 			width: this.width,
 			height: this.height,
@@ -149,12 +147,10 @@
 		return base."@end of data"
 	}
 
-	// TODO: a Wuffs (not just C) name for the
-	// WUFFS_BASE__PIXEL_FORMAT__Y magic pixfmt constant.
 	status = this.swizzler.prepare!(
 		dst_pixfmt: args.dst.pixel_format(),
 		dst_palette: args.dst.palette(),
-		src_pixfmt: this.util.make_pixel_format(repr: 0x2000_0008),
+		src_pixfmt: this.util.make_pixel_format(repr: base.PIXEL_FORMAT__Y),
 		src_palette: this.util.empty_slice_u8(),
 		blend: args.blend)
 	if not status.is_ok() {