├── README.md ├── rtcread-ds ├── .gitignore ├── Makefile └── source │ └── main.c └── rtcread ├── .gitignore ├── Makefile ├── source └── rtcread.c └── template.pnproj /README.md: -------------------------------------------------------------------------------- 1 | # GBA RTCRead 2 | 3 | This tool can read/write data in the RTC found inside carts of some GBA games (Pokemon Ruby/Sapphire/Emerald and Boktai games). 4 | 5 | The original tool and details about the RTC chip was found here: [http://www.furlocks-forest.net/wiki/?page=Pokemon_Ruby/Sapphire_New_Battery_Glitch](https://web.archive.org/web/20180413154901/http://www.furlocks-forest.net/wiki/?page=Pokemon_Ruby/Sapphire_New_Battery_Glitch) 6 | 7 | The DS port is still available here: [https://sourceforge.net/projects/rtcread-ds/](https://sourceforge.net/projects/rtcread-ds/) 8 | 9 | 10 | ## Features 11 | 12 | - Enables read current date and time from RTC data 13 | - Enables write new date and time to the RTC data 14 | - The GBA version must be written to a GBA flashcart, and works with cartridge swap 15 | - The GBA version can also edit the RTC found in the Everdrive GBA cartridge 16 | - The DS version is a homebrew for R4 carts that access the GBA carts through Slot-2 insertion 17 | 18 | ## Known Issues 19 | 20 | - Both the GBA and DS original release versions have a rollover bug in February of a leap year, where it rollsover at Feb 09 instead of Feb 29. 21 | -------------------------------------------------------------------------------- /rtcread-ds/.gitignore: -------------------------------------------------------------------------------- 1 | /*.elf 2 | /*.nds 3 | /build 4 | -------------------------------------------------------------------------------- /rtcread-ds/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | include $(DEVKITARM)/ds_rules 10 | 11 | #--------------------------------------------------------------------------------- 12 | # TARGET is the name of the output 13 | # BUILD is the directory where object files & intermediate files will be placed 14 | # SOURCES is a list of directories containing source code 15 | # INCLUDES is a list of directories containing extra header files 16 | #--------------------------------------------------------------------------------- 17 | TARGET := $(shell basename $(CURDIR)) 18 | BUILD := build 19 | SOURCES := gfx source data 20 | INCLUDES := include build 21 | 22 | #--------------------------------------------------------------------------------- 23 | # options for code generation 24 | #--------------------------------------------------------------------------------- 25 | ARCH := -mthumb -mthumb-interwork 26 | 27 | CFLAGS := -g -Wall -O2\ 28 | -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ 29 | -ffast-math \ 30 | $(ARCH) 31 | 32 | CFLAGS += $(INCLUDE) -DARM9 33 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 34 | 35 | ASFLAGS := -g $(ARCH) 36 | LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 37 | 38 | #--------------------------------------------------------------------------------- 39 | # any extra libraries we wish to link with the project 40 | #--------------------------------------------------------------------------------- 41 | LIBS := -lnds9 42 | 43 | 44 | #--------------------------------------------------------------------------------- 45 | # list of directories containing libraries, this must be the top level containing 46 | # include and lib 47 | #--------------------------------------------------------------------------------- 48 | LIBDIRS := $(LIBNDS) 49 | 50 | #--------------------------------------------------------------------------------- 51 | # no real need to edit anything past this point unless you need to add additional 52 | # rules for different file extensions 53 | #--------------------------------------------------------------------------------- 54 | ifneq ($(BUILD),$(notdir $(CURDIR))) 55 | #--------------------------------------------------------------------------------- 56 | 57 | export OUTPUT := $(CURDIR)/$(TARGET) 58 | 59 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 60 | export DEPSDIR := $(CURDIR)/$(BUILD) 61 | 62 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 63 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 64 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 65 | BINFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin))) 66 | 67 | #--------------------------------------------------------------------------------- 68 | # use CXX for linking C++ projects, CC for standard C 69 | #--------------------------------------------------------------------------------- 70 | ifeq ($(strip $(CPPFILES)),) 71 | #--------------------------------------------------------------------------------- 72 | export LD := $(CC) 73 | #--------------------------------------------------------------------------------- 74 | else 75 | #--------------------------------------------------------------------------------- 76 | export LD := $(CXX) 77 | #--------------------------------------------------------------------------------- 78 | endif 79 | #--------------------------------------------------------------------------------- 80 | 81 | export OFILES := $(BINFILES:.bin=.o) \ 82 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 83 | 84 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 85 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 86 | -I$(CURDIR)/$(BUILD) 87 | 88 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 89 | 90 | .PHONY: $(BUILD) clean 91 | 92 | #--------------------------------------------------------------------------------- 93 | $(BUILD): 94 | @[ -d $@ ] || mkdir -p $@ 95 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 96 | 97 | #--------------------------------------------------------------------------------- 98 | clean: 99 | @echo clean ... 100 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).ds.gba 101 | 102 | 103 | #--------------------------------------------------------------------------------- 104 | else 105 | 106 | DEPENDS := $(OFILES:.o=.d) 107 | 108 | #--------------------------------------------------------------------------------- 109 | # main targets 110 | #--------------------------------------------------------------------------------- 111 | $(OUTPUT).nds : $(OUTPUT).elf 112 | $(OUTPUT).elf : $(OFILES) 113 | 114 | #--------------------------------------------------------------------------------- 115 | %.o : %.bin 116 | #--------------------------------------------------------------------------------- 117 | @echo $(notdir $<) 118 | $(bin2o) 119 | 120 | 121 | -include $(DEPENDS) 122 | 123 | #--------------------------------------------------------------------------------------- 124 | endif 125 | #--------------------------------------------------------------------------------------- 126 | -------------------------------------------------------------------------------- /rtcread-ds/source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /********************************************************************************** 5 | rtcread - created by Adam of Furlock's Forest 6 | Ported to DS by Rikten 7 | 8 | The following is a DS port of rtcread.gba, created by Adam of Furlock's 9 | Forest. His own code was made possible by a variety of sources, detailed in 10 | his original comment below. The license for rtc.c is also included. 11 | 12 | As far as code is concerned, this version is essentially identical to its 13 | gba predecessor. The program no longer instructs the user to remove the 14 | flash cart from the console, as this is no longer necessary with dual-slot 15 | operation. 16 | **********************************************************************************/ 17 | 18 | 19 | //Cobbled together from this: 20 | //http://pastebin.com/ApcR878P Thank you POPSDECO 21 | //and from the source for Vana'Diel Clock Advance: 22 | //http://sourceforge.net/projects/vca/ thanks golddbz2000 and travistyoj 23 | //here is the original license for rtc.c, thanks Jonas Minnberg 24 | /******************************************************************************** 25 | * All the following RTC functions were taken from pogoshell as per the GNU 26 | * license. Here is the license from pogoshell. Thanks Jonas, I could not have 27 | * figured this out on my own. :) 28 | * 29 | * Copyright (c) 2002-2004 Jonas Minnberg 30 | 31 | * Permission is hereby granted, free of charge, to any person obtaining a copy 32 | * of this software and associated documentation files (the "Software"), to deal 33 | * in the Software without restriction, including without limitation the rights 34 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | * copies of the Software, and to permit persons to whom the Software is 36 | * furnished to do so, subject to the following conditions: 37 | * 38 | * The above copyright notice and this permission notice shall be included in 39 | * all copies or substantial portions of the Software. 40 | * 41 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 47 | * SOFTWARE. 48 | *******************************************************************************/ 49 | 50 | #define UNBCD(x) (((x) & 0xF) + (((x) >> 4) * 10)) 51 | #define _BCD(x) ((((x) / 10)<<4) + ((x) % 10)) 52 | #define RTC_DATA ((vu16 *)0x080000C4) 53 | #define RTC_RW ((vu16 *)0x080000C6) 54 | #define RTC_ENABLE ((vu16 *)0x080000C8) 55 | #define CART_NAME ((vu8 *)0x080000A0) 56 | #define RTC_CMD_READ(x) (((x)<<1) | 0x61) 57 | #define RTC_CMD_WRITE(x) (((x)<<1) | 0x60) 58 | #define _YEAR 0 59 | #define _MONTH 1 60 | #define _DAY 2 61 | #define _WKD 3 62 | #define _HOUR 4 63 | #define _MIN 5 64 | #define _SEC 6 65 | 66 | //this sends commands to the RTC so it knows what to send/receive 67 | //see the data sheet for the Seiko S-3511 for more details 68 | //0x65 to read the 7byte date/time BCDs and 0x64 to write them 69 | void rtc_cmd(int v) 70 | { 71 | int l; 72 | u16 b; 73 | v = v<<1; 74 | for(l=7; l>=0; l--) 75 | { 76 | b = (v>>l) & 0x2; 77 | *RTC_DATA = b | 4; 78 | *RTC_DATA = b | 4; 79 | *RTC_DATA = b | 4; 80 | *RTC_DATA = b | 5; 81 | } 82 | } 83 | 84 | //this pipes data out to the RTC 85 | //remember that data must be BCDs 86 | void rtc_data(int v) 87 | { 88 | int l; 89 | u16 b; 90 | v = v<<1; 91 | for(l=0; l<8; l++) 92 | { 93 | b = (v>>l) & 0x2; 94 | *RTC_DATA = b | 4; 95 | *RTC_DATA = b | 4; 96 | *RTC_DATA = b | 4; 97 | *RTC_DATA = b | 5; 98 | } 99 | } 100 | 101 | //this pipes data in from the RTC 102 | int rtc_read(void) 103 | { 104 | int j,l; 105 | u16 b; 106 | int v = 0; 107 | for(l=0; l<8; l++) 108 | { 109 | for(j=0;j<5; j++) 110 | *RTC_DATA = 4; 111 | *RTC_DATA = 5; 112 | b = *RTC_DATA; 113 | v = v | ((b & 2)<>1; 116 | return v; 117 | } 118 | 119 | static int check_val = 0; 120 | 121 | void rtc_enable(void) 122 | { 123 | *RTC_ENABLE = 1; 124 | *RTC_DATA = 1; 125 | *RTC_DATA = 5; 126 | *RTC_RW = 7; 127 | rtc_cmd(RTC_CMD_READ(1)); 128 | *RTC_RW = 5; 129 | check_val = rtc_read(); 130 | } 131 | 132 | // Normally returns 0x40 133 | int rtc_check(void) 134 | { 135 | return (check_val & 0x40); //01000000 136 | } 137 | 138 | int rtc_get(u8 *data) 139 | { 140 | int i; 141 | *RTC_DATA = 1; 142 | *RTC_RW = 7; 143 | *RTC_DATA = 1; 144 | *RTC_DATA = 5; 145 | rtc_cmd(RTC_CMD_READ(2)); 146 | *RTC_RW = 5; 147 | for(i=0; i<4; i++) 148 | data[i] = (u8)rtc_read(); 149 | *RTC_RW = 5; 150 | for(i=4; i<7; i++) 151 | data[i] = (u8)rtc_read(); 152 | return 0; 153 | } 154 | 155 | void rtc_set(u8 *data) { 156 | int i; u8 newdata[7]; 157 | 158 | for(i=0;i<7;i++) { 159 | newdata[i] = _BCD(data[i]); 160 | } 161 | 162 | *RTC_ENABLE = 1; 163 | *RTC_DATA = 1; 164 | *RTC_DATA = 5; 165 | *RTC_RW = 7; 166 | rtc_cmd(RTC_CMD_WRITE(2)); 167 | //*RTC_RW = 0; 168 | for(i=0;i<4;i++) { 169 | rtc_data(newdata[i]); 170 | } 171 | //*RTC_RW = 0; 172 | for(i=4;i<7;i++) { 173 | rtc_data(newdata[i]); 174 | } 175 | } 176 | 177 | void getGameString(u8 *gametitle) { 178 | int i; 179 | for(i=0;i<12;i++) { 180 | gametitle[i] = CART_NAME[i]; 181 | } 182 | gametitle[12] = '\0'; 183 | } 184 | 185 | int main() 186 | { 187 | consoleDemoInit(); 188 | sysSetCartOwner(1); 189 | 190 | int keys_pressed; 191 | u8 gamename[13]; 192 | int gamestate; 193 | int currstate; 194 | 195 | u8 edit_pos; 196 | edit_pos=0; 197 | 198 | iprintf("\n Real Time Clock Reader DS\n ----------------------------\n\n 1. Insert PKMN R/S/E Cart\n 2. Press START"); 199 | iprintf("\n\n\n\n\n\n\n\n\n\n\n Cobbled together by adam\n http://furlocks-forest.net"); 200 | iprintf("\n\n Ported to DS by Rikten"); 201 | 202 | u8 datetime[7]; 203 | u8 edit_datetime[7]; 204 | 205 | edit_datetime[_HOUR]=0; edit_datetime[_MIN]=0; edit_datetime[_SEC]=0; 206 | edit_datetime[_DAY]=0; edit_datetime[_MONTH]=0; edit_datetime[_YEAR]=0; edit_datetime[_WKD]=0; 207 | 208 | gamestate = 0; 209 | 210 | while(1) 211 | { 212 | currstate = gamestate; //not sure how switch handles changes to gamestate mid-flow 213 | switch(currstate) { 214 | case 0: //initial state 215 | scanKeys(); 216 | keys_pressed = keysDown(); 217 | 218 | if ( keys_pressed & KEY_START ) { 219 | edit_datetime[_HOUR]=0; edit_datetime[_MIN]=0; edit_datetime[_SEC]=0; 220 | edit_datetime[_DAY]=0; edit_datetime[_MONTH]=0; edit_datetime[_YEAR]=0; edit_datetime[_WKD]=0; 221 | 222 | //update data from cart 223 | getGameString(gamename); 224 | rtc_enable(); 225 | rtc_get(datetime); 226 | //print to screen 227 | iprintf("\x1b[2J"); //clear the screen 228 | iprintf("\n Real Time Clock Reader DS\n ----------------------------\n\n Cart Inserted is:\n %s\n\n",gamename); 229 | if(check_val & 0x80) { 230 | //power flag is raised - everything else is invalid 231 | iprintf(" Power flag raised!\n\n Battery probably dead.\n\n"); 232 | } else { 233 | //probably okay to read the clock 234 | iprintf(" Current date is:\n %02u/%02u/%u wkday: % 2d\n Current time is:\n %02d:%02d:%02d\n",UNBCD(datetime[2]&0x3F),UNBCD(datetime[1]),UNBCD(datetime[0])+1900+100,UNBCD(datetime[3]),UNBCD(datetime[4]&0x3F),UNBCD(datetime[5]),UNBCD(datetime[6])); 235 | } 236 | iprintf(" Power: %u 12/24: %u IntAE: %u\n IntME: %u IntFE: %u\n",(check_val&0x80)>>7,(check_val&0x40)>>6,(check_val&0x20)>>5,(check_val&0x08)>>3,(check_val&0x02)>>1); 237 | iprintf("\n\n Press START to refresh."); 238 | if(!(check_val & 0x80)) { 239 | iprintf("\n\n Press SELECT to edit."); 240 | } 241 | } else if((keys_pressed & KEY_SELECT) && !(check_val & 0x80)) { 242 | gamestate = 1; 243 | } 244 | break; 245 | 246 | case 1: //edit clock state 247 | scanKeys(); 248 | keys_pressed = keysDown(); 249 | 250 | if(edit_datetime[_DAY]==0) { 251 | rtc_enable(); 252 | rtc_get(datetime); 253 | 254 | edit_datetime[_HOUR] = UNBCD(datetime[_HOUR]&0x3F); 255 | edit_datetime[_MIN] = UNBCD(datetime[_MIN]); 256 | edit_datetime[_SEC] = UNBCD(datetime[_SEC]); 257 | edit_datetime[_DAY] = UNBCD(datetime[_DAY]&0x3F); 258 | edit_datetime[_MONTH] = UNBCD(datetime[_MONTH]); 259 | edit_datetime[_YEAR] = UNBCD(datetime[_YEAR]); 260 | edit_datetime[_WKD] = UNBCD(datetime[_WKD]); 261 | } 262 | 263 | iprintf("\x1b[2J"); //clear the screen 264 | 265 | iprintf("\n Edit Real-Time Clock\n ----------------------------\n\n Date (dd/mm/yyyy)\n\n "); 266 | 267 | //line to show cursor position 268 | iprintf("%s %s %s %s",(edit_pos==0?"--":" "),(edit_pos==1?"--":" "),(edit_pos==2?"--":" "),(edit_pos==3?"-":" ")); 269 | 270 | iprintf("\n %02d / %02d / 20%02d wkd: %d\n ",edit_datetime[_DAY],edit_datetime[_MONTH],edit_datetime[_YEAR],edit_datetime[_WKD]); 271 | 272 | //line to show cursor position 273 | iprintf("%s %s %s %s",(edit_pos==0?"--":" "),(edit_pos==1?"--":" "),(edit_pos==2?"--":" "),(edit_pos==3?"-":" ")); 274 | 275 | iprintf("\n\n Time (hh:mm:ss) \n\n "); 276 | 277 | //line to show cursor position 278 | iprintf("%s %s %s",(edit_pos==4?"--":" "),(edit_pos==5?"--":" "),(edit_pos==6?"--":" ")); 279 | 280 | iprintf("\n %02d : %02d : %02d\n ",edit_datetime[_HOUR],edit_datetime[_MIN],edit_datetime[_SEC]); 281 | 282 | //line to show cursor position 283 | iprintf("%s %s %s",(edit_pos==4?"--":" "),(edit_pos==5?"--":" "),(edit_pos==6?"--":" ")); 284 | 285 | iprintf("\n\n Press START to save to RTC."); 286 | 287 | if(keys_pressed & KEY_UP) { 288 | switch(edit_pos) { 289 | case 0: 290 | //day 291 | switch(edit_datetime[_MONTH]) { 292 | case 1: case 3: case 5: case 7: case 8: case 10: case 12: 293 | 294 | if(edit_datetime[_DAY]==31) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]++;} 295 | break; 296 | case 4: case 6: case 9: case 11: 297 | if(edit_datetime[_DAY]==30) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]++;} 298 | break; 299 | case 2: 300 | if((edit_datetime[_YEAR]%4==0 && edit_datetime[_DAY]==9) || (edit_datetime[_YEAR]%4>0 && edit_datetime[_DAY]==28)) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]++;} 301 | break; 302 | } 303 | break; 304 | case 1: 305 | //month 306 | if(edit_datetime[_MONTH]==12) {edit_datetime[_MONTH]=1;} else {edit_datetime[_MONTH]++;} 307 | break; 308 | case 2: 309 | //year 310 | if(edit_datetime[_YEAR]==99) {edit_datetime[_YEAR]=0;} else {edit_datetime[_YEAR]++;} 311 | break; 312 | case 3: 313 | //week day 314 | if(edit_datetime[_WKD]==6) {edit_datetime[_WKD]=0;} else {edit_datetime[_WKD]++;} 315 | break; 316 | case 4: 317 | //hour 318 | if(edit_datetime[_HOUR]==23) {edit_datetime[_HOUR]=0;} else {edit_datetime[_HOUR]++;} 319 | break; 320 | case 5: 321 | //minute 322 | if(edit_datetime[_MIN]==59) {edit_datetime[_MIN]=0;} else {edit_datetime[_MIN]++;} 323 | break; 324 | case 6: 325 | //second 326 | if(edit_datetime[_SEC]==59) {edit_datetime[_SEC]=0;} else {edit_datetime[_SEC]++;} 327 | break; 328 | 329 | } 330 | } else if(keys_pressed & KEY_DOWN) { 331 | switch(edit_pos) { 332 | case 0: 333 | switch(edit_datetime[_MONTH]) { 334 | case 1: case 3: case 5: case 7: case 8: case 10: case 12: 335 | if(edit_datetime[_DAY]==1) {edit_datetime[_DAY]=31;} else {edit_datetime[_DAY]--;} 336 | break; 337 | case 4: case 6: case 9: case 11: 338 | if(edit_datetime[_DAY]==0) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]--;} 339 | break; 340 | case 2: 341 | if(edit_datetime[_DAY]==1) { 342 | if(edit_datetime[_YEAR]%4==0) { 343 | edit_datetime[_DAY]=29; 344 | } else { 345 | edit_datetime[_DAY]=28; 346 | } 347 | } else { 348 | edit_datetime[_DAY]--; 349 | } 350 | break; 351 | } 352 | break; 353 | case 1: 354 | if(edit_datetime[_MONTH]==1) {edit_datetime[_MONTH]=12;} else {edit_datetime[_MONTH]--;} 355 | break; 356 | case 2: 357 | if(edit_datetime[_YEAR]==0) {edit_datetime[_YEAR]=99;} else {edit_datetime[_YEAR]--;} 358 | break; 359 | case 3: 360 | //week day 361 | if(edit_datetime[_WKD]==0) {edit_datetime[_WKD]=6;} else {edit_datetime[_WKD]--;} 362 | break; 363 | case 4: 364 | //hour 365 | if(edit_datetime[_HOUR]==0) {edit_datetime[_HOUR]=23;} else {edit_datetime[_HOUR]--;} 366 | break; 367 | case 5: 368 | //minute 369 | if(edit_datetime[_MIN]==0) {edit_datetime[_MIN]=59;} else {edit_datetime[_MIN]--;} 370 | break; 371 | case 6: 372 | //second 373 | if(edit_datetime[_SEC]==0) {edit_datetime[_SEC]=59;} else {edit_datetime[_SEC]--;} 374 | break; 375 | 376 | } 377 | } else if(keys_pressed & KEY_RIGHT) { 378 | if(edit_pos==6) { 379 | edit_pos=0; 380 | } else { 381 | edit_pos++; 382 | } 383 | } else if(keys_pressed & KEY_LEFT) { 384 | if(edit_pos==0) { 385 | edit_pos=6; 386 | } else { 387 | edit_pos--; 388 | } 389 | } else if(keys_pressed & KEY_START) { 390 | //totally save the shit out of that RTC value 391 | 392 | rtc_set(edit_datetime); 393 | gamestate = 0; 394 | iprintf("\x1b[2J"); //clear the screen 395 | iprintf("\n Clock updated.\n Press START to continue."); 396 | 397 | } else if(keys_pressed & KEY_SELECT) { 398 | 399 | gamestate = 0; 400 | iprintf("\x1b[2J"); //clear the screen 401 | iprintf("\n Real Time Clock Reader DS\n ----------------------------\n\n 1. Insert PKMN R/S/E Cart\n 2. Press START"); 402 | iprintf("\n\n\n\n\n\n\n\n\n\n\n Cobbled together by adam\n http://furlocks-forest.net"); 403 | iprintf("\n\n Ported to DS by Rikten"); 404 | } 405 | 406 | break; 407 | } 408 | 409 | swiWaitForVBlank(); 410 | } 411 | } -------------------------------------------------------------------------------- /rtcread/.gitignore: -------------------------------------------------------------------------------- 1 | /*.elf 2 | /*.gba 3 | /build 4 | -------------------------------------------------------------------------------- /rtcread/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITARM)),) 7 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM) 8 | endif 9 | 10 | include $(DEVKITARM)/gba_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output, if this ends with _mb a multiboot image is generated 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # DATA is a list of directories containing data files 17 | # INCLUDES is a list of directories containing header files 18 | #--------------------------------------------------------------------------------- 19 | TARGET := $(shell basename $(CURDIR))_mb 20 | BUILD := build 21 | SOURCES := source 22 | DATA := 23 | GRAPHICS := gfx 24 | INCLUDES := 25 | 26 | #--------------------------------------------------------------------------------- 27 | # options for code generation 28 | #--------------------------------------------------------------------------------- 29 | ARCH := -mthumb -mthumb-interwork 30 | 31 | CFLAGS := -g -Wall -O3\ 32 | -mcpu=arm7tdmi -mtune=arm7tdmi\ 33 | -fomit-frame-pointer\ 34 | -ffast-math \ 35 | $(ARCH) 36 | 37 | CFLAGS += $(INCLUDE) 38 | 39 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions 40 | 41 | ASFLAGS := $(ARCH) 42 | LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $@).map 43 | 44 | #--------------------------------------------------------------------------------- 45 | # any extra libraries we wish to link with the project 46 | #--------------------------------------------------------------------------------- 47 | LIBS := -lgba 48 | 49 | #--------------------------------------------------------------------------------- 50 | # list of directories containing libraries, this must be the top level containing 51 | # include and lib 52 | #--------------------------------------------------------------------------------- 53 | LIBDIRS := $(LIBGBA) 54 | 55 | #--------------------------------------------------------------------------------- 56 | # no real need to edit anything past this point unless you need to add additional 57 | # rules for different file extensions 58 | #--------------------------------------------------------------------------------- 59 | ifneq ($(BUILD),$(notdir $(CURDIR))) 60 | #--------------------------------------------------------------------------------- 61 | 62 | export OUTPUT := $(CURDIR)/$(TARGET) 63 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 64 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 65 | 66 | export DEPSDIR := $(CURDIR)/$(BUILD) 67 | 68 | #--------------------------------------------------------------------------------- 69 | # automatically build a list of object files for our project 70 | #--------------------------------------------------------------------------------- 71 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 72 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 73 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 74 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 75 | BMPFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.bmp))) 76 | 77 | #--------------------------------------------------------------------------------- 78 | # use CXX for linking C++ projects, CC for standard C 79 | #--------------------------------------------------------------------------------- 80 | ifeq ($(strip $(CPPFILES)),) 81 | #--------------------------------------------------------------------------------- 82 | export LD := $(CC) 83 | #--------------------------------------------------------------------------------- 84 | else 85 | #--------------------------------------------------------------------------------- 86 | export LD := $(CXX) 87 | #--------------------------------------------------------------------------------- 88 | endif 89 | #--------------------------------------------------------------------------------- 90 | 91 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 92 | $(BMPFILES:.bmp=.o) \ 93 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 94 | 95 | #--------------------------------------------------------------------------------- 96 | # build a list of include paths 97 | #--------------------------------------------------------------------------------- 98 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 99 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 100 | -I$(CURDIR)/$(BUILD) 101 | 102 | #--------------------------------------------------------------------------------- 103 | # build a list of library paths 104 | #--------------------------------------------------------------------------------- 105 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 106 | 107 | .PHONY: $(BUILD) clean 108 | 109 | #--------------------------------------------------------------------------------- 110 | $(BUILD): 111 | @[ -d $@ ] || mkdir -p $@ 112 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 113 | 114 | all : $(BUILD) 115 | #--------------------------------------------------------------------------------- 116 | clean: 117 | @echo clean ... 118 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba 119 | 120 | #--------------------------------------------------------------------------------- 121 | else 122 | 123 | DEPENDS := $(OFILES:.o=.d) 124 | 125 | #--------------------------------------------------------------------------------- 126 | # main targets 127 | #--------------------------------------------------------------------------------- 128 | $(OUTPUT).gba : $(OUTPUT).elf 129 | 130 | $(OUTPUT).elf : $(OFILES) 131 | 132 | 133 | #--------------------------------------------------------------------------------- 134 | # The bin2o rule should be copied and modified 135 | # for each extension used in the data directories 136 | #--------------------------------------------------------------------------------- 137 | 138 | #--------------------------------------------------------------------------------- 139 | # This rule links in binary data with the .bin extension 140 | #--------------------------------------------------------------------------------- 141 | %.bin.o : %.bin 142 | #--------------------------------------------------------------------------------- 143 | @echo $(notdir $<) 144 | @$(bin2o) 145 | 146 | #--------------------------------------------------------------------------------- 147 | # This rule links in binary data with the .raw extension 148 | #--------------------------------------------------------------------------------- 149 | %.raw.o : %.raw 150 | #--------------------------------------------------------------------------------- 151 | @echo $(notdir $<) 152 | @$(bin2o) 153 | 154 | #--------------------------------------------------------------------------------- 155 | # This rule creates assembly source files using grit 156 | # grit takes an image file and a .grit describing how the file is to be processed 157 | # add additional rules like this for each image extension 158 | # you use in the graphics folders 159 | #--------------------------------------------------------------------------------- 160 | %.s %.h : %.bmp %.grit 161 | #--------------------------------------------------------------------------------- 162 | grit $< -fts -o$* 163 | 164 | -include $(DEPENDS) 165 | 166 | #--------------------------------------------------------------------------------- 167 | endif 168 | #--------------------------------------------------------------------------------- 169 | -------------------------------------------------------------------------------- /rtcread/source/rtcread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //above includes are from DevKitPro 9 | 10 | //Cobbled together from this: 11 | //http://pastebin.com/ApcR878P Thank you POPSDECO 12 | //and from the source for Vana'Diel Clock Advance: 13 | //http://sourceforge.net/projects/vca/ thanks golddbz2000 and travistyoj 14 | //here is the original license for rtc.c, thanks Jonas Minnberg 15 | /******************************************************************************** 16 | * All the following RTC functions were taken from pogoshell as per the GNU 17 | * license. Here is the license from pogoshell. Thanks Jonas, I could not have 18 | * figured this out on my own. :) 19 | * 20 | * Copyright (c) 2002-2004 Jonas Minnberg 21 | 22 | * Permission is hereby granted, free of charge, to any person obtaining a copy 23 | * of this software and associated documentation files (the "Software"), to deal 24 | * in the Software without restriction, including without limitation the rights 25 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 | * copies of the Software, and to permit persons to whom the Software is 27 | * furnished to do so, subject to the following conditions: 28 | * 29 | * The above copyright notice and this permission notice shall be included in 30 | * all copies or substantial portions of the Software. 31 | * 32 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | * SOFTWARE. 39 | *******************************************************************************/ 40 | 41 | #define UNBCD(x) (((x) & 0xF) + (((x) >> 4) * 10)) 42 | #define _BCD(x) ((((x) / 10)<<4) + ((x) % 10)) 43 | #define RTC_DATA ((vu16 *)0x080000C4) 44 | #define RTC_RW ((vu16 *)0x080000C6) 45 | #define RTC_ENABLE ((vu16 *)0x080000C8) 46 | #define CART_NAME ((vu8 *)0x080000A0) 47 | #define RTC_CMD_READ(x) (((x)<<1) | 0x61) 48 | #define RTC_CMD_WRITE(x) (((x)<<1) | 0x60) 49 | #define _YEAR 0 50 | #define _MONTH 1 51 | #define _DAY 2 52 | #define _WKD 3 53 | #define _HOUR 4 54 | #define _MIN 5 55 | #define _SEC 6 56 | 57 | //this sends commands to the RTC so it knows what to send/receive 58 | //see the data sheet for the Seiko S-3511 for more details 59 | //0x65 to read the 7byte date/time BCDs and 0x64 to write them 60 | void rtc_cmd(int v) 61 | { 62 | int l; 63 | u16 b; 64 | v = v<<1; 65 | for(l=7; l>=0; l--) 66 | { 67 | b = (v>>l) & 0x2; 68 | *RTC_DATA = b | 4; 69 | *RTC_DATA = b | 4; 70 | *RTC_DATA = b | 4; 71 | *RTC_DATA = b | 5; 72 | } 73 | } 74 | 75 | //this pipes data out to the RTC 76 | //remember that data must be BCDs 77 | void rtc_data(int v) 78 | { 79 | int l; 80 | u16 b; 81 | v = v<<1; 82 | for(l=0; l<8; l++) 83 | { 84 | b = (v>>l) & 0x2; 85 | *RTC_DATA = b | 4; 86 | *RTC_DATA = b | 4; 87 | *RTC_DATA = b | 4; 88 | *RTC_DATA = b | 5; 89 | } 90 | } 91 | 92 | //this pipes data in from the RTC 93 | int rtc_read(void) 94 | { 95 | int j,l; 96 | u16 b; 97 | int v = 0; 98 | for(l=0; l<8; l++) 99 | { 100 | for(j=0;j<5; j++) 101 | *RTC_DATA = 4; 102 | *RTC_DATA = 5; 103 | b = *RTC_DATA; 104 | v = v | ((b & 2)<>1; 107 | return v; 108 | } 109 | 110 | static int check_val = 0; 111 | 112 | void rtc_enable(void) 113 | { 114 | *RTC_ENABLE = 1; 115 | *RTC_DATA = 1; 116 | *RTC_DATA = 5; 117 | *RTC_RW = 7; 118 | rtc_cmd(RTC_CMD_READ(1)); 119 | *RTC_RW = 5; 120 | check_val = rtc_read(); 121 | } 122 | 123 | // Normally returns 0x40 124 | int rtc_check(void) 125 | { 126 | return (check_val & 0x40); //01000000 127 | } 128 | 129 | int rtc_get(u8 *data) 130 | { 131 | int i; 132 | *RTC_DATA = 1; 133 | *RTC_RW = 7; 134 | *RTC_DATA = 1; 135 | *RTC_DATA = 5; 136 | rtc_cmd(RTC_CMD_READ(2)); 137 | *RTC_RW = 5; 138 | for(i=0; i<4; i++) 139 | data[i] = (u8)rtc_read(); 140 | *RTC_RW = 5; 141 | for(i=4; i<7; i++) 142 | data[i] = (u8)rtc_read(); 143 | return 0; 144 | } 145 | 146 | void rtc_set(u8 *data) { 147 | int i; u8 newdata[7]; 148 | 149 | for(i=0;i<7;i++) { 150 | newdata[i] = _BCD(data[i]); 151 | } 152 | 153 | *RTC_ENABLE = 1; 154 | *RTC_DATA = 1; 155 | *RTC_DATA = 5; 156 | *RTC_RW = 7; 157 | rtc_cmd(RTC_CMD_WRITE(2)); 158 | //*RTC_RW = 0; 159 | for(i=0;i<4;i++) { 160 | rtc_data(newdata[i]); 161 | } 162 | //*RTC_RW = 0; 163 | for(i=4;i<7;i++) { 164 | rtc_data(newdata[i]); 165 | } 166 | } 167 | 168 | /* 169 | struct tm get_time() 170 | { 171 | struct tm tmp_tm; 172 | uchar data[7]; 173 | 174 | rtc_get(data); 175 | tmp_tm.tm_sec = UNBCD(data[6]); 176 | tmp_tm.tm_min = UNBCD(data[5]); 177 | tmp_tm.tm_hour = UNBCD(data[4] & 0x3F); //The & 0x3F was added to work with my EFA cart 178 | 179 | tmp_tm.tm_mday = UNBCD(data[2] & 0x3F); //The & 0x3F was added to work with my EFA cart 180 | tmp_tm.tm_mon = UNBCD(data[1]-1); // Subtract one since C time functins expect months 0-11 181 | tmp_tm.tm_year = UNBCD(data[0]) + 100; //C expects years from 1900, 1e 1999 = 99, 2000 = 100 182 | return tmp_tm; 183 | } 184 | */ 185 | /* 186 | void refreshClockDate() { 187 | enableRTC(0); 188 | enableRTC(1); 189 | setRTCcommand(0x65); 190 | iprintf("DtTm:%u/%02u/%02u %d %02d:%02d:%02d\n",getRTCbyte()+1900+100,getRTCbyte(),getRTCbyte(),getRTCbyte(),getRTCbyte(),getRTCbyte(),getRTCbyte()); 191 | 192 | } 193 | void refreshClockTime() { 194 | enableRTC(0); 195 | enableRTC(1); 196 | setRTCcommand(0x67); 197 | iprintf("Time:%02d:%02d:%02d\n",getRTCbyte(),getRTCbyte(),getRTCbyte()); 198 | 199 | } 200 | void refreshClockStatus() { 201 | enableRTC(0); 202 | enableRTC(1); 203 | setRTCcommand(0x63); 204 | iprintf("Stat:%02X\n",getRTCbyte()); 205 | 206 | } 207 | */ 208 | 209 | void getGameString(u8 *gametitle) { 210 | int i; 211 | for(i=0;i<12;i++) { 212 | gametitle[i] = CART_NAME[i]; 213 | } 214 | gametitle[12] = '\0'; 215 | } 216 | 217 | int main(){ 218 | int keys_pressed; 219 | u8 gamename[13]; 220 | int gamestate; 221 | int currstate; 222 | /* 223 | u8 edit_hour; 224 | u8 edit_min; 225 | u8 edit_sec; 226 | u8 edit_day; 227 | u8 edit_month; 228 | u8 edit_year; 229 | u8 edit_wkd; 230 | */ 231 | 232 | 233 | u8 edit_pos; 234 | edit_pos=0; 235 | 236 | //edit_hour=0; edit_min=0; edit_sec=0; edit_day=0; edit_month=0; edit_year=0; edit_wkd=0; 237 | 238 | irqInit(); 239 | irqEnable(IRQ_VBLANK); 240 | consoleDemoInit(); 241 | 242 | iprintf("\n Real Time Clock Reader\n ----------------------------\n\n 1. Remove Flash Cart\n 2. Insert PKMN R/S/E Cart\n 3. Press START"); 243 | iprintf("\n\n\n\n\n\n\n\n\n\n\n Cobbled together by adam\n http://furlocks-forest.net"); 244 | 245 | u8 datetime[7]; 246 | u8 edit_datetime[7]; 247 | 248 | edit_datetime[_HOUR]=0; edit_datetime[_MIN]=0; edit_datetime[_SEC]=0; 249 | edit_datetime[_DAY]=0; edit_datetime[_MONTH]=0; edit_datetime[_YEAR]=0; edit_datetime[_WKD]=0; 250 | 251 | gamestate = 0; 252 | 253 | while(1){ 254 | currstate = gamestate; //not sure how switch handles changes to gamestate mid-flow 255 | switch(currstate) { 256 | case 0: //initial state 257 | scanKeys(); 258 | keys_pressed = keysDown(); 259 | 260 | if ( keys_pressed & KEY_START ) { 261 | //edit_hour=0; edit_min=0; edit_sec=0; edit_day=0; edit_month=0; edit_year=0; edit_pos=0; edit_wkd=0; 262 | edit_datetime[_HOUR]=0; edit_datetime[_MIN]=0; edit_datetime[_SEC]=0; 263 | edit_datetime[_DAY]=0; edit_datetime[_MONTH]=0; edit_datetime[_YEAR]=0; edit_datetime[_WKD]=0; 264 | 265 | //update data from cart 266 | getGameString(gamename); 267 | rtc_enable(); 268 | rtc_get(datetime); 269 | //print to screen 270 | iprintf("\x1b[2J"); //clear the screen 271 | iprintf("\n Real Time Clock Reader\n ----------------------------\n\n Cart Inserted is:\n %s\n\n",gamename); 272 | if(check_val & 0x80) { 273 | //power flag is raised - everything else is invalid 274 | iprintf(" Power flag raised!\n\n Battery probably dead.\n\n"); 275 | } else { 276 | //probably okay to read the clock 277 | iprintf(" Current date is:\n %02u/%02u/%u wkday: % 2d\n Current time is:\n %02d:%02d:%02d\n",UNBCD(datetime[2]&0x3F),UNBCD(datetime[1]),UNBCD(datetime[0])+1900+100,UNBCD(datetime[3]),UNBCD(datetime[4]&0x3F),UNBCD(datetime[5]),UNBCD(datetime[6])); 278 | } 279 | iprintf(" Power: %u 12/24: %u IntAE: %u\n IntME: %u IntFE: %u\n",(check_val&0x80)>>7,(check_val&0x40)>>6,(check_val&0x20)>>5,(check_val&0x08)>>3,(check_val&0x02)>>1); 280 | iprintf("\n\n Press START to refresh."); 281 | if(!(check_val & 0x80)) { 282 | iprintf("\n\n Press SELECT to edit."); 283 | } 284 | } else if((keys_pressed & KEY_SELECT) && !(check_val & 0x80)) { 285 | gamestate = 1; 286 | } 287 | break; 288 | 289 | case 1: //edit clock state 290 | scanKeys(); 291 | keys_pressed = keysDown(); 292 | 293 | if(edit_datetime[_DAY]==0) { 294 | //edit_* are not set - set them from datetime 295 | rtc_enable(); 296 | rtc_get(datetime); 297 | /* 298 | edit_hour = UNBCD(datetime[4]&0x3F); 299 | edit_min = UNBCD(datetime[5]); 300 | edit_sec = UNBCD(datetime[6]); 301 | edit_day = UNBCD(datetime[2]&0x3F); 302 | edit_month = UNBCD(datetime[1]); 303 | edit_year = UNBCD(datetime[0]); 304 | edit_wkd = UNBCD(datetime[3]); 305 | */ 306 | edit_datetime[_HOUR] = UNBCD(datetime[_HOUR]&0x3F); 307 | edit_datetime[_MIN] = UNBCD(datetime[_MIN]); 308 | edit_datetime[_SEC] = UNBCD(datetime[_SEC]); 309 | edit_datetime[_DAY] = UNBCD(datetime[_DAY]&0x3F); 310 | edit_datetime[_MONTH] = UNBCD(datetime[_MONTH]); 311 | edit_datetime[_YEAR] = UNBCD(datetime[_YEAR]); 312 | edit_datetime[_WKD] = UNBCD(datetime[_WKD]); 313 | } 314 | 315 | iprintf("\x1b[2J"); //clear the screen 316 | 317 | iprintf("\n Edit Real-Time Clock\n ----------------------------\n\n Date (dd/mm/yyyy)\n\n "); 318 | 319 | //line to show cursor position 320 | iprintf("%s %s %s %s",(edit_pos==0?"--":" "),(edit_pos==1?"--":" "),(edit_pos==2?"--":" "),(edit_pos==3?"-":" ")); 321 | 322 | iprintf("\n %02d / %02d / 20%02d wkd: %d\n ",edit_datetime[_DAY],edit_datetime[_MONTH],edit_datetime[_YEAR],edit_datetime[_WKD]); 323 | 324 | //line to show cursor position 325 | iprintf("%s %s %s %s",(edit_pos==0?"--":" "),(edit_pos==1?"--":" "),(edit_pos==2?"--":" "),(edit_pos==3?"-":" ")); 326 | 327 | iprintf("\n\n Time (hh:mm:ss) \n\n "); 328 | 329 | //line to show cursor position 330 | iprintf("%s %s %s",(edit_pos==4?"--":" "),(edit_pos==5?"--":" "),(edit_pos==6?"--":" ")); 331 | 332 | iprintf("\n %02d : %02d : %02d\n ",edit_datetime[_HOUR],edit_datetime[_MIN],edit_datetime[_SEC]); 333 | 334 | //line to show cursor position 335 | iprintf("%s %s %s",(edit_pos==4?"--":" "),(edit_pos==5?"--":" "),(edit_pos==6?"--":" ")); 336 | 337 | iprintf("\n\n Press START to save to RTC."); 338 | 339 | //iprintf("\n\n Press START to save to RTC.\n Values: %02X/%02X/%02X %02X %02X:%02X:%02X",_BCD(edit_datetime[_DAY]),_BCD(edit_datetime[_MONTH]),_BCD(edit_datetime[_YEAR]),_BCD(edit_datetime[_WKD]),_BCD(edit_datetime[_HOUR]),_BCD(edit_datetime[_MIN]),_BCD(edit_datetime[_SEC])); 340 | 341 | if(keys_pressed & KEY_UP) { 342 | switch(edit_pos) { 343 | case 0: 344 | //day 345 | switch(edit_datetime[_MONTH]) { 346 | case 1: case 3: case 5: case 7: case 8: case 10: case 12: 347 | 348 | if(edit_datetime[_DAY]==31) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]++;} 349 | break; 350 | case 4: case 6: case 9: case 11: 351 | if(edit_datetime[_DAY]==30) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]++;} 352 | break; 353 | case 2: 354 | if((edit_datetime[_YEAR]%4==0 && edit_datetime[_DAY]==9) || (edit_datetime[_YEAR]%4>0 && edit_datetime[_DAY]==28)) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]++;} 355 | break; 356 | } 357 | break; 358 | case 1: 359 | //month 360 | if(edit_datetime[_MONTH]==12) {edit_datetime[_MONTH]=1;} else {edit_datetime[_MONTH]++;} 361 | break; 362 | case 2: 363 | //year 364 | if(edit_datetime[_YEAR]==99) {edit_datetime[_YEAR]=0;} else {edit_datetime[_YEAR]++;} 365 | break; 366 | case 3: 367 | //week day 368 | if(edit_datetime[_WKD]==6) {edit_datetime[_WKD]=0;} else {edit_datetime[_WKD]++;} 369 | break; 370 | case 4: 371 | //hour 372 | if(edit_datetime[_HOUR]==23) {edit_datetime[_HOUR]=0;} else {edit_datetime[_HOUR]++;} 373 | break; 374 | case 5: 375 | //minute 376 | if(edit_datetime[_MIN]==59) {edit_datetime[_MIN]=0;} else {edit_datetime[_MIN]++;} 377 | break; 378 | case 6: 379 | //second 380 | if(edit_datetime[_SEC]==59) {edit_datetime[_SEC]=0;} else {edit_datetime[_SEC]++;} 381 | break; 382 | 383 | } 384 | } else if(keys_pressed & KEY_DOWN) { 385 | switch(edit_pos) { 386 | case 0: 387 | switch(edit_datetime[_MONTH]) { 388 | case 1: case 3: case 5: case 7: case 8: case 10: case 12: 389 | if(edit_datetime[_DAY]==1) {edit_datetime[_DAY]=31;} else {edit_datetime[_DAY]--;} 390 | break; 391 | case 4: case 6: case 9: case 11: 392 | if(edit_datetime[_DAY]==0) {edit_datetime[_DAY]=1;} else {edit_datetime[_DAY]--;} 393 | break; 394 | case 2: 395 | if(edit_datetime[_DAY]==1) { 396 | if(edit_datetime[_YEAR]%4==0) { 397 | edit_datetime[_DAY]=29; 398 | } else { 399 | edit_datetime[_DAY]=28; 400 | } 401 | } else { 402 | edit_datetime[_DAY]--; 403 | } 404 | break; 405 | } 406 | break; 407 | case 1: 408 | if(edit_datetime[_MONTH]==1) {edit_datetime[_MONTH]=12;} else {edit_datetime[_MONTH]--;} 409 | break; 410 | case 2: 411 | if(edit_datetime[_YEAR]==0) {edit_datetime[_YEAR]=99;} else {edit_datetime[_YEAR]--;} 412 | break; 413 | case 3: 414 | //week day 415 | if(edit_datetime[_WKD]==0) {edit_datetime[_WKD]=6;} else {edit_datetime[_WKD]--;} 416 | break; 417 | case 4: 418 | //hour 419 | if(edit_datetime[_HOUR]==0) {edit_datetime[_HOUR]=23;} else {edit_datetime[_HOUR]--;} 420 | break; 421 | case 5: 422 | //minute 423 | if(edit_datetime[_MIN]==0) {edit_datetime[_MIN]=59;} else {edit_datetime[_MIN]--;} 424 | break; 425 | case 6: 426 | //second 427 | if(edit_datetime[_SEC]==0) {edit_datetime[_SEC]=59;} else {edit_datetime[_SEC]--;} 428 | break; 429 | 430 | } 431 | } else if(keys_pressed & KEY_RIGHT) { 432 | if(edit_pos==6) { 433 | edit_pos=0; 434 | } else { 435 | edit_pos++; 436 | } 437 | } else if(keys_pressed & KEY_LEFT) { 438 | if(edit_pos==0) { 439 | edit_pos=6; 440 | } else { 441 | edit_pos--; 442 | } 443 | } else if(keys_pressed & KEY_START) { 444 | //totally save the shit out of that RTC value 445 | //iprintf("\n Updating Real-Time Clock\n ----------------------------\n\n Update to:\n %02d/%02d/%04d wkd %d\n %02d:%02d:%02d 446 | 447 | rtc_set(edit_datetime); 448 | gamestate = 0; 449 | iprintf("\x1b[2J"); //clear the screen 450 | iprintf("\n Clock updated.\n Press START to continue."); 451 | 452 | } else if(keys_pressed & KEY_SELECT) { 453 | 454 | gamestate = 0; 455 | iprintf("\x1b[2J"); //clear the screen 456 | iprintf("\n Real Time Clock Reader\n ----------------------------\n\n 1. Remove Flash Cart\n 2. Insert PKMN R/S/E Cart\n 3. Press START"); 457 | iprintf("\n\n\n\n\n\n\n\n\n\n\n Cobbled together by adam\n http://furlocks-forest.net"); 458 | } 459 | 460 | break; 461 | } 462 | VBlankIntrWait(); 463 | } 464 | } 465 | -------------------------------------------------------------------------------- /rtcread/template.pnproj: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------