Skip to content

Commit

Permalink
Initial support for iQue player
Browse files Browse the repository at this point in the history
  • Loading branch information
rasky committed Nov 15, 2021
1 parent 2b818f4 commit d1a4818
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 26 deletions.
36 changes: 19 additions & 17 deletions examples/timers/timers.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,66 +15,68 @@ static volatile int running = 1; // clear by one-shot after 30 sec

void one_msec(int ovfl)
{
t1 += 0.001;
t1 += 0.001;
}

void half_sec(int ovfl)
{
t2 += 0.5;
t2 += 0.5;
}

void one_sec(int ovfl)
{
t3 += 1.0;
t3 += 1.0;
}

void one_shot(int ovfl)
{
running = 0;
running = 0;
}

int main(void)
{
timer_link_t *one_shot_t;
long long start, end;
timer_link_t *one_shot_t;
long long start, end;

/* Initialize peripherals */
display_init( res, bit, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE );
console_init();

console_set_render_mode(RENDER_MANUAL);

timer_init();
start = timer_ticks();
new_timer(TIMER_TICKS(1000), TF_CONTINUOUS, one_msec);
new_timer(TIMER_TICKS(500000), TF_CONTINUOUS, half_sec);
new_timer(TIMER_TICKS(1000000), TF_CONTINUOUS, one_sec);
one_shot_t = new_timer(TIMER_TICKS(30000000), TF_ONE_SHOT, one_shot); // the only one we have to keep track of
timer_init();
start = timer_ticks();
new_timer(TIMER_TICKS(1000), TF_CONTINUOUS, one_msec);
new_timer(TIMER_TICKS(500000), TF_CONTINUOUS, half_sec);
new_timer(TIMER_TICKS(1000000), TF_CONTINUOUS, one_sec);
one_shot_t = new_timer(TIMER_TICKS(30000000), TF_ONE_SHOT, one_shot); // the only one we have to keep track of

/* Main loop test */
while(running)
{
console_clear();

printf("Running on: %s\n", sys_bbplayer() ? "iQue" : "N64");
printf( "\n Every msec : %f", t1 );
printf( "\n Every half sec: %f", t2 );
printf( "\n Every sec : %f", t3 );

console_render();
}
end = timer_ticks();
// one-shot timers have to be explicitly freed
delete_timer(one_shot_t);
timer_close();
end = timer_ticks();
// one-shot timers have to be explicitly freed
delete_timer(one_shot_t);
timer_close();

console_clear();

printf("Running on: %s\n", sys_bbplayer() ? "iQue" : "N64");
printf( "\n Every msec : %f", t1 );
printf( "\n Every half sec: %f", t2 );
printf( "\n Every sec : %f", t3 );
printf( "\n\n Done in %f", (float)TIMER_MICROS_LL(end-start)/1000000.0f);

console_render();

while (1) ;
while (1) ;
}
9 changes: 8 additions & 1 deletion include/n64sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
* @{
*/

/**
* @brief Indicates whether we are running on a vanilla N64 or a iQue player
*/
extern int __bbplayer;

/**
* @brief Frequency of the MIPS R4300 CPU
*/
#define CPU_FREQUENCY 93750000
#define CPU_FREQUENCY (__bbplayer ? 140625000 : 93750000)


/**
Expand Down Expand Up @@ -143,6 +148,8 @@
extern "C" {
#endif

bool sys_bbplayer(void);

int sys_get_boot_cic();
void sys_set_boot_cic(int bc);
/**
Expand Down
7 changes: 6 additions & 1 deletion src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,12 @@ static bool usb_initialize_once(void) {
if (!once)
{
once = true;
ok = usb_initialize();
if (!sys_bbplayer())
ok = usb_initialize();
else
/* 64drive autodetection makes iQue player crash; disable USB
support altogether for now. */
ok = false;
}
return ok;
}
Expand Down
2 changes: 1 addition & 1 deletion src/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ void display_init( resolution_t res, bitdepth_t bit, uint32_t num_buffers, gamma
{
uint32_t registers[REGISTER_COUNT];
uint32_t tv_type = get_tv_type();
uint32_t control = 0x3000;
uint32_t control = !sys_bbplayer() ? 0x3000 : 0x1000;

/* Can't have the video interrupt happening here */
disable_interrupts();
Expand Down
24 changes: 24 additions & 0 deletions src/entrypoint.S
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@
.global _start
_start:
lw t0, 0x80000318 /* memory size */

/* Check whether we are running on iQue or N64. Use the MI version register
which has LSB set to 0xB0 on iQue. We assume 0xBn was meant for BBPlayer.
Notice that we want this test to be hard for emulators to pass by mistake,
so checking for a specific value while reading seems solid enough. */
lw t1, 0xA4300004
andi t1, 0xF0
bne t1, 0xB0, set_sp
li fp, 0 /* fp=0 -> vanilla N64 */

/* In iQue player, memory allocated to game can be configured and it appears
in 0x80000318. On the other hand, the top 8Mb of RDRAM is reserved to
savegames. So avoid putting the stack there, capping the size to 0x7C0000.
See also get_memory_size. */
li fp, 1 /* fp=1 -> iQue player */
li t1, 0x800000
blt t0, t1, set_sp
nop
li t0, 0x7C0000

set_sp:
li t1, 0x7FFFFFF0
addu sp,t0,t1 /* init stack */
la gp, _gp /* init data pointer */
Expand Down Expand Up @@ -58,6 +79,9 @@ bss_init:
jal data_cache_hit_writeback_invalidate
nop

/* Store the bbplayer flag now that BSS has been cleared */
sw fp, __bbplayer

/* load interrupt vector */
la t0,intvector
la t1,0xa0000000
Expand Down
26 changes: 25 additions & 1 deletion src/n64sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
* @{
*/

/**
* @brief Indicates whether we are running on a vanilla N64 or a iQue player
*/
int __bbplayer = 0;

/** @brief Return true if we are running on a iQue player */
bool sys_bbplayer(void) {
return __bbplayer != 0;
}

/**
* @brief Boot CIC
*
Expand Down Expand Up @@ -198,6 +208,17 @@ void inst_cache_invalidate_all(void)
*/
int get_memory_size()
{
if (sys_bbplayer()) {
/* On iQue, memory allocated to the game can be decided by the OS.
Even if the memory is allocated as 8Mb, the top part handles
save states (emulation of EEPROM/Flash/SRAM), so we should avoid
writing there anyway. See also entrypoint.S which sets up the
stack with the same logic. */
int size = (*(int*)0xA0000318);
if (size == 0x800000)
size = 0x7C0000;
return size;
}
return (__bootcic != 6105) ? (*(int*)0xA0000318) : (*(int*)0xA00003F0);
}

Expand All @@ -207,10 +228,13 @@ int get_memory_size()
* Checks whether the maximum available memory has been expanded to 8MB
*
* @return true if expansion pak detected, false otherwise.
*
* @note On iQue, this function returns true only if the game has been assigned
* exactly 8MB of RAM.
*/
bool is_memory_expanded()
{
return get_memory_size() == 0x800000;
return get_memory_size() >= 0x7C0000;
}

/** @brief Memory location to read which determines the TV type. */
Expand Down
2 changes: 1 addition & 1 deletion tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BUILD_DIR=build/
BUILD_DIR=build
include $(N64_INST)/include/n64.mk

all: testrom.z64 testrom_emu.z64
Expand Down
9 changes: 7 additions & 2 deletions tests/test_ticks.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,18 @@ void test_ticks(TestContext *ctx) {
register_VI_handler(frame_callback);
enable_interrupts();

ASSERT(ticks_0 == 0 && ticks_1 == 45812, "not reading correct register or function not inlined. Received %lu and %lu", ticks_0, ticks_1);
ASSERT(ticks_0 == 0 && ticks_1 == (!sys_bbplayer() ? 45812 : 30542), "not reading correct register or function not inlined. Received %lu and %lu", ticks_0, ticks_1);

// Sync to nearest video frame to use as an interval
while (state < Start);

test_ticks_func(ctx, wait_ticks, "wait_ticks", test_ticks_cases, sizeof(test_ticks_cases) / sizeof(test_ticks_cases[0]));
test_ticks_func(ctx, wait_ms, "wait_ms", test_ticks_ms_cases, sizeof(test_ticks_ms_cases) / sizeof(test_ticks_ms_cases[0]));

// The wait_ms test contains hardcoded tick values that refer to the conversion
// between milliseconds and ticks, as computed on a N64. It won't work on
// iQue, so just skip this part.
if (!sys_bbplayer())
test_ticks_func(ctx, wait_ms, "wait_ms", test_ticks_ms_cases, sizeof(test_ticks_ms_cases) / sizeof(test_ticks_ms_cases[0]));

// Cleanup
unregister_VI_handler(frame_callback);
Expand Down
4 changes: 2 additions & 2 deletions tests/testrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ int main() {
return 0;
}

printf("libdragon testsuite\n\n");
printf("libdragon testsuite (%s)\n\n", sys_bbplayer() ? "iQue" : "N64");
int failures = 0;
int successes = 0;
int skipped = 0;
Expand Down Expand Up @@ -293,7 +293,7 @@ int main() {
// happened and we need to double check this.
// In general, this benchmarking is extremely hard to get right for
// emulators, so don't even attempt it because we would get too many failures.
else if (!IN_EMULATOR &&
else if (!IN_EMULATOR && !sys_bbplayer() &&
!(tests[i].flags & TEST_FLAGS_NO_BENCHMARK) &&
((float)test_diff / (float)test_duration > ((tests[i].flags & TEST_FLAGS_IO) ? 0.1f : 0.05f))
) {
Expand Down

0 comments on commit d1a4818

Please sign in to comment.