dragonminded / libdragon Goto Github PK
View Code? Open in Web Editor NEWOpen source library for N64 development.
Home Page: https://libdragon.dev
License: The Unlicense
Open source library for N64 development.
Home Page: https://libdragon.dev
License: The Unlicense
Voice Recognition Units are currently not reverse engineered. Libdragon needs to be written to take advantage of this peripheral.
Adapting the spritemap example about how to create an dfs filesystem on a different project, the function dfs_open()
hangs on an infinite loop when executing recurse_path
.
Even if I did something wrong (i.e., failed to initialize the dfs or it wasn't properly created), it should never hang on an infinite loop there. An error should be returned.
[edit]
The cause of the issue is dfs_init()
failing to initialize the dfs, probably because the dfs offset is incorrect. How can I know exactly where the filesystem is located in memory?
This is due to the fact that libdragonsys links against the libdragon file system. I intend to rework how libdragonsys works in the future. For now, replace libdragonsys.a with libnosys.a in the makefile.
Hi,
i am trying to get into n64 dev. I followed the steps in the readme and compiled the example roms. However, in my case they dont run in an emulator (tried mupen64plus and nemu64). Are they supposed to do so?
When I build libdragon from git according to documentation I get a maxBuffer exceeded exception. Default is 1024 * 1024, I had to set it to 1024 * 1024 * 64 to compile through, 1024 * 1024 * 32 wasn't enough.
@@ -16,7 +16,7 @@ const options = {
function runCommand(cmd) {
return new Promise((resolve, reject) => {
- const command = exec(cmd, {}, (err, stdout, stderr) => {
+ const command = exec(cmd, {maxBuffer: 67108864}, (err, stdout, stderr) => {
That is some pretty hefty increase, is it possible that some default logging parameter was set accidentally?
The program outputs a corrupt .dfs file on windows although there are no errors. When trying to use a .dfs file generated on windows with n64tool you only get an error (Couldn't pad image). Using a .dfs file from linux fixes the problem
I'm attaching the windos and linux version of the .dfs file from the spritemap example. When using a diff tool I can see the two files differ (and I assume there should not be a difference)
spritemap-linux.zip
spritemap-windows.zip
I read from someone that there may be issues with how offsets are handled with n64tool. This person seems rather frustrated at the moment, and I don't want to start any drama, but I will copy and paste verbatim what they said and leave at your discretion how to handle it. If there are issues, I think it's best you know about them. In any case, this is what was said:
Message 1:
Not unconvinced that n64tool bundled with libdragon has some bugs that only show up if you use it to append multiple files at different offsets and maybe it doesnt get used that way too often because people just use DFS? I dont know. Cant use DFS for Doom, probably nobody was around for that but
- file size maxes out at 16M which means no TNT or Plutonia
- it has to start from 0 every time to seek or read and go through lists to get to the data you want and this leads to slowdown at boot and during game. Takes 2 to 5 minutes just to get to title screen, more time for game itself, and then it freezes while playing when doing file access
All of that is to say I'm about to code my own replacement
Message 2:
Yeah so apparently I havent been using good samples for the last 6 years because I was fighting bugs in libdragon n64tool. Spent 20 minutes rolling my own and everything works as expected. Extremely annoyed about that.
I'm not going to rewrite their shit for them so I'm not filing any issues or PRs against it
Message 3:
I have a drop-in replacement for n64tool except mine actually works π
No error handling though so if you pass things in wrong order it dies
But that's not far from the way the "real" one works
Message 4:
here's my n64tool, if you follow the exact argument ordering required for the real one, this will do what you actually expect it to do based on reading the usage details and not fuck up padding and offsets or throw an error message like the libdragon one π
I'm not going so far as to make it production ready but also not gonna be a completely selfish dick so that's why I figured it's at least here, I dont do discords or forums or anything really because then people make demands and I'm too old and miserable to be polite lol
Also mine has hardcoded assumptions about the size unit for padding the output file, always "M", and for the offsets to include data from files (-s) it always assumes "B"
Again, not trying to start drama, and I ask that no one attempt to start any either; just wanted to inform you of the possible issues. I've attached the replacement n64tool.c in a zip file below.
n64tool.c.zip
I managed to make a ROM that hangs at boot. Making cen64 print what it executes, it jumps to data_cache_hit_writeback_invalidate after data_init, and never returns. It spins there forever.
Are the cache functions buggy in that they expect a divisible-by-four size without checking, or is it the linker script that somehow outputs non-4-divisible symbols?
Here's the relevant boot code disasm:
80000460 <data_init>:
80000460: 8cc80000 lw t0,0(a2)
80000464: 24c60004 addiu a2,a2,4
80000468: ac880000 sw t0,0(a0)
8000046c: 24840004 addiu a0,a0,4
80000470: 0085082b sltu at,a0,a1
80000474: 1420fffa bnez at,80000460 <data_init>
80000478: 00000000 nop
8000047c: 00000000 nop
80000480: 3c048000 lui a0,0x8000
80000484: 24840560 addiu a0,a0,1376
80000488: 3c058005 lui a1,0x8005
8000048c: 24a5adde addiu a1,a1,-21026
80000490: 00a42822 sub a1,a1,a0
80000494: 0c000e42 jal 80003908 <data_cache_hit_writeback_invalidate>
So a0, __text_start is 0x80000560, and a1 __data_end 0x8005ADDE, making the %4 be 2, and the cache op never gets out of the loop.
When clipping on the top or left of the screen, a stretched textured rectangle does not properly calculate the offset s,t into the texture memory.
We already have a travis configuration for this repository and it is running at https://github.com/anacierdem/libdragon. Can you also enable for https://github.com/DragonMinded/libdragon so that any PR will trigger a test. Currently deployments are only enabled on anacierdem/libdragon
and will not cause an issue. I will update the changelog and deploy when necessary.
A stride parameter needs to be added to graphics functions to allow for sprite maps and animated sprites.
It compiles OK but linking with g++
does not work.
See the Makefile -> LD = $(GCCN64PREFIX)g++
In entrypoint, libdragon activates the 64-bit addressing mode:
Line 18 in 1c522f2
This is not very useful nor used at all, since our GCC toolchain uses 32-bit pointers. The only way to construct and dereference a 64-bit pointers would be through assembly. There is no code in libdragon that does this, nor it sounds specifically useful. Also, notice that the 64-bit addressing mode is backward compatible with 32-bit, so whatever you do from C would work exactly the same way with 32-bit addressing.
This is also not used in any commercial games as it was unsupported by Nintendo. So the end result is that emulators fail to run libdragon code because they see that bit set and they panic because they haven't implemented 64-bit addressing, when in reality this is not even used.
See for instance: mupen64plus/mupen64plus-core#738
We should just avoid activating 64-bit addressing.
I've renamed the default branch to trunk. This had the side effect of closing the two open pull requests, please re-open them. To update your local branch pointers, run the following:
$ git checkout master
$ git branch -m master trunk
$ git fetch
$ git branch --unset-upstream
$ git branch -u origin/trunk
$ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/trunk
Hi, I'm on ubuntu16:04 and I'm having trouble compiling the dfsdemo
When I try to download the sources, and complile with ./configure --prefix=${N64_INST} --target=mips64-elf
it tells me kipping incompatible /usr/mips64-elf/lib/libmikmod.a when searching for -lmikmod
Any idea ?
I know some N64DD stuff has been released already, but adding some useful examples to libdragon couldn't hurt.
libdragon currently overwrites the first 256 bytes of a mempak using Mupen64's template data. Many emulators use unique templates for the initialized data of an emulated .MPK file, and Project64/cen64/mupen64plus borrowed this from the original Mupen64 emulator.
This is bad for a few reasons.
Also, the concept of 'formatting' a mempak (such as preparing it in the factory) is separate from what N64 software actually do through libultra, which is a simpler 'repair' operation, which includes a permanent indicator in the data that a repair had been done.
I suggest emulating libultra's repair functions to some extent, incorporating a random element to the data.
Here is the general structure of the 32-byte ID block, according to libultra (Using the Mupen64 data as an anti-example):
The only bytes that matter are:
checksum
and inverted_checksum
must be correct.banks
must be set to 0x01
to specify the correct mempak size.deviceid
must be setrandom
is intended to be random (libultra uses CP0 Register 9, Timer count for this)repaired
is written with FF FF FF FF
to indicate a repair was performed, but has no function.Everything else is not checked, used or overwritten in any way. However version
is always 0 in over 300 DexDrive and legitimate dumps I have checked. Here are some examples of libultra repaired data found in real mempaks:
And how it fits into page 0 (first 256 bytes of the mempak):
0x81
is written in the first byte of the label area during a repair, but it has no functional purpose.Also, I did a bit of research into the initial factory state of the mempak contents here: https://rentry.co/mpk_serials. In summary, the first 24 bytes can vary wildly, and differ between manufacturers. Even all zeroes is valid. But games rely on the final checksum to detect if a different mempak is inserted. Unfortunately there are too few samples of official controller pak data to make any conclusions as to how to generate fresh serial data. But the only requirement is that the serial data changes sufficiently during a reformat or repair operation, so that the checksum is different.
Current interrupt handler saves and restores gp/fp registers on entry end restores them on exit except for k0
and k1
, which do not require saving. Theoretically it should be possible to skip; s0-s7
, gp
, sp
, ra
, and f21-f31
as MIPS calling convention stipulates that they are saved on function pro/epilogues when necessary. GCC seem to complyas some experimentation shown that they are indeed saved in disassembled output. On the other hand we had issues with fp registers (causing unimplemented exceptions where they seem to be loaded from s0-s7
). Also a test benchmark was failing without them being saved, although I couldn't verify if it is directly related.
We may work on this further in the future.
DFS can encode only file sizes up to 2^24 because it uses a uint32_t flags
that uses only 24 bits to encode file size, and 8 bit for flags:
Line 216 in 122a615
I think size and flags could safely be splitted into two different variables, considering that the same structure contains a pathname with MAX_PATH_LEN
size, so a single additional byte for flags shouldn't matter much. The rest of the code (dfs_read
, etc.) seems not to have problems with files larger than 16M.
Alternatively, if this is not wanted, at least mkdfs
should abort when a file's size is bigger than 16M, rather than silently truncating it.
Hi,
I'm using Mint Linux 18.1 64bit (gcc version 5.4.0 20160609)
The build script (run with sudo) works fine up to this point:
It configures it, and make builds a xgcc exe but the xgcc program always buffer overflow's.
Any idea's why?
Thanks
Mike.
make[2]: Entering directory '/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/gcc'
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc -B/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/ -dumpspecs > tmp-specs
*** buffer overflow detected ***: /home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f76e7d967e5]
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x5c)[0x7f76e7e3756c]
/lib/x86_64-linux-gnu/libc.so.6(+0x116570)[0x7f76e7e35570]
/lib/x86_64-linux-gnu/libc.so.6(+0x116af4)[0x7f76e7e35af4]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x461a3b]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x461e6d]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x407ef8]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x41068c]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x402bfe]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x402f14]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f76e7d3f830]
/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc[0x403069]
======= Memory map: ========
00400000-004da000 r-xp 00000000 08:07 16114756 /home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/gcc/xgcc
006d9000-006db000 r--p 000d9000 08:07 16114756 /home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/gcc/xgcc
006db000-006dc000 rw-p 000db000 08:07 16114756 /home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/gcc/xgcc
006dc000-006df000 rw-p 00000000 00:00 0
01d2b000-01d70000 rw-p 00000000 00:00 0 [heap]
7f76e7b09000-7f76e7b1f000 r-xp 00000000 08:05 478336 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f76e7b1f000-7f76e7d1e000 ---p 00016000 08:05 478336 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f76e7d1e000-7f76e7d1f000 rw-p 00015000 08:05 478336 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f76e7d1f000-7f76e7ede000 r-xp 00000000 08:05 478298 /lib/x86_64-linux-gnu/libc-2.23.so
7f76e7ede000-7f76e80de000 ---p 001bf000 08:05 478298 /lib/x86_64-linux-gnu/libc-2.23.so
7f76e80de000-7f76e80e2000 r--p 001bf000 08:05 478298 /lib/x86_64-linux-gnu/libc-2.23.so
7f76e80e2000-7f76e80e4000 rw-p 001c3000 08:05 478298 /lib/x86_64-linux-gnu/libc-2.23.so
7f76e80e4000-7f76e80e8000 rw-p 00000000 00:00 0
7f76e80e8000-7f76e810e000 r-xp 00000000 08:05 478270 /lib/x86_64-linux-gnu/ld-2.23.so
7f76e82dd000-7f76e82e0000 rw-p 00000000 00:00 0
7f76e830a000-7f76e830d000 rw-p 00000000 00:00 0
7f76e830d000-7f76e830e000 r--p 00025000 08:05 478270 /lib/x86_64-linux-gnu/ld-2.23.so
7f76e830e000-7f76e830f000 rw-p 00026000 08:05 478270 /lib/x86_64-linux-gnu/ld-2.23.so
7f76e830f000-7f76e8310000 rw-p 00000000 00:00 0
7ffc15f6a000-7ffc15f8c000 rw-p 00000000 00:00 0 [stack]
7ffc15fb8000-7ffc15fba000 r--p 00000000 00:00 0 [vvar]
7ffc15fba000-7ffc15fbc000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
/bin/sh: line 1: 13151 Aborted /home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/xgcc -B/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/./gcc/ -dumpspecs > tmp-specs
Makefile:1903: recipe for target 'specs' failed
make[2]: *** [specs] Error 134
make[2]: Leaving directory '/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile/gcc'
Makefile:4109: recipe for target 'all-gcc' failed
make[1]: *** [all-gcc] Error 2
make[1]: Leaving directory '/home/xp/Downloads/00-64dev/libdragon-master/build/gcc_compile'
Makefile:856: recipe for target 'all' failed
make: *** [all] Error 2
e->info = __get_exception_name((uint32_t)e->regs->gpr[30]);
in the __fetch_regs
method is causing another exception, resulting in an exception loop.
This only happens when (uint32_t)e->regs->gpr[30]
is used, so propably there is a problem with addresses.
Libdragon requires the user to manually initialize its components (e,g, call dfs_init()
). This can lead to bizarre side effects with C++ global objects, for instance, the following stacktrace:
#0 dma_busy () at /home/giulianob/bagunca/libdragon/src/dma.c:52
#1 0x801855cc in dma_read (ram_address=0x7ff758, pi_address=2907242500, len=256)
at /home/giulianob/bagunca/libdragon/src/dma.c:81
#2 0x8017d434 in grab_sector (cart_loc=0xad490004, ram_loc=0x807ff758)
at /home/giulianob/bagunca/libdragon/src/dragonfs.c:97
#3 0x8017da60 in find_dirent (name=0x807ff8a8 "record.bin", cur_node=0xad490004)
at /home/giulianob/bagunca/libdragon/src/dragonfs.c:442
#4 0x8017dc48 in recurse_path (path=0x802c6e78 "/record.bin", mode=1, dirent=0x807ffc68,
type=1) at /home/giulianob/bagunca/libdragon/src/dragonfs.c:539
#5 0x8017e0e0 in dfs_open (path=0x802c6e78 "/record.bin")
at /home/giulianob/bagunca/libdragon/src/dragonfs.c:773
#6 0x801c58fc in Find_File_Data_Libdragon::FindFirst (this=0x802c6e70,
fname=0x802c6e60 "record.bin")
--Type <RET> for more, q to quit, c to continue without paging--
pp:68
#7 0x801a2960 in Resolve_File_Single (fname=0x802c6e60 "record.bin") at /home/giulianob/bagunca/Vanilla-Conquer/common/file.cpp:15
#8 0x801a2ad0 in Resolve_File (fname=0x802c6e60 "record.bin") at /home/giulianob/bagunca/Vanilla-Conquer/common/file.cpp:34
#9 0x801ba848 in RawFileClass::Set_Name (this=0x802a0d88 <RecordFile>, filename=0x80207260 "RECORD.BIN") at /home/giulianob/bagunca/Vanilla-Conquer/common/rawfile.cpp:176
#10 0x8019a238 in BufferIOFileClass::Set_Name (this=0x802a0d88 <RecordFile>, filename=0x80207260 "RECORD.BIN") at /home/giulianob/bagunca/Vanilla-Conquer/common/bfiofile.cpp:409
#11 0x8019dfb0 in CDFileClass::Set_Name (this=0x802a0d88 <RecordFile>, filename=0x80207260 "RECORD.BIN") at /home/giulianob/bagunca/Vanilla-Conquer/common/cdfile.cpp:379
#12 0x8019bf7c in CCFileClass::CCFileClass (this=0x802a0d88 <RecordFile>, filename=0x80207260 "RECORD.BIN") at /home/giulianob/bagunca/Vanilla-Conquer/common/ccfile.cpp:67
#13 0x800a9820 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/giulianob/bagunca/Vanilla-Conquer/tiberiandawn/globals.cpp:424
#14 0x800b32dc in _GLOBAL__sub_I_Debug_Quiet () at /home/giulianob/bagunca/Vanilla-Conquer/tiberiandawn/globals.cpp:954
#15 0x801862c4 in __do_global_ctors () at /home/giulianob/bagunca/libdragon/src/do_ctors.c:31
#16 0x8000053c in loadintvectorloop ()
In here, the application hangs because dfs_init
was never called, even if the programmer wrote main to call dfs_init
on the first line.
The only workaround to this is to initialize libdragon in the constructor of some global object D:
#include <stdio.h>
#include <libdragon.h>
int main(void)
{
resolution_t res = RESOLUTION_320x240;
bitdepth_t bit = DEPTH_32_BPP;
init_interrupts();
display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE );
console_init();
console_set_render_mode(RENDER_MANUAL);
while(1)
{
printf("Test");
wait_ms(1);
console_render();
}
}
This is getting stuck at wait_ms(1)
.
There isn't currently a license in the repo.
Mentioning the license in the readme might be a good idea as well.
It is becoming another project in itself :) What do you think @DragonMinded if we move Dockerfile
and javascript stuff elsewhere which will use DragonMinded/libdragon
as a say git module?
When the interrupts are enabled, e.g the VI, unrelated code gets executed potentially invalidating the cache and breaking the test.
I can swear I have seen a case where there was garbage data in the asserted memory region but I was not able to reproduce it, so take that with a grain of salt.
Additionally, we may consider disabling interrups for other tests as well, especially the ones with the benchmarks, as they consistently fail for me on an everdrive whereas they pass on @rasky's 64drive.
I'm still getting my head around makefiles and linkers, but I ran into a problem using <math.h>
functions.
Because I didn't know what I was doing with the makefile, I adapted mine from one of the examples which contained this line.
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64ld.x
Everything worked fine for a long time until I tried to use the pow
function and I got this build error (repeated five times)
[...]/n64inst/mips64-elf/lib/libm.a(lib_a-w_pow.o): In function 'pow': (.text+0x318): undefined reference to '__errno'
I swapped -lc
and -lm
in that LINK_FLAGS line and it now builds, so this might be something libdragon needs to change as well. Or there was a better solution and I've shot myself in the foot for something down the line.
With the following patch for spritemap.c:
diff --git a/examples/spritemap/spritemap.c b/examples/spritemap/spritemap.c
index 1174e52..46047f5 100644
--- a/examples/spritemap/spritemap.c
+++ b/examples/spritemap/spritemap.c
@@ -24,13 +24,19 @@ int main(void)
rdp_init();
controller_init();
timer_init();
+ debug_init_isviewer();
/* Read in single sprite */
int fp = dfs_open("/mudkip.sprite");
sprite_t *mudkip = malloc( dfs_size( fp ) );
dfs_read( mudkip, 1, dfs_size( fp ), fp );
dfs_close( fp );
-
+
+ FILE* fptr = fopen("rom://should_not_exist", "r");
+ if (!fptr)
+ debugf("File not found\n");
+ fclose(fptr);
+
fp = dfs_open("/earthbound.sprite");
sprite_t *earthbound = malloc( dfs_size( fp ) );
dfs_read( earthbound, 1, dfs_size( fp ), fp );
Clearly, should_not_exist
is not present in the DragonFS. However, running with:
cen64 -is-viewer ~/bagunca/n64pif/pifdata.bin spritemap.z64
The file not found message is never print, and a seemly valid (but invalid) pointer is returned, where it should have returned NULL
.
Hello,
i had an issue with my homebrew games on the N64. (They were using libdragon for rendering of course)
When using something like :
display_init( RESOLUTION_320x240, DEPTH_16_BPP, 2, GAMMA_NONE, ANTIALIAS_OFF );
It would glitch up the display and pretty much make things unplayable
This is how it's supposed to look like
If you replace ANTIALIAS_OFF with ANTIALIAS_RESAMPLE, then it works again. (but you have AA all over the screen, bummer)
Oddly enough, if you try to set up another video mode after that, it can glitch up like disabling AA.
I have no idea what causes this, i could get no AA mode to work just fine with n64chain for example.
Hi,
I want to discuss the need for the following lines:
Lines 22 to 40 in d310a6b
I came across this because, in my project, I had to remove them, as I load the ROM from the PIF instead of the cartridge. The funny thing is that, after compiling Libdragon without this code, the ROMs were still working from the cart. This is because the bootcode (at least 6102) copies 1 MiB of data using DMA from cart to RAM.
So I see the following problems:
Most small projects should be in memory after the DMA transfer of the bootcode. If someone needs more code/data then loading should be implemented separately.
Things I am not aware of:
You mention requiring GMP, MPFR etc. to be required before compiling GCC, but this is not necessary. GCC comes with a script that'll download the prerequisites and compile/use them for the build:
# In GCC source dir
./contrib/download_prerequisites
Error: Command failed: docker exec libdragon make examples
ctest.c: In function 'main':
ctest.c:77:27: error: too few arguments to function 'get_accessories_present'
int accessories = get_accessories_present();
^~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/mips64-elf/include/libdragon.h:49:0,
from ctest.c:5:
/usr/local/mips64-elf/include/controller.h:183:5: note: declared here
int get_accessories_present(struct controller_data * data);
It always uses 0x80000318
. Also see system.c
which uses both addresses 0xA0000318
and 0xA00003F0
.
The n64 supports any resolution below 640x480 through manipulation of the x and y scale along with width on the VI. So it can support arbitrary resolutions but the capability isn't exposed in libdragon. Resolutions with a height greater than 240 will need to be interlaced. Can you please expose it in libdragon.
Currently libdragon validates the mempak header by checking if all three 16-byte blocks are the same. This only works because the mempak SDK functions write it multiple times. They act as a backup if the first one is found invalid. If all the blocks were corrupt but identical, it would not fail the validation.
Instead, validate the checksum itself by summing the first fourteen 16-bit words of the block, then AND-masking the value against 0xFFFF. This should match the 15th word in the block, and also match the 16th word in the block when subtracted from 0xFFF2.
All applications that rely on libdragon would benefit from more robust Controller Pak support. The algorithm is simple and can be used to dynamically generate the header with format_mempak
Haven't really looked into this one. Might be more of an issue of fitting more than one item in TRAM properly. Haven't tried giving a sprite a nonzero texture slot ID without adding additional sprites. I think the reason that multiple slots doesn't work is that the RDP is up converting the texture on copy to the output format and so the offset returned by the original copy function is wrong and thus corrupts the first sprite when you copy the second. I'll have to look into that theory in the future.
When I build and run tools/n64tool.c
passing the -t
option, I expected the ROM header to have the title set as the option indicates. Instead, the default title of "N64 Demo" is used. The command I ran was:
./n64tool -l 2M -h header -o helloworld.z64 helloworld.bin -t "HELLOWORLD"
Yet, when I examine the first 40 bytes of the ROM, n64tool.c's DEF_TITLE
value is present instead of HELLOWORLD
:
hexyl -n 40 helloworld.z64
ββββββββββ¬ββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββ¬βββββββββ¬βββββββββ
β00000000β 80 37 12 40 00 00 00 0f β 80 00 04 00 00 00 14 44 βΓ7β’@000β’βΓ0β’000β’Dβ
β00000010β ed 42 a2 d4 7a 71 cd 91 β 00 00 00 00 00 00 00 00 βΓBΓΓzqΓΓβ00000000β
β00000020β 4e 36 34 20 44 65 6d 6f β βN64 Demoβ β
ββββββββββ΄ββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββ΄βββββββββ΄βββββββββ
With the following code:
#include <cstdio>
#ifdef N64
#include <libdragon.h>
#endif
class Test
{
public:
const char *str;
int a; int b;
Test(const char *str1, int a1, int b1)
: str(str1)
, a(a1)
, b(b1)
{}
};
Test test_ctor("Hello", 42, 1379);
int main()
{
#ifdef N64
static resolution_t res = RESOLUTION_320x240;
static bitdepth_t bit = DEPTH_32_BPP;
init_interrupts();
console_init();
rdp_init();
controller_init();
timer_init();
debug_init_isviewer();
display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE );
console_set_render_mode(RENDER_AUTOMATIC);
#endif
printf("First print\n");
printf("Test: %s, %d, %d\n", test_ctor.str, test_ctor.a, test_ctor.b);
return 0;
}
Compiling for x86_64 (g++ 10.2.1, glibc 2.31, linux 5.10.0-7) with g++ a,cpp -Wl,--gc-sections
and executing, the output is:
First print
Test: Hello, 42, 1379
Compiling for Nintendo 64 (libdragon) with:
mips64-elf-g++ a.cpp -DN64 -o a.elf -ldragon -lc -lstdc++ -ldragonsys -Tn64.ld -Wl,--gc-sections
mips64-elf-objcopy a.elf a.bin -O binary
n64tool -l 1M -h /usr/local/mips64-elf/lib/header -o a.z64 a.bin
chksum64 a.z64
The output is:
First print
Test: (null), 0, 0
This issue vanishes if -Wl,--gc-sections is removed from the compilation flags. It means that the code used to initialize test_ctor
was somehow removed when garbage collecting the functions.
We can also remove the code disableing interrupts in inthandler
I've added support for Gamecube controllers in my gc branch:
https://github.com/clbr/libdragon/commits/gc
Not sure if you'd be interested in that? I only added the direct get api, since I like it more than the abstraction. You can use GC controllers on a N64 via a "straight through" cable, ie the raphnet and cube64-dx options won't work, they emulate N64 controllers.
The cleanup commit, "Constify a few SI controller command blocks", is independent and should probably be applied to your tree in any case. The padding in struct controller_data was wrong, it made the struct 160 bytes instead of 64, so if you decide not to include the GC support, please fix that some other way. In my gc branch, the struct is correctly 64 bytes.
I have this display function:
/* Assure RDP is ready for new commands */
rdp_sync( SYNC_PIPE );
/* Remove any clipping windows */
rdp_set_default_clipping();
/* Enable sprite display instead of solid color fill */
rdp_enable_texture_copy();
/* Attach RDP to display */
rdp_attach_display( disp );
/* Ensure the RDP is ready to receive sprites */
rdp_sync( SYNC_PIPE );
rdp_enable_primitive_fill();
rdp_set_primitive_color(0x000080FF);
rdp_sync( SYNC_PIPE );
rdp_draw_filled_rectangle(0, 0, 320, 240);
rdp_sync(SYNC_PIPE);
rdp_set_primitive_color(0x808080FF);
rdp_sync(SYNC_PIPE);
rdp_draw_filled_triangle(203, 98, 160, 120, 150, 150);
rdp_detach_display();
display_show(disp);
It works in CEN64. On a real N64, the resulting triangle is corrupt.
I run into this issue when trying to build the toolchain on mint linux.
I appologise if this stems from my lack of experience with linux, gcc and building from source in general, but I was wondering if I might be from following the readme to rigidly? Can you suggest a better forum for getting assistance with building the toolchain?
http://pastie.org/10242162
Currently it isnot well documented and may cause confusion.
In version.c
, libdragon tries to get LIBDRAGON_VERSION_MAJOR
, LIBDRAGON_VERSION_MINOR
and LIBDRAGON_VERSION_REVISION
.
This behavior was useful when we were injecting them from NPM package version, but now they may have become a chore to update.
Decide and remove as necessary or update them based on libdragon changes.
The header tool does not allow you to set or set the territory code in the header to any ROM file created during the compile process.
There should be no reason these are different. Need to look into merging C and C++ support back into one coherent package.
when i type "make" after ./build, i have an error like this : "error command not found bin/mips64-elf-gcc " so i have change this line in makefile : "N64PREFIX =
Some quick specs:
npm version 6.9.0
node version 10.16.3
OS: Windows 10
As the title states, running the npm run download command fails with the following errors:
Error: Cannot find module 'lodash'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object. (C:\users\user\repos\n64\libdragon\index.js:5:11)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] tc: node index.js "download"
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] tc script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?
The log file mentioned in the trace contains the following:
0 info it worked if it ends with ok
1 verbose cli [ 'C:\Program Files\nodejs\node.exe',
1 verbose cli 'C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js',
1 verbose cli 'run',
1 verbose cli 'tc',
1 verbose cli '--',
1 verbose cli 'download' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'pretc', 'tc', 'posttc' ]
5 info lifecycle [email protected]pretc: [email protected]tc: [email protected]
6 info lifecycle [email protected]
7 verbose lifecycle [email protected]tc: unsafe-perm in lifecycle truetc: PATH: C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;C:\users\userl\repos\n64\libdragon\node_modules.bin;C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin;C:\users\user\repos\n64\libdragon\node_modules.bin;C:\Users\user\bin;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\local\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Docker Toolbox;C:\Users\user\bin;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\local\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Users\user\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\libnvvp;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\libnvvp;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\iCLS;C:\Program Files\Intel\Intel(R) Management Engine Components\iCLS;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Windows\System32\OpenSSH;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\WiFi\bin;C:\Program Files\Common Files\Intel\WirelessCommon;C:\Python;C:\Python\Scripts;C:\Python\Lib\Site-Packages;C:\Program Files\Git\cmd;C:\Program Files\dotnet;C:\Program Files (x86)\GnuWin32\bin;C:\sqlite;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Program Files\PuTTY;C:\PostgreSQL\pg11\bin;C:\Users\user.cargo\bin;C:\Program Files\nodejs;C:\Users\user.cargo\bin;C:\Users\user\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Docker Toolbox;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\extras\CUPTI\libx64;C:\Users\user\Anaconda3_64;C:\Users\user\Anaconda3;C:\Users\user\AppData\Roaming\npm;C:\Program Files\Git\usr\bin\vendor_perl;C:\Program Files\Git\usr\bin\core_perl;C:\Program Files\Git\usr\bin\vendor_perl;C:\Program Files\Git\usr\bin\core_perl
8 verbose lifecycle [email protected]
9 verbose lifecycle [email protected]tc: CWD: C:\users\user\repos\n64\libdragontc: Args: [ '/d /s /c', 'node index.js "download"' ]
10 silly lifecycle [email protected]
11 silly lifecycle [email protected]tc: Returned: code: 1 signal: nulltc: Failed to exec tc script
12 info lifecycle [email protected]
13 verbose stack Error: [email protected] tc: node index.js "download"
13 verbose stack Exit status 1
13 verbose stack at EventEmitter. (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\index.js:301:16)
13 verbose stack at EventEmitter.emit (events.js:198:13)
13 verbose stack at ChildProcess. (C:\Program Files\nodejs\node_modules\npm\node_modules\npm-lifecycle\lib\spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:198:13)
13 verbose stack at maybeClose (internal/child_process.js:982:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:259:5)
14 verbose pkgid [email protected]
15 verbose cwd C:\users\user\repos\n64\libdragon
16 verbose Windows_NT 10.0.17134
17 verbose argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "run" "tc" "--" "download"
18 verbose node v10.16.3
19 verbose npm v6.9.0
20 error code ELIFECYCLE
21 error errno 1
22 error [email protected] tc: node index.js "download"
22 error Exit status 1
23 error Failed at the [email protected] tc script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]
N64 natively supports YUV texture format, while the sprite routines do not.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.