// Path: src/main/java/eu/rekawek/coffeegb/AddressSpace.java
// public interface AddressSpace {
// 
//     boolean accepts(int address);
// 
//     void setByte(int address, int value);
// 
//     int getByte(int address);
// 
// }
// 
// Path: src/main/java/eu/rekawek/coffeegb/memory/cart/battery/Battery.java
// public interface Battery {
// 
//     void loadRam(int[] ram);
// 
//     void saveRam(int[] ram);
// 
//     void loadRamWithClock(int[] ram, long[] clockData);
// 
//     void saveRamWithClock(int[] ram, long[] clockData);
// 
//     Battery NULL_BATTERY = new Battery() {
//         @Override
//         public void loadRam(int[] ram) {
//         }
// 
//         @Override
//         public void saveRam(int[] ram) {
//         }
// 
//         @Override
//         public void loadRamWithClock(int[] ram, long[] clockData) {
//         }
// 
//         @Override
//         public void saveRamWithClock(int[] ram, long[] clockData) {
//         }
//     };
// }
// 
// Path: src/main/java/eu/rekawek/coffeegb/memory/cart/CartridgeType.java
// public enum CartridgeType {
// 
//     ROM(0x00),
//     ROM_MBC1(0x01),
//     ROM_MBC1_RAM(0x02),
//     ROM_MBC1_RAM_BATTERY(0x03),
//     ROM_MBC2(0x05),
//     ROM_MBC2_BATTERY(0x06),
//     ROM_RAM(0x08),
//     ROM_RAM_BATTERY(0x09),
//     ROM_MMM01(0x0b),
//     ROM_MMM01_SRAM(0x0c),
//     ROM_MMM01_SRAM_BATTERY(0x0d),
//     ROM_MBC3_TIMER_BATTERY(0x0f),
//     ROM_MBC3_TIMER_RAM_BATTERY(0x10),
//     ROM_MBC3(0x11),
//     ROM_MBC3_RAM(0x12),
//     ROM_MBC3_RAM_BATTERY(0x13),
//     ROM_MBC5(0x19),
//     ROM_MBC5_RAM(0x1a),
//     ROM_MBC5_RAM_BATTERY(0x01b),
//     ROM_MBC5_RUMBLE(0x1c),
//     ROM_MBC5_RUMBLE_SRAM(0x1d),
//     ROM_MBC5_RUMBLE_SRAM_BATTERY(0x1e);
// 
//     private final int id;
// 
//     CartridgeType(int id) {
//         this.id = id;
//     }
// 
//     public boolean isMbc1() {
//         return nameContainsSegment("MBC1");
//     }
// 
//     public boolean isMbc2() {
//         return nameContainsSegment("MBC2");
//     }
// 
//     public boolean isMbc3() {
//         return nameContainsSegment("MBC3");
//     }
// 
//     public boolean isMbc5() {
//         return nameContainsSegment("MBC5");
//     }
// 
//     public boolean isMmm01() {
//         return nameContainsSegment("MMM01");
//     }
// 
//     public boolean isRam() {
//         return nameContainsSegment("RAM");
//     }
// 
//     public boolean isSram() {
//         return nameContainsSegment("SRAM");
//     }
// 
//     public boolean isTimer() {
//         return nameContainsSegment("TIMER");
//     }
// 
//     public boolean isBattery() {
//         return nameContainsSegment("BATTERY");
//     }
// 
//     public boolean isRumble() {
//         return nameContainsSegment("RUMBLE");
//     }
// 
//     private boolean nameContainsSegment(String segment) {
//         Pattern p = Pattern.compile("(^|_)" + Pattern.quote(segment) + "($|_)");
//         return p.matcher(name()).find();
//     }
// 
//     public static CartridgeType getById(int id) {
//         for (CartridgeType t : values()) {
//             if (t.id == id) {
//                 return t;
//             }
//         }
//         throw new IllegalArgumentException("Unsupported cartridge type: " + Integer.toHexString(id));
//     }
// }


