public int command(int cmd) {
        if (cmd_pending) // If this is the second word of a command
        {
            int A14_15 = (cmd & 0x0003) << 14;
            rw_addr = (rw_addr & 0xffff3fff) | A14_15;

            // Copy rw_addr to mirror register
            rw_addr = (rw_addr & 0x0000ffff) | (rw_addr << 16);

            // CD{4,3,2}
            int CD4_2 = (cmd & 0x0070);
            rw_mode |= CD4_2;

            // if CD5 == 1
            rw_dma = ((cmd & 0x80) == 0x80) ? 1 : 0;

            cmd_pending = false;
        } else // This is the first word of a command
        {
            // masking away command bits CD1 CD0
            int A00_13 = cmd & 0x3fff;
            rw_addr = (rw_addr & 0xffffc000) | A00_13;

            // Copy rw_addr to mirror register
            rw_addr = (rw_addr & 0x0000ffff) | (rw_addr << 16);

            // CD {1,0}
            int CD0_1 = (cmd & 0xc000) >> 12;
            rw_mode = CD0_1;
            rw_dma = 0;

            // we will expect the second half of the command next
            cmd_pending = true;

            return 0;
        }

        // if it's a dma request do it straight away
        if (rw_dma != 0) {
            int mode = (reg[0x17] >> 6) & 3;
            int s = 0, d = 0, i = 0, len = 0;
            s = dma_addr();
            d = rw_addr;
            len = dma_length();
            switch (mode) {
                case 0:
                case 1:
                    for (i = 0; i < len; i++) {
                        int val;
                        val = dma_mem_read(s++);
                        val <<= 8;
                        val |= dma_mem_read(s++);
                        putWord(val);
                    }
                    break;
                case 2:
                    // Done later on (VRAM fill I believe)
                    break;
                case 3:
                    for (i = 0; i < len; i++) {
                        int val;
                        val = vram[(s++) & 0xffff];
                        val <<= 8;
                        val |= vram[(s++) & 0xffff];
                        putWord(val);
                    }
                    break;
            }
        }

        return 0;
    }