A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 171 lines 3.8 kB view raw
1#include "rockmacros.h" 2 3#include "defs.h" 4#include "hw.h" 5#include "cpu-gb.h" 6#include "regs.h" 7#include "lcd-gb.h" 8#include "fb.h" 9#include "lcdc.h" 10 11 12#define C (cpu.lcdc) 13 14 15/* 16 * stat_trigger updates the STAT interrupt line to reflect whether any 17 * of the conditions set to be tested (by bits 3-6 of R_STAT) are met. 18 * This function should be called whenever any of the following occur: 19 * 1) LY or LYC changes. 20 * 2) A state transition affects the low 2 bits of R_STAT (see below). 21 * 3) The program writes to the upper bits of R_STAT. 22 * stat_trigger also updates bit 2 of R_STAT to reflect whether LY=LYC. 23 */ 24 25void stat_trigger(void) 26{ 27 static const int condbits[4] = { 0x08, 0x10, 0x20, 0x00 }; 28 int flag = 0; 29 30 if (R_LY == R_LYC) 31 { 32 R_STAT |= 0x04; 33 if (R_STAT & 0x40) flag = IF_STAT; 34 } 35 else R_STAT &= ~0x04; 36 37 if (R_STAT & condbits[R_STAT&3]) flag = IF_STAT; 38 39 if (!(R_LCDC & 0x80)) flag = 0; 40 41 hw_interrupt(flag, IF_STAT); 42} 43 44/* 45 * stat_change is called when a transition results in a change to the 46 * LCD STAT condition (the low 2 bits of R_STAT). It raises or lowers 47 * the VBLANK interrupt line appropriately and calls stat_trigger to 48 * update the STAT interrupt line. 49 */ 50 51static void stat_change(unsigned int stat) 52{ 53 R_STAT = (R_STAT & 0x7C) | stat; 54 55 if (stat != 1) hw_interrupt(0, IF_VBLANK); 56 /* hw_interrupt((stat == 1) ? IF_VBLANK : 0, IF_VBLANK); */ 57 stat_trigger(); 58} 59 60 61void lcdc_change(byte b) 62{ 63 byte old = R_LCDC; 64 R_LCDC = b; 65 if ((R_LCDC ^ old) & 0x80) /* lcd on/off change */ 66 { 67 R_LY = 0; 68 stat_change(2); 69 C = 40; 70 lcd_begin(); 71 } 72} 73 74 75void lcdc_trans(void) 76{ 77 if (!(R_LCDC & 0x80)) 78 { 79 while (C <= 0) 80 { 81 switch ((byte)(R_STAT & 3)) 82 { 83 case 0: 84 case 1: 85 stat_change(2); 86 C += 40; 87 break; 88 case 2: 89 stat_change(3); 90 C += 86; 91 break; 92 case 3: 93 stat_change(0); 94 if (hw.hdma & 0x80) 95 hw_hdma(); 96 else 97 C += 102; 98 break; 99 } 100 return; 101 } 102 } 103 while (C <= 0) 104 { 105 switch ((byte)(R_STAT & 3)) 106 { 107 case 1: 108 if (!(hw.ilines & IF_VBLANK)) 109 { 110 C += 218; 111 hw_interrupt(IF_VBLANK, IF_VBLANK); 112 break; 113 } 114 if (R_LY == 0) 115 { 116 lcd_begin(); 117 stat_change(2); 118 C += 40; 119 break; 120 } 121 else if (R_LY < 152) 122 C += 228; 123 else if (R_LY == 152) 124 C += 28; 125 else 126 { 127 R_LY = -1; 128 C += 200; 129 } 130 R_LY++; 131 stat_trigger(); 132 break; 133 case 2: 134 if (fb.enabled) 135 lcd_refreshline(); 136 stat_change(3); 137 C += 86; 138 break; 139 case 3: 140 stat_change(0); 141 if (hw.hdma & 0x80) 142 hw_hdma(); 143 /* FIXME -- how much of the hblank does hdma use?? */ 144 /* else */ 145 C += 102; 146 break; 147 case 0: 148 if (++R_LY >= 144) 149 { 150 if (cpu.halt) 151 { 152 hw_interrupt(IF_VBLANK, IF_VBLANK); 153 C += 228; 154 } 155 else C += 10; 156 stat_change(1); 157 break; 158 } 159 stat_change(2); 160 C += 40; 161 break; 162 } 163 } 164} 165 166 167 168 169 170 171