import eu.rekawek.coffeegb.AddressSpace;
import eu.rekawek.coffeegb.memory.cart.battery.Battery;
import eu.rekawek.coffeegb.memory.cart.CartridgeType;
    public boolean accepts(int address) {
        return (address >= 0x0000 && address < 0x8000) ||
               (address >= 0xa000 && address < 0xc000);
    }

    @Override
    public void setByte(int address, int value) {
        if (address >= 0x0000 && address < 0x2000) {
            if ((address & 0x0100) == 0) {
                ramWriteEnabled = (value & 0b1010) != 0;
                if (!ramWriteEnabled) {
                    battery.saveRam(ram);
                }
            }
        } else if (address >= 0x2000 && address < 0x4000) {
            if ((address & 0x0100) != 0) {
                selectedRomBank = value & 0b00001111;
            }
        } else if (address >= 0xa000 && address < 0xc000 && ramWriteEnabled) {
            int ramAddress = getRamAddress(address);
            if (ramAddress < ram.length) {
                ram[ramAddress] = value & 0x0f;
            }
        }
    }

    @Override
    public int getByte(int address) {
        if (address >= 0x0000 && address < 0x4000) {
            return getRomByte(0, address);
// Path: src/main/java/eu/rekawek/coffeegb/AddressSpace.java
// public interface AddressSpace {
// 
//     boolean accepts(int address);
// 
//     void setByte(int address, int value);
// 
//     int getByte(int address);
// 
// }
// 
// Path: src/main/java/eu/rekawek/coffeegb/memory/cart/battery/Battery.java
// public interface Battery {
// 
//     void loadRam(int[] ram);
// 
//     void saveRam(int[] ram);
// 
//     void loadRamWithClock(int[] ram, long[] clockData);
// 
//     void saveRamWithClock(int[] ram, long[] clockData);
// 
//     Battery NULL_BATTERY = new Battery() {
//         @Override
//         public void loadRam(int[] ram) {
//         }
// 
//         @Override
//         public void saveRam(int[] ram) {
//         }
// 
//         @Override
//         public void loadRamWithClock(int[] ram, long[] clockData) {
//         }
// 
//         @Override
//         public void saveRamWithClock(int[] ram, long[] clockData) {
//         }
//     };
// }
// 
// Path: src/main/java/eu/rekawek/coffeegb/memory/cart/CartridgeType.java
// public enum CartridgeType {
// 
//     ROM(0x00),
//     ROM_MBC1(0x01),
//     ROM_MBC1_RAM(0x02),
//     ROM_MBC1_RAM_BATTERY(0x03),
//     ROM_MBC2(0x05),
//     ROM_MBC2_BATTERY(0x06),
//     ROM_RAM(0x08),
//     ROM_RAM_BATTERY(0x09),
//     ROM_MMM01(0x0b),
//     ROM_MMM01_SRAM(0x0c),
//     ROM_MMM01_SRAM_BATTERY(0x0d),
//     ROM_MBC3_TIMER_BATTERY(0x0f),
//     ROM_MBC3_TIMER_RAM_BATTERY(0x10),
//     ROM_MBC3(0x11),
//     ROM_MBC3_RAM(0x12),
//     ROM_MBC3_RAM_BATTERY(0x13),
//     ROM_MBC5(0x19),
//     ROM_MBC5_RAM(0x1a),
//     ROM_MBC5_RAM_BATTERY(0x01b),
//     ROM_MBC5_RUMBLE(0x1c),
//     ROM_MBC5_RUMBLE_SRAM(0x1d),
//     ROM_MBC5_RUMBLE_SRAM_BATTERY(0x1e);
// 
//     private final int id;
// 
//     CartridgeType(int id) {
//         this.id = id;
//     }
// 
//     public boolean isMbc1() {
//         return nameContainsSegment("MBC1");
//     }
// 
//     public boolean isMbc2() {
//         return nameContainsSegment("MBC2");
//     }
// 
//     public boolean isMbc3() {
//         return nameContainsSegment("MBC3");
//     }
// 
//     public boolean isMbc5() {
//         return nameContainsSegment("MBC5");
//     }
// 
//     public boolean isMmm01() {
//         return nameContainsSegment("MMM01");
//     }
// 
//     public boolean isRam() {
//         return nameContainsSegment("RAM");
//     }
// 
//     public boolean isSram() {
//         return nameContainsSegment("SRAM");
//     }
// 
//     public boolean isTimer() {
//         return nameContainsSegment("TIMER");
//     }
// 
//     public boolean isBattery() {
//         return nameContainsSegment("BATTERY");
//     }
// 
//     public boolean isRumble() {
//         return nameContainsSegment("RUMBLE");
//     }
// 
//     private boolean nameContainsSegment(String segment) {
//         Pattern p = Pattern.compile("(^|_)" + Pattern.quote(segment) + "($|_)");
//         return p.matcher(name()).find();
//     }
// 
//     public static CartridgeType getById(int id) {
//         for (CartridgeType t : values()) {
//             if (t.id == id) {
//                 return t;
//             }
//         }
//         throw new IllegalArgumentException("Unsupported cartridge type: " + Integer.toHexString(id));
//     }
// }


// Path: src/main/java/eu/rekawek/coffeegb/memory/cart/type/Mbc2.java
import eu.rekawek.coffeegb.AddressSpace;
import eu.rekawek.coffeegb.memory.cart.battery.Battery;
import eu.rekawek.coffeegb.memory.cart.CartridgeType;

    public boolean accepts(int address) {
        return (address >= 0x0000 && address < 0x8000) ||
               (address >= 0xa000 && address < 0xc000);
    }

    @Override
    public void setByte(int address, int value) {
        if (address >= 0x0000 && address < 0x2000) {
            if ((address & 0x0100) == 0) {
                ramWriteEnabled = (value & 0b1010) != 0;
                if (!ramWriteEnabled) {
                    battery.saveRam(ram);
                }
            }
        } else if (address >= 0x2000 && address < 0x4000) {
            if ((address & 0x0100) != 0) {
                selectedRomBank = value & 0b00001111;
            }
        } else if (address >= 0xa000 && address < 0xc000 && ramWriteEnabled) {
            int ramAddress = getRamAddress(address);
            if (ramAddress < ram.length) {
                ram[ramAddress] = value & 0x0f;
            }
        }
    }

    @Override
    public int getByte(int address) {
        if (address >= 0x0000 && address < 0x4000) {
            return getRomByte(0, address);
        } else if (address >= 0x4000 && address < 0x8000) {