gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > something wrong with iprintf (r21)

#157203 - PypeBros - Tue May 20, 2008 9:55 am

hey there.
i'm migrating some of my software from devkitARM r20 to r21, and i noticed that iprintf() isn't working properly anymore. To put it clear: it doesn't print anything at all.

The font is there, calling consoleWriteChar('h') manually works, fprintf(stderr,"hello, world") works too, but i cannot get iprintf("hello, world") to work.

any clue ? I'm doing consoleInitDefault() as usual, too ...
_________________
SEDS: Sprite Edition on DS :: modplayer

#157207 - Maxxie - Tue May 20, 2008 11:05 am

There was no problem for me when r21 was active here. However r21 is outdated.

Whenever iprintf fails on me i am quite sure that i have a stack problem somewhere. In 9/10th of all cases i went out of or corrupted the stack somehow.

#157209 - PypeBros - Tue May 20, 2008 11:18 am

Maxxie wrote:
There was no problem for me when r21 was active here. However r21 is outdated.

(yeah, i know, i just can't keep up to date with devkitARM for those hobby projects ... )

Quote:
Whenever iprintf fails on me i am quite sure that i have a stack problem somewhere. In 9/10th of all cases i went out of or corrupted the stack somehow.

Straight ahead, i'd say it is unlikely to be the case here (even putting a 'hello' straight on the second line of the program doesn't show... i can't have messed up the stack *that* early), but thanks for the suggestion: i'll investigate anyway.

I was more thinking of some initialisation step going wrong (or being corrupted) somehow. I guess i'll just grab the sources and go for another "debugging session darker than the night" :P

oh, btw, i must mention that this is happening in C++ code.
_________________
SEDS: Sprite Edition on DS :: modplayer

#157210 - kusma - Tue May 20, 2008 11:26 am

PypeBros wrote:

Quote:
Whenever iprintf fails on me i am quite sure that i have a stack problem somewhere. In 9/10th of all cases i went out of or corrupted the stack somehow.

Straight ahead, i'd say it is unlikely to be the case here (even putting a 'hello' straight on the second line of the program doesn't show... i can't have messed up the stack *that* early)

How did you manage to setup the console in just one line?

#157211 - PypeBros - Tue May 20, 2008 12:53 pm

okay, line #1 was instaciation of the GuiEngine class that initialises the console and stuff.
But that wasn't the point. Replacing it with consoleDemoInit(void) would do it one-liner too, which i did since i do not trust my own code in such case :P

Well, anyway, it turns out that iprintf is a wrapper around vfiprintf.c which is auto-generated out of vfprintf.c at compile-time (so i don't have any source for inspecting further), and that it's an 'integer-only' version of printf (which appear to be there and working even in crude environment). so i guess i'll just strip all those 'i's from my code, use regular (and working) printf and stop wondering.

If one day i find what was wrong, i'll come back and post the cause.
_________________
SEDS: Sprite Edition on DS :: modplayer

#157212 - kusma - Tue May 20, 2008 1:21 pm

PypeBros wrote:
okay, line #1 was instaciation of the GuiEngine class that initialises the console and stuff.

Which totally makes it NOT being the second line of code in your application, only in your main-function. Which is a completely different thing :)

Quote:
But that wasn't the point. Replacing it with consoleDemoInit(void) would do it one-liner too, which i did since i do not trust my own code in such case :P

Would you mind posting the minimal code to reproduce this?

Quote:
Well, anyway, it turns out [...] so i guess i'll just strip all those 'i's from my code, use regular (and working) printf and stop wondering.

Sounds like the best way of assuring any hidden bug WILL come back later and haunt you :)

#157213 - PypeBros - Tue May 20, 2008 1:42 pm

Well, you're right, and that's how i work usually ... debugging your debugging tools sometimes cannot let you go your usual ways. If it happens again with the regular printf, at least i'll have source code to study :P

anyway.

main.cpp:
Code:

#include <nds.h>
#include <nds/arm9/console.h>
#include <fat.h>
#include <stdio.h>
#include <stdarg.h>


int main()
{
  defaultExceptionHandler();
  BG0_CR = BG_MAP_BASE(28)|BG_TILE_BASE(0)|BG_PRIORITY(0);
  videoSetMode(  MODE_0_2D | DISPLAY_BG0_ACTIVE);
  vramSetMainBanks(   VRAM_A_MAIN_SPRITE,        // flat allocation: everything has 128K
            VRAM_B_MAIN_BG_0x06000000,       
            VRAM_C_SUB_BG_0x06200000,  //map C to background memory
            VRAM_D_SUB_SPRITE
            );
  BG_PALETTE[0]=RGB15(0,0,0);
  BG_PALETTE[255] = RGB15(31,31,31);//by default font rendered with color 255
  BG_PALETTE[15] = RGB15(31,31,31);//by default font rendered with color 255
  consoleInitDefault((u16*)SCREEN_BASE_BLOCK(28), (u16*)CHAR_BASE_BLOCK(0), 16);
 
  fatInitDefault();
  iprintf("ready.\n"); // <-- don't show up
  va_list dummy;
  vfiprintf(stdout,"don't work?",dummy); // <-- don't show up either

  fprintf(stderr,"(or so it seems ...)\n"); // <-- this one is fine.
  fprintf(stdout,"(maybe that's just stdout going wrong?)\n"); // <-- this one too.
  while(1) {
  }
}


Makefile (yes, i'm using some custom ARM7 code, which shouldn't interfere with the observed problem, afaik)
Code:

#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif

include $(DEVKITARM)/ds_rules

