this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #1222 from asiekierka/3ds-prescale

n3ds: add prescale linear filter, wide mode support; close #1219

authored by

Vadim Grigoruk and committed by
GitHub
d6dea1d9 ddf0cffa

+143 -77
+4 -4
src/system/n3ds/keyboard.c
··· 128 128 #define touch_areas_len (sizeof(touch_areas) / sizeof(touch_area_t)) 129 129 130 130 extern void n3ds_draw_texture(C3D_Tex* tex, int x, int y, int tx, int ty, int width, int height, int twidth, int theight, 131 - float cmul); 131 + int tgtheight, float cmul); 132 132 133 133 void n3ds_keyboard_init(tic_n3ds_keyboard *kbd) { 134 134 memset(kbd, 0, sizeof(tic_n3ds_keyboard)); ··· 148 148 n3ds_draw_texture(&(kbd->tex), area->x, area->y, 149 149 area->x, 16 + (area->y - 1), 150 150 area->w, area->h - 1, 151 - area->w, area->h - 1, 0.5f); 151 + area->w, area->h - 1, 240, 0.5f); 152 152 } 153 153 154 154 void n3ds_keyboard_draw(tic_n3ds_keyboard *kbd) { 155 155 if (kbd->tex.data != NULL) 156 156 { 157 - n3ds_draw_texture(&(kbd->tex), 0, 0, 0, 16, 320, 240, 320, 240, 1.0f); 157 + n3ds_draw_texture(&(kbd->tex), 0, 0, 0, 16, 320, 240, 320, 240, 240, 1.0f); 158 158 for(int i = 0; i < kbd->kd_count; i++) 159 159 { 160 160 n3ds_keyboard_draw_pressed(kbd, kbd->kd[i]); ··· 352 352 kbd->scroll_debounce = curr_clock + (u64) (delay * CPU_TICKS_PER_MSEC); 353 353 } 354 354 } 355 - } 355 + }
+139 -73
src/system/n3ds/main.c
··· 41 41 #define AUDIO_FREQ 44100 42 42 #define AUDIO_BLOCKS 4 43 43 44 + typedef struct { 45 + float x, y, z; 46 + float u, v, opa; 47 + } texture_vertex; 48 + 44 49 static struct 45 50 { 46 51 Studio* studio; ··· 52 57 struct 53 58 { 54 59 u32* tic_buf; 55 - C3D_Tex tic_tex; 56 - C3D_Mtx proj_top, proj_bottom; 57 - C3D_RenderTarget *target_top, *target_bottom; 60 + C3D_Tex tic_tex, tic_scaler_tex; 61 + C3D_Mtx proj_top, proj_bottom, proj_scaler; 62 + C3D_RenderTarget *target_top, *target_bottom, *target_scaler; 58 63 59 64 DVLB_s* shader_dvlb; 60 65 shaderProgram_s shader_program; ··· 63 68 64 69 int scaled; 65 70 bool on_bottom; 71 + bool wide_mode; 72 + 73 + texture_vertex *vbuf; 74 + int vbuf_pos; 75 + int vbuf_size; 66 76 } render; 67 77 68 78 struct { ··· 83 93 #endif 84 94 LightLock tick_lock; 85 95 } platform; 96 + 97 + // 256-wide 98 + // 384-wide 99 + // 400-wide 100 + #define N3DS_SCALED_MODE_COUNT 3 86 101 87 102 static const char n3ds_shader_shbin[289] = { 88 103 0x44, 0x56, 0x4c, 0x42, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, ··· 116 131 117 132 static const int n3ds_shader_shbin_length = 289; 118 133 134 + static void n3ds_vbuf_init(void) { 135 + C3D_BufInfo *bufInfo; 136 + platform.render.vbuf_pos = 0; 137 + platform.render.vbuf_size = 6 * 160; 138 + platform.render.vbuf = linearAlloc(sizeof(texture_vertex) * platform.render.vbuf_size); 139 + 140 + bufInfo = C3D_GetBufInfo(); 141 + BufInfo_Init(bufInfo); 142 + BufInfo_Add(bufInfo, platform.render.vbuf, sizeof(texture_vertex), 2, 0x10); 143 + } 144 + 145 + static void n3ds_vbuf_exit(void) { 146 + linearFree(platform.render.vbuf); 147 + platform.render.vbuf_size = 0; 148 + } 149 + 150 + static int n3ds_vbuf_clear(void) { 151 + platform.render.vbuf_pos = 0; 152 + } 153 + 154 + static int n3ds_vbuf_append(float x, float y, float z, float u, float v, float opa) { 155 + int pos = platform.render.vbuf_pos++; 156 + platform.render.vbuf[pos].x = x; 157 + platform.render.vbuf[pos].y = y; 158 + platform.render.vbuf[pos].z = z; 159 + platform.render.vbuf[pos].u = u; 160 + platform.render.vbuf[pos].v = v; 161 + platform.render.vbuf[pos].opa = opa; 162 + return pos; 163 + } 164 + 119 165 static void setClipboardText(const char* text) 120 166 { 121 167 if(platform.clipboard) ··· 215 261 216 262 static void update_screen_size(void) { 217 263 int scr_width = platform.render.on_bottom ? 320 : 400; 218 - 264 + 219 265 if (platform.render.scaled > 0) { 220 - float sw = platform.render.on_bottom ? 316.0f : 400.0f; 266 + float sw = platform.render.on_bottom ? 320.0f : (platform.render.scaled == 2 ? 400.0f : 384.0f); 221 267 float sh = TIC80_FULLHEIGHT * sw / TIC80_FULLWIDTH; 222 268 platform.screen_size.width = (int) (sw + 0.5f); 223 269 platform.screen_size.height = (int) (sh + 0.5f); ··· 232 278 233 279 static void n3ds_draw_init(void) 234 280 { 281 + u8 consoleModelId = 3; 235 282 C3D_TexEnv *texEnv; 236 283 237 - C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); 284 + platform.render.wide_mode = false; 285 + CFGU_GetSystemModel(&consoleModelId); 286 + if (consoleModelId != 3) { // O2DS 287 + gfxSetWide(true); 288 + platform.render.wide_mode = true; 289 + } 238 290 239 - platform.render.target_top = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, GPU_RB_DEPTH16); 240 - platform.render.target_bottom = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, GPU_RB_DEPTH16); 291 + C3D_Init(0x10000); 292 + 293 + platform.render.target_top = C3D_RenderTargetCreate(240, platform.render.wide_mode ? 800 : 400, GPU_RB_RGB8, 0); 294 + platform.render.target_bottom = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, 0); 241 295 C3D_RenderTargetClear(platform.render.target_top, C3D_CLEAR_ALL, 0, 0); 242 296 C3D_RenderTargetClear(platform.render.target_bottom, C3D_CLEAR_ALL, 0, 0); 243 297 C3D_RenderTargetSetOutput(platform.render.target_top, GFX_TOP, GFX_LEFT, ··· 245 299 C3D_RenderTargetSetOutput(platform.render.target_bottom, GFX_BOTTOM, GFX_LEFT, 246 300 GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); 247 301 248 - C3D_TexInitVRAM(&platform.render.tic_tex, 256, 256, GPU_RGBA8); 249 302 platform.render.tic_buf = linearAlloc(256 * 256 * 4); 303 + C3D_TexInitVRAM(&platform.render.tic_tex, 256, 256, GPU_RGBA8); // 256KB 304 + // maximum size: (256 x 144) * 3 => 768 x 432 305 + C3D_TexInitVRAM(&platform.render.tic_scaler_tex, 1024, 512, GPU_RGBA8); // 2MB 306 + 307 + platform.render.target_scaler = C3D_RenderTargetCreateFromTex(&platform.render.tic_scaler_tex, GPU_TEXFACE_2D, 0, 0); 250 308 251 309 Mtx_OrthoTilt(&platform.render.proj_top, 0.0, 400.0, 0.0, 240.0, -1.0, 1.0, true); 252 310 Mtx_OrthoTilt(&platform.render.proj_bottom, 0.0, 320.0, 0.0, 240.0, -1.0, 1.0, true); 311 + Mtx_Ortho(&platform.render.proj_scaler, 0.0, 1024.0, 512.0, 0.0, -1.0, 1.0, true); 312 + 313 + C3D_TexSetFilter(&platform.render.tic_tex, GPU_NEAREST, GPU_NEAREST); 314 + C3D_TexSetFilter(&platform.render.tic_scaler_tex, GPU_LINEAR, GPU_LINEAR); 253 315 254 316 texEnv = C3D_GetTexEnv(0); 255 317 C3D_TexEnvSrc(texEnv, C3D_Both, GPU_TEXTURE0, 0, 0); ··· 257 319 C3D_TexEnvOpAlpha(texEnv, 0, 0, 0); 258 320 C3D_TexEnvFunc(texEnv, C3D_Both, GPU_MODULATE); 259 321 260 - C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); 322 + C3D_DepthTest(false, GPU_GEQUAL, GPU_WRITE_ALL); 261 323 C3D_CullFace(GPU_CULL_NONE); 262 324 263 325 platform.render.shader_dvlb = DVLB_ParseFile((u32 *) n3ds_shader_shbin, n3ds_shader_shbin_length); ··· 273 335 C3D_SetAttrInfo(&(platform.render.shader_attr)); 274 336 275 337 update_screen_size(); 338 + 339 + n3ds_vbuf_init(); 276 340 } 277 341 278 342 static void n3ds_draw_exit(void) 279 343 { 344 + n3ds_vbuf_exit(); 345 + 280 346 linearFree(platform.render.tic_buf); 347 + C3D_TexDelete(&platform.render.tic_scaler_tex); 281 348 C3D_TexDelete(&platform.render.tic_tex); 282 349 283 350 C3D_RenderTargetDelete(platform.render.target_top); 284 351 C3D_RenderTargetDelete(platform.render.target_bottom); 352 + C3D_RenderTargetDelete(platform.render.target_scaler); 285 353 286 354 C3D_Fini(); 287 355 } 288 356 289 - void n3ds_draw_texture(C3D_Tex* tex, int x, int y, int tx, int ty, int width, int height, int twidth, int theight, 357 + void n3ds_draw_texture(C3D_Tex *tex, int x, int y, int tx, int ty, int width, int height, int twidth, int theight, 358 + int tgtheight, 290 359 float cmul) { 291 360 float txmin, tymin, txmax, tymax; 361 + int pos; 292 362 txmin = (float) tx / tex->width; 293 363 tymax = (float) ty / tex->height; 294 364 txmax = (float) (tx+twidth) / tex->width; 295 365 tymin = (float) (ty+theight) / tex->height; 296 366 297 367 C3D_TexBind(0, tex); 298 - C3D_ImmDrawBegin(GPU_TRIANGLE_STRIP); 299 - C3D_ImmSendAttrib((float) x, (float) 240 - y - height, 0.0f, 0.0f); 300 - C3D_ImmSendAttrib((float) txmin, (float) tymin, cmul, 0.0f); 301 368 302 - C3D_ImmSendAttrib((float) x + width, (float) 240 - y - height, 0.0f, 0.0f); 303 - C3D_ImmSendAttrib((float) txmax, (float) tymin, cmul, 0.0f); 369 + pos = n3ds_vbuf_append((float) x, (float) tgtheight - y - height, 0.0f, (float) txmin, (float) tymin, cmul); 370 + n3ds_vbuf_append((float) x + width, (float) tgtheight - y - height, 0.0f, (float) txmax, (float) tymin, cmul); 371 + n3ds_vbuf_append((float) x + width, (float) tgtheight - y, 0.0f, (float) txmax, (float) tymax, cmul); 304 372 305 - C3D_ImmSendAttrib((float) x, (float) 240 - y, 0.0f, 0.0f); 306 - C3D_ImmSendAttrib((float) txmin, (float) tymax, cmul, 0.0f); 373 + n3ds_vbuf_append((float) x, (float) tgtheight - y - height, 0.0f, (float) txmin, (float) tymin, cmul); 374 + n3ds_vbuf_append((float) x, (float) tgtheight - y, 0.0f, (float) txmin, (float) tymax, cmul); 375 + n3ds_vbuf_append((float) x + width, (float) tgtheight - y, 0.0f, (float) txmax, (float) tymax, cmul); 307 376 308 - C3D_ImmSendAttrib((float) x + width, (float) 240 - y, 0.0f, 0.0f); 309 - C3D_ImmSendAttrib((float) txmax, (float) tymax, cmul, 0.0f); 310 - C3D_ImmDrawEnd(); 377 + C3D_DrawArrays(GPU_TRIANGLES, pos, 6); 311 378 } 312 379 313 380 #define FRAME_PITCH (TIC80_FULLWIDTH * sizeof(u32)) ··· 316 383 { 317 384 u32 *in = platform.studio->tic->screen; 318 385 319 - /* for (int y = 0; y < TIC80_FULLHEIGHT; y++) { 320 - out = platform.render.tic_buf + (y * 256); 321 - for (int x = 0; x < TIC80_FULLWIDTH; x++, in++, out++) { 322 - *out = __builtin_bswap32(*in); 323 - } 324 - memcpy(out, in, sizeof(u32) * TIC80_FULLWIDTH); 325 - } */ 326 - 327 - if (platform.render.scaled == 2) { 386 + if (platform.render.scaled >= 1) { 328 387 // pad border 1 pixel lower to minimize glitches in "linear" scaling mode 329 388 memcpy( 330 389 in + (FRAME_PITCH * TIC80_FULLHEIGHT), ··· 332 391 FRAME_PITCH 333 392 ); 334 393 GSPGPU_FlushDataCache(in, (TIC80_FULLHEIGHT + 1) * FRAME_PITCH); 335 - } else { 394 + } else { 336 395 GSPGPU_FlushDataCache(in, TIC80_FULLHEIGHT * FRAME_PITCH); 337 396 } 338 397 ··· 343 402 GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | 344 403 GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) 345 404 ); 346 - GSPGPU_FlushDataCache(platform.render.tic_tex.data, 256 * 256 * 4); 405 + } 406 + 407 + static inline void n3ds_clear_border(C3D_RenderTarget *target) 408 + { 409 + C3D_RenderTargetClear(target, C3D_CLEAR_ALL, platform.studio->tic->screen[0] >> 8, 0); 410 + } 411 + 412 + static void n3ds_draw_screen(int scale_multiplier) 413 + { 414 + n3ds_draw_texture((scale_multiplier > 1) ? &platform.render.tic_scaler_tex : &platform.render.tic_tex, 415 + platform.screen_size.x, platform.screen_size.y, 416 + 0, 0, 417 + platform.screen_size.width, platform.screen_size.height, 418 + TIC80_FULLWIDTH * scale_multiplier, TIC80_FULLHEIGHT * scale_multiplier, 419 + 240, 1.0f); 347 420 } 348 421 349 422 static void n3ds_draw_frame(void) 350 423 { 351 - if (platform.keyboard.render_dirty && !platform.render.on_bottom) { 352 - C3D_FrameDrawOn(platform.render.target_bottom); 353 - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_bottom); 424 + int scale_multiplier = (platform.render.scaled > 0) ? 3 : 1; 354 425 355 - n3ds_keyboard_draw(&platform.keyboard); 356 - platform.keyboard.render_dirty = false; 426 + if (scale_multiplier > 1) { 427 + // prescale 428 + C3D_FrameDrawOn(platform.render.target_scaler); 429 + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_scaler); 430 + 431 + n3ds_draw_texture(&platform.render.tic_tex, 432 + 0, 0, 433 + 0, 0, 434 + TIC80_FULLWIDTH * scale_multiplier, TIC80_FULLHEIGHT * scale_multiplier, 435 + TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 436 + 512, 1.0f); 357 437 } 358 438 439 + #ifndef RENDER_CONSOLE_TOP 440 + // draw top screen 441 + C3D_FrameDrawOn(platform.render.target_top); 442 + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_top); 443 + n3ds_clear_border(platform.render.target_top); 444 + 359 445 if (!platform.render.on_bottom) { 360 - #ifdef RENDER_CONSOLE_TOP 361 - return; 446 + n3ds_draw_screen(scale_multiplier); 447 + } 362 448 #endif 363 - } else { 364 - // clear top screen 365 - C3D_FrameDrawOn(platform.render.target_top); 366 - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_top); 367 449 368 - // fill with border color 369 - C3D_RenderTargetClear(platform.render.target_top, C3D_CLEAR_ALL, platform.studio->tic->screen[0] >> 8, 0); 370 - } 450 + // draw bottom screen 451 + C3D_FrameDrawOn(platform.render.target_bottom); 452 + C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_bottom); 371 453 372 454 if (platform.render.on_bottom) { 373 - C3D_FrameDrawOn(platform.render.target_bottom); 374 - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_bottom); 375 - 376 - // fill with border color 377 - C3D_RenderTargetClear(platform.render.target_bottom, C3D_CLEAR_ALL, platform.studio->tic->screen[0] >> 8, 0); 378 - } else { 379 - C3D_FrameDrawOn(platform.render.target_top); 380 - C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, platform.render.shader_proj_mtx_loc, &platform.render.proj_top); 381 - 382 - // fill with border color 383 - C3D_RenderTargetClear(platform.render.target_top, C3D_CLEAR_ALL, platform.studio->tic->screen[0] >> 8, 0); 455 + n3ds_clear_border(platform.render.target_bottom); 456 + n3ds_draw_screen(scale_multiplier); 457 + } else if (platform.keyboard.render_dirty) { 458 + n3ds_keyboard_draw(&platform.keyboard); 459 + platform.keyboard.render_dirty = false; 384 460 } 385 - 386 - n3ds_draw_texture(&platform.render.tic_tex, 387 - platform.screen_size.x, platform.screen_size.y, 388 - 0, 0, 389 - platform.screen_size.width, platform.screen_size.height, 390 - TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 391 - 1.0f); 392 461 } 393 462 394 463 void n3ds_sound_init(int sample_rate) ··· 478 547 479 548 if (key_held & KEY_TOUCH) 480 549 { 481 - hidTouchRead(&touch); 550 + hidTouchRead(&touch); 482 551 if ( 483 552 touch.px >= platform.screen_size.x 484 553 && touch.py >= platform.screen_size.y ··· 514 583 515 584 u32 kup = hidKeysUp(); 516 585 if (kup & KEY_SELECT) { 517 - platform.render.scaled = (platform.render.scaled + 1) % 3; 518 - 519 - if (platform.render.scaled == 2) { 520 - C3D_TexSetFilter(&platform.render.tic_tex, GPU_LINEAR, GPU_LINEAR); 521 - } else { 522 - C3D_TexSetFilter(&platform.render.tic_tex, GPU_NEAREST, GPU_LINEAR); 523 - } 524 - 586 + platform.render.scaled = (platform.render.scaled + 1) % N3DS_SCALED_MODE_COUNT; 525 587 update_screen_size(); 526 588 } 527 589 if (kup & (KEY_L | KEY_R)) { ··· 549 611 #ifdef RENDER_CONSOLE_TOP 550 612 consoleInit(GFX_TOP, NULL); 551 613 #endif 614 + cfguInit(); 552 615 romfsInit(); 553 616 554 617 memset(&platform, 0, sizeof(platform)); ··· 580 643 581 644 platform.studio->tick(); 582 645 audio_update(); 646 + 583 647 n3ds_copy_frame(); 584 648 585 649 LightLock_Unlock(&platform.tick_lock); 586 650 587 651 bool sync = (C3D_FrameCounter(0) == start_frame); 588 652 C3D_FrameBegin(sync ? C3D_FRAME_SYNCDRAW : 0); 653 + n3ds_vbuf_clear(); 589 654 590 655 n3ds_draw_frame(); 591 656 ··· 607 672 #endif 608 673 609 674 romfsExit(); 675 + cfguExit(); 610 676 gfxExit(); 611 677 612 678 return 0;