From patchwork Thu Jan 4 21:58:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882649 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=CM1M/2+r; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gTg6H3kz1ydd for ; Fri, 5 Jan 2024 08:59:02 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjM-0001YS-7F; Thu, 04 Jan 2024 16:58:24 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjL-0001YD-7L for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:23 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjJ-0003Nq-MW for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405501; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/uDi4hdadcNMfRKx6ixOC0QgHn/W3XRuPYkCGT+T/aw=; b=CM1M/2+r9x++P1cO0z3Y4QbgLXE2zbDPRYC0l5nfmh89pqqPIdNrxbyVN6aHFgRIg1iB1J iZ1jVi/An1jjQX9dWQJIJ1pxi4X9vN8lECaxjvd6m5p4T8aP3zn8XWBwSFkTZygZ/LLaDc RzCnV6+7+241ln17NKMc5FXIF9ilpPg= Received: from mail-lj1-f197.google.com (mail-lj1-f197.google.com [209.85.208.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-692-VeJIljweM1iq4jo9xXfvSw-1; Thu, 04 Jan 2024 16:58:19 -0500 X-MC-Unique: VeJIljweM1iq4jo9xXfvSw-1 Received: by mail-lj1-f197.google.com with SMTP id 38308e7fff4ca-2ccc4841251so10562311fa.0 for ; Thu, 04 Jan 2024 13:58:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405497; x=1705010297; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/uDi4hdadcNMfRKx6ixOC0QgHn/W3XRuPYkCGT+T/aw=; b=YVrhMrcJQ+uqOIgHhQtm6KatNmrnSlCrtgnzCQ+5AqvD+qhnnPyXd0PwNCIA/GlZUh DghLJb2VMt4OQgiF7sO9rVHhlvzYjHRSS/U+lD74AwPeNHMLAhCKLBaXm3pn0CqJqNJj 7EEjZzeXbQBbpiDeKlBfBNvaO88vQJhOYTHGwQKT6lt9jv41yKg+2/CdQC3VQK+0w+JN neALM8AJC6wu5pfrdvnS4XkeRmYmZF7SS7bKWpPMY8IrGe23S3eJYHHutfdFbKX+bOri VfTIogqUiDzGsJ8vWg9XHPnsQVLrgxwBnI2DTeO+MjdDlxX2mGMuy64o7d3hZOKQmBNh FJfA== X-Gm-Message-State: AOJu0YzKi3NYYjuCcENVHMCUaj/TUqYndzZ9ZVaYnc+ySlRLGce+wTeS dJjFoQHVV7RywVM348Z2eSYnoCVpQZ44ksRG9YT9YeCuj25foW0uiEFkVfohanVgtRn6lk3xpCF qxoLqR6N6zbYfnUcMX1/E+FTNoEtMFHvZPM9oFsIK7AnRDbhrDcYcjtHBGrVVumeEpp8okWrAL4 dCi1CYPvA= X-Received: by 2002:a05:6512:3c86:b0:50e:3818:ec3c with SMTP id h6-20020a0565123c8600b0050e3818ec3cmr586930lfv.63.1704405497416; Thu, 04 Jan 2024 13:58:17 -0800 (PST) X-Google-Smtp-Source: AGHT+IHKG2OBfDdQASbFQfqMePlnTN1r/Zqfb+luUP+gN+Y4AvtcoeE5OmBovEv48yZz7cGnJkIOpw== X-Received: by 2002:a05:6512:3c86:b0:50e:3818:ec3c with SMTP id h6-20020a0565123c8600b0050e3818ec3cmr586925lfv.63.1704405497019; Thu, 04 Jan 2024 13:58:17 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id q12-20020a056402248c00b005561c3997c6sm182979eda.9.2024.01.04.13.58.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:16 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu Subject: [PATCH v2 1/8] vga: use common endian swap macros Date: Thu, 4 Jan 2024 22:58:04 +0100 Message-ID: <20240104215813.156153-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The constant-expression bswap is provided by const_le32(), and GET_PLANE() can also be implemented using cpu_to_le32(). Remove the custom macros in vga.c. Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 67 +++++++++++++----------------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 37557c3442a..02a7deb66f8 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -90,58 +90,25 @@ const uint8_t gr_mask[16] = { 0x00, /* 0x0f */ }; -#define cbswap_32(__x) \ -((uint32_t)( \ - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) - -#if HOST_BIG_ENDIAN -#define PAT(x) cbswap_32(x) -#else -#define PAT(x) (x) -#endif - -#if HOST_BIG_ENDIAN -#define BIG 1 -#else -#define BIG 0 -#endif - -#if HOST_BIG_ENDIAN -#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) -#else -#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) -#endif - static const uint32_t mask16[16] = { - PAT(0x00000000), - PAT(0x000000ff), - PAT(0x0000ff00), - PAT(0x0000ffff), - PAT(0x00ff0000), - PAT(0x00ff00ff), - PAT(0x00ffff00), - PAT(0x00ffffff), - PAT(0xff000000), - PAT(0xff0000ff), - PAT(0xff00ff00), - PAT(0xff00ffff), - PAT(0xffff0000), - PAT(0xffff00ff), - PAT(0xffffff00), - PAT(0xffffffff), + const_le32(0x00000000), + const_le32(0x000000ff), + const_le32(0x0000ff00), + const_le32(0x0000ffff), + const_le32(0x00ff0000), + const_le32(0x00ff00ff), + const_le32(0x00ffff00), + const_le32(0x00ffffff), + const_le32(0xff000000), + const_le32(0xff0000ff), + const_le32(0xff00ff00), + const_le32(0xff00ffff), + const_le32(0xffff0000), + const_le32(0xffff00ff), + const_le32(0xffffff00), + const_le32(0xffffffff), }; -#undef PAT - -#if HOST_BIG_ENDIAN -#define PAT(x) (x) -#else -#define PAT(x) cbswap_32(x) -#endif - static uint32_t expand4[256]; static uint16_t expand2[256]; static uint8_t expand4to8[16]; @@ -1015,6 +982,8 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d, uint32_t srcaddr, int width); +#define GET_PLANE(data, p) ((cpu_to_le32(data) >> ((p) * 8)) & 0xff) + #include "vga-access.h" #include "vga-helpers.h" From patchwork Thu Jan 4 21:58:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882651 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=HejoVz4j; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gTx62DHz1ydd for ; Fri, 5 Jan 2024 08:59:17 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjQ-0001ZD-OF; Thu, 04 Jan 2024 16:58:28 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjO-0001Z3-UE for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:26 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjM-0003OB-Jj for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:26 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405503; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cYtvpGOJsiUPqkI0epr0yc71idGp9+0xtJJsMQORx8I=; b=HejoVz4jDe4Ta1DONXsk3TeVylR26QwGMbJ8a6o3YxbFWBo6qHgVaBqQwqLSximBbhiNPq ZeoXCDwwPyxQJn8Sb9g9wqYcQkII51VW6NHfryxHNMhrQNd+acBxlfwzp0jFXDUwVNUyAa RUvJ6lElVOt7c+iNHyVMNGHIenW+/NA= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-205-JRHFPQs0N_ahmBYrypu4rQ-1; Thu, 04 Jan 2024 16:58:22 -0500 X-MC-Unique: JRHFPQs0N_ahmBYrypu4rQ-1 Received: by mail-ej1-f72.google.com with SMTP id a640c23a62f3a-a28f0137fd9so32008166b.2 for ; Thu, 04 Jan 2024 13:58:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405500; x=1705010300; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cYtvpGOJsiUPqkI0epr0yc71idGp9+0xtJJsMQORx8I=; b=IaCCVPi6N3xR/SG4GtJ/v3Wqfoaz+qqu6SzrL7GEF1ihxKBqfms2FF8028a7aCcQsa vQlvRhpWiXj5GhroipH+vOjiwEUew2jKxQ3bev7rrLNdWis2VWJmOmQJ1VmGbX6l3NJY kBPyaOqN7/McgQ9nxlemx7T5BCZvTdNKdZATJYlqph63ZrvE2nXFNcCU3KZ8h/GBiuJQ zdPOoCRjmjN/2hagspzJ8dQA3+FPseaf7GHFoHw6WEV1qHtK3UuWNI4XiPuR7e1k7Sqw mAI0JzokxPBeJzlb6m8eg2hj1dDqaiBHnO8dgfr2vq0pjEyjTD7U5eWMkVQiNDIn/oVg +Yxw== X-Gm-Message-State: AOJu0YyaH9aSTaGT7U44vpEdTOX6iZun/8iNLE74PEb76O1PAII5xcYO f6vVIy45Oln6N5lldGM57U9NyimNpHqqZn0K26E2v9q4GWBvGtFxmlRNj4Lb7oB0g+/x/BJH4nH hVmdNDZu7xQywCnWZk0hkpERSvkLr5GRCCdtibiZeaZPhO9d+ZU1j7mlLYgrFg6vx4ApuRmI6/G 8FY7Zgyd4= X-Received: by 2002:a17:907:829a:b0:a19:e62:1fc4 with SMTP id mr26-20020a170907829a00b00a190e621fc4mr469757ejc.30.1704405500602; Thu, 04 Jan 2024 13:58:20 -0800 (PST) X-Google-Smtp-Source: AGHT+IGlxNASFcQ5w5De+4OX4vcxl5eMrfgj48/jM9qsDZ631hG1asP9U6ECam77I3lLKLg0K67Iug== X-Received: by 2002:a17:907:829a:b0:a19:e62:1fc4 with SMTP id mr26-20020a170907829a00b00a190e621fc4mr469749ejc.30.1704405500221; Thu, 04 Jan 2024 13:58:20 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id h24-20020a17090791d800b00a235b01886dsm114229ejz.10.2024.01.04.13.58.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:19 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu, =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= Subject: [PATCH v2 2/8] vga: introduce VGADisplayParams Date: Thu, 4 Jan 2024 22:58:05 +0100 Message-ID: <20240104215813.156153-3-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The next patches will introduce more parameters that cause a full refresh. Instead of adding arguments to get_offsets and lines to update_basic_params, do everything through a struct. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/display/vga_int.h | 15 ++++---- hw/display/cirrus_vga.c | 24 +++++------- hw/display/vga.c | 82 +++++++++++++++++------------------------ 3 files changed, 52 insertions(+), 69 deletions(-) diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 7cf0d11201a..6be61e04284 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -56,6 +56,12 @@ struct VGACommonState; typedef uint8_t (* vga_retrace_fn)(struct VGACommonState *s); typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s); +typedef struct VGADisplayParams { + uint32_t line_offset; + uint32_t start_addr; + uint32_t line_compare; +} VGADisplayParams; + typedef struct VGACommonState { MemoryRegion *legacy_address_space; uint8_t *vram_ptr; @@ -90,10 +96,7 @@ typedef struct VGACommonState { uint8_t palette[768]; int32_t bank_offset; int (*get_bpp)(struct VGACommonState *s); - void (*get_offsets)(struct VGACommonState *s, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare); + void (*get_params)(struct VGACommonState *s, VGADisplayParams *params); void (*get_resolution)(struct VGACommonState *s, int *pwidth, int *pheight); @@ -111,9 +114,7 @@ typedef struct VGACommonState { int graphic_mode; uint8_t shift_control; uint8_t double_scan; - uint32_t line_offset; - uint32_t line_compare; - uint32_t start_addr; + VGADisplayParams params; uint32_t plane_updated; uint32_t last_line_offset; uint8_t last_cw, last_ch; diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index b80f98b6c4c..e6d2581d4eb 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -798,9 +798,9 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) if (blit_is_unsafe(s, false)) return 0; - return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr, - s->cirrus_blt_srcaddr - s->vga.start_addr, - s->cirrus_blt_width, s->cirrus_blt_height); + return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.params.start_addr, + s->cirrus_blt_srcaddr - s->vga.params.start_addr, + s->cirrus_blt_width, s->cirrus_blt_height); } /*************************************** @@ -1101,30 +1101,26 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) * ***************************************/ -static void cirrus_get_offsets(VGACommonState *s1, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare) +static void cirrus_get_params(VGACommonState *s1, + VGADisplayParams *params) { CirrusVGAState * s = container_of(s1, CirrusVGAState, vga); - uint32_t start_addr, line_offset, line_compare; + uint32_t line_offset; line_offset = s->vga.cr[0x13] | ((s->vga.cr[0x1b] & 0x10) << 4); line_offset <<= 3; - *pline_offset = line_offset; + params->line_offset = line_offset; - start_addr = (s->vga.cr[0x0c] << 8) + params->start_addr = (s->vga.cr[0x0c] << 8) | s->vga.cr[0x0d] | ((s->vga.cr[0x1b] & 0x01) << 16) | ((s->vga.cr[0x1b] & 0x0c) << 15) | ((s->vga.cr[0x1d] & 0x80) << 12); - *pstart_addr = start_addr; - line_compare = s->vga.cr[0x18] | + params->line_compare = s->vga.cr[0x18] | ((s->vga.cr[0x07] & 0x10) << 4) | ((s->vga.cr[0x09] & 0x40) << 3); - *pline_compare = line_compare; } static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) @@ -2925,7 +2921,7 @@ void cirrus_init_common(CirrusVGAState *s, Object *owner, s->linear_mmio_mask = s->real_vram_size - 256; s->vga.get_bpp = cirrus_get_bpp; - s->vga.get_offsets = cirrus_get_offsets; + s->vga.get_params = cirrus_get_params; s->vga.get_resolution = cirrus_get_resolution; s->vga.cursor_invalidate = cirrus_cursor_invalidate; s->vga.cursor_draw_line = cirrus_cursor_draw_line; diff --git a/hw/display/vga.c b/hw/display/vga.c index 02a7deb66f8..aebc1aeaaef 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1042,52 +1042,40 @@ static int update_palette256(VGACommonState *s) return full_update; } -static void vga_get_offsets(VGACommonState *s, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare) +static void vga_get_params(VGACommonState *s, + VGADisplayParams *params) { - uint32_t start_addr, line_offset, line_compare; - if (vbe_enabled(s)) { - line_offset = s->vbe_line_offset; - start_addr = s->vbe_start_addr; - line_compare = 65535; + params->line_offset = s->vbe_line_offset; + params->start_addr = s->vbe_start_addr; + params->line_compare = 65535; } else { /* compute line_offset in bytes */ - line_offset = s->cr[VGA_CRTC_OFFSET]; - line_offset <<= 3; + params->line_offset = s->cr[VGA_CRTC_OFFSET] << 3; /* starting address */ - start_addr = s->cr[VGA_CRTC_START_LO] | + params->start_addr = s->cr[VGA_CRTC_START_LO] | (s->cr[VGA_CRTC_START_HI] << 8); /* line compare */ - line_compare = s->cr[VGA_CRTC_LINE_COMPARE] | + params->line_compare = s->cr[VGA_CRTC_LINE_COMPARE] | ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) | ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3); } - *pline_offset = line_offset; - *pstart_addr = start_addr; - *pline_compare = line_compare; } /* update start_addr and line_offset. Return TRUE if modified */ static int update_basic_params(VGACommonState *s) { int full_update; - uint32_t start_addr, line_offset, line_compare; + VGADisplayParams current; full_update = 0; - s->get_offsets(s, &line_offset, &start_addr, &line_compare); + s->get_params(s, ¤t); - if (line_offset != s->line_offset || - start_addr != s->start_addr || - line_compare != s->line_compare) { - s->line_offset = line_offset; - s->start_addr = start_addr; - s->line_compare = line_compare; + if (memcmp(¤t, &s->params, sizeof(current))) { + s->params = current; full_update = 1; } return full_update; @@ -1188,7 +1176,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) } full_update |= update_basic_params(s); - line_offset = s->line_offset; + line_offset = s->params.line_offset; vga_get_text_resolution(s, &width, &height, &cw, &cheight); if ((height * width) <= 1) { @@ -1227,7 +1215,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) } cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | - s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; + s->cr[VGA_CRTC_CURSOR_LO]) - s->params.start_addr; if (cursor_offset != s->cursor_offset || s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start || s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) { @@ -1241,7 +1229,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) s->cursor_start = s->cr[VGA_CRTC_CURSOR_START]; s->cursor_end = s->cr[VGA_CRTC_CURSOR_END]; } - cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; + cursor_ptr = s->vram_ptr + (s->params.start_addr + cursor_offset) * 4; if (now >= s->cursor_blink_time) { s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2; s->cursor_visible_phase = !s->cursor_visible_phase; @@ -1251,7 +1239,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) linesize = surface_stride(surface); ch_attr_ptr = s->last_ch_attr; line = 0; - offset = s->start_addr * 4; + offset = s->params.start_addr * 4; for(cy = 0; cy < height; cy++) { d1 = dest; src = s->vram_ptr + offset; @@ -1331,7 +1319,7 @@ static void vga_draw_text(VGACommonState *s, int full_update) dest += linesize * cheight; line1 = line + cheight; offset += line_offset; - if (line < s->line_compare && line1 >= s->line_compare) { + if (line < s->params.line_compare && line1 >= s->params.line_compare) { offset = 0; } line = line1; @@ -1461,10 +1449,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) disp_width = width; depth = s->get_bpp(s); - region_start = (s->start_addr * 4); - region_end = region_start + (ram_addr_t)s->line_offset * height; + region_start = (s->params.start_addr * 4); + region_end = region_start + (ram_addr_t)s->params.line_offset * height; region_end += width * depth / 8; /* scanline length */ - region_end -= s->line_offset; + region_end -= s->params.line_offset; if (region_end > s->vbe_size || depth == 0 || depth == 15) { /* * We land here on: @@ -1529,7 +1517,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) share_surface = false; } - if (s->line_offset != s->last_line_offset || + if (s->params.line_offset != s->last_line_offset || disp_width != s->last_width || height != s->last_height || s->last_depth != depth || @@ -1540,12 +1528,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s->last_scr_height = height; s->last_width = disp_width; s->last_height = height; - s->last_line_offset = s->line_offset; + s->last_line_offset = s->params.line_offset; s->last_depth = depth; s->last_byteswap = byteswap; full_update = 1; } - if (surface_data(surface) != s->vram_ptr + (s->start_addr * 4) + if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4) && is_buffer_shared(surface)) { /* base address changed (page flip) -> shared display surfaces * must be updated with the new base address */ @@ -1555,8 +1543,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (full_update) { if (share_surface) { surface = qemu_create_displaysurface_from(disp_width, - height, format, s->line_offset, - s->vram_ptr + (s->start_addr * 4)); + height, format, s->params.line_offset, + s->vram_ptr + (s->params.start_addr * 4)); dpy_gfx_replace_surface(s->con, surface); } else { qemu_console_resize(s->con, disp_width, height); @@ -1620,9 +1608,9 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) #if 0 printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE], - s->line_compare, sr(s, VGA_SEQ_CLOCK_MODE)); + s->params.line_compare, sr(s, VGA_SEQ_CLOCK_MODE)); #endif - addr1 = (s->start_addr * 4); + addr1 = (s->params.start_addr * 4); bwidth = DIV_ROUND_UP(width * bits, 8); y_start = -1; d = surface_data(surface); @@ -1630,7 +1618,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) y1 = 0; if (!full_update) { - if (s->line_compare < height) { + if (s->params.line_compare < height) { /* split screen mode */ region_start = 0; } @@ -1686,14 +1674,14 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (!multi_run) { mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3; if ((y1 & mask) == mask) - addr1 += s->line_offset; + addr1 += s->params.line_offset; y1++; multi_run = multi_scan; } else { multi_run--; } /* line compare acts on the displayed lines */ - if (y == s->line_compare) + if (y == s->params.line_compare) addr1 = 0; d += linesize; } @@ -1810,9 +1798,7 @@ void vga_common_reset(VGACommonState *s) s->graphic_mode = -1; /* force full update */ s->shift_control = 0; s->double_scan = 0; - s->line_offset = 0; - s->line_compare = 0; - s->start_addr = 0; + memset(&s->params, '\0', sizeof(s->params)); s->plane_updated = 0; s->last_cw = 0; s->last_ch = 0; @@ -1934,7 +1920,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) /* Update "hardware" cursor */ cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) | - s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr; + s->cr[VGA_CRTC_CURSOR_LO]) - s->params.start_addr; if (cursor_offset != s->cursor_offset || s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start || s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) { @@ -1950,7 +1936,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) s->cursor_end = s->cr[VGA_CRTC_CURSOR_END]; } - src = (uint32_t *) s->vram_ptr + s->start_addr; + src = (uint32_t *) s->vram_ptr + s->params.start_addr; dst = chardata; if (full_update) { @@ -2195,7 +2181,7 @@ bool vga_common_init(VGACommonState *s, Object *obj, Error **errp) xen_register_framebuffer(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); s->get_bpp = vga_get_bpp; - s->get_offsets = vga_get_offsets; + s->get_params = vga_get_params; s->get_resolution = vga_get_resolution; s->hw_ops = &vga_ops; switch (vga_retrace_method) { From patchwork Thu Jan 4 21:58:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882650 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IEJH2Qpp; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gTl6PFTz1ydd for ; Fri, 5 Jan 2024 08:59:07 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjS-0001Zh-Ee; Thu, 04 Jan 2024 16:58:30 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjR-0001ZK-2S for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:29 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjP-0003OG-EP for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405506; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dggxOoMGSHPsNTmOlVnHH3e8clB1PCJuMh7wIlsQipU=; b=IEJH2Qpp00/NuEbQuZUVwF4lgmE6euFAG4W2NndqgfaWjwT/oBytUeIgRhVAGm8wHbfZy4 Xzm/hYcOjcczc7ScMViyED0rgxGO/N8tenIdNE1AZJak/52zVp79KmM3rOTtKM+Ha7vurH knm+NgZRimVDa2PmtnFd1NHqP6JGZ50= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-508-hG0csCU1Nba2gi0Savje1Q-1; Thu, 04 Jan 2024 16:58:24 -0500 X-MC-Unique: hG0csCU1Nba2gi0Savje1Q-1 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-40e34df6fdcso5790685e9.1 for ; Thu, 04 Jan 2024 13:58:24 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405502; x=1705010302; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dggxOoMGSHPsNTmOlVnHH3e8clB1PCJuMh7wIlsQipU=; b=kveGS3XXkkf2kp0W6Px6iZkjJ5kHsB2l1rskhWWl3AYTze9hHauiBEWl+MHo075uBS VBtlVYeywJj9iXSFvDiB2vLH1YFVcu4yGnHkvL7PvnNm7yEVwrotajvCou/aScviCQlU s6sIv6HwTLxbyju0ySe9AGBwEXN6LB+yGe3MhWZEH5JyA8QxdvhslQRDg7qC+IcDkGh1 t+L/cbG1cdQUx/rqf88ijZrmXBbSPCsYRYo4EDJOXiU2Qvi2uhJzgqTGHYGnLDc+N07a BP/53abWSO/3kd+v3KA/MQteFgE+yUU5QqEoe34iQzwzVX6p9FgNz0KTqnON/z3PWFJI 7RIg== X-Gm-Message-State: AOJu0YzZGOkAfaSv/Gjz63JYjoqVZK3/zy4Az+DHuKX0AINJsRraz4ZZ HOgxIR7yqv0cnsSvXicpkH1oCyae+mjYCHmNbai+9OJcGgsnauHktIhNAKAdqHd5UWJXLPKBKSj 3GOrIod0fPeGJ/o8g7hh+NZHICv5XeJ/ewkOr+VohNk9Xv9r5gfEy0kwwZoyCGY9P83ZWOfiu9N Hby0A8qdY= X-Received: by 2002:a05:600c:474d:b0:40e:3505:3326 with SMTP id w13-20020a05600c474d00b0040e35053326mr646793wmo.19.1704405502605; Thu, 04 Jan 2024 13:58:22 -0800 (PST) X-Google-Smtp-Source: AGHT+IFRSKIlSUOBUk4/2AUefchVoRW+1EyXNs88WdW0sMk5He7GiiNE2hR0gOXrY+9Ukhbza+bV7g== X-Received: by 2002:a05:600c:474d:b0:40e:3505:3326 with SMTP id w13-20020a05600c474d00b0040e35053326mr646789wmo.19.1704405502364; Thu, 04 Jan 2024 13:58:22 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id mb16-20020a170906eb1000b00a26aeb9e37csm113268ejb.6.2024.01.04.13.58.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:21 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu Subject: [PATCH v2 3/8] vga: mask addresses in non-VESA modes to 256k Date: Thu, 4 Jan 2024 22:58:06 +0100 Message-ID: <20240104215813.156153-4-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This allows setting the start address to a high value, and reading the bottom of the screen from the beginning of VRAM. Commander Keen 4 ("Goodbye, Galaxy!") relies on this behavior. Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 9 +++++---- hw/display/vga.c | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 10e9cfd40a0..83b9a15604a 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -108,7 +108,7 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = vga_read_dword_le(vga, addr); + data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -144,7 +144,7 @@ static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = vga_read_dword_le(vga, addr); + data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand2[GET_PLANE(data, 0)]; v |= expand2[GET_PLANE(data, 2)] << 2; @@ -177,7 +177,7 @@ static void vga_draw_line4(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = vga_read_dword_le(vga, addr); + data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -209,7 +209,7 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; width >>= 3; for(x = 0; x < width; x++) { - data = vga_read_dword_le(vga, addr); + data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); data &= plane_mask; v = expand4[GET_PLANE(data, 0)]; v |= expand4[GET_PLANE(data, 1)] << 1; @@ -242,6 +242,7 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, palette = vga->last_palette; width >>= 3; for(x = 0; x < width; x++) { + addr &= VGA_VRAM_SIZE - 1; PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); diff --git a/hw/display/vga.c b/hw/display/vga.c index aebc1aeaaef..296182b0b93 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -47,6 +47,9 @@ bool have_vga = true; /* 16 state changes per vertical frame @60 Hz */ #define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60) +/* Address mask for non-VESA modes. */ +#define VGA_VRAM_SIZE (256 * KiB) + /* * Video Graphics Array (VGA) * From patchwork Thu Jan 4 21:58:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882652 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=PfMIYONK; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gV66Xsbz1ydd for ; Fri, 5 Jan 2024 08:59:26 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjV-0001aG-4Q; Thu, 04 Jan 2024 16:58:33 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjU-0001Zx-9O for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:32 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjR-0003Ov-Rp for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405509; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PiLgiU6NaopJ5BO1xNmRBnoDl1SO2F7kA5EA72hKn5Q=; b=PfMIYONKkBcZhpsROwLgXQ0Niykgyd6mSwONrPefnUCsMx2Tf6v4vLrYYH2HVfc2w3zsmg sf9Yd7mo+/1sWPUqmt4YkdiYq7QMhybRSZphnmdHNaEPbinl8ywM73fSHo9ZvyGB5GuHHf MePytiri+38ciLGftetQx0ywR0t9Hjg= Received: from mail-lj1-f199.google.com (mail-lj1-f199.google.com [209.85.208.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-257--tIiOTbUPLqKmJ_6ze_ATQ-1; Thu, 04 Jan 2024 16:58:27 -0500 X-MC-Unique: -tIiOTbUPLqKmJ_6ze_ATQ-1 Received: by mail-lj1-f199.google.com with SMTP id 38308e7fff4ca-2ccaf8667f9so7852391fa.1 for ; Thu, 04 Jan 2024 13:58:27 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405505; x=1705010305; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PiLgiU6NaopJ5BO1xNmRBnoDl1SO2F7kA5EA72hKn5Q=; b=KGZEfsX0Jp/A6w4tFB83g8H6+nxpD/iCPWrgfz/umHFIJsMFS1LSNLVSnKNUAcpn4M WpycZsciztuHbifmVlxJfbCBBQ3NK3BMhqFbSNwfdXjjozmyTvqSZtPT5NuA4F3SvAhi MnUe+F/zhZzyVGg1u+wG8Uoi/ABhjfylS6OST5rPo8k35tl6EfkAWHfS+5w5VplQTzG8 dojSWTFBk+9YOkLWGtdbu0pIb4L9Lh28BiWfKBgprwQ27ywH1uOjMMNDaLaSI4qXK4GF AyBo6t7hmKVv9hmpkBnKtpTtPPwUfFEOgnevzJx1X2qbFI4hEzSnhZi+IHA8mRN16lKx U8ng== X-Gm-Message-State: AOJu0YwW9O2nDc/9F62TGr5xnS+Zk9Lt3JqlhLAXdXB3t51xOULi0Gjc U36d2D0rM5M+gqMXswhogdMN5LamToX9FR3/LeYOnpHlabaEC8NjWf7HUmKRDm40QWZiJGJVRlw wQr4RxFZN4XEePD3pPEx2y5kvN2NgjFCjJTFwhUKBBCw8kPhW9PuoyFYw1x+66p7/RxUwf5rLCG 37Yux69tY= X-Received: by 2002:a2e:be83:0:b0:2cc:82ee:287f with SMTP id a3-20020a2ebe83000000b002cc82ee287fmr405508ljr.52.1704405505382; Thu, 04 Jan 2024 13:58:25 -0800 (PST) X-Google-Smtp-Source: AGHT+IFWme5Duo8h475XavMYM2i0g4yB98mjSFUFdzDbN4wf50+ZYaXHIxd/kZODgLXJzvLq3QHOBA== X-Received: by 2002:a2e:be83:0:b0:2cc:82ee:287f with SMTP id a3-20020a2ebe83000000b002cc82ee287fmr405503ljr.52.1704405504939; Thu, 04 Jan 2024 13:58:24 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id cm25-20020a0564020c9900b00556ee10cfe3sm172611edb.92.2024.01.04.13.58.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:24 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu Subject: [PATCH v2 4/8] vga: implement horizontal pel panning in graphics modes Date: Thu, 4 Jan 2024 22:58:07 +0100 Message-ID: <20240104215813.156153-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This implements smooth scrolling, as used for example by Commander Keen and Second Reality. Unfortunately, this is not enough to avoid tearing in Commander Keen, because sometimes the wrong start address is used for a frame. On real EGA, the panning register is sampled on every line, while the display start is latched for the next frame at the start of the vertical retrace. On real VGA, the panning register is also latched, but at the end of the vertical retrace. It looks like Keen exploits this by only waiting for horizontal retrace when setting the display start, but implementing it breaks the 256-color Keen games... Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 100 ++++++++++++++++++++++++++++----------- hw/display/vga_int.h | 3 ++ hw/display/cirrus_vga.c | 4 ++ hw/display/vga.c | 36 ++++++++++++-- 4 files changed, 111 insertions(+), 32 deletions(-) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 83b9a15604a..29933562c45 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -98,14 +98,19 @@ static void vga_draw_glyph9(uint8_t *d, int linesize, /* * 4 color mode */ -static void vga_draw_line2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t plane_mask, *palette, data, v; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + hpel &= 7; + if (hpel) { + width += 8; + d = vga->panning_buf; + } width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -126,6 +131,7 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, d += 32; addr += 4; } + return hpel ? vga->panning_buf + 4 * hpel : NULL; } #define PUT_PIXEL2(d, n, v) \ @@ -134,14 +140,19 @@ static void vga_draw_line2(VGACommonState *vga, uint8_t *d, /* * 4 color mode, dup2 horizontal */ -static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line2d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t plane_mask, *palette, data, v; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + hpel &= 7; + if (hpel) { + width += 8; + d = vga->panning_buf; + } width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -162,19 +173,25 @@ static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, d += 64; addr += 4; } + return hpel ? vga->panning_buf + 8 * hpel : NULL; } /* * 16 color mode */ -static void vga_draw_line4(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line4(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t plane_mask, data, v, *palette; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + hpel &= 7; + if (hpel) { + width += 8; + d = vga->panning_buf; + } width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -194,19 +211,25 @@ static void vga_draw_line4(VGACommonState *vga, uint8_t *d, d += 32; addr += 4; } + return hpel ? vga->panning_buf + 4 * hpel : NULL; } /* * 16 color mode, dup2 horizontal */ -static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line4d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t plane_mask, data, v, *palette; int x; palette = vga->last_palette; plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; + hpel &= 7; + if (hpel) { + width += 8; + d = vga->panning_buf; + } width >>= 3; for(x = 0; x < width; x++) { data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1)); @@ -226,6 +249,7 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, d += 64; addr += 4; } + return hpel ? vga->panning_buf + 8 * hpel : NULL; } /* @@ -233,13 +257,18 @@ static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, * * XXX: add plane_mask support (never used in standard VGA modes) */ -static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t *palette; int x; palette = vga->last_palette; + hpel = (hpel >> 1) & 3; + if (hpel) { + width += 8; + d = vga->panning_buf; + } width >>= 3; for(x = 0; x < width; x++) { addr &= VGA_VRAM_SIZE - 1; @@ -250,6 +279,7 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, d += 32; addr += 4; } + return hpel ? vga->panning_buf + 8 * hpel : NULL; } /* @@ -257,13 +287,18 @@ static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, * * XXX: add plane_mask support (never used in standard VGA modes) */ -static void vga_draw_line8(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line8(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { uint32_t *palette; int x; palette = vga->last_palette; + hpel = (hpel >> 1) & 3; + if (hpel) { + width += 8; + d = vga->panning_buf; + } width >>= 3; for(x = 0; x < width; x++) { ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)]; @@ -277,13 +312,14 @@ static void vga_draw_line8(VGACommonState *vga, uint8_t *d, d += 32; addr += 8; } + return hpel ? vga->panning_buf + 4 * hpel : NULL; } /* * 15 bit color */ -static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t v, r, g, b; @@ -298,10 +334,11 @@ static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d, addr += 2; d += 4; } while (--w != 0); + return NULL; } -static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t v, r, g, b; @@ -316,13 +353,14 @@ static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d, addr += 2; d += 4; } while (--w != 0); + return NULL; } /* * 16 bit color */ -static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t v, r, g, b; @@ -337,10 +375,11 @@ static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d, addr += 2; d += 4; } while (--w != 0); + return NULL; } -static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line16_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t v, r, g, b; @@ -355,13 +394,14 @@ static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d, addr += 2; d += 4; } while (--w != 0); + return NULL; } /* * 24 bit color */ -static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t r, g, b; @@ -375,10 +415,11 @@ static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d, addr += 3; d += 4; } while (--w != 0); + return NULL; } -static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t r, g, b; @@ -392,13 +433,14 @@ static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d, addr += 3; d += 4; } while (--w != 0); + return NULL; } /* * 32 bit color */ -static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t r, g, b; @@ -412,10 +454,11 @@ static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d, addr += 4; d += 4; } while (--w != 0); + return NULL; } -static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d, - uint32_t addr, int width) +static void *vga_draw_line32_be(VGACommonState *vga, uint8_t *d, + uint32_t addr, int width, int hpel) { int w; uint32_t r, g, b; @@ -429,4 +472,5 @@ static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d, addr += 4; d += 4; } while (--w != 0); + return NULL; } diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 6be61e04284..876a1d3697b 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -60,6 +60,8 @@ typedef struct VGADisplayParams { uint32_t line_offset; uint32_t start_addr; uint32_t line_compare; + uint8_t hpel; + bool hpel_split; } VGADisplayParams; typedef struct VGACommonState { @@ -111,6 +113,7 @@ typedef struct VGACommonState { /* display refresh support */ QemuConsole *con; uint32_t font_offsets[2]; + uint8_t *panning_buf; int graphic_mode; uint8_t shift_control; uint8_t double_scan; diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index e6d2581d4eb..849eff43898 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -43,6 +43,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "ui/pixel_ops.h" +#include "vga_regs.h" #include "cirrus_vga_internal.h" #include "qom/object.h" #include "ui/console.h" @@ -1121,6 +1122,9 @@ static void cirrus_get_params(VGACommonState *s1, params->line_compare = s->vga.cr[0x18] | ((s->vga.cr[0x07] & 0x10) << 4) | ((s->vga.cr[0x09] & 0x40) << 3); + + params->hpel = s->vga.ar[VGA_ATC_PEL]; + params->hpel_split = s->vga.ar[VGA_ATC_MODE] & 0x20; } static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) diff --git a/hw/display/vga.c b/hw/display/vga.c index 296182b0b93..2c7b8e54805 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -50,6 +50,13 @@ bool have_vga = true; /* Address mask for non-VESA modes. */ #define VGA_VRAM_SIZE (256 * KiB) +/* This value corresponds to a shift of zero pixels + * in 9-dot text mode. In other modes, bit 3 is undefined; + * we just ignore it, so that 8 corresponds to zero pixels + * in all modes. + */ +#define VGA_HPEL_NEUTRAL 8 + /* * Video Graphics Array (VGA) * @@ -982,8 +989,8 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) } } -typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d, - uint32_t srcaddr, int width); +typedef void *vga_draw_line_func(VGACommonState *s1, uint8_t *d, + uint32_t srcaddr, int width, int hpel); #define GET_PLANE(data, p) ((cpu_to_le32(data) >> ((p) * 8)) & 0xff) @@ -1052,6 +1059,8 @@ static void vga_get_params(VGACommonState *s, params->line_offset = s->vbe_line_offset; params->start_addr = s->vbe_start_addr; params->line_compare = 65535; + params->hpel = VGA_HPEL_NEUTRAL; + params->hpel_split = false; } else { /* compute line_offset in bytes */ params->line_offset = s->cr[VGA_CRTC_OFFSET] << 3; @@ -1064,6 +1073,9 @@ static void vga_get_params(VGACommonState *s, params->line_compare = s->cr[VGA_CRTC_LINE_COMPARE] | ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) | ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3); + + params->hpel = s->ar[VGA_ATC_PEL]; + params->hpel_split = s->ar[VGA_ATC_MODE] & 0x20; } } @@ -1435,6 +1447,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) ram_addr_t page0, page1, region_start, region_end; DirtyBitmapSnapshot *snap = NULL; int disp_width, multi_scan, multi_run; + int hpel; uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line = NULL; @@ -1534,6 +1547,9 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) s->last_line_offset = s->params.line_offset; s->last_depth = depth; s->last_byteswap = byteswap; + /* 16 extra pixels are needed for double-width planar modes. */ + s->panning_buf = g_realloc(s->panning_buf, + (disp_width + 16) * sizeof(uint32_t)); full_update = 1; } if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4) @@ -1613,8 +1629,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE], s->params.line_compare, sr(s, VGA_SEQ_CLOCK_MODE)); #endif + hpel = bits <= 8 ? s->params.hpel : 0; addr1 = (s->params.start_addr * 4); bwidth = DIV_ROUND_UP(width * bits, 8); + if (hpel) { + bwidth += 4; + } y_start = -1; d = surface_data(surface); linesize = surface_stride(surface); @@ -1662,7 +1682,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) if (y_start < 0) y_start = y; if (!(is_buffer_shared(surface))) { - vga_draw_line(s, d, addr, width); + uint8_t *p; + p = vga_draw_line(s, d, addr, width, hpel); + if (p) { + memcpy(d, p, disp_width * sizeof(uint32_t)); + } if (s->cursor_draw_line) s->cursor_draw_line(s, d, y); } @@ -1684,8 +1708,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) multi_run--; } /* line compare acts on the displayed lines */ - if (y == s->params.line_compare) + if (y == s->params.line_compare) { + if (s->params.hpel_split) { + hpel = VGA_HPEL_NEUTRAL; + } addr1 = 0; + } d += linesize; } if (y_start >= 0) { From patchwork Thu Jan 4 21:58:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882655 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=XS5U/z4W; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gVr5q6Cz23dn for ; Fri, 5 Jan 2024 09:00:04 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjX-0001ao-Ax; Thu, 04 Jan 2024 16:58:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjU-0001Zy-DN for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:32 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjT-0003P1-0G for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405510; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zGuVDWpXyHgDtnpBoCqtCU0iZWlD325c2JY3QKidV/E=; b=XS5U/z4Wfi7IyNI59H0Vt4SlUN5GJEb7RH6CAFnCsO2qJmLuKUTEHd9zKdDFrSu1IGnHcW dCYHSxN8qF1Ox3DWIzaWmK9u03vz8USsNUT6mbU5K9Eeh5yji009ebq/82/smxKNfeIbwI faBK2/X/IZk3lwgqtvIxiOl51wO96TU= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-569-gmHQcxtROhW7RA7tyihEng-1; Thu, 04 Jan 2024 16:58:29 -0500 X-MC-Unique: gmHQcxtROhW7RA7tyihEng-1 Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-a28f6a233afso36966066b.0 for ; Thu, 04 Jan 2024 13:58:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405507; x=1705010307; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zGuVDWpXyHgDtnpBoCqtCU0iZWlD325c2JY3QKidV/E=; b=eYPCZAGPpKU1r0zw2BM+BJmeDxEAd7sESEitCcWJY8ts3inaHKQ9rVn3qF9dfn0XG7 mBXzLuR35mfXDV7gchW4hahkAqDiWFJJUd8wmRH4eUTVaQD64L0ffnjjVu/TL9Pech7X s3iAnQ44+e7c0EmHh+PQGttaDTQ1JaSQAb157MPYAw8qlLy8Vd7if6PKRAjjT/yPf2u5 a+ekEsRvDRDizkK0pt9vyvFbp3iv8FzHjdKOrENKxov9DTnLsS1GKSC+yvEXwH6sbCJt pzmF5p6a2F4toU7F2MGv8aQ9/TlfL21Z4hSS0G5/NoMW0s77KuudX3z4+hk1/F66Mtoa zvUw== X-Gm-Message-State: AOJu0Yxui0mZdCBspMgY7xxjgSXvor/J62BtGK2IKeoPi6a3oWzshVqa C3fFJk8gm17H+MyXY/7mqFlbSUGNPYGv1/RAt7Cve8bmdpUxTjxjduoW/Q2YJKGZ96C1rVpkxSe 3+WhQgp4G8WJFFaGK+cER1kqVql27ewxrhOmZaVyYL02qaFqjpHa3EROXnm7lNbhWp7RClXWhu1 0Yls+uCsY= X-Received: by 2002:a17:907:76c5:b0:a26:c055:9e85 with SMTP id kf5-20020a17090776c500b00a26c0559e85mr456452ejc.58.1704405507395; Thu, 04 Jan 2024 13:58:27 -0800 (PST) X-Google-Smtp-Source: AGHT+IEd5WE4IQ5UzNfn4dgY0IAdIYpqD3kjJ4lXUOBZ7rRdzJwAonExfp87NAK11PSr2Kn/xhhE1A== X-Received: by 2002:a17:907:76c5:b0:a26:c055:9e85 with SMTP id kf5-20020a17090776c500b00a26c0559e85mr456447ejc.58.1704405507209; Thu, 04 Jan 2024 13:58:27 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id m21-20020a1709061ed500b00a236378a43fsm112642ejj.62.2024.01.04.13.58.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:26 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu Subject: [PATCH v2 5/8] vga: optimize horizontal pel panning in 256-color modes Date: Thu, 4 Jan 2024 22:58:08 +0100 Message-ID: <20240104215813.156153-6-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Do not go through the panning buffer unless the address wraps in the middle of the line. Signed-off-by: Paolo Bonzini --- hw/display/vga-helpers.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h index 29933562c45..60ddb27d946 100644 --- a/hw/display/vga-helpers.h +++ b/hw/display/vga-helpers.h @@ -265,6 +265,18 @@ static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d, palette = vga->last_palette; hpel = (hpel >> 1) & 3; + + /* For 256 color modes, we can adjust the source address and write directly + * to the destination, even if horizontal pel panning is active. However, + * the loop below assumes that the address does not wrap in the middle of a + * plane. If that happens... + */ + if (addr + (width >> 3) * 4 < VGA_VRAM_SIZE) { + addr += hpel * 4; + hpel = 0; + } + + /* ... use the panning buffer as in planar modes. */ if (hpel) { width += 8; d = vga->panning_buf; From patchwork Thu Jan 4 21:58:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882656 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Rrq0xfA9; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gVw1M1Mz23fC for ; Fri, 5 Jan 2024 09:00:08 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjc-0001dL-RP; Thu, 04 Jan 2024 16:58:40 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjZ-0001cx-Vb for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:37 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjY-0003PQ-4g for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:37 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NQLcT9KTPjg2f3Hw+CbWFYTnjCtLhdth+T+FsYyXx/o=; b=Rrq0xfA9sFYbh00DaECwxEQfjxyZTIfSx9rcMVz+r4vFHwels6vhaO+nPK49KwMe/YADZZ AkDTwUqidlJr0Txr7fkEcSNpWH+GbF5nBKuW7LYNHc36sXE3uQMNjji/jDeF4C0A2Ff9DM B0ALtmNy4cDgNsLPQ7n2tKg7TUE3nhI= Received: from mail-ej1-f71.google.com (mail-ej1-f71.google.com [209.85.218.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-274-yJCbwwYVMPWOZ7Sht5LguA-1; Thu, 04 Jan 2024 16:58:32 -0500 X-MC-Unique: yJCbwwYVMPWOZ7Sht5LguA-1 Received: by mail-ej1-f71.google.com with SMTP id a640c23a62f3a-a28fd256e44so1097666b.1 for ; Thu, 04 Jan 2024 13:58:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405510; x=1705010310; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NQLcT9KTPjg2f3Hw+CbWFYTnjCtLhdth+T+FsYyXx/o=; b=P4ycmSc7sohN7c1NmUV1EGDtu4ifV+szdYXArUYtD2MMa+rCdDo9zZfbbCs4c2+qvl WUrrkjhirKYUJ7hstEty73YV9tvt7beXoW6A2iBMwKOTXkBk89JZPFUZNmdc8ShiU/3i gqBw5rvSpDP6mVBqM35xIi6Xe65subOBEvHM/o/sSOFoS5Nje+9804YRYHIRYSY3cquI OSkdrNJXvN/J+N4PoxlDyXPpcxL8PR+s4kdFQbnpxysuZc3TDuxkFxMRrCKehBI8qC88 7js55TcKONyLuTaXzdctYFjuf/JA5q3AfcGl/Vyp4eMrfR0NqvFGlvGslqib41YILBjd 2GIA== X-Gm-Message-State: AOJu0YwEpNqRlh72SGdcsyWm8QzTJyBasvdjJU7874w5ZVQnAmsHnQ0O 4SCuGMMZXOrFy0Ns2TOANKt5kNUlAgD2IE9Wr6tnC0GBricnGxWmcFkep/MHggd3zIw4vUPIQO1 XFMpU+27Mq1l2e7OcZehM8UyUhEdPuXQM5N3CpVntL3f09IxJcT1LjkcAJw5LuKfQ1cJFg/RC09 g7Nmucjk4= X-Received: by 2002:a17:906:8464:b0:a28:dd23:df92 with SMTP id hx4-20020a170906846400b00a28dd23df92mr1092389ejc.71.1704405510439; Thu, 04 Jan 2024 13:58:30 -0800 (PST) X-Google-Smtp-Source: AGHT+IEHUKayH2o6XBFSFah/dP/x96WDuInGbPSokl1PZ+vbBzJeDb6QimuQub3sx3ksShqQ1nW4Gw== X-Received: by 2002:a17:906:8464:b0:a28:dd23:df92 with SMTP id hx4-20020a170906846400b00a28dd23df92mr1092380ejc.71.1704405510196; Thu, 04 Jan 2024 13:58:30 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id kz9-20020a17090777c900b00a28d1d73654sm106025ejc.207.2024.01.04.13.58.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:28 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu, =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= Subject: [PATCH v2 6/8] vga: reindent memory access code Date: Thu, 4 Jan 2024 22:58:09 +0100 Message-ID: <20240104215813.156153-7-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The next patch will reuse latched memory access in text modes. Start with a patch that moves the latched access code out of the "if". Best reviewed with "git diff -b". Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 211 ++++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 101 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 2c7b8e54805..1ec1b5aa29f 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -813,37 +813,41 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) } if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { - /* chain 4 mode : simplest access */ + /* chain 4 mode : simplest access (but it should use the same + * algorithms as below; see e.g. vga_mem_writeb's plane mask check). + */ assert(addr < s->vram_size); - ret = s->vram_ptr[addr]; - } else if (s->gr[VGA_GFX_MODE] & 0x10) { + return s->vram_ptr[addr]; + } + + if (s->gr[VGA_GFX_MODE] & 0x10) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); addr = ((addr & ~1) << 1) | plane; if (addr >= s->vram_size) { return 0xff; } - ret = s->vram_ptr[addr]; - } else { - /* standard VGA latched access */ - if (addr * sizeof(uint32_t) >= s->vram_size) { - return 0xff; - } - s->latch = ((uint32_t *)s->vram_ptr)[addr]; - - if (!(s->gr[VGA_GFX_MODE] & 0x08)) { - /* read mode 0 */ - plane = s->gr[VGA_GFX_PLANE_READ]; - ret = GET_PLANE(s->latch, plane); - } else { - /* read mode 1 */ - ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) & - mask16[s->gr[VGA_GFX_COMPARE_MASK]]; - ret |= ret >> 16; - ret |= ret >> 8; - ret = (~ret) & 0xff; - } + return s->vram_ptr[addr]; } + + /* standard VGA latched access */ + plane = s->gr[VGA_GFX_PLANE_READ]; + if (addr * sizeof(uint32_t) >= s->vram_size) { + return 0xff; + } + s->latch = ((uint32_t *)s->vram_ptr)[addr]; + if (!(s->gr[VGA_GFX_MODE] & 0x08)) { + /* read mode 0 */ + ret = GET_PLANE(s->latch, plane); + } else { + /* read mode 1 */ + ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) & + mask16[s->gr[VGA_GFX_COMPARE_MASK]]; + ret |= ret >> 16; + ret |= ret >> 8; + ret = (~ret) & 0xff; + } + return ret; } @@ -893,7 +897,10 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) s->plane_updated |= mask; /* only used to detect font change */ memory_region_set_dirty(&s->vram, addr, 1); } - } else if (s->gr[VGA_GFX_MODE] & 0x10) { + return; + } + + if (s->gr[VGA_GFX_MODE] & 0x10) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); mask = (1 << plane); @@ -909,84 +916,86 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) s->plane_updated |= mask; /* only used to detect font change */ memory_region_set_dirty(&s->vram, addr, 1); } - } else { - /* standard VGA latched access */ - write_mode = s->gr[VGA_GFX_MODE] & 3; - switch(write_mode) { - default: - case 0: - /* rotate */ - b = s->gr[VGA_GFX_DATA_ROTATE] & 7; - val = ((val >> b) | (val << (8 - b))) & 0xff; - val |= val << 8; - val |= val << 16; - - /* apply set/reset mask */ - set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]]; - val = (val & ~set_mask) | - (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask); - bit_mask = s->gr[VGA_GFX_BIT_MASK]; - break; - case 1: - val = s->latch; - goto do_write; - case 2: - val = mask16[val & 0x0f]; - bit_mask = s->gr[VGA_GFX_BIT_MASK]; - break; - case 3: - /* rotate */ - b = s->gr[VGA_GFX_DATA_ROTATE] & 7; - val = (val >> b) | (val << (8 - b)); - - bit_mask = s->gr[VGA_GFX_BIT_MASK] & val; - val = mask16[s->gr[VGA_GFX_SR_VALUE]]; - break; - } - - /* apply logical operation */ - func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3; - switch(func_select) { - case 0: - default: - /* nothing to do */ - break; - case 1: - /* and */ - val &= s->latch; - break; - case 2: - /* or */ - val |= s->latch; - break; - case 3: - /* xor */ - val ^= s->latch; - break; - } - - /* apply bit mask */ - bit_mask |= bit_mask << 8; - bit_mask |= bit_mask << 16; - val = (val & bit_mask) | (s->latch & ~bit_mask); - - do_write: - /* mask data according to sr[2] */ - mask = sr(s, VGA_SEQ_PLANE_WRITE); - s->plane_updated |= mask; /* only used to detect font change */ - write_mask = mask16[mask]; - if (addr * sizeof(uint32_t) >= s->vram_size) { - return; - } - ((uint32_t *)s->vram_ptr)[addr] = - (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | - (val & write_mask); -#ifdef DEBUG_VGA_MEM - printf("vga: latch: [0x" HWADDR_FMT_plx "] mask=0x%08x val=0x%08x\n", - addr * 4, write_mask, val); -#endif - memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t)); + return; } + + mask = sr(s, VGA_SEQ_PLANE_WRITE); + + /* standard VGA latched access */ + write_mode = s->gr[VGA_GFX_MODE] & 3; + switch(write_mode) { + default: + case 0: + /* rotate */ + b = s->gr[VGA_GFX_DATA_ROTATE] & 7; + val = ((val >> b) | (val << (8 - b))) & 0xff; + val |= val << 8; + val |= val << 16; + + /* apply set/reset mask */ + set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]]; + val = (val & ~set_mask) | + (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask); + bit_mask = s->gr[VGA_GFX_BIT_MASK]; + break; + case 1: + val = s->latch; + goto do_write; + case 2: + val = mask16[val & 0x0f]; + bit_mask = s->gr[VGA_GFX_BIT_MASK]; + break; + case 3: + /* rotate */ + b = s->gr[VGA_GFX_DATA_ROTATE] & 7; + val = (val >> b) | (val << (8 - b)); + + bit_mask = s->gr[VGA_GFX_BIT_MASK] & val; + val = mask16[s->gr[VGA_GFX_SR_VALUE]]; + break; + } + + /* apply logical operation */ + func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3; + switch(func_select) { + case 0: + default: + /* nothing to do */ + break; + case 1: + /* and */ + val &= s->latch; + break; + case 2: + /* or */ + val |= s->latch; + break; + case 3: + /* xor */ + val ^= s->latch; + break; + } + + /* apply bit mask */ + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + val = (val & bit_mask) | (s->latch & ~bit_mask); + +do_write: + /* mask data according to sr[2] */ + s->plane_updated |= mask; /* only used to detect font change */ + write_mask = mask16[mask]; + if (addr * sizeof(uint32_t) >= s->vram_size) { + return; + } + ((uint32_t *)s->vram_ptr)[addr] = + (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | + (val & write_mask); +#ifdef DEBUG_VGA_MEM + printf("vga: latch: [0x" HWADDR_FMT_plx "] mask=0x%08x val=0x%08x\n", + addr * 4, write_mask, val); +#endif + memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t)); } typedef void *vga_draw_line_func(VGACommonState *s1, uint8_t *d, From patchwork Thu Jan 4 21:58:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882648 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bFJQ8MVF; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gTg6Rfbz23dn for ; Fri, 5 Jan 2024 08:59:02 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVjb-0001dR-Un; Thu, 04 Jan 2024 16:58:39 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVja-0001d7-Tj for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:38 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjZ-0003PU-76 for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405516; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sFQ9SU6iL9SY2TRWlknBYTXuZ0/vQTXHRHb+w2gtcmI=; b=bFJQ8MVFzyAu90hXhfhQA6OSUlXpA/7oiaaFsV1UC0xvqoNWzqNDYsh4NUQzy4YoJ0P94S DRpy2cDSCHi2xTXEgg6pSPxniXF+7TJ102ZtTg32s5bsbC/11nVaPe+H7nFgegCKt22b6I k/YYtxlv3QFhJVVWsM98he6KBClT81w= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-563-de15viUiNtW1GD-ovrmAPA-1; Thu, 04 Jan 2024 16:58:35 -0500 X-MC-Unique: de15viUiNtW1GD-ovrmAPA-1 Received: by mail-ej1-f72.google.com with SMTP id a640c23a62f3a-a2801b68a97so41489766b.0 for ; Thu, 04 Jan 2024 13:58:34 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405513; x=1705010313; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sFQ9SU6iL9SY2TRWlknBYTXuZ0/vQTXHRHb+w2gtcmI=; b=vve/GKRNv33zZnsTpZLtvcOu0eYEt+y56VFJBiT2jLvyMUYkERlr2UK3eynttIBqUA 0FL+oIDqnv2dDvMmbaTVs7t3RcAQ6Cq5UlDPB4ZJQ1ogS29LKAYFoa0vbie45qyRtrC8 6TwtX1MRWg6Mnd6whvuMvKwYtU2RF/N846JvJ1Zyl8O3rEBNYMe8Ohqv5jG0dH4Qx72p OHT8dPwf9Q0a5ffaYClv3cegMFzGsw5/V0URTzw9BNUcaniGFH4wEUCBz+lN8C3GYCZC FSEXqCg4Y/lA3MzqCk+51PDJ6dNuDumPmoZPDcZNEGTAu0yENKttsBMnnSggpgHwuTyr Yhhw== X-Gm-Message-State: AOJu0YytGt+GWUKD12vYlRd1DAK9PGvBVX3x6dcJo6jFvu6AJ8LmYv49 nbV3HfkI+REmIbMMqyLgkp6KKCIcHkguxBhULEJsQpYGaYLuycYK9hE+eqTG1Rp6SAjNOnWX3Bb 9JtAYFdE2rzzPmqrO5iFa6Vi1LJHSUIkk6B+H+W2n9XsXkEEBEu942zooDhE+Z3GpQMXvpD1Fe7 1fArOE1vY= X-Received: by 2002:a17:906:a08b:b0:a23:46df:f449 with SMTP id q11-20020a170906a08b00b00a2346dff449mr567498ejy.55.1704405513212; Thu, 04 Jan 2024 13:58:33 -0800 (PST) X-Google-Smtp-Source: AGHT+IFcYD2LyTu1fUXw1uqYQQE/+gHiAi/QX5JPblHU/cGYlnT0OeiknM1IbCupqd7wQN3cpyDRqQ== X-Received: by 2002:a17:906:a08b:b0:a23:46df:f449 with SMTP id q11-20020a170906a08b00b00a2346dff449mr567491ejy.55.1704405512890; Thu, 04 Jan 2024 13:58:32 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id t20-20020a170906609400b00a28badcf367sm113645ejj.54.2024.01.04.13.58.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:32 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu Subject: [PATCH v2 7/8] vga: use latches in odd/even mode too Date: Thu, 4 Jan 2024 22:58:10 +0100 Message-ID: <20240104215813.156153-8-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.129.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Jazz Jackrabbit uses odd/even mode with 256-color graphics. This is probably so that it can do very fast blitting with a decent resolution (two pixels, compared to four pixels for "regular" mode X). Accesses still use all planes (reads go to the latches and the game uses read mode 1 so that the CPU always gets 0xFF; writes use the plane mask register because the game sets bit 2 of the sequencer's memory mode register). For this to work, QEMU needs to use the code for latched memory accesses in odd/even mode. The only difference between odd/even mode and "regular" planar mode is how the plane is computed in read mode 0, and how the planes are masked if the aforementioned bit 2 is reset. It is almost enough to fix the game. You also need to honor byte/word mode selection, which is done in the next patch. Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 1ec1b5aa29f..2be46cb1255 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -823,15 +823,12 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) if (s->gr[VGA_GFX_MODE] & 0x10) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); - addr = ((addr & ~1) << 1) | plane; - if (addr >= s->vram_size) { - return 0xff; - } - return s->vram_ptr[addr]; + addr >>= 1; + } else { + /* standard VGA latched access */ + plane = s->gr[VGA_GFX_PLANE_READ]; } - /* standard VGA latched access */ - plane = s->gr[VGA_GFX_PLANE_READ]; if (addr * sizeof(uint32_t) >= s->vram_size) { return 0xff; } @@ -884,11 +881,12 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) break; } + mask = sr(s, VGA_SEQ_PLANE_WRITE); if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { /* chain 4 mode : simplest access */ plane = addr & 3; - mask = (1 << plane); - if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) { + mask &= (1 << plane); + if (mask) { assert(addr < s->vram_size); s->vram_ptr[addr] = val; #ifdef DEBUG_VGA_MEM @@ -900,26 +898,14 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) return; } - if (s->gr[VGA_GFX_MODE] & 0x10) { - /* odd/even mode (aka text mode mapping) */ - plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); - mask = (1 << plane); - if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) { - addr = ((addr & ~1) << 1) | plane; - if (addr >= s->vram_size) { - return; - } - s->vram_ptr[addr] = val; -#ifdef DEBUG_VGA_MEM - printf("vga: odd/even: [0x" HWADDR_FMT_plx "]\n", addr); -#endif - s->plane_updated |= mask; /* only used to detect font change */ - memory_region_set_dirty(&s->vram, addr, 1); - } - return; + if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) { + mask &= (addr & 1) ? 0x0a : 0x05; } - mask = sr(s, VGA_SEQ_PLANE_WRITE); + if (s->gr[VGA_GFX_MODE] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + addr >>= 1; + } /* standard VGA latched access */ write_mode = s->gr[VGA_GFX_MODE] & 3; From patchwork Thu Jan 4 21:58:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 1882654 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LdSGfOgm; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5gVm43kwz1ydd for ; Fri, 5 Jan 2024 09:00:00 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rLVje-0001fj-JD; Thu, 04 Jan 2024 16:58:42 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVjc-0001e4-Mo for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:40 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rLVja-0003Pg-QD for qemu-devel@nongnu.org; Thu, 04 Jan 2024 16:58:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704405518; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9hbUNUhEukd/7xR3Y6JDbtqolI3MMwA2JCCquzten8Y=; b=LdSGfOgmPNSQkLTO+punoHqyEw87HfJej/Ov2my5qhPfSdx69i+vQ3ikNMZnvncG1xtbt6 CDuR1r164P38cJljA8K9+EnYj7jO8FtbPLr8QWHxDSKyBy+y/FMO39/zaUet+v2aqVYiZF bRZyxLWyyth31MG0uQPaBY3NQlgLY0g= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-298-1Fl6TKUjNciQSZ4HLR9Hrw-1; Thu, 04 Jan 2024 16:58:37 -0500 X-MC-Unique: 1Fl6TKUjNciQSZ4HLR9Hrw-1 Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-a28b9b87013so1683366b.0 for ; Thu, 04 Jan 2024 13:58:36 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704405515; x=1705010315; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9hbUNUhEukd/7xR3Y6JDbtqolI3MMwA2JCCquzten8Y=; b=GJSXGAAMCXNeWs5zsJKf388qpXc6notjfOaKonONUr5n+sAK3uPAOKL1Niph36UxmR /meAI1XSWMNeFsguNiUEKm/jPrRXeYGrGqcCQ7e+AVlPmkfnmC11+w7jGRR+BOYfvgod SqZyR3UfkGCOt0go1zxLL5uBNWEYNgF3vHTvE+tNHFvwlnG1ROKXkpW65Kk2YuOYEXmO 4jiW020oIE1CFXUhEqJiWVBkDzdym7R6ontB9i/fUrTHjTjus4RGlkfPvLqIiCs3RK6J c34IKXo8D1wsc5x6VuPiPXI01dZrC01bkWxjwFLTPNewk3c8Id2PjbToIAXliLWAzFxG ZgTw== X-Gm-Message-State: AOJu0YxBj/SDs1V5VLezbPPGgHKulT8QvSOPe6Jlef6SFLP3gccJsRtJ JkeNWWChxeDJzHrRv9Tu0lvNUgFSJ8Q6ioTbSoE1BGa1MndgQLRTDZDmeUPNyrCE1MILBDRLoa4 cMzovGKL/pbwBPTuLfwIMd2SW3RfJmXGlfSympZUdNXtwHLQsBhS7SAoNnkrdA83tXVcUWxUI6X mghxGEcBs= X-Received: by 2002:a17:906:d154:b0:a28:6621:5801 with SMTP id br20-20020a170906d15400b00a2866215801mr1210930ejb.19.1704405515213; Thu, 04 Jan 2024 13:58:35 -0800 (PST) X-Google-Smtp-Source: AGHT+IGFvK0BbBJ3aBgMSrj1eG8KjziM/JaPj0nBwZwBWPmwTdoUh1O82B6x8geOBxSkoEaGlc7zvg== X-Received: by 2002:a17:906:d154:b0:a28:6621:5801 with SMTP id br20-20020a170906d15400b00a2866215801mr1210919ejb.19.1704405514836; Thu, 04 Jan 2024 13:58:34 -0800 (PST) Received: from [192.168.10.118] ([2001:b07:6468:f312:1c09:f536:3de6:228c]) by smtp.gmail.com with ESMTPSA id b6-20020a170906708600b00a268002274csm113512ejk.52.2024.01.04.13.58.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Jan 2024 13:58:34 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Cc: kraxel@redhat.com, balaton@eik.bme.hu Subject: [PATCH v2 8/8] vga: sort-of implement word and double-word access modes Date: Thu, 4 Jan 2024 22:58:11 +0100 Message-ID: <20240104215813.156153-9-pbonzini@redhat.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240104215813.156153-1-pbonzini@redhat.com> References: <20240104215813.156153-1-pbonzini@redhat.com> MIME-Version: 1.0 Received-SPF: pass client-ip=170.10.133.124; envelope-from=pbonzini@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -47 X-Spam_score: -4.8 X-Spam_bar: ---- X-Spam_report: (-4.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-2.691, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Jazz Jackrabbit has a very unusual VGA setup, where it uses odd/even mode with 256-color graphics. Probably, it wants to use fast VRAM-to-VRAM copies without having to store 4 copies of the sprites as needed in mode X, one for each mod-4 alignment; odd/even mode simplifies the code a lot if it's okay to place on a 160-pixels horizontal grid. At the same time, because it wants to use double buffering (a la "mode X") it uses byte mode, not word mode as is the case in text modes. In order to implement the combination of odd/even mode (plane number comes from bit 0 of the address) and byte mode (use all bytes of VRAM, whereas word mode only uses bytes 0, 2, 4,... on each of the four planes), we need to separate the effect on the plane number from the effect on the address. Implementing the modes properly is a mess in QEMU, because it would change the layout of VRAM and break migration. As an approximation, shift right when the CPU accesses memory instead of shifting left when the CRT controller reads it. A hack is needed in order to write font data properly (see comment in the code), but it works well enough for the game. Because doubleword and chain4 modes are now independent, chain4 does not assert anymore that the address is in range. Instead it just returns all ones and discards writes, like other modes. Signed-off-by: Paolo Bonzini --- hw/display/vga_regs.h | 4 ++ hw/display/vga.c | 89 +++++++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 24 deletions(-) diff --git a/hw/display/vga_regs.h b/hw/display/vga_regs.h index 7fdba34b9b1..40e673f164d 100644 --- a/hw/display/vga_regs.h +++ b/hw/display/vga_regs.h @@ -100,7 +100,9 @@ /* VGA CRT controller bit masks */ #define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */ +#define VGA_CR14_DW 0x40 #define VGA_CR17_H_V_SIGNALS_ENABLED 0x80 +#define VGA_CR17_WORD_BYTE 0x40 /* VGA attribute controller register indices */ #define VGA_ATC_PALETTE0 0x00 @@ -154,6 +156,8 @@ #define VGA_GFX_BIT_MASK 0x08 /* VGA graphics controller bit masks */ +#define VGA_GR05_HOST_ODD_EVEN 0x10 #define VGA_GR06_GRAPHICS_MODE 0x01 +#define VGA_GR06_CHAIN_ODD_EVEN 0x02 #endif /* HW_VGA_REGS_H */ diff --git a/hw/display/vga.c b/hw/display/vga.c index 2be46cb1255..1fa8bed5c0f 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -813,25 +813,40 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) } if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { - /* chain 4 mode : simplest access (but it should use the same - * algorithms as below; see e.g. vga_mem_writeb's plane mask check). - */ - assert(addr < s->vram_size); - return s->vram_ptr[addr]; - } - - if (s->gr[VGA_GFX_MODE] & 0x10) { + /* chain4 mode */ + plane = addr & 3; + addr &= ~3; + } else if (s->gr[VGA_GFX_MODE] & VGA_GR05_HOST_ODD_EVEN) { /* odd/even mode (aka text mode mapping) */ plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1); - addr >>= 1; } else { /* standard VGA latched access */ plane = s->gr[VGA_GFX_PLANE_READ]; } + if (s->gr[VGA_GFX_MISC] & VGA_GR06_CHAIN_ODD_EVEN) { + addr &= ~1; + } + + /* Doubleword/word mode. See comment in vga_mem_writeb */ + if (s->cr[VGA_CRTC_UNDERLINE] & VGA_CR14_DW) { + addr >>= 2; + } else if ((s->gr[VGA_GFX_MODE] & VGA_GR05_HOST_ODD_EVEN) && + (s->cr[VGA_CRTC_MODE] & VGA_CR17_WORD_BYTE) == 0) { + addr >>= 1; + } + if (addr * sizeof(uint32_t) >= s->vram_size) { return 0xff; } + + if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) { + /* chain 4 mode: simplified access (but it should use the same + * algorithms as below, see e.g. vga_mem_writeb's plane mask check). + */ + return s->vram_ptr[(addr << 2) | plane]; + } + s->latch = ((uint32_t *)s->vram_ptr)[addr]; if (!(s->gr[VGA_GFX_MODE] & 0x08)) { /* read mode 0 */ @@ -851,8 +866,9 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr) /* called for accesses between 0xa0000 and 0xc0000 */ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) { - int memory_map_mode, plane, write_mode, b, func_select, mask; + int memory_map_mode, write_mode, b, func_select, mask; uint32_t write_mask, bit_mask, set_mask; + int plane = 0; #ifdef DEBUG_VGA_MEM printf("vga: [0x" HWADDR_FMT_plx "] = 0x%02x\n", addr, val); @@ -886,9 +902,46 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) /* chain 4 mode : simplest access */ plane = addr & 3; mask &= (1 << plane); + addr &= ~3; + } else { + if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) { + mask &= (addr & 1) ? 0x0a : 0x05; + } + if (s->gr[VGA_GFX_MISC] & VGA_GR06_CHAIN_ODD_EVEN) { + addr &= ~1; + } + } + + /* Doubleword/word mode. These should be honored when displaying, + * not when reading/writing to memory! For example, chain4 modes + * use double-word mode and, on real hardware, would fetch bytes + * 0,1,2,3, 16,17,18,19, 32,33,34,35, etc. Text modes use word + * mode and, on real hardware, would fetch bytes 0,1, 8,9, etc. + * + * QEMU instead shifted addresses on memory accesses because it + * allows more optimizations (e.g. chain4_alias) and simplifies + * the draw_line handlers. Unfortunately, there is one case where + * the difference shows. When fetching font data, accesses are + * always in consecutive bytes, even if the text/attribute pairs + * are done in word mode. Hence, doing a right shift when operating + * on font data is wrong. So check the odd/even mode bits together with + * word mode bit. The odd/even read bit is 0 when reading font data, + * and the odd/even write bit is 1 when writing it. + */ + if (s->cr[VGA_CRTC_UNDERLINE] & VGA_CR14_DW) { + addr >>= 2; + } else if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0 && + (s->cr[VGA_CRTC_MODE] & VGA_CR17_WORD_BYTE) == 0) { + addr >>= 1; + } + + if (addr * sizeof(uint32_t) >= s->vram_size) { + return; + } + + if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) { if (mask) { - assert(addr < s->vram_size); - s->vram_ptr[addr] = val; + s->vram_ptr[(addr << 2) | plane] = val; #ifdef DEBUG_VGA_MEM printf("vga: chain4: [0x" HWADDR_FMT_plx "]\n", addr); #endif @@ -898,15 +951,6 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) return; } - if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) { - mask &= (addr & 1) ? 0x0a : 0x05; - } - - if (s->gr[VGA_GFX_MODE] & 0x10) { - /* odd/even mode (aka text mode mapping) */ - addr >>= 1; - } - /* standard VGA latched access */ write_mode = s->gr[VGA_GFX_MODE] & 3; switch(write_mode) { @@ -971,9 +1015,6 @@ do_write: /* mask data according to sr[2] */ s->plane_updated |= mask; /* only used to detect font change */ write_mask = mask16[mask]; - if (addr * sizeof(uint32_t) >= s->vram_size) { - return; - } ((uint32_t *)s->vram_ptr)[addr] = (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | (val & write_mask);