ifeq ($(CURDIR)/build,$(shell pwd))
@echo "we are in the 'build' directory"
BASEDIR := ..
else
BASEDIR := $(CURDIR)
endif

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET      :=   $(shell basename $(CURDIR))
BUILD      :=   build
SOURCES      :=   source
DATA      :=   data 
INCLUDES   :=   ../include

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH   :=   -mthumb -mthumb-interwork

# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD
# *insists* it has a FPU or VFP, and it won't take no for an answer!
CFLAGS   :=   -g -Wall -O2\
         -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
         -ffast-math \
         $(ARCH)

CFLAGS   +=   $(INCLUDE) -DARM9
CXXFLAGS   := $(CFLAGS) -fno-rtti -fno-exceptions

ASFLAGS   :=   -g $(ARCH)
LDFLAGS   =   -specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wall -Xlinker -Map -Xlinker test.map

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
# for some unknown reasons, i may not put NDS9 ahead of my own lib :?
LIBS := -lfat -lnds9


#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS   :=   $(LIBNDS)

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export OUTPUT   :=   $(BASEDIR)/$(TARGET)

export VPATH   :=   $(foreach dir,$(SOURCES),$(BASEDIR)/$(dir)) \
               $(foreach dir,$(DATA),$(BASEDIR)/$(dir))

export DEPSDIR   :=   $(BASEDIR)/$(BUILD)

CFILES      :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES   :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES      :=   $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES   :=   $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))

#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
   export LD   :=   $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
   export LD   :=   $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

export OFILES   :=   $(addsuffix .o,$(BINFILES)) \
         $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)

export INCLUDE   :=   $(foreach dir,$(INCLUDES),-I$(BASEDIR)/$(dir)) \
               $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
               $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
               -I$(BASEDIR)/$(BUILD)

export LIBPATHS   :=   $(foreach dir,$(LIBDIRS),-L$(dir)/lib)

.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
$(BUILD):
   @echo "adds $(BASEDIR)/$(BUILD) if doesn't exists"
   @echo "VPATH = $(VPATH)"
   @[ -d $@ ] || mkdir -p $@
   @make -C $(BUILD) -f $(CURDIR)/Makefile
   @echo "back to `pwd`"
all: $(BUILD)

#---------------------------------------------------------------------------------
clean:
   @echo clean ...
   @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).arm9 $(TARGET).ds.gba

install:
   rsync $(TARGET).nds $(REPOSITORY)/justatest.nds

#---------------------------------------------------------------------------------
else

DEPENDS   :=   $(OFILES:.o=.d)
all: $(OUTPUT).nds

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).ds.gba   :    $(OUTPUT).nds
$(OUTPUT).nds   :    $(OUTPUT).arm9 ../../lib/ppp.arm7
   ndstool   -c $(OUTPUT).nds -7 ../../lib/ppp.arm7 -9 $(OUTPUT).arm9
$(OUTPUT).arm9   :   $(OUTPUT).elf
$(OUTPUT).elf   :   $(OFILES) ../../lib/libpppds.a ../../lib/libgeds.a

#---------------------------------------------------------------------------------
%.bin.o   :   %.bin
#---------------------------------------------------------------------------------
   @echo $(notdir $<)
   @$(bin2o)

-include $(DEPENDS)


#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

_________________
SEDS: Sprite Edition on DS :: modplayer

#157231 - Quirky - Tue May 20, 2008 8:54 pm

PypeBros wrote:

anyway.

main.cpp:


That exact code copy pasted over the hello world example from devkitpro works with dka r21 here. I even checked on hardware. I'd search for the bug in your own code before cracking open printf.c.

#157354 - PypeBros - Thu May 22, 2008 12:57 pm

Quirky wrote:
That exact code copy pasted over the hello world example from devkitpro works with dka r21 here.

not much surprising. The error is most likely coming from some odd libraries combination (maybe some symbols wrongly linked) than really from a bug in iprintf.

Quote:
I'd search for the bug in your own code before cracking open printf.c.

Well, i realise now how this could sound to you. I'm not suspecting some bug in the newlib, rather something i don't know about iprintf that could make it behave differently from fprintf, and how and why, so that i can go further investigating what in my code broke the library. That's usually how i'm debugging things.

Anyway, without the sources for that specific file, i can't investigate that way further, so my only chance is to increase warning levels (-Weffc++ added), do another pass of code refactoring and hope better luck.
_________________
SEDS: Sprite Edition on DS :: modplayer

#157357 - PypeBros - Thu May 22, 2008 1:16 pm

oooow.
comparing one of my older program that was still working and the one causing troubles, i realised the only difference comes from defaultExceptionHandler() to be called either before or after consoleInitDefault()..

And i happen to have hacked defaultExceptionHandler() for my own purposes, and "casually" placed a iprintf("beware the guru") in that function.

So apparently, if iprintf() is called before consoleInitDefault(), all the further calls to iprintf() will fail to display anything ... i'd have expected something similar with printf() being called earlier causing further printf() to fail, but no. calling printf() before consoleInitDefault() also makes iprintf() not to work... weirder and weirder.

Expect more from PypeBros in Wonderland++ to come soon :P
_________________
SEDS: Sprite Edition on DS :: modplayer

#157370 - Quirky - Thu May 22, 2008 8:56 pm

PypeBros wrote:
oooow.
<snip>
Expect more from PypeBros in Wonderland++ to come soon :P


That is odd, but then "undefined behaviour" tends to result in odd things happening. At least you found the problem and told us about your mini-blunder. Respect. :-)

(I prefer just to keep quiet about things - last time I made a song and dance about an error, it was all my fault ;-))