uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)

{

    int memory_map_mode, plane;

    uint32_t ret;



    /* convert to VGA memory offset */

    memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;

    addr &= 0x1ffff;

    switch(memory_map_mode) {

    case 0:

        break;

    case 1:

        if (addr >= 0x10000)

            return 0xff;

        addr += s->bank_offset;

        break;

    case 2:

        addr -= 0x10000;

        if (addr >= 0x8000)

            return 0xff;

        break;

    default:

    case 3:

        addr -= 0x18000;

        if (addr >= 0x8000)

            return 0xff;

        break;

    }



    if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {

        /* chain 4 mode : simplest access */

        ret = s->vram_ptr[addr];

    } else if (s->gr[VGA_GFX_MODE] & 0x10) {

        /* odd/even mode (aka text mode mapping) */

        plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);

        ret = s->vram_ptr[((addr & ~1) << 1) | plane];

    } else {

        /* standard VGA latched access */

        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 ret;

}
