from __future__ import annotations

from enum import IntEnum


class MemoryAccess(IntEnum):
    NON_SEQUENTIAL = 0
    SEQUENTIAL = 1


class MemoryRegion(IntEnum):
    BIOS_START = 0x00000000
    BIOS_END = 0x00003FFF
    BIOS_REGION = BIOS_START >> 24
    BIOS_MASK = BIOS_END - BIOS_START
    BIOS_SIZE = BIOS_END - BIOS_START + 1

    EWRAM_START = 0x02000000
    EWRAM_END = 0x0203FFFF
    EWRAM_REGION = EWRAM_START >> 24
    EWRAM_MASK = EWRAM_END - EWRAM_START
    EWRAM_SIZE = EWRAM_END - EWRAM_START + 1

    IWRAM_START = 0x03000000
    IWRAM_END = 0x03007FFF
    IWRAM_REGION = IWRAM_START >> 24
    IWRAM_MASK = IWRAM_END - IWRAM_START
    IWRAM_SIZE = IWRAM_END - IWRAM_START + 1

    IO_START = 0x04000000
    IO_END = 0x040003FF
    IO_REGION = IO_START >> 24
    IO_MASK = IO_END - IO_START
    IO_SIZE = IO_END - IO_START + 1

    PALRAM_START = 0x05000000
    PALRAM_END = 0x050003FF
    PALRAM_REGION = PALRAM_START >> 24
    PALRAM_MASK = PALRAM_END - PALRAM_START
    PALRAM_SIZE = PALRAM_END - PALRAM_START + 1

    VRAM_START = 0x06000000
    VRAM_END = 0x06017FFF
    VRAM_REGION = VRAM_START >> 24
    VRAM_MASK_1 = 0x00017FFF
    VRAM_MASK_2 = 0x0001FFFF
    VRAM_SIZE = VRAM_END - VRAM_START + 1

    OAM_START = 0x07000000
    OAM_END = 0x070003FF
    OAM_REGION = OAM_START >> 24
    OAM_MASK = OAM_END - OAM_START
    OAM_SIZE = OAM_END - OAM_START + 1

    GAMEPAK_0_START = 0x08000000
    GAMEPAK_0_END = 0x09FFFFFF
    GAMEPAK_0_REGION_1 = GAMEPAK_0_START >> 24
    GAMEPAK_0_REGION_2 = GAMEPAK_0_END >> 24

    GAMEPAK_1_START = 0x0A000000
    GAMEPAK_1_END = 0x0BFFFFFF
    GAMEPAK_1_REGION_1 = GAMEPAK_1_START >> 24
    GAMEPAK_1_REGION_2 = GAMEPAK_1_END >> 24

    GAMEPAK_2_START = 0x0C000000
    GAMEPAK_2_END = 0x0DFFFFFF
    GAMEPAK_2_REGION_1 = GAMEPAK_2_START >> 24
    GAMEPAK_2_REGION_2 = GAMEPAK_2_END >> 24

    GAMEPAK_MASK = GAMEPAK_0_END - GAMEPAK_0_START
    GAMEPAK_SIZE = GAMEPAK_0_END - GAMEPAK_0_START + 1
    GAMEPAK_REGION_START = GAMEPAK_0_START >> 24
    GAMEPAK_REGION_END = GAMEPAK_2_END >> 24

    SRAM_START = 0x0E000000
    SRAM_END = 0x0E007FFF
    SRAM_REGION = SRAM_START >> 24
    SRAM_MASK = SRAM_END - SRAM_START
    SRAM_SIZE = SRAM_END - SRAM_START + 1


class IOAddress(IntEnum):
    # Display Control Registers
    REG_DISPCNT = 0x04000000
    REG_DISPSTAT = 0x04000004
    REG_VCOUNT = 0x04000006

    # Background Control Registers
    REG_BG0CNT = 0x04000008
    REG_BG1CNT = 0x0400000A
    REG_BG2CNT = 0x0400000C
    REG_BG3CNT = 0x0400000E

    # Background Offset Registers
    REG_BG0HOFS = 0x04000010
    REG_BG0VOFS = 0x04000012
    REG_BG1HOFS = 0x04000014
    REG_BG1VOFS = 0x04000016
    REG_BG2HOFS = 0x04000018
    REG_BG2VOFS = 0x0400001A
    REG_BG3HOFS = 0x0400001C
    REG_BG3VOFS = 0x0400001E

    # Window Registers
    REG_WIN0H = 0x04000040
    REG_WIN1H = 0x04000042
    REG_WIN0V = 0x04000044
    REG_WIN1V = 0x04000046
    REG_WININ = 0x04000048
    REG_WINOUT = 0x0400004A

    # Special Effects Registers
    REG_BLDCNT = 0x04000050
    REG_BLDALPHA = 0x04000052
    REG_BLDY = 0x04000054

    # Sound Control Registers
    REG_SOUNDBIAS = 0x04000088
    REG_FIFO_A = 0x040000A0
    REG_FIFO_B = 0x040000A4

    # DMA Source/Destination Registers
    REG_DMA0SAD_L = 0x040000B0
    REG_DMA0SAD_H = 0x040000B2
    REG_DMA0DAD_L = 0x040000B4
    REG_DMA0DAD_H = 0x040000B6
    REG_DMA1SAD_L = 0x040000BC
    REG_DMA1SAD_H = 0x040000BE
    REG_DMA1DAD_L = 0x040000C0
    REG_DMA1DAD_H = 0x040000C2
    REG_DMA2SAD_L = 0x040000C8
    REG_DMA2SAD_H = 0x040000CA
    REG_DMA2DAD_L = 0x040000CC
    REG_DMA2DAD_H = 0x040000CE
    REG_DMA3SAD_L = 0x040000D4
    REG_DMA3SAD_H = 0x040000D6
    REG_DMA3DAD_L = 0x040000D8
    REG_DMA3DAD_H = 0x040000DA

    # DMA Control Registers
    REG_DMA0CNT_L = 0x040000B8
    REG_DMA0CNT_H = 0x040000BA
    REG_DMA1CNT_L = 0x040000C4
    REG_DMA1CNT_H = 0x040000C6
    REG_DMA2CNT_L = 0x040000D0
    REG_DMA2CNT_H = 0x040000D2
    REG_DMA3CNT_L = 0x040000DC
    REG_DMA3CNT_H = 0x040000DE

    # Timer Registers
    REG_TM0CNT_L = 0x04000100
    REG_TM0CNT_H = 0x04000102
    REG_TM1CNT_L = 0x04000104
    REG_TM1CNT_H = 0x04000106
    REG_TM2CNT_L = 0x04000108
    REG_TM2CNT_H = 0x0400010A
    REG_TM3CNT_L = 0x0400010C
    REG_TM3CNT_H = 0x0400010E

    # Keypad Registers
    REG_KEYINPUT = 0x04000130
    REG_KEYCNT = 0x04000132

    # Interrupt Registers
    REG_IE = 0x04000200
    REG_IF = 0x04000202
    REG_WAITCNT = 0x04000204
    REG_IME = 0x04000208
    REG_HALTCNT = 0x04000300


class DMAAddressAdjustment(IntEnum):
    INCREMENT = 0
    DECREMENT = 1
    LEAVE_UNCHANGED = 2
    INCREMENT_RELOAD = 3


class DMATransferSize(IntEnum):
    HALFWORD = 0
    WORD = 1


class DMAStartTiming(IntEnum):
    IMMEDIATELY = 0
    VBLANK = 1
    HBLANK = 2
    SPECIAL = 3
