public static void check_irp() { UInt16 irpmask = (UInt16)GBRegs.Sect_keypad.KEYCNT.read(); if ((irpmask & 0x4000) > 0) { if ((irpmask & 0x8000) > 0) // logical and -> all mentioned { irpmask &= 0x3FF; UInt16 newvalue = (UInt16)((~value) & irpmask); if (newvalue == irpmask) { IRP.set_irp_bit(IRP.IRPMASK_Keypad); } } else // logical or -> at least one { irpmask &= 0x3FF; UInt16 newvalue = (UInt16)((~value) & irpmask); newvalue &= 0x3FF; if (newvalue > 0) { IRP.set_irp_bit(IRP.IRPMASK_Keypad); } } } }
public static void work() { if (start) { serialcnt += CPU.newticks; if ((!hispeed && serialcnt >= 64) || (hispeed && serialcnt >= 8)) { if (hispeed) { serialcnt -= 8; } else { serialcnt -= 64; } bitcount++; if (bitcount == bits) { if (IRP_enable) { IRP.set_irp_bit(IRP.IRPMASK_Serial); } GBRegs.Sect_serial.SIOCNT.mask(0xDF7F); start = false; } } } }
private static void nextline() { line++; if (line == 228) { line = 0; } GBRegs.Sect_display.VCOUNT.write(line); if (line == GBRegs.Sect_display.DISPSTAT_V_Count_Setting.read()) { if (GBRegs.Sect_display.DISPSTAT_V_Counter_IRQ_Enable.on()) { IRP.set_irp_bit(IRP.IRPMASK_LCD_V_Counter_Match); } GBRegs.Sect_display.DISPSTAT_V_Counter_flag.write(1); } else { GBRegs.Sect_display.DISPSTAT_V_Counter_flag.write(0); } }
public static void write_gbreg(UInt32 adr, UInt32 value, bool dwaccess) { if (adr == GBRegs.Sect_display.DISPCNT.address) { GPU.dispcnt_write(); } if (adr == GBRegs.Sect_display.DISPSTAT.address) { GPU_Timing.dispstat_write(); } else if (adr == GBRegs.Sect_display.BG2RefX.address) { GPU.refpoint_update_2x_new(); } else if (adr == GBRegs.Sect_display.BG2RefX.address + 2) { GPU.refpoint_update_2x_new(); } else if (adr == GBRegs.Sect_display.BG2RefY.address) { GPU.refpoint_update_2y_new(); } else if (adr == GBRegs.Sect_display.BG2RefY.address + 2) { GPU.refpoint_update_2y_new(); } else if (adr == GBRegs.Sect_display.BG3RefX.address) { GPU.refpoint_update_3x_new(); } else if (adr == GBRegs.Sect_display.BG3RefX.address + 2) { GPU.refpoint_update_3x_new(); } else if (adr == GBRegs.Sect_display.BG3RefY.address) { GPU.refpoint_update_3y_new(); } else if (adr == GBRegs.Sect_display.BG3RefY.address + 2) { GPU.refpoint_update_3y_new(); } else if (adr >= GBRegs.Sect_sound.SOUND1CNT_L.address && adr < GBRegs.Sect_sound.FIFO_A.address) { Sound.set_soundreg(adr); } else if (adr == GBRegs.Sect_sound.FIFO_A.address) { SoundDMA.fill_fifo(0, value, dwaccess); } else if (adr == GBRegs.Sect_sound.FIFO_B.address) { SoundDMA.fill_fifo(1, value, dwaccess); } else if (adr == GBRegs.Sect_serial.SIOCNT.address) { Serial.write_SIOCNT(BitConverter.ToUInt16(GBRegs.data, (int)GBRegs.Sect_serial.SIOCNT.address)); } else if (adr == GBRegs.Sect_timer.TM0CNT_L.address) { Timer.set_reload(0); } else if (adr == GBRegs.Sect_timer.TM0CNT_L.address + 2) { Timer.set_settings(0); } else if (adr == GBRegs.Sect_timer.TM1CNT_L.address) { Timer.set_reload(1); } else if (adr == GBRegs.Sect_timer.TM1CNT_L.address + 2) { Timer.set_settings(1); } else if (adr == GBRegs.Sect_timer.TM2CNT_L.address) { Timer.set_reload(2); } else if (adr == GBRegs.Sect_timer.TM2CNT_L.address + 2) { Timer.set_settings(2); } else if (adr == GBRegs.Sect_timer.TM3CNT_L.address) { Timer.set_reload(3); } else if (adr == GBRegs.Sect_timer.TM3CNT_L.address + 2) { Timer.set_settings(3); } else if (adr == GBRegs.Sect_dma.DMA0CNT_H.address + 2) { DMA.set_settings(0); } else if (adr == GBRegs.Sect_dma.DMA1CNT_H.address + 2) { DMA.set_settings(1); } else if (adr == GBRegs.Sect_dma.DMA2CNT_H.address + 2) { DMA.set_settings(2); } else if (adr == GBRegs.Sect_dma.DMA3CNT_H.address + 2) { DMA.set_settings(3); } else if (adr == GBRegs.Sect_keypad.KEYINPUT.address) { Joypad.set_reg(); } else if (adr == GBRegs.Sect_system.IME.address) { IRP.update_IME(BitConverter.ToUInt16(GBRegs.data, (int)GBRegs.Sect_system.IME.address)); } else if (adr == GBRegs.Sect_system.IE.address) { IRP.update_IE(); } else if (adr == GBRegs.Sect_system.IF.address + 2) { IRP.clear_irp_bits(); } else if (adr == GBRegs.Sect_system.WAITCNT.address) { BusTiming.update(BitConverter.ToUInt16(GBRegs.data, (int)GBRegs.Sect_system.WAITCNT.address)); } else if (adr == GBRegs.Sect_system.POSTFLG.address & value == 1) { } else if (adr == GBRegs.Sect_system.HALTCNT.address && !gameboy.loading_state) { if ((GBRegs.Sect_system.HALTCNT.read() & 0x80) == 0x80) { CPU.stop = true; } else { CPU.halt = true; } } }
public static void work() { // must save here, as dma may reset to zero int cputicks = CPU.newticks; for (uint i = 0; i < 4; i++) { if (timers[i].startnow) { timers[i].startnow = false; timers[i].value = timers[i].reload; timers[i].retval = (UInt16)timers[i].value; } else if (timers[i].on || timers[i].stopnow) { timers[i].stopnow = false; if (!timers[i].countup || i == 0) { if (timers[i].prescale == 1) { timers[i].value += cputicks; } else { timers[i].prescalevalue += cputicks; while (timers[i].prescalevalue >= timers[i].prescale) { timers[i].prescalevalue -= timers[i].prescale; timers[i].value += 1; } } } while (timers[i].value >= 0x10000) { timers[i].value -= 0x10000; timers[i].value += timers[i].reload; if (i < 2) { SoundDMA.timer_overflow(i); } if (i < 3 && timers[i + 1].countup) { timers[i + 1].value++; timers[i + 1].retval = (UInt16)timers[i].value; } if (timers[i].irp_on) { IRP.set_irp_bit(timers[i].irpmask); } } if (!timers[i].countup) { timers[i].retval = (UInt16)timers[i].value; } } } }
public static void work() { cycles += CPU.newticks; bool runagain = true; while (runagain) { runagain = false; switch (gpustate) { case GPUState.VISIBLE: if (cycles >= 1008) // 960 is drawing time { runagain = true; cycles -= 1008; gpustate = GPUState.HBLANK; GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(1); DMA.new_hblank = true; if (GBRegs.Sect_display.DISPSTAT_H_Blank_IRQ_Enable.on()) { IRP.set_irp_bit(IRP.IRPMASK_LCD_H_Blank); } old_dispstat = GBRegs.data[4]; GPU.once_per_hblank(); GPU.next_line(line); } break; case GPUState.HBLANK: if (cycles >= 224) // 272 { runagain = true; cycles -= 224; nextline(); GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(0); DMA.new_hblank = false; if (line < 160) { gpustate = GPUState.VISIBLE; } else { gpustate = GPUState.VBLANK; GPU.refpoint_update_all(); Cheats.apply_cheats(); GBRegs.Sect_display.DISPSTAT_V_Blank_flag.write(1); DMA.new_vblank = true; if (GBRegs.Sect_display.DISPSTAT_V_Blank_IRQ_Enable.on()) { IRP.set_irp_bit(IRP.IRPMASK_LCD_V_Blank); } } old_dispstat = GBRegs.data[4]; } break; case GPUState.VBLANK: if (cycles >= 1008) { runagain = true; cycles -= 1008; gpustate = GPUState.VBLANKHBLANK; GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(1); //DMA.new_hblank = true; //!!! don't do here! if (GBRegs.Sect_display.DISPSTAT_H_Blank_IRQ_Enable.on()) { IRP.set_irp_bit(IRP.IRPMASK_LCD_H_Blank); // Note that no H-Blank interrupts are generated within V-Blank period. Really? } old_dispstat = GBRegs.data[4]; } break; case GPUState.VBLANKHBLANK: if (cycles >= 224) { runagain = true; cycles -= 224; nextline(); GBRegs.Sect_display.DISPSTAT_H_Blank_flag.write(0); DMA.new_hblank = false; GPU.once_per_hblank(); if (line == 0) { gpio.framecount++; gpio.update_time(); gpustate = GPUState.VISIBLE; //GPU.next_line(line); GBRegs.Sect_display.DISPSTAT_V_Blank_flag.write(0); DMA.new_vblank = false; } else { gpustate = GPUState.VBLANK; if (line == 227) { //GBRegs.Sect_display.DISPSTAT_V_Blank_flag.write(0); } } old_dispstat = GBRegs.data[4]; } break; } } }
public static void work() { dma_active = false; delayed = false; for (int i = 0; i < 4; i++) { if (DMAs[i].dMA_Enable) { if (DMAs[i].waiting) { check_run(i); } if (DMAs[i].waitTicks > 0) { if (CPU.newticks >= DMAs[i].waitTicks) { DMAs[i].running = true; DMAs[i].waitTicks = 0; } else { DMAs[i].waitTicks -= CPU.newticks; } } if (DMAs[i].running) { // remember for timing UInt32 sm = Math.Min(15, DMAs[i].addr_source >> 24); UInt32 dm = Math.Min(15, DMAs[i].addr_target >> 24); // eeprom hack cpuDmaCount = (int)DMAs[i].fullcount; dma_active = true; if (DMAs[i].dMA_Transfer_Type) { UInt32 value; if (DMAs[i].addr_source >= 0x02000000) { value = Memory.read_dword(DMAs[i].addr_source); if (!Memory.unreadable) { last_dma_value = value; last_dma_index = i; CPU.op_since_dma = 0; } value = last_dma_value; } else { value = last_dma_value; } Memory.write_dword(DMAs[i].addr_target, value); if (DMAs[i].source_Adr_Control == 0 || DMAs[i].source_Adr_Control == 3 || (DMAs[i].addr_source >= 0x08000000 && DMAs[i].addr_source < 0x0E000000)) { DMAs[i].addr_source += 4; } else if (DMAs[i].source_Adr_Control == 1) { DMAs[i].addr_source -= 4; } if (DMAs[i].dest_Addr_Control == 0 || (DMAs[i].dest_Addr_Control == 3 && DMAs[i].dMA_Start_Timing != 3)) { DMAs[i].addr_target += 4; } else if (DMAs[i].dest_Addr_Control == 1) { DMAs[i].addr_target -= 4; } } else { UInt16 value; if (DMAs[i].addr_source >= 0x02000000) { UInt32 newvalue = Memory.read_word(DMAs[i].addr_source) & 0xFFFF; if (!Memory.unreadable) { last_dma_value = (UInt32)newvalue | ((UInt32)newvalue << 16); last_dma_index = i; CPU.op_since_dma = 0; } value = (UInt16)last_dma_value; } else { value = (UInt16)last_dma_value; } value = (UInt16)last_dma_value; Memory.write_word(DMAs[i].addr_target, value); if (DMAs[i].source_Adr_Control == 0 || DMAs[i].source_Adr_Control == 3 || (DMAs[i].addr_source >= 0x08000000 && DMAs[i].addr_source < 0x0E000000)) { DMAs[i].addr_source += 2; } else if (DMAs[i].source_Adr_Control == 1) { DMAs[i].addr_source -= 2; } if (DMAs[i].dest_Addr_Control == 0 || (DMAs[i].dest_Addr_Control == 3 && DMAs[i].dMA_Start_Timing != 3)) { DMAs[i].addr_target += 2; } else if (DMAs[i].dest_Addr_Control == 1) { DMAs[i].addr_target -= 2; } } debug_dmatranfers++; DMAs[i].count--; // calc timing int ticks; if (DMAs[i].first) { if (DMAs[i].dMA_Transfer_Type) { ticks = 4 + BusTiming.memoryWait32[sm & 15] + BusTiming.memoryWaitSeq32[dm & 15]; } else { ticks = 4 + BusTiming.memoryWait[sm & 15] + BusTiming.memoryWaitSeq[dm & 15]; } DMAs[i].first = false; } else { if (DMAs[i].dMA_Transfer_Type) { ticks = 2 + BusTiming.memoryWaitSeq32[sm & 15] + BusTiming.memoryWaitSeq32[dm & 15]; } else { ticks = 2 + BusTiming.memoryWaitSeq[sm & 15] + BusTiming.memoryWaitSeq[dm & 15]; } } CPU.newticks += ticks; DMAs[i].totalTicks += ticks; if (DMAs[i].count == 0) { DMAs[i].running = false; if (DMAs[i].iRQ_on) { switch (i) { case 0: IRP.set_irp_bit(IRP.IRPMASK_DMA_0); break; case 1: IRP.set_irp_bit(IRP.IRPMASK_DMA_1); break; case 2: IRP.set_irp_bit(IRP.IRPMASK_DMA_2); break; case 3: IRP.set_irp_bit(IRP.IRPMASK_DMA_3); break; } } if (DMAs[i].dMA_Repeat && DMAs[i].dMA_Start_Timing != 0) { DMAs[i].waiting = true; if (DMAs[i].dMA_Start_Timing == 3 && (i == 1 || i == 2)) { DMAs[i].count = 4; } else { DMAs[i].count = DMAs[i].CNT_L.read(); if (DMAs[i].dest_Addr_Control == 3) { DMAs[i].addr_target = DMAs[i].DAD.read(); switch (i) { case 0: DMAs[i].addr_target &= 0x07FFFFFF; break; case 1: DMAs[i].addr_target &= 0x07FFFFFF; break; case 2: DMAs[i].addr_target &= 0x07FFFFFF; break; case 3: DMAs[i].addr_target &= 0x0FFFFFFF; break; } } } } else { DMAs[i].DMA_Enable.write(0); DMAs[i].dMA_Enable = false; } #if DEBUG //if (CPU.traclist_ptr > 0 && !DMAs[i].skipdebugout) //{ // CPU.Tracelist[CPU.traclist_ptr - 1].thumbmode = 3; // CPU.Tracelist[CPU.traclist_ptr - 1].memory01 = (UInt32) DMAs[i].totalTicks; // CPU.Tracelist[CPU.traclist_ptr - 1].memory02 = DMAs[i].addr_source_save; //} DMAs[i].skipdebugout = false; #endif } break; } } } new_hblank = false; new_vblank = false; }