Codebase list higan / 01b9698
Imported Upstream version 0.082 Tobias Hansen 12 years ago
245 changed file(s) with 7349 addition(s) and 9651 deletion(s). Raw diff Collapse all Expand all
00 include nall/Makefile
1
12 snes := snes
23 gameboy := gameboy
34 profile := accuracy
45 ui := ui
5 # phoenix := gtk
66
77 # options += debugger
88
1313 link :=
1414 objects := libco
1515
16 # profile-guided instrumentation
17 # flags += -fprofile-generate
18 # link += -lgcov
16 # profile-guided optimization mode
17 # pgo := instrument
18 # pgo := optimize
1919
20 # profile-guided optimization
21 # flags += -fprofile-use
20 ifeq ($(pgo),instrument)
21 flags += -fprofile-generate
22 link += -lgcov
23 else ifeq ($(pgo),optimize)
24 flags += -fprofile-use
25 endif
2226
2327 flags := $(flags) $(foreach o,$(call strupper,$(options)),-D$o)
2428
77777777 <cartridge sha256="d9b7f9356be0780f0037093a86ef8450f15e569cbd3680073d1cd345dfadb709">
77787778 <name>Captain Commando (USA)</name>
77797779 <cheat>
7780 <description>Invincibility - p1</description>
7780 <description>Invincibility - P1</description>
77817781 <code>CB4E-7FD4</code>
77827782 <code>D04E-7F04</code>
77837783 <code>B24E-7F64</code>
81928192 <description>Chopper can carry 30 hostages</description>
81938193 <code>F3C7-3D53</code>
81948194 <code>F3C1-1F5E</code>
8195 </cheat>
8196 </cartridge>
8197 <cartridge sha256="224572832b988f31a81c907f751f0292f5702a3acea5866ce6742387c7c6239d">
8198 <name>Choujikuu Yousai Macross - Scrambled Valkyrie (Japan)</name>
8199 <cheat>
8200 <description>Invincibility</description>
8201 <code>7E0A90FF</code>
8202 </cheat>
8203 <cheat>
8204 <description>Infinite health</description>
8205 <code>C268-4F64</code>
8206 <code>C269-47A4</code>
8207 </cheat>
8208 <cheat>
8209 <description>Infinite absorb charge</description>
8210 <code>C2B2-C4D1</code>
8211 </cheat>
8212 <cheat>
8213 <description>Infinite continues</description>
8214 <code>7E02AA09</code>
8215 </cheat>
8216 <cheat>
8217 <description>Hit anywhere</description>
8218 <code>DD6B-3FD7</code>
8219 <code>DD65-3467</code>
8220 <code>DD66-34D7</code>
81958221 </cheat>
81968222 </cartridge>
81978223 <cartridge sha256="06d1c2b06b716052c5596aaa0c2e5632a027fee1a9a28439e509f813c30829a9">
1011210138 <code>DD3B-6FA5</code>
1011310139 </cheat>
1011410140 <cheat>
10115 <description>Start with 99 lives - both players</description>
10116 <code>7E106799</code>
10117 </cheat>
10118 <cheat>
1011910141 <description>Infinite Shield - P1</description>
1012010142 <code>7E177BFF</code>
1012110143 </cheat>
1013610158 <code>7E17EB08</code>
1013710159 </cheat>
1013810160 <cheat>
10139 <description>Max 2ndGun - P2</description>
10161 <description>Max 2nd Gun - P2</description>
1014010162 <code>7E177C08</code>
10163 </cheat>
10164 <cheat>
10165 <description>Hit anywhere - both players</description>
10166 <code>6D23-6FA4</code>
10167 <code>C22D-A764</code>
10168 <code>DD28-67A4</code>
10169 <code>DD2E-6D04</code>
10170 </cheat>
10171 <cheat>
10172 <description>Start with the strongest main weapon and 8 lives - both players</description>
10173 <code>3CC3-6DA7</code>
10174 <code>62C3-6467</code>
10175 <code>62C3-6707</code>
10176 <code>CBC3-6D07</code>
10177 <code>D6C3-6D67</code>
1014110178 </cheat>
1014210179 <cheat>
1014310180 <description>Start with 1 Green Power Cube - P1</description>
1018210219 <code>49C3-6D67</code>
1018310220 <code>CBC3-6D07</code>
1018410221 <code>3CC3-6DA7</code>
10222 </cheat>
10223 <cheat>
10224 <description>Start with 99 lives - both players</description>
10225 <code>7E106799</code>
1018510226 </cheat>
1018610227 <cheat>
1018710228 <description>Start on planet B</description>
2588325924 <cartridge sha256="457abe634e0a8be03e29513a3dca8f3e9d0ddc6bf97d8931f2316094260f3712">
2588425925 <name>Lion King, The (USA)</name>
2588525926 <cheat>
25927 <description>Almost infinite health</description>
25928 <code>C298-7DDE</code>
25929 </cheat>
25930 <cheat>
2588625931 <description>Infinite lives</description>
2588725932 <code>CE6E-8464</code>
25888 </cheat>
25889 <cheat>
25890 <description>Almost infinite energy</description>
25891 <code>C298-7DDE</code>
2589225933 </cheat>
2589325934 <cheat>
2589425935 <description>Roaring doesn't decrease your roar meter</description>
3041930460 <cartridge sha256="2731f0bd1c87e75121f41d1ed5cc9fbf177f414b8bf831c76fd9c4b58c86ed08">
3042030461 <name>Mary Shelley's Frankenstein (USA)</name>
3042130462 <cheat>
30463 <description>Invincibility (blinking)</description>
30464 <code>7E200D09</code>
30465 </cheat>
30466 <cheat>
3042230467 <description>Infinite health</description>
3042330468 <code>C2B9-1DA4</code>
3042430469 <code>8533-3F0D</code>
30470 </cheat>
30471 <cheat>
30472 <description>Infinite health (alt)</description>
30473 <code>7E20431D</code>
3042530474 </cheat>
3042630475 <cheat>
3042730476 <description>Energy balls don't deplete health</description>
3093830987 <code>F0CA-3FA0</code>
3093930988 <code>DDCA-34D0</code>
3094030989 </cheat>
30990 <cheat>
30991 <description>View ending (select Capcom Championship)</description>
30992 <code>81829BEE</code>
30993 <code>81829CE0</code>
30994 </cheat>
3094130995 </cartridge>
3094230996 <cartridge sha256="b8f70a6e7fb93819f79693578887e2c11e196bdf1ac6ddc7cb924b1ad0be2d32">
3094330997 <name>Mega Man X (USA) (Rev 1)</name>
3137731431 <cartridge sha256="057484558ebd18165f98e556b994080535e31cefdd98b5edb190516f7040fc9d">
3137831432 <name>Metal Morph (USA)</name>
3137931433 <cheat>
31434 <description>Invincibility</description>
31435 <code>7E038703</code>
31436 </cheat>
31437 <cheat>
31438 <description>Infinite ammo for all weapons (disable to change weapons)</description>
31439 <code>C926-C7A1</code>
31440 </cheat>
31441 <cheat>
31442 <description>Infinite continues</description>
31443 <code>C9A9-4F65</code>
31444 </cheat>
31445 <cheat>
31446 <description>Infinite time on continue screen</description>
31447 <code>C2AD-4D65</code>
31448 </cheat>
31449 <cheat>
3138031450 <description>Start with 255 continues</description>
3138131451 <code>EE6C-1FDD</code>
31382 </cheat>
31383 <cheat>
31384 <description>Freeze timer on continue screen</description>
31385 <code>C2AD-4D65</code>
31386 </cheat>
31387 <cheat>
31388 <description>Infinite ammo for all weapons (to change weapons, turn code off, pick up new weapon, turn back on)</description>
31389 <code>C926-C7A1</code>
31390 </cheat>
31391 <cheat>
31392 <description>Infinite continues</description>
31393 <code>C9A9-4F65</code>
3139431452 </cheat>
3139531453 </cartridge>
3139631454 <cartridge sha256="0d7f875877fe856066cfb39b4ecdbbe7d48393a75770720876c94419f809bb1c">
4932749385 <description>Infinite lives</description>
4932849386 <code>A268-4716</code>
4932949387 </cheat>
49388 <cheat>
49389 <description>Hit anywhere</description>
49390 <code>6DA9-1DA7</code>
49391 <code>DD87-1D41</code>
49392 <code>DDA5-4FD7</code>
49393 </cheat>
49394 <cheat>
49395 <description>Keep main weapon after dying</description>
49396 <code>C26C-4446</code>
49397 </cheat>
49398 <cheat>
49399 <description>Start with strongest main weapon</description>
49400 <code>62C4-1F46</code>
49401 </cheat>
4933049402 </cartridge>
4933149403 <cartridge sha256="16f9c90d75bd23d0620be00ecf818fcb25c5935d4ee26b1fe17b926f8987aa65">
4933249404 <name>Super Off Road - The Baja (USA)</name>
4955849630 <cartridge sha256="05c7f6461209020785fba33007e1830820aa44ada4b1a6f991d936bf2335b15b">
4955949631 <name>Super R-Type (USA)</name>
4956049632 <cheat>
49561 <description>Start with Invincibility (blinking)</description>
49562 <code>82C2-DF61</code>
49563 </cheat>
49564 <cheat>
49565 <description>Start with Invincibility (blinking) (alt)</description>
49566 <code>7E15BD00</code>
49567 </cheat>
49568 <cheat>
4956949633 <description>Infinite lives</description>
4957049634 <code>C2C7-6D0F</code>
49635 </cheat>
49636 <cheat>
49637 <description>Infinite FORCE once obtained</description>
49638 <code>C267-A4D9</code>
49639 </cheat>
49640 <cheat>
49641 <description>Always fire charged shots (hold B)</description>
49642 <code>7287-0FD1</code>
49643 <code>DD87-0D61</code>
4957149644 </cheat>
4957249645 <cheat>
4957349646 <description>Spiral motion gun takes less time to power up</description>
4960149674 <code>7D68-6D6B</code>
4960249675 </cheat>
4960349676 <cheat>
49604 <description>Once FORCE has been obtained, keep it forever</description>
49605 <code>C267-A4D9</code>
49677 <description>Start with Invincibility (blinking)</description>
49678 <code>82C2-DF61</code>
49679 </cheat>
49680 <cheat>
49681 <description>Start with Invincibility (blinking) (alt)</description>
49682 <code>7E15BD00</code>
4960649683 </cheat>
4960749684 <cheat>
4960849685 <description>Start with 1 life instead of 3</description>
5764057717 <cartridge sha256="b27e2e957fa760f4f483e2af30e03062034a6c0066984f2e284cc2cb430b2059">
5764157718 <name>Zombies Ate My Neighbors (USA)</name>
5764257719 <cheat>
57643 <description>Infinite health</description>
57720 <description>Invincibility, hit anywhere, get items from anywhere (do not use martian gun) - both players</description>
57721 <code>6DEC-14D4</code>
57722 <code>DD2F-476D</code>
57723 <code>DD8D-37D7</code>
57724 <code>DD8E-C767</code>
57725 </cheat>
57726 <cheat>
57727 <description>Invincibility - both players</description>
57728 <code>DD2F-476D</code>
57729 </cheat>
57730 <cheat>
57731 <description>Infinite health - both players</description>
5764457732 <code>3C20-4D0D</code>
5764557733 </cheat>
5764657734 <cheat>
5765257740 <code>7E1CBA0A</code>
5765357741 </cheat>
5765457742 <cheat>
57655 <description>Infinite weapons</description>
57743 <description>Infinite weapons - both players</description>
5765657744 <code>DD30-1FA7</code>
5765757745 </cheat>
5765857746 <cheat>
5766457752 <code>DD39-34D4</code>
5766557753 </cheat>
5766657754 <cheat>
57667 <description>Infinite lives</description>
57755 <description>Infinite lives - both players</description>
5766857756 <code>82AA-CF07</code>
5766957757 </cheat>
5767057758 <cheat>
5786057948 <code>7E1CF250</code>
5786157949 </cheat>
5786257950 <cheat>
57951 <description>Victims are invincible</description>
57952 <code>18CC-37DA</code>
57953 </cheat>
57954 <cheat>
5786357955 <description>Package of 99 Squirtgun shots worth 999</description>
5786457956 <code>DBEC-4704</code>
5786557957 </cheat>
44 period = divisor << frequency;
55 if(frequency < 14) {
66 bool bit = (lfsr ^ (lfsr >> 1)) & 1;
7 lfsr = (lfsr >> 1) ^ (bit << 14);
8 if(narrow_lfsr) lfsr |= (bit << 6);
7 lfsr = (lfsr >> 1) ^ (bit << (narrow_lfsr ? 6 : 14));
98 }
109 }
1110
3029 void APU::Noise::write(unsigned r, uint8 data) {
3130 if(r == 1) {
3231 initial_length = 64 - (data & 0x3f);
33
3432 length = initial_length;
3533 }
3634
4543 narrow_lfsr = data & 0x08;
4644 divisor = (data & 0x07) << 4;
4745 if(divisor == 0) divisor = 8;
48
4946 period = divisor << frequency;
5047 }
5148
6360 }
6461
6562 void APU::Noise::power() {
66 initial_length = 0;
6763 envelope_volume = 0;
6864 envelope_direction = 0;
6965 envelope_frequency = 0;
7369 counter = 0;
7470
7571 output = 0;
72 initial_length = 0;
7673 length = 0;
7774 envelope_period = 0;
7875 volume = 0;
8178 }
8279
8380 void APU::Noise::serialize(serializer &s) {
84 s.integer(initial_length);
8581 s.integer(envelope_volume);
8682 s.integer(envelope_direction);
8783 s.integer(envelope_frequency);
9187 s.integer(counter);
9288
9389 s.integer(output);
90 s.integer(initial_length);
9491 s.integer(length);
9592 s.integer(envelope_period);
9693 s.integer(volume);
00 struct Noise {
1 unsigned initial_length;
21 unsigned envelope_volume;
32 bool envelope_direction;
43 unsigned envelope_frequency;
87 bool counter;
98
109 int16 output;
10 unsigned initial_length;
1111 unsigned length;
1212 unsigned envelope_period;
1313 unsigned volume;
6565
6666 if(r == 1) {
6767 duty = data >> 6;
68 length = data & 0x3f;
68 initial_length = 64 - (data & 0x3f);
69 length = initial_length;
6970 }
7071
7172 if(r == 2) {
8485 frequency = ((data & 7) << 8) | (frequency & 0x00ff);
8586
8687 if(initialize) {
88 length = initial_length;
8789 envelope_period = envelope_frequency;
8890 volume = envelope_volume;
8991 frequency_shadow = frequency;
101103 sweep_direction = 0;
102104 sweep_shift = 0;
103105 duty = 0;
106 initial_length = 0;
104107 length = 0;
105108 envelope_volume = 0;
106109 envelope_direction = 0;
124127 s.integer(sweep_direction);
125128 s.integer(sweep_shift);
126129 s.integer(duty);
130 s.integer(initial_length);
127131 s.integer(length);
128132 s.integer(envelope_volume);
129133 s.integer(envelope_direction);
22 unsigned sweep_direction;
33 unsigned sweep_shift;
44 unsigned duty;
5 unsigned initial_length;
56 unsigned length;
67 unsigned envelope_volume;
78 unsigned envelope_direction;
3232 void APU::Square2::write(unsigned r, uint8 data) {
3333 if(r == 1) {
3434 duty = data >> 6;
35 length = data & 0x3f;
35 initial_length = 64 - (data & 0x3f);
36 length = initial_length;
3637 }
3738
3839 if(r == 2) {
5152 frequency = ((data & 7) << 8) | (frequency & 0x00ff);
5253
5354 if(initialize) {
55 length = initial_length;
5456 envelope_period = envelope_frequency;
5557 volume = envelope_volume;
5658 }
6163
6264 void APU::Square2::power() {
6365 duty = 0;
66 initial_length = 0;
6467 length = 0;
6568 envelope_volume = 0;
6669 envelope_direction = 0;
7881
7982 void APU::Square2::serialize(serializer &s) {
8083 s.integer(duty);
84 s.integer(initial_length);
8185 s.integer(length);
8286 s.integer(envelope_volume);
8387 s.integer(envelope_direction);
00 struct Square2 {
11 unsigned duty;
2 unsigned initial_length;
23 unsigned length;
34 unsigned envelope_volume;
45 unsigned envelope_direction;
2727
2828 if(r == 1) {
2929 initial_length = 256 - data;
30
3130 length = initial_length;
3231 }
3332
6766
6867 void APU::Wave::power() {
6968 dac_enable = 0;
70 initial_length = 0;
7169 volume = 0;
7270 frequency = 0;
7371 counter = 0;
7775
7876 output = 0;
7977 enable = 0;
78 initial_length = 0;
8079 length = 0;
8180 period = 0;
8281 pattern_offset = 0;
8584
8685 void APU::Wave::serialize(serializer &s) {
8786 s.integer(dac_enable);
88 s.integer(initial_length);
8987 s.integer(volume);
9088 s.integer(frequency);
9189 s.integer(counter);
9391
9492 s.integer(output);
9593 s.integer(enable);
94 s.integer(initial_length);
9695 s.integer(length);
9796 s.integer(period);
9897 s.integer(pattern_offset);
00 struct Wave {
11 bool dac_enable;
2 unsigned initial_length;
32 unsigned volume;
43 unsigned frequency;
54 bool counter;
76
87 int16 output;
98 bool enable;
9 unsigned initial_length;
1010 unsigned length;
1111 unsigned period;
1212 unsigned pattern_offset;
5454
5555 void Cartridge::MMM01::power() {
5656 rom_mode = 0;
57 rom_base = 0x00;
57 rom_base = 0;
5858
5959 ram_enable = false;
6060 rom_select = 0x01;
579579 }
580580
581581 void CPU::op_ei() {
582 status.ime = 1;
582 status.ei = true;
583 //status.ime = 1;
583584 }
584585
585586 //jump commands
113113 status.clock = 0;
114114 status.halt = false;
115115 status.stop = false;
116 status.ei = false;
116117 status.ime = 0;
117118
118119 status.p15 = 0;
1616 unsigned clock;
1717 bool halt;
1818 bool stop;
19 bool ei;
1920 bool ime;
2021
2122 //$ff00 JOYP
2020 s.integer(status.clock);
2121 s.integer(status.halt);
2222 s.integer(status.stop);
23 s.integer(status.ei);
2324 s.integer(status.ime);
2425
2526 s.integer(status.p15);
00 #ifdef CPU_CPP
11
22 void CPU::op_io() {
3 cycle_edge();
34 add_clocks(4);
45 }
56
67 uint8 CPU::op_read(uint16 addr) {
8 cycle_edge();
79 uint8 r = bus.read(addr);
810 add_clocks(4);
911 return r;
1012 }
1113
1214 void CPU::op_write(uint16 addr, uint8 data) {
15 cycle_edge();
1316 bus.write(addr, data);
1417 add_clocks(4);
1518 }
1619
20 void CPU::cycle_edge() {
21 if(status.ei) {
22 status.ei = false;
23 status.ime = 1;
24 }
25 }
26
1727 #endif
88 void op_io();
99 uint8 op_read(uint16 addr);
1010 void op_write(uint16 addr, uint8 data);
11 void cycle_edge();
44 namespace GameBoy {
55 namespace Info {
66 static const char Name[] = "bgameboy";
7 static const char Version[] = "000.19";
8 static unsigned SerializerVersion = 1;
7 static const char Version[] = "000.21";
8 static unsigned SerializerVersion = 2;
99 }
1010 }
1111
1717 }
1818
1919 add_clocks(4);
20
21 if(status.lx == 0) {
20 status.lx += 4;
21 if(status.lx >= 456) scanline();
22
23 if(status.display_enable && status.lx == 0) {
2224 if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat);
2325 }
2426
25 if(status.lx == 252) {
27 if(status.display_enable && status.lx == 252) {
2628 if(status.interrupt_hblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
2729 }
2830 }
2931 }
3032
3133 void LCD::add_clocks(unsigned clocks) {
32 status.lx += clocks;
33 if(status.lx >= 456) scanline();
34
3534 clock += clocks;
3635 if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) {
3736 co_switch(scheduler.active_thread = cpu.thread);
4241 status.lx -= 456;
4342 if(++status.ly == 154) frame();
4443
45 if(status.interrupt_lyc == true) {
44 if(status.display_enable && status.interrupt_lyc == true) {
4645 if(status.ly == status.lyc) cpu.interrupt_raise(CPU::Interrupt::Stat);
4746 }
4847
4948 if(status.ly < 144) render();
5049
51 if(status.ly == 144) {
50 if(status.display_enable && status.ly == 144) {
5251 cpu.interrupt_raise(CPU::Interrupt::Vblank);
5352 if(status.interrupt_vblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
5453 }
6463 }
6564
6665 void LCD::render() {
67 for(unsigned n = 0; n < 160; n++) line[n] = 0x00;
66 for(unsigned n = 0; n < 160; n++) {
67 line[n] = 0x00;
68 origin[n] = Origin::None;
69 }
6870
6971 if(status.display_enable == true) {
7072 if(status.bg_enable == true) render_bg();
9799 for(unsigned ox = 0; ox < 160; ox++) {
98100 uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0)
99101 | ((data & (0x8000 >> tx)) ? 2 : 0);
102
100103 line[ox] = status.bgp[palette];
104 origin[ox] = Origin::BG;
101105
102106 ix = (ix + 1) & 255;
103107 tx = (tx + 1) & 7;
109113 void LCD::render_window() {
110114 if(status.ly - status.wy >= 144U) return;
111115 unsigned iy = status.ly - status.wy;
112 unsigned ix = (status.wx - 7) & 255, tx = ix & 7;
116 unsigned ix = (7 - status.wx) & 255, tx = ix & 7;
113117 unsigned data = read_tile(status.window_tilemap_select, ix, iy);
114118
115119 for(unsigned ox = 0; ox < 160; ox++) {
116120 uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0)
117121 | ((data & (0x8000 >> tx)) ? 2 : 0);
118 if(ox - (status.wx - 7) < 160U) line[ox] = status.bgp[palette];
122 if(ox - (status.wx - 7) < 160U) {
123 line[ox] = status.bgp[palette];
124 origin[ox] = Origin::Window;
125 }
119126
120127 ix = (ix + 1) & 255;
121128 tx = (tx + 1) & 7;
125132 }
126133
127134 void LCD::render_obj() {
135 enum : unsigned { Priority = 0x80, YFlip = 0x40, XFlip = 0x20, Palette = 0x10 };
136
128137 unsigned obj_size = (status.obj_size == 0 ? 8 : 16);
129138
130139 unsigned sprite[10], sprites = 0;
164173
165174 sy = status.ly - sy;
166175 if(sy >= obj_size) continue;
167 if(attribute & 0x40) sy ^= (obj_size - 1);
176 if(attribute & YFlip) sy ^= (obj_size - 1);
168177
169178 unsigned tdaddr = (tile << 4) + (sy << 1);
170179 uint8 d0 = vram[tdaddr + 0];
171180 uint8 d1 = vram[tdaddr + 1];
172 unsigned xflip = attribute & 0x20 ? 7 : 0;
181 unsigned xflip = attribute & XFlip ? 7 : 0;
173182
174183 for(unsigned tx = 0; tx < 8; tx++) {
175184 uint8 palette = ((d0 & (0x80 >> tx)) ? 1 : 0)
176185 | ((d1 & (0x80 >> tx)) ? 2 : 0);
177186 if(palette == 0) continue;
178187
179 palette = status.obp[(bool)(attribute & 0x10)][palette];
188 palette = status.obp[(bool)(attribute & Palette)][palette];
180189 unsigned ox = sx + (tx ^ xflip);
181190
182191 if(ox <= 159) {
183 if(attribute & 0x80) {
184 if(line[ox] > 0) continue;
192 if(attribute & Priority) {
193 if(origin[ox] == Origin::BG || origin[ox] == Origin::Window) {
194 if(line[ox] > 0) continue;
195 }
185196 }
186197 line[ox] = palette;
198 origin[ox] = Origin::OBJ;
187199 }
188200 }
189201 }
5050 uint8 oam[160];
5151 uint8 line[160];
5252
53 struct Origin { enum : unsigned { None, BG, Window, OBJ }; };
54 uint8 origin[160];
55
5356 static void Main();
5457 void main();
5558 void add_clocks(unsigned clocks);
1616
1717 if(addr == 0xff41) { //STAT
1818 unsigned mode;
19 if(status.ly >= 144) mode = 1; //Vblank
20 else if(status.lx < 80) mode = 2; //OAM
19 if(status.ly >= 144) mode = 1; //Vblank
20 else if(status.lx < 80) mode = 2; //OAM
2121 else if(status.lx < 252) mode = 3; //LCD
22 else mode = 0; //Hblank
22 else mode = 0; //Hblank
2323
2424 return (status.interrupt_lyc << 6)
2525 | (status.interrupt_oam << 5)
8282 if(addr >= 0xfe00 && addr <= 0xfe9f) { oam[addr & 0xff] = data; return; }
8383
8484 if(addr == 0xff40) { //LCDC
85 if(status.display_enable == false && (data & 0x80)) {
86 status.lx = 0; //unverified behavior; fixes Super Mario Land 2 - Tree Zone
87 }
88
8589 status.display_enable = data & 0x80;
8690 status.window_tilemap_select = data & 0x40;
8791 status.window_display_enable = data & 0x20;
3232 s.array(vram);
3333 s.array(oam);
3434 s.array(line);
35 s.array(origin);
3536 }
3637
3738 #endif
0 #ifndef NALL_BPS_DELTA_HPP
1 #define NALL_BPS_DELTA_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpsdelta {
12 inline void source(const uint8_t *data, unsigned size);
13 inline void target(const uint8_t *data, unsigned size);
14
15 inline bool source(const string &filename);
16 inline bool target(const string &filename);
17 inline bool create(const string &filename, const string &metadata = "");
18
19 protected:
20 enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
21 enum : unsigned { Granularity = 1 };
22
23 struct Node {
24 unsigned offset;
25 Node *next;
26 inline Node() : offset(0), next(0) {}
27 inline ~Node() { if(next) delete next; }
28 };
29
30 filemap sourceFile;
31 const uint8_t *sourceData;
32 unsigned sourceSize;
33
34 filemap targetFile;
35 const uint8_t *targetData;
36 unsigned targetSize;
37 };
38
39 void bpsdelta::source(const uint8_t *data, unsigned size) {
40 sourceData = data;
41 sourceSize = size;
42 }
43
44 void bpsdelta::target(const uint8_t *data, unsigned size) {
45 targetData = data;
46 targetSize = size;
47 }
48
49 bool bpsdelta::source(const string &filename) {
50 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
51 source(sourceFile.data(), sourceFile.size());
52 return true;
53 }
54
55 bool bpsdelta::target(const string &filename) {
56 if(targetFile.open(filename, filemap::mode::read) == false) return false;
57 target(targetFile.data(), targetFile.size());
58 return true;
59 }
60
61 bool bpsdelta::create(const string &filename, const string &metadata) {
62 file modifyFile;
63 if(modifyFile.open(filename, file::mode::write) == false) return false;
64
65 uint32_t sourceChecksum = ~0, modifyChecksum = ~0;
66 unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
67
68 auto write = [&](uint8_t data) {
69 modifyFile.write(data);
70 modifyChecksum = crc32_adjust(modifyChecksum, data);
71 };
72
73 auto encode = [&](uint64_t data) {
74 while(true) {
75 uint64_t x = data & 0x7f;
76 data >>= 7;
77 if(data == 0) {
78 write(0x80 | x);
79 break;
80 }
81 write(x);
82 data--;
83 }
84 };
85
86 write('B');
87 write('P');
88 write('S');
89 write('1');
90
91 encode(sourceSize);
92 encode(targetSize);
93
94 unsigned markupSize = metadata.length();
95 encode(markupSize);
96 for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
97
98 Node *sourceTree[65536], *targetTree[65536];
99 for(unsigned n = 0; n < 65536; n++) sourceTree[n] = 0, targetTree[n] = 0;
100
101 //source tree creation
102 for(unsigned offset = 0; offset < sourceSize; offset++) {
103 uint16_t symbol = sourceData[offset + 0];
104 sourceChecksum = crc32_adjust(sourceChecksum, symbol);
105 if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8;
106 Node *node = new Node;
107 node->offset = offset;
108 node->next = sourceTree[symbol];
109 sourceTree[symbol] = node;
110 }
111
112 unsigned targetReadLength = 0;
113
114 auto targetReadFlush = [&]() {
115 if(targetReadLength) {
116 encode(TargetRead | ((targetReadLength - 1) << 2));
117 unsigned offset = outputOffset - targetReadLength;
118 while(targetReadLength) write(targetData[offset++]), targetReadLength--;
119 }
120 };
121
122 while(outputOffset < targetSize) {
123 unsigned maxLength = 0, maxOffset = 0, mode = TargetRead;
124
125 uint16_t symbol = targetData[outputOffset + 0];
126 if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8;
127
128 { //source read
129 unsigned length = 0, offset = outputOffset;
130 while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) {
131 length++;
132 offset++;
133 }
134 if(length > maxLength) maxLength = length, mode = SourceRead;
135 }
136
137 { //source copy
138 Node *node = sourceTree[symbol];
139 while(node) {
140 unsigned length = 0, x = node->offset, y = outputOffset;
141 while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++;
142 if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy;
143 node = node->next;
144 }
145 }
146
147 { //target copy
148 Node *node = targetTree[symbol];
149 while(node) {
150 unsigned length = 0, x = node->offset, y = outputOffset;
151 while(y < targetSize && targetData[x++] == targetData[y++]) length++;
152 if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy;
153 node = node->next;
154 }
155
156 //target tree append
157 node = new Node;
158 node->offset = outputOffset;
159 node->next = targetTree[symbol];
160 targetTree[symbol] = node;
161 }
162
163 { //target read
164 if(maxLength < 4) {
165 maxLength = min((unsigned)Granularity, targetSize - outputOffset);
166 mode = TargetRead;
167 }
168 }
169
170 if(mode != TargetRead) targetReadFlush();
171
172 switch(mode) {
173 case SourceRead:
174 encode(SourceRead | ((maxLength - 1) << 2));
175 break;
176 case TargetRead:
177 //delay write to group sequential TargetRead commands into one
178 targetReadLength += maxLength;
179 break;
180 case SourceCopy:
181 case TargetCopy:
182 encode(mode | ((maxLength - 1) << 2));
183 signed relativeOffset;
184 if(mode == SourceCopy) {
185 relativeOffset = maxOffset - sourceRelativeOffset;
186 sourceRelativeOffset = maxOffset + maxLength;
187 } else {
188 relativeOffset = maxOffset - targetRelativeOffset;
189 targetRelativeOffset = maxOffset + maxLength;
190 }
191 encode((relativeOffset < 0) | (abs(relativeOffset) << 1));
192 break;
193 }
194
195 outputOffset += maxLength;
196 }
197
198 targetReadFlush();
199
200 sourceChecksum = ~sourceChecksum;
201 for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n);
202 uint32_t targetChecksum = crc32_calculate(targetData, targetSize);
203 for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n);
204 uint32_t outputChecksum = ~modifyChecksum;
205 for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
206
207 modifyFile.close();
208 return true;
209 }
210
211 }
212
213 #endif
0 #ifndef NALL_BPS_LINEAR_HPP
1 #define NALL_BPS_LINEAR_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpslinear {
12 inline void source(const uint8_t *data, unsigned size);
13 inline void target(const uint8_t *data, unsigned size);
14
15 inline bool source(const string &filename);
16 inline bool target(const string &filename);
17 inline bool create(const string &filename, const string &metadata = "");
18
19 protected:
20 enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
21 enum : unsigned { Granularity = 1 };
22
23 filemap sourceFile;
24 const uint8_t *sourceData;
25 unsigned sourceSize;
26
27 filemap targetFile;
28 const uint8_t *targetData;
29 unsigned targetSize;
30 };
31
32 void bpslinear::source(const uint8_t *data, unsigned size) {
33 sourceData = data;
34 sourceSize = size;
35 }
36
37 void bpslinear::target(const uint8_t *data, unsigned size) {
38 targetData = data;
39 targetSize = size;
40 }
41
42 bool bpslinear::source(const string &filename) {
43 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
44 source(sourceFile.data(), sourceFile.size());
45 return true;
46 }
47
48 bool bpslinear::target(const string &filename) {
49 if(targetFile.open(filename, filemap::mode::read) == false) return false;
50 target(targetFile.data(), targetFile.size());
51 return true;
52 }
53
54 bool bpslinear::create(const string &filename, const string &metadata) {
55 file modifyFile;
56 if(modifyFile.open(filename, file::mode::write) == false) return false;
57
58 uint32_t modifyChecksum = ~0;
59 unsigned targetRelativeOffset = 0, outputOffset = 0;
60
61 auto write = [&](uint8_t data) {
62 modifyFile.write(data);
63 modifyChecksum = crc32_adjust(modifyChecksum, data);
64 };
65
66 auto encode = [&](uint64_t data) {
67 while(true) {
68 uint64_t x = data & 0x7f;
69 data >>= 7;
70 if(data == 0) {
71 write(0x80 | x);
72 break;
73 }
74 write(x);
75 data--;
76 }
77 };
78
79 unsigned targetReadLength = 0;
80
81 auto targetReadFlush = [&]() {
82 if(targetReadLength) {
83 encode(TargetRead | ((targetReadLength - 1) << 2));
84 unsigned offset = outputOffset - targetReadLength;
85 while(targetReadLength) write(targetData[offset++]), targetReadLength--;
86 }
87 };
88
89 write('B');
90 write('P');
91 write('S');
92 write('1');
93
94 encode(sourceSize);
95 encode(targetSize);
96
97 unsigned markupSize = metadata.length();
98 encode(markupSize);
99 for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
100
101 while(outputOffset < targetSize) {
102 unsigned sourceLength = 0;
103 for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) {
104 if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break;
105 sourceLength++;
106 }
107
108 unsigned rleLength = 0;
109 for(unsigned n = 1; outputOffset + n < targetSize; n++) {
110 if(targetData[outputOffset] != targetData[outputOffset + n]) break;
111 rleLength++;
112 }
113
114 if(rleLength >= 4) {
115 //write byte to repeat
116 targetReadLength++;
117 outputOffset++;
118 targetReadFlush();
119
120 //copy starting from repetition byte
121 encode(TargetCopy | ((rleLength - 1) << 2));
122 unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset;
123 encode(relativeOffset << 1);
124 outputOffset += rleLength;
125 targetRelativeOffset = outputOffset - 1;
126 } else if(sourceLength >= 4) {
127 targetReadFlush();
128 encode(SourceRead | ((sourceLength - 1) << 2));
129 outputOffset += sourceLength;
130 } else {
131 targetReadLength += Granularity;
132 outputOffset += Granularity;
133 }
134 }
135
136 targetReadFlush();
137
138 uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize);
139 for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n);
140 uint32_t targetChecksum = crc32_calculate(targetData, targetSize);
141 for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n);
142 uint32_t outputChecksum = ~modifyChecksum;
143 for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
144
145 modifyFile.close();
146 return true;
147 }
148
149 }
150
151 #endif
0 #ifndef NALL_BPS_METADATA_HPP
1 #define NALL_BPS_METADATA_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpsmetadata {
12 inline bool load(const string &filename);
13 inline bool save(const string &filename, const string &metadata);
14 inline string metadata() const;
15
16 protected:
17 file sourceFile;
18 string metadataString;
19 };
20
21 bool bpsmetadata::load(const string &filename) {
22 if(sourceFile.open(filename, file::mode::read) == false) return false;
23
24 auto read = [&]() -> uint8_t {
25 return sourceFile.read();
26 };
27
28 auto decode = [&]() -> uint64_t {
29 uint64_t data = 0, shift = 1;
30 while(true) {
31 uint8_t x = read();
32 data += (x & 0x7f) * shift;
33 if(x & 0x80) break;
34 shift <<= 7;
35 data += shift;
36 }
37 return data;
38 };
39
40 if(read() != 'B') return false;
41 if(read() != 'P') return false;
42 if(read() != 'S') return false;
43 if(read() != '1') return false;
44 decode();
45 decode();
46 unsigned metadataSize = decode();
47 char data[metadataSize + 1];
48 for(unsigned n = 0; n < metadataSize; n++) data[n] = read();
49 data[metadataSize] = 0;
50 metadataString = (const char*)data;
51
52 return true;
53 }
54
55 bool bpsmetadata::save(const string &filename, const string &metadata) {
56 file targetFile;
57 if(targetFile.open(filename, file::mode::write) == false) return false;
58 if(sourceFile.open() == false) return false;
59 sourceFile.seek(0);
60
61 auto read = [&]() -> uint8_t {
62 return sourceFile.read();
63 };
64
65 auto decode = [&]() -> uint64_t {
66 uint64_t data = 0, shift = 1;
67 while(true) {
68 uint8_t x = read();
69 data += (x & 0x7f) * shift;
70 if(x & 0x80) break;
71 shift <<= 7;
72 data += shift;
73 }
74 return data;
75 };
76
77 uint32_t checksum = ~0;
78
79 auto write = [&](uint8_t data) {
80 targetFile.write(data);
81 checksum = crc32_adjust(checksum, data);
82 };
83
84 auto encode = [&](uint64_t data) {
85 while(true) {
86 uint64_t x = data & 0x7f;
87 data >>= 7;
88 if(data == 0) {
89 write(0x80 | x);
90 break;
91 }
92 write(x);
93 data--;
94 }
95 };
96
97 for(unsigned n = 0; n < 4; n++) write(read());
98 encode(decode());
99 encode(decode());
100 unsigned sourceLength = decode();
101 unsigned targetLength = metadata.length();
102 encode(targetLength);
103 sourceFile.seek(sourceLength, file::index::relative);
104 for(unsigned n = 0; n < targetLength; n++) write(metadata[n]);
105 unsigned length = sourceFile.size() - sourceFile.offset() - 4;
106 for(unsigned n = 0; n < length; n++) write(read());
107 uint32_t outputChecksum = ~checksum;
108 for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
109
110 targetFile.close();
111 return true;
112 }
113
114 string bpsmetadata::metadata() const {
115 return metadataString;
116 }
117
118 }
119
120 #endif
0 #ifndef NALL_BPS_PATCH_HPP
1 #define NALL_BPS_PATCH_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpspatch {
12 inline bool modify(const uint8_t *data, unsigned size);
13 inline void source(const uint8_t *data, unsigned size);
14 inline void target(uint8_t *data, unsigned size);
15
16 inline bool modify(const string &filename);
17 inline bool source(const string &filename);
18 inline bool target(const string &filename);
19
20 inline string metadata() const;
21 inline unsigned size() const;
22
23 enum result : unsigned {
24 unknown,
25 success,
26 patch_too_small,
27 patch_invalid_header,
28 source_too_small,
29 target_too_small,
30 source_checksum_invalid,
31 target_checksum_invalid,
32 patch_checksum_invalid,
33 };
34
35 inline result apply();
36
37 protected:
38 enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
39
40 filemap modifyFile;
41 const uint8_t *modifyData;
42 unsigned modifySize;
43
44 filemap sourceFile;
45 const uint8_t *sourceData;
46 unsigned sourceSize;
47
48 filemap targetFile;
49 uint8_t *targetData;
50 unsigned targetSize;
51
52 unsigned modifySourceSize;
53 unsigned modifyTargetSize;
54 unsigned modifyMarkupSize;
55 string metadataString;
56 };
57
58 bool bpspatch::modify(const uint8_t *data, unsigned size) {
59 if(size < 19) return false;
60 modifyData = data;
61 modifySize = size;
62
63 unsigned offset = 4;
64 auto decode = [&]() -> uint64_t {
65 uint64_t data = 0, shift = 1;
66 while(true) {
67 uint8_t x = modifyData[offset++];
68 data += (x & 0x7f) * shift;
69 if(x & 0x80) break;
70 shift <<= 7;
71 data += shift;
72 }
73 return data;
74 };
75
76 modifySourceSize = decode();
77 modifyTargetSize = decode();
78 modifyMarkupSize = decode();
79
80 char buffer[modifyMarkupSize + 1];
81 for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++];
82 buffer[modifyMarkupSize] = 0;
83 metadataString = (const char*)buffer;
84
85 return true;
86 }
87
88 void bpspatch::source(const uint8_t *data, unsigned size) {
89 sourceData = data;
90 sourceSize = size;
91 }
92
93 void bpspatch::target(uint8_t *data, unsigned size) {
94 targetData = data;
95 targetSize = size;
96 }
97
98 bool bpspatch::modify(const string &filename) {
99 if(modifyFile.open(filename, filemap::mode::read) == false) return false;
100 return modify(modifyFile.data(), modifyFile.size());
101 }
102
103 bool bpspatch::source(const string &filename) {
104 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
105 source(sourceFile.data(), sourceFile.size());
106 return true;
107 }
108
109 bool bpspatch::target(const string &filename) {
110 file fp;
111 if(fp.open(filename, file::mode::write) == false) return false;
112 fp.truncate(modifyTargetSize);
113 fp.close();
114
115 if(targetFile.open(filename, filemap::mode::readwrite) == false) return false;
116 target(targetFile.data(), targetFile.size());
117 return true;
118 }
119
120 string bpspatch::metadata() const {
121 return metadataString;
122 }
123
124 unsigned bpspatch::size() const {
125 return modifyTargetSize;
126 }
127
128 bpspatch::result bpspatch::apply() {
129 if(modifySize < 19) return result::patch_too_small;
130
131 uint32_t modifyChecksum = ~0, targetChecksum = ~0;
132 unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
133
134 auto read = [&]() -> uint8_t {
135 uint8_t data = modifyData[modifyOffset++];
136 modifyChecksum = crc32_adjust(modifyChecksum, data);
137 return data;
138 };
139
140 auto decode = [&]() -> uint64_t {
141 uint64_t data = 0, shift = 1;
142 while(true) {
143 uint8_t x = read();
144 data += (x & 0x7f) * shift;
145 if(x & 0x80) break;
146 shift <<= 7;
147 data += shift;
148 }
149 return data;
150 };
151
152 auto write = [&](uint8_t data) {
153 targetData[outputOffset++] = data;
154 targetChecksum = crc32_adjust(targetChecksum, data);
155 };
156
157 if(read() != 'B') return result::patch_invalid_header;
158 if(read() != 'P') return result::patch_invalid_header;
159 if(read() != 'S') return result::patch_invalid_header;
160 if(read() != '1') return result::patch_invalid_header;
161
162 modifySourceSize = decode();
163 modifyTargetSize = decode();
164 modifyMarkupSize = decode();
165 for(unsigned n = 0; n < modifyMarkupSize; n++) read();
166
167 if(modifySourceSize > sourceSize) return result::source_too_small;
168 if(modifyTargetSize > targetSize) return result::target_too_small;
169
170 while(modifyOffset < modifySize - 12) {
171 unsigned length = decode();
172 unsigned mode = length & 3;
173 length = (length >> 2) + 1;
174
175 switch(mode) {
176 case SourceRead:
177 while(length--) write(sourceData[outputOffset]);
178 break;
179 case TargetRead:
180 while(length--) write(read());
181 break;
182 case SourceCopy:
183 case TargetCopy:
184 signed offset = decode();
185 bool negative = offset & 1;
186 offset >>= 1;
187 if(negative) offset = -offset;
188
189 if(mode == SourceCopy) {
190 sourceRelativeOffset += offset;
191 while(length--) write(sourceData[sourceRelativeOffset++]);
192 } else {
193 targetRelativeOffset += offset;
194 while(length--) write(targetData[targetRelativeOffset++]);
195 }
196 break;
197 }
198 }
199
200 uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
201 for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
202 for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
203 uint32_t checksum = ~modifyChecksum;
204 for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
205
206 uint32_t sourceChecksum = crc32_calculate(sourceData, modifySourceSize);
207 targetChecksum = ~targetChecksum;
208
209 if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid;
210 if(targetChecksum != modifyTargetChecksum) return result::target_checksum_invalid;
211 if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid;
212
213 return result::success;
214 }
215
216 }
217
218 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 struct Buffer {
3 double *sample[2];
4 uint16_t rdoffset;
5 uint16_t wroffset;
6
7 inline double& read(bool channel, signed offset = 0) {
8 return sample[channel][(uint16_t)(rdoffset + offset)];
9 }
10
11 inline double& write(bool channel, signed offset = 0) {
12 return sample[channel][(uint16_t)(wroffset + offset)];
13 }
14
15 inline void clear() {
16 for(unsigned n = 0; n < 65536; n++) {
17 sample[0][n] = 0;
18 sample[1][n] = 0;
19 }
20 rdoffset = 0;
21 wroffset = 0;
22 }
23
24 Buffer() {
25 sample[0] = new double[65536];
26 sample[1] = new double[65536];
27 }
28
29 ~Buffer() {
30 delete[] sample[0];
31 delete[] sample[1];
32 }
33 };
34
35 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 #include <math.h>
3 #include <nall/stdint.hpp>
4
5 namespace nall {
6
7 struct DSP {
8 enum class Resampler : unsigned {
9 Point,
10 Linear,
11 Cosine,
12 Cubic,
13 Hermite,
14 Average,
15 };
16
17 inline void setPrecision(unsigned precision);
18 inline void setFrequency(double frequency); //inputFrequency
19 inline void setVolume(double volume);
20 inline void setBalance(double balance);
21
22 inline void setResampler(Resampler resampler);
23 inline void setResamplerFrequency(double frequency); //outputFrequency
24
25 inline void sample(signed lchannel, signed rchannel);
26 inline bool pending();
27 inline void read(signed &lchannel, signed &rchannel);
28
29 inline void clear();
30 inline DSP();
31 inline ~DSP();
32
33 protected:
34 struct Settings {
35 unsigned precision;
36 double frequency;
37 double volume;
38 double balance;
39 //internal
40 double intensity;
41 } settings;
42
43 struct ResamplerSettings {
44 Resampler engine;
45 double frequency;
46 //internal
47 double fraction;
48 double step;
49 } resampler;
50
51 inline void resamplerRun();
52 inline void resamplerWrite(double lchannel, double rchannel);
53
54 inline void resamplePoint();
55 inline void resampleLinear();
56 inline void resampleCosine();
57 inline void resampleCubic();
58 inline void resampleHermite();
59 inline void resampleAverage();
60
61 #include "buffer.hpp"
62 Buffer buffer;
63 Buffer output;
64
65 inline void adjustVolume();
66 inline void adjustBalance();
67 inline signed clamp(const unsigned bits, const signed x);
68 };
69
70 #include "settings.hpp"
71
72 void DSP::sample(signed lchannel, signed rchannel) {
73 buffer.write(0) = (double)lchannel / settings.intensity;
74 buffer.write(1) = (double)rchannel / settings.intensity;
75 buffer.wroffset++;
76 resamplerRun();
77 }
78
79 bool DSP::pending() {
80 return output.rdoffset != output.wroffset;
81 }
82
83 void DSP::read(signed &lchannel, signed &rchannel) {
84 adjustVolume();
85 adjustBalance();
86
87 lchannel = clamp(settings.precision, output.read(0) * settings.intensity);
88 rchannel = clamp(settings.precision, output.read(1) * settings.intensity);
89 output.rdoffset++;
90 }
91
92 void DSP::resamplerRun() {
93 switch(resampler.engine) {
94 case Resampler::Point: return resamplePoint();
95 case Resampler::Linear: return resampleLinear();
96 case Resampler::Cosine: return resampleCosine();
97 case Resampler::Cubic: return resampleCubic();
98 case Resampler::Hermite: return resampleHermite();
99 case Resampler::Average: return resampleAverage();
100 }
101 }
102
103 void DSP::resamplerWrite(double lchannel, double rchannel) {
104 output.write(0) = lchannel;
105 output.write(1) = rchannel;
106 output.wroffset++;
107 }
108
109 #include "resample/point.hpp"
110 #include "resample/linear.hpp"
111 #include "resample/cosine.hpp"
112 #include "resample/cubic.hpp"
113 #include "resample/hermite.hpp"
114 #include "resample/average.hpp"
115
116 void DSP::adjustVolume() {
117 output.read(0) *= settings.volume;
118 output.read(1) *= settings.volume;
119 }
120
121 void DSP::adjustBalance() {
122 if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance;
123 if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance;
124 }
125
126 signed DSP::clamp(const unsigned bits, const signed x) {
127 const signed b = 1U << (bits - 1);
128 const signed m = (1U << (bits - 1)) - 1;
129 return (x > m) ? m : (x < -b) ? -b : x;
130 }
131
132 void DSP::clear() {
133 resampler.fraction = 0.0;
134 buffer.clear();
135 output.clear();
136 }
137
138 DSP::DSP() {
139 setPrecision(16);
140 setFrequency(44100.0);
141 setVolume(1.0);
142 setBalance(0.0);
143 setResampler(Resampler::Hermite);
144 setResamplerFrequency(44100.0);
145 clear();
146 }
147
148 DSP::~DSP() {
149 }
150
151 }
152
153 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleAverage() {
3 //can only average if input frequency >= output frequency
4 if(resampler.step < 1.0) return resampleHermite();
5
6 resampler.fraction += 1.0;
7
8 double scalar = 1.0;
9 if(resampler.fraction > resampler.step) scalar = 1.0 - (resampler.fraction - resampler.step);
10
11 output.write(0) += buffer.read(0) * scalar;
12 output.write(1) += buffer.read(1) * scalar;
13
14 if(resampler.fraction >= resampler.step) {
15 output.write(0) /= resampler.step;
16 output.write(1) /= resampler.step;
17 output.wroffset++;
18
19 resampler.fraction -= resampler.step;
20 output.write(0) = buffer.read(0) * resampler.fraction;
21 output.write(1) = buffer.read(1) * resampler.fraction;
22 }
23
24 buffer.rdoffset++;
25 }
26
27 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleCosine() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -1);
8 double b = buffer.read(n, -0);
9
10 double mu = resampler.fraction;
11 mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
12
13 channel[n] = a * (1.0 - mu) + b * mu;
14 }
15
16 resamplerWrite(channel[0], channel[1]);
17 resampler.fraction += resampler.step;
18 }
19
20 buffer.rdoffset++;
21 resampler.fraction -= 1.0;
22 }
23
24 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleCubic() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -3);
8 double b = buffer.read(n, -2);
9 double c = buffer.read(n, -1);
10 double d = buffer.read(n, -0);
11
12 double mu = resampler.fraction;
13
14 double A = d - c - a + b;
15 double B = a - b - A;
16 double C = c - a;
17 double D = b;
18
19 channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D;
20 }
21
22 resamplerWrite(channel[0], channel[1]);
23 resampler.fraction += resampler.step;
24 }
25
26 buffer.rdoffset++;
27 resampler.fraction -= 1.0;
28 }
29
30 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleHermite() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -3);
8 double b = buffer.read(n, -2);
9 double c = buffer.read(n, -1);
10 double d = buffer.read(n, -0);
11
12 const double tension = 0.0; //-1 = low, 0 = normal, +1 = high
13 const double bias = 0.0; //-1 = left, 0 = even, +1 = right
14
15 double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3;
16
17 mu1 = resampler.fraction;
18 mu2 = mu1 * mu1;
19 mu3 = mu2 * mu1;
20
21 m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0;
22 m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0;
23 m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0;
24 m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0;
25
26 a0 = +2 * mu3 - 3 * mu2 + 1;
27 a1 = mu3 - 2 * mu2 + mu1;
28 a2 = mu3 - mu2;
29 a3 = -2 * mu3 + 3 * mu2;
30
31 channel[n] = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
32 }
33
34 resamplerWrite(channel[0], channel[1]);
35 resampler.fraction += resampler.step;
36 }
37
38 buffer.rdoffset++;
39 resampler.fraction -= 1.0;
40 }
41
42 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleLinear() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -1);
8 double b = buffer.read(n, -0);
9
10 double mu = resampler.fraction;
11
12 channel[n] = a * (1.0 - mu) + b * mu;
13 }
14
15 resamplerWrite(channel[0], channel[1]);
16 resampler.fraction += resampler.step;
17 }
18
19 buffer.rdoffset++;
20 resampler.fraction -= 1.0;
21 }
22
23 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resamplePoint() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -1);
8 double b = buffer.read(n, -0);
9
10 double mu = resampler.fraction;
11
12 channel[n] = mu < 0.5 ? a : b;
13 }
14
15 resamplerWrite(channel[0], channel[1]);
16 resampler.fraction += resampler.step;
17 }
18
19 buffer.rdoffset++;
20 resampler.fraction -= 1.0;
21 }
22
23 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::setPrecision(unsigned precision) {
3 settings.precision = precision;
4 settings.intensity = 1 << (settings.precision - 1);
5 }
6
7 void DSP::setFrequency(double frequency) {
8 settings.frequency = frequency;
9 resampler.fraction = 0;
10 resampler.step = settings.frequency / resampler.frequency;
11 }
12
13 void DSP::setVolume(double volume) {
14 settings.volume = volume;
15 }
16
17 void DSP::setBalance(double balance) {
18 settings.balance = balance;
19 }
20
21 void DSP::setResampler(Resampler engine) {
22 resampler.engine = engine;
23 }
24
25 void DSP::setResamplerFrequency(double frequency) {
26 resampler.frequency = frequency;
27 resampler.fraction = 0;
28 resampler.step = settings.frequency / resampler.frequency;
29 }
30
31 #endif
0 #ifndef NALL_DSP_HPP
1 #define NALL_DSP_HPP
2
3 #define NALL_DSP_INTERNAL_HPP
4 #include <nall/dsp/core.hpp>
5 #undef NALL_DSP_INTERNAL_HPP
6
7 #endif
2929 fp.read(data, size);
3030 fp.close();
3131 return true;
32 }
33
34 static bool read(const string &filename, const uint8_t *&data, unsigned &size) {
35 return file::read(filename, (uint8_t*&)data, size);
3236 }
3337
3438 static bool write(const string &filename, const uint8_t *data, unsigned size) {
4646 }
4747
4848 bool p_open(const char *filename, mode mode_) {
49 if(file::exists(filename) && file::size(filename) == 0) {
50 p_handle = 0;
51 p_size = 0;
52 return true;
53 }
54
4955 int desired_access, creation_disposition, flprotect, map_access;
5056
5157 switch(mode_) {
132138 }
133139
134140 bool p_open(const char *filename, mode mode_) {
141 if(file::exists(filename) && file::size(filename) == 0) {
142 p_handle = 0;
143 p_size = 0;
144 return true;
145 }
146
135147 int open_flags, mmap_flags;
136148
137149 switch(mode_) {
55 class GameBoyCartridge {
66 public:
77 string xml;
8 inline GameBoyCartridge(const uint8_t *data, unsigned size);
8 inline GameBoyCartridge(uint8_t *data, unsigned size);
99
1010 //private:
1111 struct Information {
2020 } info;
2121 };
2222
23 GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
23 GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
2424 xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
2525 if(romsize < 0x4000) return;
2626
3232
3333 info.romsize = 0;
3434 info.ramsize = 0;
35
36 unsigned base = romsize - 0x8000;
37 if(romdata[base + 0x0104] == 0xce && romdata[base + 0x0105] == 0xed
38 && romdata[base + 0x0106] == 0x66 && romdata[base + 0x0107] == 0x66
39 && romdata[base + 0x0108] == 0xcc && romdata[base + 0x0109] == 0x0d
40 && romdata[base + 0x0147] >= 0x0b && romdata[base + 0x0147] <= 0x0d
41 ) {
42 //MMM01 stores header at bottom of image
43 //flip this around for consistency with all other mappers
44 uint8_t header[0x8000];
45 memcpy(header, romdata + base, 0x8000);
46 memmove(romdata + 0x8000, romdata, romsize - 0x8000);
47 memcpy(romdata, header, 0x8000);
48 }
3549
3650 switch(romdata[0x0147]) {
3751 case 0x00: info.mapper = "none"; break;
0 #ifndef NALL_IPS_HPP
1 #define NALL_IPS_HPP
2
3 #include <nall/file.hpp>
4 #include <nall/stdint.hpp>
5 #include <nall/string.hpp>
6
7 namespace nall {
8
9 struct ips {
10 inline bool apply();
11 inline void source(const uint8_t *data, unsigned size);
12 inline void modify(const uint8_t *data, unsigned size);
13 inline bool source(const string &filename);
14 inline bool modify(const string &filename);
15 inline ips();
16 inline ~ips();
17
18 uint8_t *data;
19 unsigned size;
20 const uint8_t *sourceData;
21 unsigned sourceSize;
22 const uint8_t *modifyData;
23 unsigned modifySize;
24 };
25
26 bool ips::apply() {
27 if(modifySize < 8) return false;
28 if(modifyData[0] != 'P') return false;
29 if(modifyData[1] != 'A') return false;
30 if(modifyData[2] != 'T') return false;
31 if(modifyData[3] != 'C') return false;
32 if(modifyData[4] != 'H') return false;
33
34 if(data) delete[] data;
35 data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding
36 size = sourceSize;
37 memcpy(data, sourceData, sourceSize);
38 unsigned offset = 5;
39
40 while(true) {
41 unsigned address, length;
42
43 if(offset > modifySize - 3) break;
44 address = modifyData[offset++] << 16;
45 address |= modifyData[offset++] << 8;
46 address |= modifyData[offset++] << 0;
47
48 if(address == 0x454f46) { //EOF
49 if(offset == modifySize) return true;
50 if(offset == modifySize - 3) {
51 size = modifyData[offset++] << 16;
52 size |= modifyData[offset++] << 8;
53 size |= modifyData[offset++] << 0;
54 return true;
55 }
56 }
57
58 if(offset > modifySize - 2) break;
59 length = modifyData[offset++] << 8;
60 length |= modifyData[offset++] << 0;
61
62 if(length) { //Copy
63 if(offset > modifySize - length) break;
64 while(length--) data[address++] = modifyData[offset++];
65 } else { //RLE
66 if(offset > modifySize - 3) break;
67 length = modifyData[offset++] << 8;
68 length |= modifyData[offset++] << 0;
69 if(length == 0) break; //illegal
70 while(length--) data[address++] = modifyData[offset];
71 offset++;
72 }
73
74 size = max(size, address);
75 }
76
77 delete[] data;
78 data = 0;
79 return false;
80 }
81
82 void ips::source(const uint8_t *data, unsigned size) {
83 sourceData = data, sourceSize = size;
84 }
85
86 void ips::modify(const uint8_t *data, unsigned size) {
87 modifyData = data, modifySize = size;
88 }
89
90 bool ips::source(const string &filename) {
91 return file::read(filename, sourceData, sourceSize);
92 }
93
94 bool ips::modify(const string &filename) {
95 return file::read(filename, modifyData, modifySize);
96 }
97
98 ips::ips() : data(0), sourceData(0), modifyData(0) {
99 }
100
101 ips::~ips() {
102 if(data) delete[] data;
103 if(sourceData) delete[] sourceData;
104 if(modifyData) delete[] modifyData;
105 }
106
107 }
108
109 #endif
00 #ifndef NALL_LZSS_HPP
11 #define NALL_LZSS_HPP
22
3 #include <nall/array.hpp>
3 #include <nall/file.hpp>
4 #include <nall/filemap.hpp>
45 #include <nall/stdint.hpp>
6 #include <nall/string.hpp>
57
68 namespace nall {
7 class lzss {
8 public:
9 static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) {
10 output = new uint8_t[inlength * 9 / 8 + 9]();
119
12 unsigned i = 0, o = 0;
13 while(i < inlength) {
14 unsigned flagoffset = o++;
15 uint8_t flag = 0x00;
10 //19:5 pulldown
11 //8:1 marker: d7-d0
12 //length: { 4 - 35 }, offset: { 1 - 0x80000 }
13 //4-byte file size header
14 //little-endian encoding
15 struct lzss {
16 inline void source(const uint8_t *data, unsigned size);
17 inline bool source(const string &filename);
18 inline unsigned size() const;
19 inline bool compress(const string &filename);
20 inline bool decompress(uint8_t *targetData, unsigned targetSize);
21 inline bool decompress(const string &filename);
1622
17 for(unsigned b = 0; b < 8 && i < inlength; b++) {
18 unsigned longest = 0, pointer;
19 for(unsigned index = 1; index < 4096; index++) {
20 unsigned count = 0;
21 while(true) {
22 if(count >= 15 + 3) break; //verify pattern match is not longer than max length
23 if(i + count >= inlength) break; //verify pattern match does not read past end of input
24 if(i + count < index) break; //verify read is not before start of input
25 if(input[i + count] != input[i + count - index]) break; //verify pattern still matches
26 count++;
27 }
23 protected:
24 struct Node {
25 unsigned offset;
26 Node *next;
27 inline Node() : offset(0), next(0) {}
28 inline ~Node() { if(next) delete next; }
29 } *tree[65536];
2830
29 if(count > longest) {
30 longest = count;
31 pointer = index;
32 }
33 }
31 filemap sourceFile;
32 const uint8_t *sourceData;
33 unsigned sourceSize;
3434
35 if(longest < 3) output[o++] = input[i++];
36 else {
37 flag |= 1 << b;
38 uint16_t x = ((longest - 3) << 12) + pointer;
39 output[o++] = x;
40 output[o++] = x >> 8;
41 i += longest;
42 }
35 public:
36 inline lzss() : sourceData(0), sourceSize(0) {}
37 };
38
39 void lzss::source(const uint8_t *data, unsigned size) {
40 sourceData = data;
41 sourceSize = size;
42 }
43
44 bool lzss::source(const string &filename) {
45 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
46 sourceData = sourceFile.data();
47 sourceSize = sourceFile.size();
48 return true;
49 }
50
51 unsigned lzss::size() const {
52 unsigned size = 0;
53 if(sourceSize < 4) return size;
54 for(unsigned n = 0; n < 32; n += 8) size |= sourceData[n >> 3] << n;
55 return size;
56 }
57
58 bool lzss::compress(const string &filename) {
59 file targetFile;
60 if(targetFile.open(filename, file::mode::write) == false) return false;
61
62 for(unsigned n = 0; n < 32; n += 8) targetFile.write(sourceSize >> n);
63 for(unsigned n = 0; n < 65536; n++) tree[n] = 0;
64
65 uint8_t buffer[25];
66 unsigned sourceOffset = 0;
67
68 while(sourceOffset < sourceSize) {
69 uint8_t mask = 0x00;
70 unsigned bufferOffset = 1;
71
72 for(unsigned iteration = 0; iteration < 8; iteration++) {
73 if(sourceOffset >= sourceSize) break;
74
75 uint16_t symbol = sourceData[sourceOffset + 0];
76 if(sourceOffset < sourceSize - 1) symbol |= sourceData[sourceOffset + 1] << 8;
77 Node *node = tree[symbol];
78 unsigned maxLength = 0, maxOffset = 0;
79
80 while(node) {
81 if(node->offset < sourceOffset - 0x80000) {
82 //out-of-range: all subsequent nodes will also be, so free up their memory
83 if(node->next) { delete node->next; node->next = 0; }
84 break;
4385 }
4486
45 output[flagoffset] = flag;
87 unsigned length = 0, x = sourceOffset, y = node->offset;
88 while(length < 35 && x < sourceSize && sourceData[x++] == sourceData[y++]) length++;
89 if(length > maxLength) maxLength = length, maxOffset = node->offset;
90 if(length == 35) break;
91
92 node = node->next;
4693 }
4794
48 outlength = o;
49 return true;
95 //attach current symbol to top of tree for subsequent searches
96 node = new Node;
97 node->offset = sourceOffset;
98 node->next = tree[symbol];
99 tree[symbol] = node;
100
101 if(maxLength < 4) {
102 buffer[bufferOffset++] = sourceData[sourceOffset++];
103 } else {
104 unsigned output = ((maxLength - 4) << 19) | (sourceOffset - 1 - maxOffset);
105 for(unsigned n = 0; n < 24; n += 8) buffer[bufferOffset++] = output >> n;
106 mask |= 0x80 >> iteration;
107 sourceOffset += maxLength;
108 }
50109 }
51110
52 static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) {
53 output = new uint8_t[length]();
111 buffer[0] = mask;
112 targetFile.write(buffer, bufferOffset);
113 }
54114
55 unsigned i = 0, o = 0;
56 while(o < length) {
57 uint8_t flag = input[i++];
115 sourceFile.close();
116 targetFile.close();
117 return true;
118 }
58119
59 for(unsigned b = 0; b < 8 && o < length; b++) {
60 if(!(flag & (1 << b))) output[o++] = input[i++];
61 else {
62 uint16_t offset = input[i++];
63 offset += input[i++] << 8;
64 uint16_t lookuplength = (offset >> 12) + 3;
65 offset &= 4095;
66 for(unsigned index = 0; index < lookuplength && o + index < length; index++) {
67 output[o + index] = output[o + index - offset];
68 }
69 o += lookuplength;
70 }
71 }
120 bool lzss::decompress(uint8_t *targetData, unsigned targetSize) {
121 if(targetSize < size()) return false;
122
123 unsigned sourceOffset = 4, targetOffset = 0;
124 while(sourceOffset < sourceSize) {
125 uint8_t mask = sourceData[sourceOffset++];
126
127 for(unsigned iteration = 0; iteration < 8; iteration++) {
128 if(sourceOffset >= sourceSize) break;
129
130 if((mask & (0x80 >> iteration)) == 0) {
131 targetData[targetOffset++] = sourceData[sourceOffset++];
132 } else {
133 unsigned code = 0;
134 for(unsigned n = 0; n < 24; n += 8) code |= sourceData[sourceOffset++] << n;
135 unsigned length = (code >> 19) + 4;
136 unsigned offset = targetOffset - 1 - (code & 0x7ffff);
137 while(length--) targetData[targetOffset++] = targetData[offset++];
72138 }
139 }
140 }
141 }
73142
74 return true;
75 }
76 };
143 bool lzss::decompress(const string &filename) {
144 if(sourceSize < 4) return false;
145 unsigned targetSize = size();
146
147 file fp;
148 if(fp.open(filename, file::mode::write) == false) return false;
149 fp.truncate(targetSize);
150 fp.close();
151
152 filemap targetFile;
153 if(targetFile.open(filename, filemap::mode::readwrite) == false) return false;
154 uint8_t *targetData = targetFile.data();
155
156 bool result = decompress(targetData, targetSize);
157 sourceFile.close();
158 targetFile.close();
159 return result;
160 }
161
77162 }
78163
79164 #endif
9494 wchar_t fn[_MAX_PATH] = L"";
9595 _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
9696 strcpy(resolvedname, nall::utf8_t(fn));
97 for(unsigned n = 0; resolvedname[n]; n++) if(resolvedname[n] == '\\') resolvedname[n] = '/';
9798 return resolvedname;
9899 }
99100
101102 wchar_t fp[_MAX_PATH] = L"";
102103 SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
103104 strcpy(path, nall::utf8_t(fp));
105 for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/';
104106 return path;
105107 }
106108
108110 wchar_t fp[_MAX_PATH] = L"";
109111 _wgetcwd(fp, _MAX_PATH);
110112 strcpy(path, nall::utf8_t(fp));
113 for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/';
111114 return path;
112115 }
113116 #else
00 class Audio {
11 public:
2 static const char *Volume;
3 static const char *Resample;
4 static const char *ResampleRatio;
5
62 static const char *Handle;
73 static const char *Synchronize;
84 static const char *Frequency;
160160
161161 /* AudioInterface */
162162
163 const char *Audio::Handle = "Handle";
164 const char *Audio::Synchronize = "Synchronize";
165 const char *Audio::Frequency = "Frequency";
166 const char *Audio::Latency = "Latency";
167
163168 void AudioInterface::driver(const char *driver) {
164169 if(p) term();
165170
268273 "None";
269274 }
270275
271 #include "ruby_audio.cpp"
276 bool AudioInterface::init() {
277 if(!p) driver();
278 return p->init();
279 }
280
281 void AudioInterface::term() {
282 if(p) {
283 delete p;
284 p = 0;
285 }
286 }
287
288 bool AudioInterface::cap(const string& name) { return p ? p->cap(name) : false; }
289 any AudioInterface::get(const string& name) { return p ? p->get(name) : false; }
290 bool AudioInterface::set(const string& name, const any& value) { return p ? p->set(name, value) : false; }
291 void AudioInterface::sample(uint16_t left, uint16_t right) { if(p) p->sample(left, right); }
292 void AudioInterface::clear() { if(p) p->clear(); }
293 AudioInterface::AudioInterface() : p(0) {}
294 AudioInterface::~AudioInterface() { term(); }
272295
273296 /* InputInterface */
274297
00 /*
11 ruby
2 version: 0.06a (2011-02-27)
2 version: 0.07 (2011-08-14)
33 license: public domain
44 */
55
6565
6666 private:
6767 Audio *p;
68
69 unsigned volume;
70
71 //resample unit
72 double hermite(double mu, double a, double b, double c, double d);
73 bool resample_enabled;
74 double r_step, r_frac;
75 int r_left[4], r_right[4];
7668 };
7769
7870 class InputInterface {
+0
-133
bsnes/ruby/ruby_audio.cpp less more
0 const char *Audio::Volume = "Volume";
1 const char *Audio::Resample = "Resample";
2 const char *Audio::ResampleRatio = "ResampleRatio";
3
4 const char *Audio::Handle = "Handle";
5 const char *Audio::Synchronize = "Synchronize";
6 const char *Audio::Frequency = "Frequency";
7 const char *Audio::Latency = "Latency";
8
9 bool AudioInterface::init() {
10 if(!p) driver();
11 return p->init();
12 }
13
14 void AudioInterface::term() {
15 if(p) {
16 delete p;
17 p = 0;
18 }
19 }
20
21 bool AudioInterface::cap(const string& name) {
22 if(name == Audio::Volume) return true;
23 if(name == Audio::Resample) return true;
24 if(name == Audio::ResampleRatio) return true;
25
26 return p ? p->cap(name) : false;
27 }
28
29 any AudioInterface::get(const string& name) {
30 if(name == Audio::Volume) return volume;
31 if(name == Audio::Resample) return resample_enabled;
32 if(name == Audio::ResampleRatio);
33
34 return p ? p->get(name) : false;
35 }
36
37 bool AudioInterface::set(const string& name, const any& value) {
38 if(name == Audio::Volume) {
39 volume = any_cast<unsigned>(value);
40 return true;
41 }
42
43 if(name == Audio::Resample) {
44 resample_enabled = any_cast<bool>(value);
45 return true;
46 }
47
48 if(name == Audio::ResampleRatio) {
49 r_step = any_cast<double>(value);
50 r_frac = 0;
51 return true;
52 }
53
54 return p ? p->set(name, value) : false;
55 }
56
57 //4-tap hermite interpolation
58 double AudioInterface::hermite(double mu1, double a, double b, double c, double d) {
59 const double tension = 0.0; //-1 = low, 0 = normal, 1 = high
60 const double bias = 0.0; //-1 = left, 0 = even, 1 = right
61
62 double mu2, mu3, m0, m1, a0, a1, a2, a3;
63
64 mu2 = mu1 * mu1;
65 mu3 = mu2 * mu1;
66
67 m0 = (b - a) * (1 + bias) * (1 - tension) / 2;
68 m0 += (c - b) * (1 - bias) * (1 - tension) / 2;
69 m1 = (c - b) * (1 + bias) * (1 - tension) / 2;
70 m1 += (d - c) * (1 - bias) * (1 - tension) / 2;
71
72 a0 = +2 * mu3 - 3 * mu2 + 1;
73 a1 = mu3 - 2 * mu2 + mu1;
74 a2 = mu3 - mu2;
75 a3 = -2 * mu3 + 3 * mu2;
76
77 return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
78 }
79
80 void AudioInterface::sample(uint16_t left, uint16_t right) {
81 int s_left = (int16_t)left;
82 int s_right = (int16_t)right;
83
84 if(volume != 100) {
85 s_left = sclamp<16>((double)s_left * (double)volume / 100.0);
86 s_right = sclamp<16>((double)s_right * (double)volume / 100.0);
87 }
88
89 r_left [0] = r_left [1];
90 r_left [1] = r_left [2];
91 r_left [2] = r_left [3];
92 r_left [3] = s_left;
93
94 r_right[0] = r_right[1];
95 r_right[1] = r_right[2];
96 r_right[2] = r_right[3];
97 r_right[3] = s_right;
98
99 if(resample_enabled == false) {
100 if(p) p->sample(left, right);
101 return;
102 }
103
104 while(r_frac <= 1.0) {
105 int output_left = sclamp<16>(hermite(r_frac, r_left [0], r_left [1], r_left [2], r_left [3]));
106 int output_right = sclamp<16>(hermite(r_frac, r_right[0], r_right[1], r_right[2], r_right[3]));
107 r_frac += r_step;
108 if(p) p->sample(output_left, output_right);
109 }
110
111 r_frac -= 1.0;
112 }
113
114 void AudioInterface::clear() {
115 r_frac = 0;
116 r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0;
117 r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0;
118 if(p) p->clear();
119 }
120
121 AudioInterface::AudioInterface() {
122 p = 0;
123 volume = 100;
124 resample_enabled = false;
125 r_step = r_frac = 0;
126 r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0;
127 r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0;
128 }
129
130 AudioInterface::~AudioInterface() {
131 term();
132 }
33
44 void Audio::coprocessor_enable(bool state) {
55 coprocessor = state;
6 dspaudio.clear();
67
78 dsp_rdoffset = cop_rdoffset = 0;
89 dsp_wroffset = cop_wroffset = 0;
910 dsp_length = cop_length = 0;
10
11 r_sum_l = r_sum_r = 0;
1211 }
1312
1413 void Audio::coprocessor_frequency(double input_frequency) {
15 double output_frequency;
16 output_frequency = system.apu_frequency() / 768.0;
17 r_step = input_frequency / output_frequency;
18 r_frac = 0;
14 dspaudio.setFrequency(input_frequency);
15 dspaudio.setResampler(nall::DSP::Resampler::Average);
16 dspaudio.setResamplerFrequency(system.apu_frequency() / 768.0);
1917 }
2018
2119 void Audio::sample(int16 left, int16 right) {
3028 }
3129
3230 void Audio::coprocessor_sample(int16 left, int16 right) {
33 if(r_frac >= 1.0) {
34 r_frac -= 1.0;
35 r_sum_l += left;
36 r_sum_r += right;
37 return;
31 dspaudio.sample(left, right);
32 while(dspaudio.pending()) {
33 signed left, right;
34 dspaudio.read(left, right);
35
36 cop_buffer[cop_wroffset] = ((uint16)left << 0) + ((uint16)right << 16);
37 cop_wroffset = (cop_wroffset + 1) & buffer_mask;
38 cop_length = (cop_length + 1) & buffer_mask;
39 flush();
3840 }
39
40 r_sum_l += left * r_frac;
41 r_sum_r += right * r_frac;
42
43 uint16 output_left = sclamp<16>(int(r_sum_l / r_step));
44 uint16 output_right = sclamp<16>(int(r_sum_r / r_step));
45
46 double first = 1.0 - r_frac;
47 r_sum_l = left * first;
48 r_sum_r = right * first;
49 r_frac = r_step - first;
50
51 cop_buffer[cop_wroffset] = (output_left << 0) + (output_right << 16);
52 cop_wroffset = (cop_wroffset + 1) & buffer_mask;
53 cop_length = (cop_length + 1) & buffer_mask;
54 flush();
5541 }
5642
5743 void Audio::init() {
77
88 private:
99 bool coprocessor;
10 enum : unsigned { buffer_size = 32768, buffer_mask = buffer_size - 1 };
10 nall::DSP dspaudio;
11 enum : unsigned { buffer_size = 256, buffer_mask = buffer_size - 1 };
1112 uint32 dsp_buffer[buffer_size], cop_buffer[buffer_size];
1213 unsigned dsp_rdoffset, cop_rdoffset;
1314 unsigned dsp_wroffset, cop_wroffset;
1415 unsigned dsp_length, cop_length;
1516
16 double r_step, r_frac;
17 int r_sum_l, r_sum_r;
18
1917 void flush();
2018 };
2119
00 class Interface {
11 public:
22 virtual void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan) {}
3 virtual void audio_sample(uint16_t l_sample, uint16_t r_sample) {}
3 virtual void audio_sample(int16_t l_sample, int16_t r_sample) {}
44 virtual int16_t input_poll(bool port, Input::Device device, unsigned index, unsigned id) { return 0; }
55
66 virtual void message(const string &text) { print(text, "\n"); }
00 namespace Info {
11 static const char Profile[] = "Performance";
22 }
3
4 #if defined(DEBUGGER)
5 #error "bsnes: debugger not supported with performance profile."
6 #endif
37
48 #include <snes/alt/cpu/cpu.hpp>
59 #include <snes/alt/smp/smp.hpp>
00 namespace SNES {
11 namespace Info {
22 static const char Name[] = "bsnes";
3 static const char Version[] = "081";
3 static const char Version[] = "082";
44 static const unsigned SerializerVersion = 21;
55 }
66 }
7
8 /*
9 bsnes - SNES emulator
10 author: byuu
11 license: GPLv2
12 */
713
814 #include <libco/libco.h>
915
1218 #include <nall/array.hpp>
1319 #include <nall/detect.hpp>
1420 #include <nall/dl.hpp>
21 #include <nall/dsp.hpp>
1522 #include <nall/endian.hpp>
1623 #include <nall/file.hpp>
1724 #include <nall/foreach.hpp>
33 #include <nall/bmp.hpp>
44 #include <nall/compositor.hpp>
55 #include <nall/config.hpp>
6 #include <nall/crc32.hpp>
67 #include <nall/directory.hpp>
8 #include <nall/dsp.hpp>
79 #include <nall/filemap.hpp>
810 #include <nall/input.hpp>
911 #include <nall/resource.hpp>
10 #include <nall/ups.hpp>
12 #include <nall/bps/patch.hpp>
1113 #include <nall/snes/cartridge.hpp>
1214 #include <nall/gameboy/cartridge.hpp>
1315 using namespace nall;
5860 void saveGeometry();
5961 };
6062
63 extern nall::DSP dspaudio;
6164 extern Application application;
8282 }
8383
8484 void Cartridge::unload() {
85 patchApplied = false;
85 patch.applied = false;
86 patch.information = "";
8687 if(SNES::cartridge.loaded() == false) return;
8788
8889 foreach(memory, SNES::cartridge.nvram) saveMemory(memory);
109110 fp.read(data, size);
110111 fp.close();
111112
112 filemap patch(string(nall::basename(filename), ".ups"), filemap::mode::read);
113 if(patch.open()) {
114 unsigned targetSize;
115 ups patcher;
116 if(patcher.apply(patch.data(), patch.size(), data, size, (uint8_t*)0, targetSize) == ups::result::target_too_small) {
117 uint8_t *targetData = new uint8_t[targetSize];
118 if(patcher.apply(patch.data(), patch.size(), data, size, targetData, targetSize) == ups::result::success) {
119 delete[] data;
120 data = targetData;
121 size = targetSize;
122 patchApplied = true;
113 string patchName = { nall::basename(filename), ".bps" };
114 if(file::exists(patchName)) {
115 bpspatch bps;
116 bps.modify(patchName);
117
118 unsigned targetSize = bps.size();
119 uint8_t *targetData = new uint8_t[targetSize];
120
121 bps.source(data, size);
122 bps.target(targetData, targetSize);
123
124 if(bps.apply() == bpspatch::result::success) {
125 delete[] data;
126 data = targetData;
127 size = targetSize;
128 patch.applied = true;
129
130 xml_element document = xml_parse(bps.metadata());
131 foreach(root, document.element) {
132 if(root.name == "metadata") {
133 if(auto x = root.content.position("<information>")) {
134 if(auto y = root.content.position("</information>")) {
135 patch.information = substr(root.content, x(), y() - x() + 14);
136 }
137 }
138 if(auto x = root.content.position("<cartridge ")) {
139 if(auto y = root.content.position("</cartridge>")) {
140 XML = substr(root.content, x(), y() - x() + 12);
141 }
142 }
143 }
123144 }
145 } else {
146 delete[] targetData;
124147 }
125148 }
126149
77
88 string baseName, bsxName, sufamiTurboAName, sufamiTurboBName, gameBoyName;
99 string baseXML, bsxXML, sufamiTurboAXML, sufamiTurboBXML, gameBoyXML;
10 bool patchApplied;
10
11 struct Patch {
12 bool applied;
13 string information;
14 } patch;
1115
1216 private:
1317 bool loadCartridge(SNES::MappedRAM &memory, string &XML, const char *filename);
3636 attach(audio.synchronize = true, "audio.synchronize");
3737 attach(audio.mute = false, "audio.mute");
3838 attach(audio.volume = 100, "audio.volume");
39 attach(audio.balance = 100, "audio.balance");
3940 attach(audio.latency = 60, "audio.latency");
4041 attach(audio.inputFrequency = 32000, "audio.inputFrequency");
4142 attach(audio.outputFrequency = 44100, "audio.outputFrequency");
1919 bool synchronize;
2020 bool mute;
2121 unsigned volume;
22 unsigned balance;
2223 unsigned latency;
2324 unsigned inputFrequency;
2425 unsigned outputFrequency;
128128 tm *info = localtime(&currentTime);
129129 string filename = { "-",
130130 decimal<4, '0'>(info->tm_year + 1900), "-", decimal<2, '0'>(info->tm_mon + 1), "-", decimal<2, '0'>(info->tm_mday), " ",
131 decimal<2, '0'>(info->tm_hour), ":", decimal<2, '0'>(info->tm_min), ":", decimal<2, '0'>(info->tm_sec), ".bmp"
131 decimal<2, '0'>(info->tm_hour), ".", decimal<2, '0'>(info->tm_min), ".", decimal<2, '0'>(info->tm_sec), ".bmp"
132132 };
133 bmp::write(path(utility.slotPath(), filename), buffer, outwidth, outheight, outpitch, false);
134 utility.showMessage("Screenshot captured");
133 if(bmp::write(path(utility.activeSlot(), filename), buffer, outwidth, outheight, outpitch, false)) {
134 utility.showMessage("Screenshot captured");
135 }
135136 }
136137 }
137138
138 void Interface::audio_sample(uint16_t left, uint16_t right) {
139 if(config.audio.mute) left = right = 0;
140 audio.sample(left, right);
139 void Interface::audio_sample(int16_t lchannel, int16_t rchannel) {
140 if(config.audio.mute) lchannel = 0, rchannel = 0;
141 dspaudio.sample(lchannel, rchannel);
142 while(dspaudio.pending()) {
143 signed lsample, rsample;
144 dspaudio.read(lsample, rsample);
145 audio.sample(lsample, rsample);
146 }
141147 }
142148
143149 int16_t Interface::input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
1515
1616 struct Interface : public SNES::Interface {
1717 void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan);
18 void audio_sample(uint16_t left, uint16_t right);
18 void audio_sample(int16_t left, int16_t right);
1919 int16_t input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id);
2020
2121 void message(const string &text);
00 #include "base.hpp"
11 #include "interface.cpp"
22 #include "config.cpp"
3 nall::DSP dspaudio;
34 Application application;
45
56 void Application::main(int argc, char **argv) {
9596 audio.driver(config.audio.driver);
9697 audio.set(Audio::Handle, mainWindow.viewport.handle());
9798 audio.set(Audio::Synchronize, config.audio.synchronize);
98 audio.set(Audio::Volume, config.audio.volume);
9999 audio.set(Audio::Latency, config.audio.latency);
100100 audio.set(Audio::Frequency, config.audio.outputFrequency);
101 audio.set(Audio::Resample, true);
102 audio.set(Audio::ResampleRatio, (double)config.audio.inputFrequency / (double)config.audio.outputFrequency);
103101 if(audio.init() == false) {
104102 MessageWindow::critical(mainWindow, "Failed to initialize audio.");
105103 audio.driver("None");
106104 audio.init();
107105 }
106
107 dspaudio.setPrecision(16); //16-bit signed audio
108 dspaudio.setVolume((double)config.audio.volume / 100.0);
109 dspaudio.setBalance((double)((signed)config.audio.balance - 100) / 100.0);
110 dspaudio.setFrequency(config.audio.inputFrequency);
111 dspaudio.setResampler(DSP::Resampler::Hermite);
112 dspaudio.setResamplerFrequency(config.audio.outputFrequency);
108113
109114 input.driver(config.input.driver);
110115 input.set(Input::Handle, mainWindow.viewport.handle());
143148 }
144149
145150 cartridge.unload();
151 utility.setFullScreen(false);
146152 saveGeometry();
147153 foreach(window, windows) window->setVisible(false);
148154 OS::processEvents();
4848 }
4949
5050 string Path::load(SNES::Cartridge::Slot slot, const string &hint) {
51 string basePath = basepath(slot);
52 string baseName = notdir(basePath);
53 string filePath = dir(basePath);
51 string baseName = utility.baseName(slot);
52 string fileName = notdir(baseName);
53 string filePath = dir(baseName);
5454
5555 if(hint == ".srm" && srm != "") filePath = srm;
5656 if(hint == ".bsp" && bsp != "") filePath = bsp;
7070 if(hint.endswith(".log") && log != "") filePath = log;
7171 if(hint.endswith(".bmp") && bmp != "") filePath = bmp;
7272
73 filePath = decode(filePath, basePath);
74 return { filePath, baseName, hint };
75 }
76
77 string Path::basepath(SNES::Cartridge::Slot slot) {
78 if(slot == SNES::Cartridge::Slot::Base) {
79 return cartridge.baseName;
80 }
81
82 if(slot == SNES::Cartridge::Slot::Bsx) {
83 if(cartridge.bsxName == "") return cartridge.baseName;
84 return cartridge.bsxName;
85 }
86
87 if(slot == SNES::Cartridge::Slot::SufamiTurbo) {
88 if(cartridge.sufamiTurboAName == "" && cartridge.sufamiTurboBName == "") return cartridge.baseName;
89 if(cartridge.sufamiTurboAName != "" && cartridge.sufamiTurboBName == "") return cartridge.sufamiTurboAName;
90 if(cartridge.sufamiTurboAName == "" && cartridge.sufamiTurboBName != "") return cartridge.sufamiTurboBName;
91 return { cartridge.sufamiTurboAName, "+", notdir(cartridge.sufamiTurboBName) };
92 }
93
94 if(slot == SNES::Cartridge::Slot::SufamiTurboA) {
95 if(cartridge.sufamiTurboAName == "") return cartridge.baseName;
96 return cartridge.sufamiTurboAName;
97 }
98
99 if(slot == SNES::Cartridge::Slot::SufamiTurboB) {
100 if(cartridge.sufamiTurboBName == "") return cartridge.baseName;
101 return cartridge.sufamiTurboBName;
102 }
103
104 if(slot == SNES::Cartridge::Slot::GameBoy) {
105 if(cartridge.gameBoyName == "") return cartridge.baseName;
106 return cartridge.gameBoyName;
107 }
108
109 throw "Path::basepath(): invalid slot ID.";
73 filePath = decode(filePath, baseName);
74 return { filePath, fileName, hint };
11075 }
11176
11277 string Path::decode(const string &filePath, const string &basePath) {
3131 string load(const string &path);
3232 void save(const string &path, const string &value);
3333 string load(SNES::Cartridge::Slot slot, const string &hint);
34
35 string basepath(SNES::Cartridge::Slot slot);
3634 string decode(const string &filePath, const string &basePath);
3735
3836 void load();
33 title.setText("Audio Settings");
44 title.setFont(application.titleFont);
55
6 frequencyLabel.setText("Frequency:");
7 frequencySlider.setLength(2001);
68 volumeLabel.setText("Volume:");
79 volumeSlider.setLength(201);
8 frequencyLabel.setText("Frequency:");
9 frequencySlider.setLength(2001);
10 balanceLabel.setText("Balance:");
11 balanceSlider.setLength(201);
1012
1113 panelLayout.setMargin(5);
1214 panelLayout.append(panel, SettingsWindow::PanelWidth, ~0, 5);
1416
1517 layout.append(title, ~0, 0, 5);
1618
19 frequencyLayout.append(frequencyLabel, 70, 0);
20 frequencyLayout.append(frequencyValue, 60, 0);
21 frequencyLayout.append(frequencySlider, ~0, 0);
22 layout.append(frequencyLayout);
23
1724 volumeLayout.append(volumeLabel, 70, 0);
1825 volumeLayout.append(volumeValue, 60, 0);
1926 volumeLayout.append(volumeSlider, ~0, 0);
2027 layout.append(volumeLayout);
2128
22 frequencyLayout.append(frequencyLabel, 70, 0);
23 frequencyLayout.append(frequencyValue, 60, 0);
24 frequencyLayout.append(frequencySlider, ~0, 0);
25 layout.append(frequencyLayout);
29 balanceLayout.append(balanceLabel, 70, 0);
30 balanceLayout.append(balanceValue, 60, 0);
31 balanceLayout.append(balanceSlider, ~0, 0);
32 layout.append(balanceLayout);
2633
2734 layout.append(spacer, ~0, ~0);
2835 settingsWindow.append(panelLayout);
2936
37 frequencySlider.onChange = [this] {
38 config.audio.inputFrequency = frequencySlider.position() + 31000;
39 dspaudio.setFrequency(config.audio.inputFrequency);
40 frequencyValue.setText({ config.audio.inputFrequency, "hz" });
41 };
42
3043 volumeSlider.onChange = [this] {
3144 config.audio.volume = volumeSlider.position();
32 audio.set(Audio::Volume, config.audio.volume);
45 dspaudio.setVolume((double)config.audio.volume / 100.0);
3346 volumeValue.setText({ config.audio.volume, "%" });
3447 };
3548
36 frequencySlider.onChange = [this] {
37 config.audio.inputFrequency = frequencySlider.position() + 31000;
38 audio.set(Audio::ResampleRatio, (double)config.audio.inputFrequency / (double)config.audio.outputFrequency);
39 frequencyValue.setText({ config.audio.inputFrequency, "hz" });
49 balanceSlider.onChange = [this] {
50 config.audio.balance = balanceSlider.position();
51 dspaudio.setBalance((double)((signed)config.audio.balance - 100) / 100.0);
52 balanceValue.setText({ (signed)config.audio.balance - 100 });
4053 };
54
55 frequencySlider.setPosition(config.audio.inputFrequency - 31000);
56 frequencyValue.setText({ config.audio.inputFrequency, "hz" });
4157
4258 volumeSlider.setPosition(config.audio.volume);
4359 volumeValue.setText({ config.audio.volume, "%" });
4460
45 frequencySlider.setPosition(config.audio.inputFrequency - 31000);
46 frequencyValue.setText({ config.audio.inputFrequency, "hz" });
61 balanceSlider.setPosition(config.audio.balance);
62 balanceValue.setText({ (signed)config.audio.balance - 100 });
4763 }
33 VerticalLayout layout;
44 Label title;
55
6 HorizontalLayout frequencyLayout;
7 Label frequencyLabel;
8 Label frequencyValue;
9 HorizontalSlider frequencySlider;
10
611 HorizontalLayout volumeLayout;
712 Label volumeLabel;
813 Label volumeValue;
914 HorizontalSlider volumeSlider;
1015
11 HorizontalLayout frequencyLayout;
12 Label frequencyLabel;
13 Label frequencyValue;
14 HorizontalSlider frequencySlider;
16 HorizontalLayout balanceLayout;
17 Label balanceLabel;
18 Label balanceValue;
19 HorizontalSlider balanceSlider;
1520
1621 Widget spacer;
1722
1111
1212 unsigned n = 0;
1313 string data;
14 data.readfile(path.load(utility.slotPath(), ".cht"));
14 data.readfile(path.load(utility.activeSlot(), ".cht"));
1515 xml_element document = xml_parse(data);
1616 foreach(head, document.element) {
1717 if(head.name == "cartridge") {
5151 }
5252 }
5353 if(lastSave == -1) {
54 unlink(path.load(utility.slotPath(), ".cht"));
54 unlink(path.load(utility.activeSlot(), ".cht"));
5555 return;
5656 }
5757
5858 file fp;
59 if(fp.open(path.load(utility.slotPath(), ".cht"), file::mode::write)) {
59 if(fp.open(path.load(utility.activeSlot(), ".cht"), file::mode::write)) {
6060 fp.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
6161 fp.print("<cartridge sha256=\"", SNES::cartridge.sha256(), "\">\n");
6262 for(unsigned i = 0; i <= lastSave; i++) {
6363 }
6464
6565 file fp;
66 if(fp.open(path.load(utility.slotPath(), ".bsa"), file::mode::read)) {
66 if(fp.open(path.load(utility.activeSlot(), ".bsa"), file::mode::read)) {
6767 if(fp.readl(4) == 0x31415342) {
6868 if(fp.readl(4) == SNES::Info::SerializerVersion) {
6969 for(unsigned i = 0; i < 32; i++) {
8888 }
8989
9090 if(hasSave == false) {
91 unlink(path.load(utility.slotPath(), ".bsa"));
91 unlink(path.load(utility.activeSlot(), ".bsa"));
9292 } else {
9393 file fp;
94 if(fp.open(path.load(utility.slotPath(), ".bsa"), file::mode::write)) {
94 if(fp.open(path.load(utility.activeSlot(), ".bsa"), file::mode::write)) {
9595 fp.writel(0x31415342, 4); //'BSA1'
9696 fp.writel(SNES::Info::SerializerVersion, 4);
9797
159159 cheatEditor.load();
160160 stateManager.load();
161161 mainWindow.synchronize();
162 utility.setTitle(notdir(cartridge.baseName));
162
163 string name = baseName(activeSlot());
164 utility.setTitle(notdir(name));
163165 utility.showMessage({
164 "Loaded ", notdir(cartridge.baseName),
165 cartridge.patchApplied ? ", and applied UPS patch" : ""
166 "Loaded ", notdir(name),
167 cartridge.patch.applied ? ", and applied BPS patch" : ""
166168 });
167169
168170 //NSS
179181 mainWindow.synchronize();
180182 }
181183
182 SNES::Cartridge::Slot Utility::slotPath() {
184 SNES::Cartridge::Slot Utility::activeSlot() {
183185 SNES::Cartridge::Slot slot = SNES::Cartridge::Slot::Base;
184186 if(SNES::cartridge.mode() == SNES::Cartridge::Mode::Bsx) slot = SNES::Cartridge::Slot::Bsx;
185187 if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SufamiTurbo) slot = SNES::Cartridge::Slot::SufamiTurbo;
187189 return slot;
188190 }
189191
192 string Utility::baseName(SNES::Cartridge::Slot slot) {
193 switch(slot) {
194 default:
195 return cartridge.baseName;
196 case SNES::Cartridge::Slot::Bsx:
197 if(cartridge.bsxName == "") return cartridge.baseName;
198 return cartridge.bsxName;
199 case SNES::Cartridge::Slot::SufamiTurbo:
200 if(cartridge.sufamiTurboAName == "" && cartridge.sufamiTurboBName == "") return cartridge.baseName;
201 if(cartridge.sufamiTurboBName == "") return cartridge.sufamiTurboAName;
202 if(cartridge.sufamiTurboAName == "") return cartridge.sufamiTurboBName;
203 return { cartridge.sufamiTurboAName, "+", cartridge.sufamiTurboBName };
204 case SNES::Cartridge::Slot::GameBoy:
205 if(cartridge.gameBoyName == "") return cartridge.baseName;
206 return cartridge.gameBoyName;
207 }
208 }
209
190210 void Utility::saveState(unsigned slot) {
191 string filename = path.load(slotPath(), { "-", slot, ".bst" });
211 string filename = path.load(activeSlot(), { "-", slot, ".bst" });
192212 SNES::system.runtosave();
193213 serializer s = SNES::system.serialize();
194214 file fp;
202222 }
203223
204224 void Utility::loadState(unsigned slot) {
205 string filename = path.load(slotPath(), { "-", slot, ".bst" });
225 string filename = path.load(activeSlot(), { "-", slot, ".bst" });
206226 file fp;
207227 if(fp.open(filename, file::mode::read)) {
208228 unsigned size = fp.size();
1414 void cartridgeLoaded();
1515 void cartridgeUnloaded();
1616
17 SNES::Cartridge::Slot slotPath();
17 SNES::Cartridge::Slot activeSlot();
18 string baseName(SNES::Cartridge::Slot slot);
19
1820 void saveState(unsigned slot);
1921 void loadState(unsigned slot);
2022
0 #include <nall/dsp.hpp>
01 #include <nall/file.hpp>
12 #include <nall/foreach.hpp>
23 #include <nall/stdint.hpp>
2829 void main(int argc, char **argv);
2930 };
3031
32 extern nall::DSP dspaudio;
3133 extern Application application;
2727 }
2828 }
2929
30 void Interface::audio_sample(int16_t center, int16_t left, int16_t right) {
31 audio.sample(left, right);
30 void Interface::audio_sample(int16_t center, int16_t lchannel, int16_t rchannel) {
31 dspaudio.sample(lchannel, rchannel);
32 while(dspaudio.pending()) {
33 signed lsample, rsample;
34 dspaudio.read(lsample, rsample);
35 audio.sample(lsample, rsample);
36 }
3237 }
3338
3439 void Interface::input_poll() {
00 #include "base.hpp"
1 nall::DSP dspaudio;
12 Application application;
23
34 #include "interface.cpp"
5051 #endif
5152 audio.set(Audio::Handle, (uintptr_t)mainWindow.viewport.handle());
5253 audio.set(Audio::Synchronize, true);
53 audio.set(Audio::Volume, 100U);
54 audio.set(Audio::Latency, 80U);
55 audio.set(Audio::Frequency, 44100U);
56 audio.set(Audio::Resample, true);
57 audio.set(Audio::ResampleRatio, 4194304.0 / 44100.0);
54 audio.set(Audio::Latency, 80u);
55 audio.set(Audio::Frequency, 44100u);
5856 audio.init();
57
58 dspaudio.setPrecision(16);
59 dspaudio.setVolume(1.0);
60 dspaudio.setBalance(0.0);
61 dspaudio.setFrequency(4194304.0);
62 dspaudio.setResampler(DSP::Resampler::Average);
63 dspaudio.setResamplerFrequency(44100.0);
5964
6065 #if defined(PLATFORM_WIN)
6166 input.driver("RawInput");
2020 if(pinput_poll) pinput_poll();
2121 }
2222
23 void audio_sample(uint16_t left, uint16_t right) {
23 void audio_sample(int16_t left, int16_t right) {
2424 if(paudio_sample) return paudio_sample(left, right);
2525 }
2626
5050 double g = (G << 3) | (G >> 2);
5151 double b = (B << 3) | (B >> 2);
5252
53 //bgr888->yuv888
53 //bgr888->yuv
5454 double y = (r + g + b) * (0.25f * (63.5f / 48.0f));
5555 double u = ((r - b) * 0.25f + 128.0f) * (7.5f / 7.0f);
5656 double v = ((g * 2.0f - r - b) * 0.125f + 128.0f) * (7.5f / 6.0f);
5858 yuvTable[i] = ((unsigned)y << 21) + ((unsigned)u << 11) + ((unsigned)v);
5959 }
6060
61 //counter-clockwise rotation table; one revolution:
62 //123 369 12346789
63 //4.6 -> 2.8 =
64 //789 147 36928147
6165 for(unsigned n = 0; n < 256; n++) {
6266 rotate[n] = ((n >> 2) & 0x11) | ((n << 2) & 0x88)
6367 | ((n & 0x01) << 5) | ((n & 0x08) << 3)
8286
8387 static uint16_t blend1(uint32_t A, uint32_t B) {
8488 grow(A); grow(B);
85 A = (A * 3 + B) >> 2;
86 return pack(A);
89 return pack((A * 3 + B) >> 2);
8790 }
8891
8992 static uint16_t blend2(uint32_t A, uint32_t B, uint32_t C) {
00 g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp `pkg-config --cflags gtk+-2.0` -DPHOENIX_GTK
1 g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_GTK
1 g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp
22 g++-4.5 -s -o snespurify-gtk snespurify.o phoenix.o `pkg-config --libs gtk+-2.0` -lX11
33 rm *.o
00 moc -i -o phoenix/qt/qt.moc phoenix/qt/qt.moc.hpp
11 g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp `pkg-config --cflags QtCore QtGui` -DPHOENIX_QT
2 g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_QT
2 g++-4.5 -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp
33 g++-4.5 -s -o snespurify-qt snespurify.o phoenix.o `pkg-config --libs QtCore QtGui`
44 rm *.o
0 windres phoenix/windows/phoenix.rc phoenix-resource.o
1 g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS
2 g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp -DPHOENIX_WINDOWS
3 g++ -mwindows -s -o snespurify snespurify.o phoenix.o phoenix-resource.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32
4 @pause
5 @del *.o
0 windres phoenix/windows/phoenix.rc phoenix-resource.o
1 g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS
2 g++ -std=gnu++0x -I. -O3 -fomit-frame-pointer -c snespurify.cpp
3 g++ -mwindows -s -o snespurify snespurify.o phoenix.o phoenix-resource.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32
4 @pause
5 @del *.o
5151
5252 void append(const T data) {
5353 operator[](buffersize) = data;
54 }
55
56 void remove() {
57 if(size > 0) resize(size - 1); //remove last element only
5458 }
5559
5660 template<typename U> void insert(unsigned index, const U list) {
132136 if(index >= buffersize) throw "array[] out of bounds";
133137 return pool[index];
134138 }
139
140 //iteration
141 T* begin() { return &pool[0]; }
142 T* end() { return &pool[buffersize]; }
143 const T* begin() const { return &pool[0]; }
144 const T* end() const { return &pool[buffersize]; }
135145 };
136146
137147 template<typename T> struct has_size<array<T>> { enum { value = true }; };
7171
7272 private:
7373 static char enc(uint8_t n) {
74 //base64 for URL encodings
7475 static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
7576 return lookup_table[n & 63];
7677 }
0 #ifndef NALL_BMP_HPP
1 #define NALL_BMP_HPP
2
3 #include <nall/file.hpp>
4
5 //BMP reader / writer
6 //author: byuu
7 //note: only 24-bit RGB and 32-bit ARGB uncompressed images supported
8
9 namespace nall {
10
11 struct bmp {
12 inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height);
13 inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha = false);
14 };
15
16 bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) {
17 file fp;
18 if(fp.open(filename, file::mode::read) == false) return false;
19 if(fp.size() < 0x36) return false;
20
21 if(fp.readm(2) != 0x424d) return false;
22 fp.seek(0x000a);
23 unsigned offset = fp.readl(4);
24 unsigned dibsize = fp.readl(4);
25 if(dibsize != 40) return false;
26 signed headerWidth = fp.readl(4);
27 if(headerWidth < 0) return false;
28 signed headerHeight = fp.readl(4);
29 fp.readl(2);
30 unsigned bitsPerPixel = fp.readl(2);
31 if(bitsPerPixel != 24 && bitsPerPixel != 32) return false;
32 unsigned compression = fp.readl(4);
33 if(compression != 0) return false;
34 fp.seek(offset);
35
36 bool noFlip = headerHeight < 0;
37 width = headerWidth, height = abs(headerHeight);
38 data = new uint32_t[width * height];
39
40 unsigned bytesPerPixel = bitsPerPixel / 8;
41 unsigned alignedWidth = width * bytesPerPixel;
42 unsigned paddingLength = 0;
43 while(alignedWidth % 4) alignedWidth++, paddingLength++;
44
45 for(unsigned y = 0; y < height; y++) {
46 uint32_t *p = noFlip ? data + y * width : data + (height - 1 - y) * width;
47 for(unsigned x = 0; x < width; x++, p++) {
48 *p = fp.readl(bytesPerPixel);
49 if(bytesPerPixel == 3) *p |= 255 << 24;
50 }
51 if(paddingLength) fp.readl(paddingLength);
52 }
53
54 fp.close();
55 return true;
56 }
57
58 bool bmp::write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha) {
59 file fp;
60 if(fp.open(filename, file::mode::write) == false) return false;
61
62 unsigned bitsPerPixel = alpha ? 32 : 24;
63 unsigned bytesPerPixel = bitsPerPixel / 8;
64 unsigned alignedWidth = width * bytesPerPixel;
65 unsigned paddingLength = 0;
66 unsigned imageSize = alignedWidth * height;
67 unsigned fileSize = 0x36 + imageSize;
68 while(alignedWidth % 4) alignedWidth++, paddingLength++;
69
70 fp.writem(0x424d, 2); //signature
71 fp.writel(fileSize, 4); //file size
72 fp.writel(0, 2); //reserved
73 fp.writel(0, 2); //reserved
74 fp.writel(0x36, 4); //offset
75
76 fp.writel(40, 4); //DIB size
77 fp.writel(width, 4); //width
78 fp.writel(-height, 4); //height
79 fp.writel(1, 2); //color planes
80 fp.writel(bitsPerPixel, 2); //bits per pixel
81 fp.writel(0, 4); //compression method (BI_RGB)
82 fp.writel(imageSize, 4); //image data size
83 fp.writel(3780, 4); //horizontal resolution
84 fp.writel(3780, 4); //vertical resolution
85 fp.writel(0, 4); //palette size
86 fp.writel(0, 4); //important color count
87
88 for(unsigned y = 0; y < height; y++) {
89 const uint32_t *p = (const uint32_t*)((const uint8_t*)data + y * pitch);
90 for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel);
91 if(paddingLength) fp.writel(0, paddingLength);
92 }
93
94 fp.close();
95 return true;
96 }
97
98 }
99
100 #endif
0 #ifndef NALL_BPS_DELTA_HPP
1 #define NALL_BPS_DELTA_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpsdelta {
12 inline void source(const uint8_t *data, unsigned size);
13 inline void target(const uint8_t *data, unsigned size);
14
15 inline bool source(const string &filename);
16 inline bool target(const string &filename);
17 inline bool create(const string &filename, const string &metadata = "");
18
19 protected:
20 enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
21 enum : unsigned { Granularity = 1 };
22
23 struct Node {
24 unsigned offset;
25 Node *next;
26 inline Node() : offset(0), next(0) {}
27 inline ~Node() { if(next) delete next; }
28 };
29
30 filemap sourceFile;
31 const uint8_t *sourceData;
32 unsigned sourceSize;
33
34 filemap targetFile;
35 const uint8_t *targetData;
36 unsigned targetSize;
37 };
38
39 void bpsdelta::source(const uint8_t *data, unsigned size) {
40 sourceData = data;
41 sourceSize = size;
42 }
43
44 void bpsdelta::target(const uint8_t *data, unsigned size) {
45 targetData = data;
46 targetSize = size;
47 }
48
49 bool bpsdelta::source(const string &filename) {
50 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
51 source(sourceFile.data(), sourceFile.size());
52 return true;
53 }
54
55 bool bpsdelta::target(const string &filename) {
56 if(targetFile.open(filename, filemap::mode::read) == false) return false;
57 target(targetFile.data(), targetFile.size());
58 return true;
59 }
60
61 bool bpsdelta::create(const string &filename, const string &metadata) {
62 file modifyFile;
63 if(modifyFile.open(filename, file::mode::write) == false) return false;
64
65 uint32_t sourceChecksum = ~0, modifyChecksum = ~0;
66 unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
67
68 auto write = [&](uint8_t data) {
69 modifyFile.write(data);
70 modifyChecksum = crc32_adjust(modifyChecksum, data);
71 };
72
73 auto encode = [&](uint64_t data) {
74 while(true) {
75 uint64_t x = data & 0x7f;
76 data >>= 7;
77 if(data == 0) {
78 write(0x80 | x);
79 break;
80 }
81 write(x);
82 data--;
83 }
84 };
85
86 write('B');
87 write('P');
88 write('S');
89 write('1');
90
91 encode(sourceSize);
92 encode(targetSize);
93
94 unsigned markupSize = metadata.length();
95 encode(markupSize);
96 for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
97
98 Node *sourceTree[65536], *targetTree[65536];
99 for(unsigned n = 0; n < 65536; n++) sourceTree[n] = 0, targetTree[n] = 0;
100
101 //source tree creation
102 for(unsigned offset = 0; offset < sourceSize; offset++) {
103 uint16_t symbol = sourceData[offset + 0];
104 sourceChecksum = crc32_adjust(sourceChecksum, symbol);
105 if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8;
106 Node *node = new Node;
107 node->offset = offset;
108 node->next = sourceTree[symbol];
109 sourceTree[symbol] = node;
110 }
111
112 unsigned targetReadLength = 0;
113
114 auto targetReadFlush = [&]() {
115 if(targetReadLength) {
116 encode(TargetRead | ((targetReadLength - 1) << 2));
117 unsigned offset = outputOffset - targetReadLength;
118 while(targetReadLength) write(targetData[offset++]), targetReadLength--;
119 }
120 };
121
122 while(outputOffset < targetSize) {
123 unsigned maxLength = 0, maxOffset = 0, mode = TargetRead;
124
125 uint16_t symbol = targetData[outputOffset + 0];
126 if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8;
127
128 { //source read
129 unsigned length = 0, offset = outputOffset;
130 while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) {
131 length++;
132 offset++;
133 }
134 if(length > maxLength) maxLength = length, mode = SourceRead;
135 }
136
137 { //source copy
138 Node *node = sourceTree[symbol];
139 while(node) {
140 unsigned length = 0, x = node->offset, y = outputOffset;
141 while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++;
142 if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy;
143 node = node->next;
144 }
145 }
146
147 { //target copy
148 Node *node = targetTree[symbol];
149 while(node) {
150 unsigned length = 0, x = node->offset, y = outputOffset;
151 while(y < targetSize && targetData[x++] == targetData[y++]) length++;
152 if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy;
153 node = node->next;
154 }
155
156 //target tree append
157 node = new Node;
158 node->offset = outputOffset;
159 node->next = targetTree[symbol];
160 targetTree[symbol] = node;
161 }
162
163 { //target read
164 if(maxLength < 4) {
165 maxLength = min((unsigned)Granularity, targetSize - outputOffset);
166 mode = TargetRead;
167 }
168 }
169
170 if(mode != TargetRead) targetReadFlush();
171
172 switch(mode) {
173 case SourceRead:
174 encode(SourceRead | ((maxLength - 1) << 2));
175 break;
176 case TargetRead:
177 //delay write to group sequential TargetRead commands into one
178 targetReadLength += maxLength;
179 break;
180 case SourceCopy:
181 case TargetCopy:
182 encode(mode | ((maxLength - 1) << 2));
183 signed relativeOffset;
184 if(mode == SourceCopy) {
185 relativeOffset = maxOffset - sourceRelativeOffset;
186 sourceRelativeOffset = maxOffset + maxLength;
187 } else {
188 relativeOffset = maxOffset - targetRelativeOffset;
189 targetRelativeOffset = maxOffset + maxLength;
190 }
191 encode((relativeOffset < 0) | (abs(relativeOffset) << 1));
192 break;
193 }
194
195 outputOffset += maxLength;
196 }
197
198 targetReadFlush();
199
200 sourceChecksum = ~sourceChecksum;
201 for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n);
202 uint32_t targetChecksum = crc32_calculate(targetData, targetSize);
203 for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n);
204 uint32_t outputChecksum = ~modifyChecksum;
205 for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
206
207 modifyFile.close();
208 return true;
209 }
210
211 }
212
213 #endif
0 #ifndef NALL_BPS_LINEAR_HPP
1 #define NALL_BPS_LINEAR_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpslinear {
12 inline void source(const uint8_t *data, unsigned size);
13 inline void target(const uint8_t *data, unsigned size);
14
15 inline bool source(const string &filename);
16 inline bool target(const string &filename);
17 inline bool create(const string &filename, const string &metadata = "");
18
19 protected:
20 enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
21 enum : unsigned { Granularity = 1 };
22
23 filemap sourceFile;
24 const uint8_t *sourceData;
25 unsigned sourceSize;
26
27 filemap targetFile;
28 const uint8_t *targetData;
29 unsigned targetSize;
30 };
31
32 void bpslinear::source(const uint8_t *data, unsigned size) {
33 sourceData = data;
34 sourceSize = size;
35 }
36
37 void bpslinear::target(const uint8_t *data, unsigned size) {
38 targetData = data;
39 targetSize = size;
40 }
41
42 bool bpslinear::source(const string &filename) {
43 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
44 source(sourceFile.data(), sourceFile.size());
45 return true;
46 }
47
48 bool bpslinear::target(const string &filename) {
49 if(targetFile.open(filename, filemap::mode::read) == false) return false;
50 target(targetFile.data(), targetFile.size());
51 return true;
52 }
53
54 bool bpslinear::create(const string &filename, const string &metadata) {
55 file modifyFile;
56 if(modifyFile.open(filename, file::mode::write) == false) return false;
57
58 uint32_t modifyChecksum = ~0;
59 unsigned targetRelativeOffset = 0, outputOffset = 0;
60
61 auto write = [&](uint8_t data) {
62 modifyFile.write(data);
63 modifyChecksum = crc32_adjust(modifyChecksum, data);
64 };
65
66 auto encode = [&](uint64_t data) {
67 while(true) {
68 uint64_t x = data & 0x7f;
69 data >>= 7;
70 if(data == 0) {
71 write(0x80 | x);
72 break;
73 }
74 write(x);
75 data--;
76 }
77 };
78
79 unsigned targetReadLength = 0;
80
81 auto targetReadFlush = [&]() {
82 if(targetReadLength) {
83 encode(TargetRead | ((targetReadLength - 1) << 2));
84 unsigned offset = outputOffset - targetReadLength;
85 while(targetReadLength) write(targetData[offset++]), targetReadLength--;
86 }
87 };
88
89 write('B');
90 write('P');
91 write('S');
92 write('1');
93
94 encode(sourceSize);
95 encode(targetSize);
96
97 unsigned markupSize = metadata.length();
98 encode(markupSize);
99 for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
100
101 while(outputOffset < targetSize) {
102 unsigned sourceLength = 0;
103 for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) {
104 if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break;
105 sourceLength++;
106 }
107
108 unsigned rleLength = 0;
109 for(unsigned n = 1; outputOffset + n < targetSize; n++) {
110 if(targetData[outputOffset] != targetData[outputOffset + n]) break;
111 rleLength++;
112 }
113
114 if(rleLength >= 4) {
115 //write byte to repeat
116 targetReadLength++;
117 outputOffset++;
118 targetReadFlush();
119
120 //copy starting from repetition byte
121 encode(TargetCopy | ((rleLength - 1) << 2));
122 unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset;
123 encode(relativeOffset << 1);
124 outputOffset += rleLength;
125 targetRelativeOffset = outputOffset - 1;
126 } else if(sourceLength >= 4) {
127 targetReadFlush();
128 encode(SourceRead | ((sourceLength - 1) << 2));
129 outputOffset += sourceLength;
130 } else {
131 targetReadLength += Granularity;
132 outputOffset += Granularity;
133 }
134 }
135
136 targetReadFlush();
137
138 uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize);
139 for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n);
140 uint32_t targetChecksum = crc32_calculate(targetData, targetSize);
141 for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n);
142 uint32_t outputChecksum = ~modifyChecksum;
143 for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
144
145 modifyFile.close();
146 return true;
147 }
148
149 }
150
151 #endif
0 #ifndef NALL_BPS_METADATA_HPP
1 #define NALL_BPS_METADATA_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpsmetadata {
12 inline bool load(const string &filename);
13 inline bool save(const string &filename, const string &metadata);
14 inline string metadata() const;
15
16 protected:
17 file sourceFile;
18 string metadataString;
19 };
20
21 bool bpsmetadata::load(const string &filename) {
22 if(sourceFile.open(filename, file::mode::read) == false) return false;
23
24 auto read = [&]() -> uint8_t {
25 return sourceFile.read();
26 };
27
28 auto decode = [&]() -> uint64_t {
29 uint64_t data = 0, shift = 1;
30 while(true) {
31 uint8_t x = read();
32 data += (x & 0x7f) * shift;
33 if(x & 0x80) break;
34 shift <<= 7;
35 data += shift;
36 }
37 return data;
38 };
39
40 if(read() != 'B') return false;
41 if(read() != 'P') return false;
42 if(read() != 'S') return false;
43 if(read() != '1') return false;
44 decode();
45 decode();
46 unsigned metadataSize = decode();
47 char data[metadataSize + 1];
48 for(unsigned n = 0; n < metadataSize; n++) data[n] = read();
49 data[metadataSize] = 0;
50 metadataString = (const char*)data;
51
52 return true;
53 }
54
55 bool bpsmetadata::save(const string &filename, const string &metadata) {
56 file targetFile;
57 if(targetFile.open(filename, file::mode::write) == false) return false;
58 if(sourceFile.open() == false) return false;
59 sourceFile.seek(0);
60
61 auto read = [&]() -> uint8_t {
62 return sourceFile.read();
63 };
64
65 auto decode = [&]() -> uint64_t {
66 uint64_t data = 0, shift = 1;
67 while(true) {
68 uint8_t x = read();
69 data += (x & 0x7f) * shift;
70 if(x & 0x80) break;
71 shift <<= 7;
72 data += shift;
73 }
74 return data;
75 };
76
77 uint32_t checksum = ~0;
78
79 auto write = [&](uint8_t data) {
80 targetFile.write(data);
81 checksum = crc32_adjust(checksum, data);
82 };
83
84 auto encode = [&](uint64_t data) {
85 while(true) {
86 uint64_t x = data & 0x7f;
87 data >>= 7;
88 if(data == 0) {
89 write(0x80 | x);
90 break;
91 }
92 write(x);
93 data--;
94 }
95 };
96
97 for(unsigned n = 0; n < 4; n++) write(read());
98 encode(decode());
99 encode(decode());
100 unsigned sourceLength = decode();
101 unsigned targetLength = metadata.length();
102 encode(targetLength);
103 sourceFile.seek(sourceLength, file::index::relative);
104 for(unsigned n = 0; n < targetLength; n++) write(metadata[n]);
105 unsigned length = sourceFile.size() - sourceFile.offset() - 4;
106 for(unsigned n = 0; n < length; n++) write(read());
107 uint32_t outputChecksum = ~checksum;
108 for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n);
109
110 targetFile.close();
111 return true;
112 }
113
114 string bpsmetadata::metadata() const {
115 return metadataString;
116 }
117
118 }
119
120 #endif
0 #ifndef NALL_BPS_PATCH_HPP
1 #define NALL_BPS_PATCH_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/filemap.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct bpspatch {
12 inline bool modify(const uint8_t *data, unsigned size);
13 inline void source(const uint8_t *data, unsigned size);
14 inline void target(uint8_t *data, unsigned size);
15
16 inline bool modify(const string &filename);
17 inline bool source(const string &filename);
18 inline bool target(const string &filename);
19
20 inline string metadata() const;
21 inline unsigned size() const;
22
23 enum result : unsigned {
24 unknown,
25 success,
26 patch_too_small,
27 patch_invalid_header,
28 source_too_small,
29 target_too_small,
30 source_checksum_invalid,
31 target_checksum_invalid,
32 patch_checksum_invalid,
33 };
34
35 inline result apply();
36
37 protected:
38 enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
39
40 filemap modifyFile;
41 const uint8_t *modifyData;
42 unsigned modifySize;
43
44 filemap sourceFile;
45 const uint8_t *sourceData;
46 unsigned sourceSize;
47
48 filemap targetFile;
49 uint8_t *targetData;
50 unsigned targetSize;
51
52 unsigned modifySourceSize;
53 unsigned modifyTargetSize;
54 unsigned modifyMarkupSize;
55 string metadataString;
56 };
57
58 bool bpspatch::modify(const uint8_t *data, unsigned size) {
59 if(size < 19) return false;
60 modifyData = data;
61 modifySize = size;
62
63 unsigned offset = 4;
64 auto decode = [&]() -> uint64_t {
65 uint64_t data = 0, shift = 1;
66 while(true) {
67 uint8_t x = modifyData[offset++];
68 data += (x & 0x7f) * shift;
69 if(x & 0x80) break;
70 shift <<= 7;
71 data += shift;
72 }
73 return data;
74 };
75
76 modifySourceSize = decode();
77 modifyTargetSize = decode();
78 modifyMarkupSize = decode();
79
80 char buffer[modifyMarkupSize + 1];
81 for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++];
82 buffer[modifyMarkupSize] = 0;
83 metadataString = (const char*)buffer;
84
85 return true;
86 }
87
88 void bpspatch::source(const uint8_t *data, unsigned size) {
89 sourceData = data;
90 sourceSize = size;
91 }
92
93 void bpspatch::target(uint8_t *data, unsigned size) {
94 targetData = data;
95 targetSize = size;
96 }
97
98 bool bpspatch::modify(const string &filename) {
99 if(modifyFile.open(filename, filemap::mode::read) == false) return false;
100 return modify(modifyFile.data(), modifyFile.size());
101 }
102
103 bool bpspatch::source(const string &filename) {
104 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
105 source(sourceFile.data(), sourceFile.size());
106 return true;
107 }
108
109 bool bpspatch::target(const string &filename) {
110 file fp;
111 if(fp.open(filename, file::mode::write) == false) return false;
112 fp.truncate(modifyTargetSize);
113 fp.close();
114
115 if(targetFile.open(filename, filemap::mode::readwrite) == false) return false;
116 target(targetFile.data(), targetFile.size());
117 return true;
118 }
119
120 string bpspatch::metadata() const {
121 return metadataString;
122 }
123
124 unsigned bpspatch::size() const {
125 return modifyTargetSize;
126 }
127
128 bpspatch::result bpspatch::apply() {
129 if(modifySize < 19) return result::patch_too_small;
130
131 uint32_t modifyChecksum = ~0, targetChecksum = ~0;
132 unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0;
133
134 auto read = [&]() -> uint8_t {
135 uint8_t data = modifyData[modifyOffset++];
136 modifyChecksum = crc32_adjust(modifyChecksum, data);
137 return data;
138 };
139
140 auto decode = [&]() -> uint64_t {
141 uint64_t data = 0, shift = 1;
142 while(true) {
143 uint8_t x = read();
144 data += (x & 0x7f) * shift;
145 if(x & 0x80) break;
146 shift <<= 7;
147 data += shift;
148 }
149 return data;
150 };
151
152 auto write = [&](uint8_t data) {
153 targetData[outputOffset++] = data;
154 targetChecksum = crc32_adjust(targetChecksum, data);
155 };
156
157 if(read() != 'B') return result::patch_invalid_header;
158 if(read() != 'P') return result::patch_invalid_header;
159 if(read() != 'S') return result::patch_invalid_header;
160 if(read() != '1') return result::patch_invalid_header;
161
162 modifySourceSize = decode();
163 modifyTargetSize = decode();
164 modifyMarkupSize = decode();
165 for(unsigned n = 0; n < modifyMarkupSize; n++) read();
166
167 if(modifySourceSize > sourceSize) return result::source_too_small;
168 if(modifyTargetSize > targetSize) return result::target_too_small;
169
170 while(modifyOffset < modifySize - 12) {
171 unsigned length = decode();
172 unsigned mode = length & 3;
173 length = (length >> 2) + 1;
174
175 switch(mode) {
176 case SourceRead:
177 while(length--) write(sourceData[outputOffset]);
178 break;
179 case TargetRead:
180 while(length--) write(read());
181 break;
182 case SourceCopy:
183 case TargetCopy:
184 signed offset = decode();
185 bool negative = offset & 1;
186 offset >>= 1;
187 if(negative) offset = -offset;
188
189 if(mode == SourceCopy) {
190 sourceRelativeOffset += offset;
191 while(length--) write(sourceData[sourceRelativeOffset++]);
192 } else {
193 targetRelativeOffset += offset;
194 while(length--) write(targetData[targetRelativeOffset++]);
195 }
196 break;
197 }
198 }
199
200 uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
201 for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
202 for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
203 uint32_t checksum = ~modifyChecksum;
204 for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
205
206 uint32_t sourceChecksum = crc32_calculate(sourceData, modifySourceSize);
207 targetChecksum = ~targetChecksum;
208
209 if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid;
210 if(targetChecksum != modifyTargetChecksum) return result::target_checksum_invalid;
211 if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid;
212
213 return result::success;
214 }
215
216 }
217
218 #endif
0 #ifndef NALL_COMPOSITOR_HPP
1 #define NALL_COMPOSITOR_HPP
2
3 #include <nall/detect.hpp>
4
5 namespace nall {
6
7 struct compositor {
8 inline static bool enabled();
9 inline static bool enable(bool status);
10 };
11
12 #if defined(PLATFORM_X)
13
14 bool compositor::enabled() {
15 FILE *fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r");
16 if(fp == 0) return false;
17
18 char buffer[512];
19 if(fgets(buffer, sizeof buffer, fp) == 0) return false;
20
21 if(!memcmp(buffer, "true", 4)) return true;
22 return false;
23 }
24
25 bool compositor::enable(bool status) {
26 FILE *fp;
27 if(status) {
28 fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r");
29 } else {
30 fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'", "r");
31 }
32 if(fp == 0) return false;
33 pclose(fp);
34 return true;
35 }
36
37 #elif defined(PLATFORM_WIN)
38
39 bool compositor::enabled() {
40 HMODULE module = GetModuleHandleW(L"dwmapi");
41 if(module == 0) module = LoadLibraryW(L"dwmapi");
42 if(module == 0) return false;
43
44 auto pDwmIsCompositionEnabled = (HRESULT (WINAPI*)(BOOL*))GetProcAddress(module, "DwmIsCompositionEnabled");
45 if(pDwmIsCompositionEnabled == 0) return false;
46
47 BOOL result;
48 if(pDwmIsCompositionEnabled(&result) != S_OK) return false;
49 return result;
50 }
51
52 bool compositor::enable(bool status) {
53 HMODULE module = GetModuleHandleW(L"dwmapi");
54 if(module == 0) module = LoadLibraryW(L"dwmapi");
55 if(module == 0) return false;
56
57 auto pDwmEnableComposition = (HRESULT (WINAPI*)(UINT))GetProcAddress(module, "DwmEnableComposition");
58 if(pDwmEnableComposition == 0) return false;
59
60 if(pDwmEnableComposition(status) != S_OK) return false;
61 return true;
62 }
63
64 #else
65
66 bool compositor::enabled() {
67 return false;
68 }
69
70 bool compositor::enable(bool) {
71 return false;
72 }
73
74 #endif
75
76 }
77
78 #endif
3333
3434 string get() const {
3535 switch(type) {
36 case boolean_t: return string() << *(bool*)data;
37 case signed_t: return string() << *(signed*)data;
38 case unsigned_t: return string() << *(unsigned*)data;
39 case double_t: return string() << *(double*)data;
40 case string_t: return string() << "\"" << *(string*)data << "\"";
36 case boolean_t: return { *(bool*)data };
37 case signed_t: return { *(signed*)data };
38 case unsigned_t: return { *(unsigned*)data };
39 case double_t: return { *(double*)data };
40 case string_t: return { "\"", *(string*)data, "\"" };
4141 }
4242 return "???";
4343 }
104104 if(fp.open(filename, file::mode::write)) {
105105 for(unsigned i = 0; i < list.size(); i++) {
106106 string output;
107 output << list[i].name << " = " << list[i].get();
108 if(list[i].desc != "") output << " # " << list[i].desc;
109 output << "\r\n";
107 output.append(list[i].name, " = ", list[i].get());
108 if(list[i].desc != "") output.append(" # ", list[i].desc);
109 output.append("\r\n");
110110 fp.print(output);
111111 }
112112
+0
-75
snespurify/nall/dictionary.hpp less more
0 #ifndef NALL_DICTIONARY_HPP
1 #define NALL_DICTIONARY_HPP
2
3 #include <nall/array.hpp>
4 #include <nall/string.hpp>
5 #include <nall/utility.hpp>
6
7 namespace nall {
8 class dictionary {
9 public:
10 string operator[](const char *input) {
11 for(unsigned i = 0; i < index_input.size(); i++) {
12 if(index_input[i] == input) return index_output[i];
13 }
14
15 //no match, use input; remove input identifier, if one exists
16 if(strbegin(input, "{{")) {
17 if(auto pos = strpos(input, "}}")) {
18 string temp = substr(input, pos() + 2);
19 return temp;
20 }
21 }
22
23 return input;
24 }
25
26 bool import(const char *filename) {
27 string data;
28 if(data.readfile(filename) == false) return false;
29 data.ltrim<1>("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists
30 data.replace("\r", "");
31
32 lstring line;
33 line.split("\n", data);
34 for(unsigned i = 0; i < line.size(); i++) {
35 lstring part;
36 //format: "Input" = "Output"
37 part.qsplit("=", line[i]);
38 if(part.size() != 2) continue;
39
40 //remove whitespace
41 part[0].trim();
42 part[1].trim();
43
44 //remove quotes
45 part[0].trim<1>("\"");
46 part[1].trim<1>("\"");
47
48 unsigned n = index_input.size();
49 index_input[n] = part[0];
50 index_output[n] = part[1];
51 }
52
53 return true;
54 }
55
56 void reset() {
57 index_input.reset();
58 index_output.reset();
59 }
60
61 ~dictionary() {
62 reset();
63 }
64
65 dictionary& operator=(const dictionary&) = delete;
66 dictionary(const dictionary&) = delete;
67
68 protected:
69 lstring index_input;
70 lstring index_output;
71 };
72 }
73
74 #endif
55 #include <nall/string.hpp>
66
77 #if defined(_WIN32)
8 #include <nall/utf8.hpp>
8 #include <nall/windows/utf8.hpp>
99 #else
1010 #include <dirent.h>
1111 #include <stdio.h>
4141 if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
4242 if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
4343 string name = (const char*)utf8_t(data.cFileName);
44 if(wildcard(name, pattern)) list.append(string(name, "/"));
44 if(wildcard(name, pattern)) list.append(name);
4545 }
4646 }
4747 while(FindNextFile(handle, &data) != false) {
4848 if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
4949 if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
5050 string name = (const char*)utf8_t(data.cFileName);
51 if(wildcard(name, pattern)) list.append(string(name, "/"));
51 if(wildcard(name, pattern)) list.append(name);
5252 }
5353 }
5454 }
5555 FindClose(handle);
5656 }
5757 if(list.size() > 0) sort(&list[0], list.size());
58 foreach(name, list) name.append("/"); //must append after sorting
5859 return list;
5960 }
6061
108109 if(!strcmp(ep->d_name, ".")) continue;
109110 if(!strcmp(ep->d_name, "..")) continue;
110111 if(ep->d_type & DT_DIR) {
111 if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/"));
112 if(wildcard(ep->d_name, pattern)) list.append(ep->d_name);
112113 }
113114 }
114115 closedir(dp);
115116 }
116117 if(list.size() > 0) sort(&list[0], list.size());
118 foreach(name, list) name.append("/"); //must append after sorting
117119 return list;
118
119120 }
120121
121122 inline lstring directory::files(const string &pathname, const string &pattern) {
1111 #include <dlfcn.h>
1212 #elif defined(PLATFORM_WIN)
1313 #include <windows.h>
14 #include <nall/utf8.hpp>
14 #include <nall/windows/utf8.hpp>
1515 #endif
1616
1717 namespace nall {
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 struct Buffer {
3 double *sample[2];
4 uint16_t rdoffset;
5 uint16_t wroffset;
6
7 inline double& read(bool channel, signed offset = 0) {
8 return sample[channel][(uint16_t)(rdoffset + offset)];
9 }
10
11 inline double& write(bool channel, signed offset = 0) {
12 return sample[channel][(uint16_t)(wroffset + offset)];
13 }
14
15 inline void clear() {
16 for(unsigned n = 0; n < 65536; n++) {
17 sample[0][n] = 0;
18 sample[1][n] = 0;
19 }
20 rdoffset = 0;
21 wroffset = 0;
22 }
23
24 Buffer() {
25 sample[0] = new double[65536];
26 sample[1] = new double[65536];
27 }
28
29 ~Buffer() {
30 delete[] sample[0];
31 delete[] sample[1];
32 }
33 };
34
35 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 #include <math.h>
3 #include <nall/stdint.hpp>
4
5 namespace nall {
6
7 struct DSP {
8 enum class Resampler : unsigned {
9 Point,
10 Linear,
11 Cosine,
12 Cubic,
13 Hermite,
14 Average,
15 };
16
17 inline void setPrecision(unsigned precision);
18 inline void setFrequency(double frequency); //inputFrequency
19 inline void setVolume(double volume);
20 inline void setBalance(double balance);
21
22 inline void setResampler(Resampler resampler);
23 inline void setResamplerFrequency(double frequency); //outputFrequency
24
25 inline void sample(signed lchannel, signed rchannel);
26 inline bool pending();
27 inline void read(signed &lchannel, signed &rchannel);
28
29 inline void clear();
30 inline DSP();
31 inline ~DSP();
32
33 protected:
34 struct Settings {
35 unsigned precision;
36 double frequency;
37 double volume;
38 double balance;
39 //internal
40 double intensity;
41 } settings;
42
43 struct ResamplerSettings {
44 Resampler engine;
45 double frequency;
46 //internal
47 double fraction;
48 double step;
49 } resampler;
50
51 inline void resamplerRun();
52 inline void resamplerWrite(double lchannel, double rchannel);
53
54 inline void resamplePoint();
55 inline void resampleLinear();
56 inline void resampleCosine();
57 inline void resampleCubic();
58 inline void resampleHermite();
59 inline void resampleAverage();
60
61 #include "buffer.hpp"
62 Buffer buffer;
63 Buffer output;
64
65 inline void adjustVolume();
66 inline void adjustBalance();
67 inline signed clamp(const unsigned bits, const signed x);
68 };
69
70 #include "settings.hpp"
71
72 void DSP::sample(signed lchannel, signed rchannel) {
73 buffer.write(0) = (double)lchannel / settings.intensity;
74 buffer.write(1) = (double)rchannel / settings.intensity;
75 buffer.wroffset++;
76 resamplerRun();
77 }
78
79 bool DSP::pending() {
80 return output.rdoffset != output.wroffset;
81 }
82
83 void DSP::read(signed &lchannel, signed &rchannel) {
84 adjustVolume();
85 adjustBalance();
86
87 lchannel = clamp(settings.precision, output.read(0) * settings.intensity);
88 rchannel = clamp(settings.precision, output.read(1) * settings.intensity);
89 output.rdoffset++;
90 }
91
92 void DSP::resamplerRun() {
93 switch(resampler.engine) {
94 case Resampler::Point: return resamplePoint();
95 case Resampler::Linear: return resampleLinear();
96 case Resampler::Cosine: return resampleCosine();
97 case Resampler::Cubic: return resampleCubic();
98 case Resampler::Hermite: return resampleHermite();
99 case Resampler::Average: return resampleAverage();
100 }
101 }
102
103 void DSP::resamplerWrite(double lchannel, double rchannel) {
104 output.write(0) = lchannel;
105 output.write(1) = rchannel;
106 output.wroffset++;
107 }
108
109 #include "resample/point.hpp"
110 #include "resample/linear.hpp"
111 #include "resample/cosine.hpp"
112 #include "resample/cubic.hpp"
113 #include "resample/hermite.hpp"
114 #include "resample/average.hpp"
115
116 void DSP::adjustVolume() {
117 output.read(0) *= settings.volume;
118 output.read(1) *= settings.volume;
119 }
120
121 void DSP::adjustBalance() {
122 if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance;
123 if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance;
124 }
125
126 signed DSP::clamp(const unsigned bits, const signed x) {
127 const signed b = 1U << (bits - 1);
128 const signed m = (1U << (bits - 1)) - 1;
129 return (x > m) ? m : (x < -b) ? -b : x;
130 }
131
132 void DSP::clear() {
133 resampler.fraction = 0.0;
134 buffer.clear();
135 output.clear();
136 }
137
138 DSP::DSP() {
139 setPrecision(16);
140 setFrequency(44100.0);
141 setVolume(1.0);
142 setBalance(0.0);
143 setResampler(Resampler::Hermite);
144 setResamplerFrequency(44100.0);
145 clear();
146 }
147
148 DSP::~DSP() {
149 }
150
151 }
152
153 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleAverage() {
3 //can only average if input frequency >= output frequency
4 if(resampler.step < 1.0) return resampleHermite();
5
6 resampler.fraction += 1.0;
7
8 double scalar = 1.0;
9 if(resampler.fraction > resampler.step) scalar = 1.0 - (resampler.fraction - resampler.step);
10
11 output.write(0) += buffer.read(0) * scalar;
12 output.write(1) += buffer.read(1) * scalar;
13
14 if(resampler.fraction >= resampler.step) {
15 output.write(0) /= resampler.step;
16 output.write(1) /= resampler.step;
17 output.wroffset++;
18
19 resampler.fraction -= resampler.step;
20 output.write(0) = buffer.read(0) * resampler.fraction;
21 output.write(1) = buffer.read(1) * resampler.fraction;
22 }
23
24 buffer.rdoffset++;
25 }
26
27 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleCosine() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -1);
8 double b = buffer.read(n, -0);
9
10 double mu = resampler.fraction;
11 mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
12
13 channel[n] = a * (1.0 - mu) + b * mu;
14 }
15
16 resamplerWrite(channel[0], channel[1]);
17 resampler.fraction += resampler.step;
18 }
19
20 buffer.rdoffset++;
21 resampler.fraction -= 1.0;
22 }
23
24 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleCubic() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -3);
8 double b = buffer.read(n, -2);
9 double c = buffer.read(n, -1);
10 double d = buffer.read(n, -0);
11
12 double mu = resampler.fraction;
13
14 double A = d - c - a + b;
15 double B = a - b - A;
16 double C = c - a;
17 double D = b;
18
19 channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D;
20 }
21
22 resamplerWrite(channel[0], channel[1]);
23 resampler.fraction += resampler.step;
24 }
25
26 buffer.rdoffset++;
27 resampler.fraction -= 1.0;
28 }
29
30 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleHermite() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -3);
8 double b = buffer.read(n, -2);
9 double c = buffer.read(n, -1);
10 double d = buffer.read(n, -0);
11
12 const double tension = 0.0; //-1 = low, 0 = normal, +1 = high
13 const double bias = 0.0; //-1 = left, 0 = even, +1 = right
14
15 double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3;
16
17 mu1 = resampler.fraction;
18 mu2 = mu1 * mu1;
19 mu3 = mu2 * mu1;
20
21 m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0;
22 m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0;
23 m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0;
24 m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0;
25
26 a0 = +2 * mu3 - 3 * mu2 + 1;
27 a1 = mu3 - 2 * mu2 + mu1;
28 a2 = mu3 - mu2;
29 a3 = -2 * mu3 + 3 * mu2;
30
31 channel[n] = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
32 }
33
34 resamplerWrite(channel[0], channel[1]);
35 resampler.fraction += resampler.step;
36 }
37
38 buffer.rdoffset++;
39 resampler.fraction -= 1.0;
40 }
41
42 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resampleLinear() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -1);
8 double b = buffer.read(n, -0);
9
10 double mu = resampler.fraction;
11
12 channel[n] = a * (1.0 - mu) + b * mu;
13 }
14
15 resamplerWrite(channel[0], channel[1]);
16 resampler.fraction += resampler.step;
17 }
18
19 buffer.rdoffset++;
20 resampler.fraction -= 1.0;
21 }
22
23 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::resamplePoint() {
3 while(resampler.fraction <= 1.0) {
4 double channel[2];
5
6 for(unsigned n = 0; n < 2; n++) {
7 double a = buffer.read(n, -1);
8 double b = buffer.read(n, -0);
9
10 double mu = resampler.fraction;
11
12 channel[n] = mu < 0.5 ? a : b;
13 }
14
15 resamplerWrite(channel[0], channel[1]);
16 resampler.fraction += resampler.step;
17 }
18
19 buffer.rdoffset++;
20 resampler.fraction -= 1.0;
21 }
22
23 #endif
0 #ifdef NALL_DSP_INTERNAL_HPP
1
2 void DSP::setPrecision(unsigned precision) {
3 settings.precision = precision;
4 settings.intensity = 1 << (settings.precision - 1);
5 }
6
7 void DSP::setFrequency(double frequency) {
8 settings.frequency = frequency;
9 resampler.fraction = 0;
10 resampler.step = settings.frequency / resampler.frequency;
11 }
12
13 void DSP::setVolume(double volume) {
14 settings.volume = volume;
15 }
16
17 void DSP::setBalance(double balance) {
18 settings.balance = balance;
19 }
20
21 void DSP::setResampler(Resampler engine) {
22 resampler.engine = engine;
23 }
24
25 void DSP::setResamplerFrequency(double frequency) {
26 resampler.frequency = frequency;
27 resampler.fraction = 0;
28 resampler.step = settings.frequency / resampler.frequency;
29 }
30
31 #endif
0 #ifndef NALL_DSP_HPP
1 #define NALL_DSP_HPP
2
3 #define NALL_DSP_INTERNAL_HPP
4 #include <nall/dsp/core.hpp>
5 #undef NALL_DSP_INTERNAL_HPP
6
7 #endif
00 #ifndef NALL_FILE_HPP
11 #define NALL_FILE_HPP
22
3 #include <stdio.h>
4 #include <string.h>
5
6 #if !defined(_WIN32)
7 #include <unistd.h>
8 #else
9 #include <io.h>
10 #endif
11
3 #include <nall/platform.hpp>
124 #include <nall/stdint.hpp>
135 #include <nall/string.hpp>
14 #include <nall/utf8.hpp>
156 #include <nall/utility.hpp>
7 #include <nall/windows/utf8.hpp>
168
179 namespace nall {
18 inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) {
10 inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) {
1911 #if !defined(_WIN32)
2012 return fopen(utf8_filename, mode);
2113 #else
2719 public:
2820 enum class mode : unsigned { read, write, readwrite, writeread };
2921 enum class index : unsigned { absolute, relative };
22 enum class time : unsigned { create, modify, access };
23
24 static bool read(const string &filename, uint8_t *&data, unsigned &size) {
25 file fp;
26 if(fp.open(filename, mode::read) == false) return false;
27 size = fp.size();
28 data = new uint8_t[size];
29 fp.read(data, size);
30 fp.close();
31 return true;
32 }
33
34 static bool read(const string &filename, const uint8_t *&data, unsigned &size) {
35 return file::read(filename, (uint8_t*&)data, size);
36 }
37
38 static bool write(const string &filename, const uint8_t *data, unsigned size) {
39 file fp;
40 if(fp.open(filename, mode::write) == false) return false;
41 fp.write(data, size);
42 fp.close();
43 return true;
44 }
3045
3146 uint8_t read() {
3247 if(!fp) return 0xff; //file not open
141156 return file_offset >= file_size;
142157 }
143158
144 static bool exists(const char *fn) {
145 #if !defined(_WIN32)
146 FILE *fp = fopen(fn, "rb");
147 #else
148 FILE *fp = _wfopen(utf16_t(fn), L"rb");
149 #endif
150 if(fp) {
151 fclose(fp);
152 return true;
153 }
154 return false;
155 }
156
157 static unsigned size(const char *fn) {
158 #if !defined(_WIN32)
159 FILE *fp = fopen(fn, "rb");
160 #else
161 FILE *fp = _wfopen(utf16_t(fn), L"rb");
162 #endif
163 unsigned filesize = 0;
164 if(fp) {
165 fseek(fp, 0, SEEK_END);
166 filesize = ftell(fp);
167 fclose(fp);
168 }
169 return filesize;
159 static bool exists(const string &filename) {
160 #if !defined(_WIN32)
161 struct stat64 data;
162 return stat64(filename, &data) == 0;
163 #else
164 struct __stat64 data;
165 return _wstat64(utf16_t(filename), &data) == 0;
166 #endif
167 }
168
169 static uintmax_t size(const string &filename) {
170 #if !defined(_WIN32)
171 struct stat64 data;
172 stat64(filename, &data);
173 #else
174 struct __stat64 data;
175 _wstat64(utf16_t(filename), &data);
176 #endif
177 return S_ISREG(data.st_mode) ? data.st_size : 0u;
178 }
179
180 static time_t timestamp(const string &filename, file::time mode = file::time::create) {
181 #if !defined(_WIN32)
182 struct stat64 data;
183 stat64(filename, &data);
184 #else
185 struct __stat64 data;
186 _wstat64(utf16_t(filename), &data);
187 #endif
188 switch(mode) { default:
189 case file::time::create: return data.st_ctime;
190 case file::time::modify: return data.st_mtime;
191 case file::time::access: return data.st_atime;
192 }
170193 }
171194
172195 bool open() {
173196 return fp;
174197 }
175198
176 bool open(const char *fn, mode mode_) {
199 bool open(const string &filename, mode mode_) {
177200 if(fp) return false;
178201
179202 switch(file_mode = mode_) {
180203 #if !defined(_WIN32)
181 case mode::read: fp = fopen(fn, "rb"); break;
182 case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering
183 case mode::readwrite: fp = fopen(fn, "rb+"); break;
184 case mode::writeread: fp = fopen(fn, "wb+"); break;
204 case mode::read: fp = fopen(filename, "rb" ); break;
205 case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering
206 case mode::readwrite: fp = fopen(filename, "rb+"); break;
207 case mode::writeread: fp = fopen(filename, "wb+"); break;
185208 #else
186 case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break;
187 case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break;
188 case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break;
189 case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break;
209 case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break;
210 case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break;
211 case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break;
212 case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break;
190213 #endif
191214 }
192215 if(!fp) return false;
11 #define NALL_FILEMAP_HPP
22
33 #include <nall/stdint.hpp>
4 #include <nall/utf8.hpp>
4 #include <nall/windows/utf8.hpp>
55
66 #include <stdio.h>
77 #include <stdlib.h>
4646 }
4747
4848 bool p_open(const char *filename, mode mode_) {
49 if(file::exists(filename) && file::size(filename) == 0) {
50 p_handle = 0;
51 p_size = 0;
52 return true;
53 }
54
4955 int desired_access, creation_disposition, flprotect, map_access;
5056
5157 switch(mode_) {
132138 }
133139
134140 bool p_open(const char *filename, mode mode_) {
141 if(file::exists(filename) && file::size(filename) == 0) {
142 p_handle = 0;
143 p_size = 0;
144 return true;
145 }
146
135147 int open_flags, mmap_flags;
136148
137149 switch(mode_) {
55 class GameBoyCartridge {
66 public:
77 string xml;
8 inline GameBoyCartridge(const uint8_t *data, unsigned size);
8 inline GameBoyCartridge(uint8_t *data, unsigned size);
99
1010 //private:
1111 struct Information {
2020 } info;
2121 };
2222
23 GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
23 GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
2424 xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
2525 if(romsize < 0x4000) return;
2626
3232
3333 info.romsize = 0;
3434 info.ramsize = 0;
35
36 unsigned base = romsize - 0x8000;
37 if(romdata[base + 0x0104] == 0xce && romdata[base + 0x0105] == 0xed
38 && romdata[base + 0x0106] == 0x66 && romdata[base + 0x0107] == 0x66
39 && romdata[base + 0x0108] == 0xcc && romdata[base + 0x0109] == 0x0d
40 && romdata[base + 0x0147] >= 0x0b && romdata[base + 0x0147] <= 0x0d
41 ) {
42 //MMM01 stores header at bottom of image
43 //flip this around for consistency with all other mappers
44 uint8_t header[0x8000];
45 memcpy(header, romdata + base, 0x8000);
46 memmove(romdata + 0x8000, romdata, romsize - 0x8000);
47 memcpy(romdata, header, 0x8000);
48 }
3549
3650 switch(romdata[0x0147]) {
3751 case 0x00: info.mapper = "none"; break;
8599
86100 if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
87101
88 xml << "<cartridge mapper='" << info.mapper << "'";
89 if(info.rtc) xml << " rtc='true'";
90 if(info.rumble) xml << " rumble='true'";
91 xml << ">\n";
102 xml.append("<cartridge mapper='", info.mapper, "'");
103 if(info.rtc) xml.append(" rtc='true'");
104 if(info.rumble) xml.append(" rumble='true'");
105 xml.append(">\n");
92106
93 xml << " <rom size='" << hex(romsize) << "'/>\n"; //TODO: trust/check info.romsize?
107 xml.append(" <rom size='", hex(romsize), "'/>\n"); //TODO: trust/check info.romsize?
94108
95109 if(info.ramsize > 0)
96 xml << " <ram size='" << hex(info.ramsize) << "' battery='" << info.battery << "'/>\n";
110 xml.append(" <ram size='", hex(info.ramsize), "' battery='", info.battery, "'/>\n");
97111
98 xml << "</cartridge>\n";
112 xml.append("</cartridge>\n");
99113 xml.transform("'", "\"");
100114 }
101115
0 #ifndef NALL_GZIP_HPP
1 #define NALL_GZIP_HPP
2
3 #include <nall/file.hpp>
4 #include <nall/inflate.hpp>
5
6 namespace nall {
7
8 struct gzip {
9 string filename;
10 uint8_t *data;
11 unsigned size;
12
13 bool decompress(const string &filename);
14 bool decompress(const uint8_t *data, unsigned size);
15
16 gzip();
17 ~gzip();
18 };
19
20 bool gzip::decompress(const string &filename) {
21 uint8_t *data;
22 unsigned size;
23 if(file::read(filename, data, size) == false) return false;
24 bool result = decompress(data, size);
25 delete[] data;
26 return result;
27 }
28
29 bool gzip::decompress(const uint8_t *data, unsigned size) {
30 if(size < 18) return false;
31 if(data[0] != 0x1f) return false;
32 if(data[1] != 0x8b) return false;
33 unsigned cm = data[2];
34 unsigned flg = data[3];
35 unsigned mtime = data[4];
36 mtime |= data[5] << 8;
37 mtime |= data[6] << 16;
38 mtime |= data[7] << 24;
39 unsigned xfl = data[8];
40 unsigned os = data[9];
41 unsigned p = 10;
42 unsigned isize = data[size - 4];
43 isize |= data[size - 3] << 8;
44 isize |= data[size - 2] << 16;
45 isize |= data[size - 1] << 24;
46 filename = "";
47
48 if(flg & 0x04) { //FEXTRA
49 unsigned xlen = data[p + 0];
50 xlen |= data[p + 1] << 8;
51 p += 2 + xlen;
52 }
53
54 if(flg & 0x08) { //FNAME
55 char buffer[PATH_MAX];
56 for(unsigned n = 0; n < PATH_MAX; n++, p++) {
57 buffer[n] = data[p];
58 if(data[p] == 0) break;
59 }
60 if(data[p++]) return false;
61 filename = buffer;
62 }
63
64 if(flg & 0x10) { //FCOMMENT
65 while(data[p++]);
66 }
67
68 if(flg & 0x02) { //FHCRC
69 p += 2;
70 }
71
72 this->size = isize;
73 this->data = new uint8_t[this->size];
74 return inflate(this->data, this->size, data + p, size - p - 8);
75 }
76
77 gzip::gzip() : data(0) {
78 }
79
80 gzip::~gzip() {
81 if(data) delete[] data;
82 }
83
84 }
85
86 #endif
0 #ifndef NALL_HTTP_HPP
1 #define NALL_HTTP_HPP
2
3 #if !defined(_WIN32)
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <netdb.h>
8 #else
9 #include <windows.h>
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
12 #endif
13
14 #include <nall/platform.hpp>
15 #include <nall/string.hpp>
16
17 namespace nall {
18
19 struct http {
20 string hostname;
21 addrinfo *serverinfo;
22 int serversocket;
23 string header;
24
25 inline void download(const string &path, uint8_t *&data, unsigned &size) {
26 data = 0;
27 size = 0;
28
29 send({
30 "GET ", path, " HTTP/1.1\r\n"
31 "Host: ", hostname, "\r\n"
32 "Connection: close\r\n"
33 "\r\n"
34 });
35
36 header = downloadHeader();
37 downloadContent(data, size);
38 }
39
40 inline bool connect(string host, unsigned port) {
41 hostname = host;
42
43 addrinfo hints;
44 memset(&hints, 0, sizeof(addrinfo));
45 hints.ai_family = AF_UNSPEC;
46 hints.ai_socktype = SOCK_STREAM;
47 hints.ai_flags = AI_PASSIVE;
48
49 int status = getaddrinfo(hostname, string(port), &hints, &serverinfo);
50 if(status != 0) return false;
51
52 serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol);
53 if(serversocket == -1) return false;
54
55 int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen);
56 if(result == -1) return false;
57
58 return true;
59 }
60
61 inline bool send(const string &data) {
62 return send((const uint8_t*)(const char*)data, data.length());
63 }
64
65 inline bool send(const uint8_t *data, unsigned size) {
66 while(size) {
67 int length = ::send(serversocket, (const char*)data, size, 0);
68 if(length == -1) return false;
69 data += length;
70 size -= length;
71 }
72 return true;
73 }
74
75 inline string downloadHeader() {
76 string output;
77 do {
78 char buffer[2];
79 int length = recv(serversocket, buffer, 1, 0);
80 if(length <= 0) return output;
81 buffer[1] = 0;
82 output.append(buffer);
83 } while(output.endswith("\r\n\r\n") == false);
84 return output;
85 }
86
87 inline string downloadChunkLength() {
88 string output;
89 do {
90 char buffer[2];
91 int length = recv(serversocket, buffer, 1, 0);
92 if(length <= 0) return output;
93 buffer[1] = 0;
94 output.append(buffer);
95 } while(output.endswith("\r\n") == false);
96 return output;
97 }
98
99 inline void downloadContent(uint8_t *&data, unsigned &size) {
100 unsigned capacity = 0;
101
102 if(header.iposition("\r\nTransfer-Encoding: chunked\r\n")) {
103 while(true) {
104 unsigned length = hex(downloadChunkLength());
105 if(length == 0) break;
106 capacity += length;
107 data = (uint8_t*)realloc(data, capacity);
108
109 char buffer[length];
110 while(length) {
111 int packetlength = recv(serversocket, buffer, length, 0);
112 if(packetlength <= 0) break;
113 memcpy(data + size, buffer, packetlength);
114 size += packetlength;
115 length -= packetlength;
116 }
117 }
118 } else if(auto position = header.iposition("\r\nContent-Length: ")) {
119 unsigned length = decimal((const char*)header + position() + 16);
120 while(length) {
121 char buffer[256];
122 int packetlength = recv(serversocket, buffer, min(256, length), 0);
123 if(packetlength <= 0) break;
124 capacity += packetlength;
125 data = (uint8_t*)realloc(data, capacity);
126 memcpy(data + size, buffer, packetlength);
127 size += packetlength;
128 length -= packetlength;
129 }
130 } else {
131 while(true) {
132 char buffer[256];
133 int packetlength = recv(serversocket, buffer, 256, 0);
134 if(packetlength <= 0) break;
135 capacity += packetlength;
136 data = (uint8_t*)realloc(data, capacity);
137 memcpy(data + size, buffer, packetlength);
138 size += packetlength;
139 }
140 }
141
142 data = (uint8_t*)realloc(data, capacity + 1);
143 data[capacity] = 0;
144 }
145
146 inline void disconnect() {
147 close(serversocket);
148 freeaddrinfo(serverinfo);
149 serverinfo = 0;
150 serversocket = -1;
151 }
152
153 #ifdef _WIN32
154 inline int close(int sock) {
155 return closesocket(sock);
156 }
157
158 inline http() {
159 int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
160 if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) {
161 WSADATA wsaData;
162 if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
163 WSACleanup();
164 return;
165 }
166 } else {
167 close(sock);
168 }
169 }
170 #endif
171 };
172
173 }
174
175 #endif
0 #ifndef NALL_INFLATE_HPP
1 #define NALL_INFLATE_HPP
2
3 #include <setjmp.h>
4
5 namespace nall {
6
7 namespace puff {
8 inline int puff(
9 unsigned char *dest, unsigned long *destlen,
10 unsigned char *source, unsigned long *sourcelen
11 );
12 }
13
14 inline bool inflate(
15 uint8_t *target, unsigned targetLength,
16 const uint8_t *source, unsigned sourceLength
17 ) {
18 unsigned long tl = targetLength, sl = sourceLength;
19 int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl);
20 return result == 0;
21 }
22
23 namespace puff {
24
25 //zlib/contrib/puff.c
26 //version 2.1*
27 //author: Mark Adler
28 //license: zlib
29 //ported by: byuu
30
31 //* I have corrected a bug in fixed(), where it was accessing uninitialized
32 // memory: calling construct() with lencode prior to initializing lencode.count
33
34 enum {
35 MAXBITS = 15,
36 MAXLCODES = 286,
37 MAXDCODES = 30,
38 FIXLCODES = 288,
39 MAXCODES = MAXLCODES + MAXDCODES,
40 };
41
42 struct state {
43 unsigned char *out;
44 unsigned long outlen;
45 unsigned long outcnt;
46
47 unsigned char *in;
48 unsigned long inlen;
49 unsigned long incnt;
50 int bitbuf;
51 int bitcnt;
52
53 jmp_buf env;
54 };
55
56 struct huffman {
57 short *count;
58 short *symbol;
59 };
60
61 inline int bits(state *s, int need) {
62 long val;
63
64 val = s->bitbuf;
65 while(s->bitcnt < need) {
66 if(s->incnt == s->inlen) longjmp(s->env, 1);
67 val |= (long)(s->in[s->incnt++]) << s->bitcnt;
68 s->bitcnt += 8;
69 }
70
71 s->bitbuf = (int)(val >> need);
72 s->bitcnt -= need;
73
74 return (int)(val & ((1L << need) - 1));
75 }
76
77 inline int stored(state *s) {
78 unsigned len;
79
80 s->bitbuf = 0;
81 s->bitcnt = 0;
82
83 if(s->incnt + 4 > s->inlen) return 2;
84 len = s->in[s->incnt++];
85 len |= s->in[s->incnt++] << 8;
86 if(s->in[s->incnt++] != (~len & 0xff) ||
87 s->in[s->incnt++] != ((~len >> 8) & 0xff)
88 ) return 2;
89
90 if(s->incnt + len > s->inlen) return 2;
91 if(s->out != 0) {
92 if(s->outcnt + len > s->outlen) return 1;
93 while(len--) s->out[s->outcnt++] = s->in[s->incnt++];
94 } else {
95 s->outcnt += len;
96 s->incnt += len;
97 }
98
99 return 0;
100 }
101
102 inline int decode(state *s, huffman *h) {
103 int len, code, first, count, index, bitbuf, left;
104 short *next;
105
106 bitbuf = s->bitbuf;
107 left = s->bitcnt;
108 code = first = index = 0;
109 len = 1;
110 next = h->count + 1;
111 while(true) {
112 while(left--) {
113 code |= bitbuf & 1;
114 bitbuf >>= 1;
115 count = *next++;
116 if(code - count < first) {
117 s->bitbuf = bitbuf;
118 s->bitcnt = (s->bitcnt - len) & 7;
119 return h->symbol[index + (code - first)];
120 }
121 index += count;
122 first += count;
123 first <<= 1;
124 code <<= 1;
125 len++;
126 }
127 left = (MAXBITS + 1) - len;
128 if(left == 0) break;
129 if(s->incnt == s->inlen) longjmp(s->env, 1);
130 bitbuf = s->in[s->incnt++];
131 if(left > 8) left = 8;
132 }
133
134 return -10;
135 }
136
137 inline int construct(huffman *h, short *length, int n) {
138 int symbol, len, left;
139 short offs[MAXBITS + 1];
140
141 for(len = 0; len <= MAXBITS; len++) h->count[len] = 0;
142 for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++;
143 if(h->count[0] == n) return 0;
144
145 left = 1;
146 for(len = 1; len <= MAXBITS; len++) {
147 left <<= 1;
148 left -= h->count[len];
149 if(left < 0) return left;
150 }
151
152 offs[1] = 0;
153 for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len];
154
155 for(symbol = 0; symbol < n; symbol++) {
156 if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol;
157 }
158
159 return left;
160 }
161
162 inline int codes(state *s, huffman *lencode, huffman *distcode) {
163 int symbol, len;
164 unsigned dist;
165 static const short lens[29] = {
166 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
167 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
168 };
169 static const short lext[29] = {
170 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
171 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
172 };
173 static const short dists[30] = {
174 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
175 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
176 8193, 12289, 16385, 24577
177 };
178 static const short dext[30] = {
179 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
180 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
181 12, 12, 13, 13
182 };
183
184 do {
185 symbol = decode(s, lencode);
186 if(symbol < 0) return symbol;
187 if(symbol < 256) {
188 if(s->out != 0) {
189 if(s->outcnt == s->outlen) return 1;
190 s->out[s->outcnt] = symbol;
191 }
192 s->outcnt++;
193 } else if(symbol > 256) {
194 symbol -= 257;
195 if(symbol >= 29) return -10;
196 len = lens[symbol] + bits(s, lext[symbol]);
197
198 symbol = decode(s, distcode);
199 if(symbol < 0) return symbol;
200 dist = dists[symbol] + bits(s, dext[symbol]);
201 #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
202 if(dist > s->outcnt) return -11;
203 #endif
204
205 if(s->out != 0) {
206 if(s->outcnt + len > s->outlen) return 1;
207 while(len--) {
208 s->out[s->outcnt] =
209 #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR
210 dist > s->outcnt ? 0 :
211 #endif
212 s->out[s->outcnt - dist];
213 s->outcnt++;
214 }
215 } else {
216 s->outcnt += len;
217 }
218 }
219 } while(symbol != 256);
220
221 return 0;
222 }
223
224 inline int fixed(state *s) {
225 static int virgin = 1;
226 static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
227 static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
228 static huffman lencode, distcode;
229
230 if(virgin) {
231 int symbol = 0;
232 short lengths[FIXLCODES];
233
234 lencode.count = lencnt;
235 lencode.symbol = lensym;
236 distcode.count = distcnt;
237 distcode.symbol = distsym;
238
239 for(; symbol < 144; symbol++) lengths[symbol] = 8;
240 for(; symbol < 256; symbol++) lengths[symbol] = 9;
241 for(; symbol < 280; symbol++) lengths[symbol] = 7;
242 for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8;
243 construct(&lencode, lengths, FIXLCODES);
244
245 for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5;
246 construct(&distcode, lengths, MAXDCODES);
247
248 virgin = 0;
249 }
250
251 return codes(s, &lencode, &distcode);
252 }
253
254 inline int dynamic(state *s) {
255 int nlen, ndist, ncode, index, err;
256 short lengths[MAXCODES];
257 short lencnt[MAXBITS + 1], lensym[MAXLCODES];
258 short distcnt[MAXBITS + 1], distsym[MAXDCODES];
259 huffman lencode, distcode;
260 static const short order[19] = {
261 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
262 };
263
264 lencode.count = lencnt;
265 lencode.symbol = lensym;
266 distcode.count = distcnt;
267 distcode.symbol = distsym;
268
269 nlen = bits(s, 5) + 257;
270 ndist = bits(s, 5) + 1;
271 ncode = bits(s, 4) + 4;
272 if(nlen > MAXLCODES || ndist > MAXDCODES) return -3;
273
274 for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3);
275 for(; index < 19; index++) lengths[order[index]] = 0;
276
277 err = construct(&lencode, lengths, 19);
278 if(err != 0) return -4;
279
280 index = 0;
281 while(index < nlen + ndist) {
282 int symbol, len;
283
284 symbol = decode(s, &lencode);
285 if(symbol < 16) {
286 lengths[index++] = symbol;
287 } else {
288 len = 0;
289 if(symbol == 16) {
290 if(index == 0) return -5;
291 len = lengths[index - 1];
292 symbol = 3 + bits(s, 2);
293 } else if(symbol == 17) {
294 symbol = 3 + bits(s, 3);
295 } else {
296 symbol = 11 + bits(s, 7);
297 }
298 if(index + symbol > nlen + ndist) return -6;
299 while(symbol--) lengths[index++] = len;
300 }
301 }
302
303 if(lengths[256] == 0) return -9;
304
305 err = construct(&lencode, lengths, nlen);
306 if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7;
307
308 err = construct(&distcode, lengths + nlen, ndist);
309 if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8;
310
311 return codes(s, &lencode, &distcode);
312 }
313
314 inline int puff(
315 unsigned char *dest, unsigned long *destlen,
316 unsigned char *source, unsigned long *sourcelen
317 ) {
318 state s;
319 int last, type, err;
320
321 s.out = dest;
322 s.outlen = *destlen;
323 s.outcnt = 0;
324
325 s.in = source;
326 s.inlen = *sourcelen;
327 s.incnt = 0;
328 s.bitbuf = 0;
329 s.bitcnt = 0;
330
331 if(setjmp(s.env) != 0) {
332 err = 2;
333 } else {
334 do {
335 last = bits(&s, 1);
336 type = bits(&s, 2);
337 err = type == 0 ? stored(&s)
338 : type == 1 ? fixed(&s)
339 : type == 2 ? dynamic(&s)
340 : -1;
341 if(err != 0) break;
342 } while(!last);
343 }
344
345 if(err <= 0) {
346 *destlen = s.outcnt;
347 *sourcelen = s.incnt;
348 }
349
350 return err;
351 }
352
353 }
354
355 }
356
357 #endif
109109 break;
110110 }
111111 }
112 return string() << "KB" << ID << "::" << KeyboardScancodeName[index];
112 return { "KB", ID, "::", KeyboardScancodeName[index] };
113113 }
114114
115115 uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
206206 break;
207207 }
208208 }
209 return string() << "MS" << ID << "::" << MouseScancodeName[index];
209 return { "MS", ID, "::", MouseScancodeName[index] };
210210 }
211211
212212 uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
329329 index = code - (Base + Size * i);
330330 }
331331 }
332 return string() << "JP" << ID << "::" << JoypadScancodeName[index];
332 return { "JP", ID, "::", JoypadScancodeName[index] };
333333 }
334334
335335 uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
0 #ifndef NALL_IPS_HPP
1 #define NALL_IPS_HPP
2
3 #include <nall/file.hpp>
4 #include <nall/stdint.hpp>
5 #include <nall/string.hpp>
6
7 namespace nall {
8
9 struct ips {
10 inline bool apply();
11 inline void source(const uint8_t *data, unsigned size);
12 inline void modify(const uint8_t *data, unsigned size);
13 inline bool source(const string &filename);
14 inline bool modify(const string &filename);
15 inline ips();
16 inline ~ips();
17
18 uint8_t *data;
19 unsigned size;
20 const uint8_t *sourceData;
21 unsigned sourceSize;
22 const uint8_t *modifyData;
23 unsigned modifySize;
24 };
25
26 bool ips::apply() {
27 if(modifySize < 8) return false;
28 if(modifyData[0] != 'P') return false;
29 if(modifyData[1] != 'A') return false;
30 if(modifyData[2] != 'T') return false;
31 if(modifyData[3] != 'C') return false;
32 if(modifyData[4] != 'H') return false;
33
34 if(data) delete[] data;
35 data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding
36 size = sourceSize;
37 memcpy(data, sourceData, sourceSize);
38 unsigned offset = 5;
39
40 while(true) {
41 unsigned address, length;
42
43 if(offset > modifySize - 3) break;
44 address = modifyData[offset++] << 16;
45 address |= modifyData[offset++] << 8;
46 address |= modifyData[offset++] << 0;
47
48 if(address == 0x454f46) { //EOF
49 if(offset == modifySize) return true;
50 if(offset == modifySize - 3) {
51 size = modifyData[offset++] << 16;
52 size |= modifyData[offset++] << 8;
53 size |= modifyData[offset++] << 0;
54 return true;
55 }
56 }
57
58 if(offset > modifySize - 2) break;
59 length = modifyData[offset++] << 8;
60 length |= modifyData[offset++] << 0;
61
62 if(length) { //Copy
63 if(offset > modifySize - length) break;
64 while(length--) data[address++] = modifyData[offset++];
65 } else { //RLE
66 if(offset > modifySize - 3) break;
67 length = modifyData[offset++] << 8;
68 length |= modifyData[offset++] << 0;
69 if(length == 0) break; //illegal
70 while(length--) data[address++] = modifyData[offset];
71 offset++;
72 }
73
74 size = max(size, address);
75 }
76
77 delete[] data;
78 data = 0;
79 return false;
80 }
81
82 void ips::source(const uint8_t *data, unsigned size) {
83 sourceData = data, sourceSize = size;
84 }
85
86 void ips::modify(const uint8_t *data, unsigned size) {
87 modifyData = data, modifySize = size;
88 }
89
90 bool ips::source(const string &filename) {
91 return file::read(filename, sourceData, sourceSize);
92 }
93
94 bool ips::modify(const string &filename) {
95 return file::read(filename, modifyData, modifySize);
96 }
97
98 ips::ips() : data(0), sourceData(0), modifyData(0) {
99 }
100
101 ips::~ips() {
102 if(data) delete[] data;
103 if(sourceData) delete[] sourceData;
104 if(modifyData) delete[] modifyData;
105 }
106
107 }
108
109 #endif
00 #ifndef NALL_LZSS_HPP
11 #define NALL_LZSS_HPP
22
3 #include <nall/array.hpp>
4 #include <nall/new.hpp>
3 #include <nall/file.hpp>
4 #include <nall/filemap.hpp>
55 #include <nall/stdint.hpp>
6 #include <nall/string.hpp>
67
78 namespace nall {
8 class lzss {
9 public:
10 static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) {
11 output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9];
129
13 unsigned i = 0, o = 0;
14 while(i < inlength) {
15 unsigned flagoffset = o++;
16 uint8_t flag = 0x00;
10 //19:5 pulldown
11 //8:1 marker: d7-d0
12 //length: { 4 - 35 }, offset: { 1 - 0x80000 }
13 //4-byte file size header
14 //little-endian encoding
15 struct lzss {
16 inline void source(const uint8_t *data, unsigned size);
17 inline bool source(const string &filename);
18 inline unsigned size() const;
19 inline bool compress(const string &filename);
20 inline bool decompress(uint8_t *targetData, unsigned targetSize);
21 inline bool decompress(const string &filename);
1722
18 for(unsigned b = 0; b < 8 && i < inlength; b++) {
19 unsigned longest = 0, pointer;
20 for(unsigned index = 1; index < 4096; index++) {
21 unsigned count = 0;
22 while(true) {
23 if(count >= 15 + 3) break; //verify pattern match is not longer than max length
24 if(i + count >= inlength) break; //verify pattern match does not read past end of input
25 if(i + count < index) break; //verify read is not before start of input
26 if(input[i + count] != input[i + count - index]) break; //verify pattern still matches
27 count++;
28 }
23 protected:
24 struct Node {
25 unsigned offset;
26 Node *next;
27 inline Node() : offset(0), next(0) {}
28 inline ~Node() { if(next) delete next; }
29 } *tree[65536];
2930
30 if(count > longest) {
31 longest = count;
32 pointer = index;
33 }
34 }
31 filemap sourceFile;
32 const uint8_t *sourceData;
33 unsigned sourceSize;
3534
36 if(longest < 3) output[o++] = input[i++];
37 else {
38 flag |= 1 << b;
39 uint16_t x = ((longest - 3) << 12) + pointer;
40 output[o++] = x;
41 output[o++] = x >> 8;
42 i += longest;
43 }
35 public:
36 inline lzss() : sourceData(0), sourceSize(0) {}
37 };
38
39 void lzss::source(const uint8_t *data, unsigned size) {
40 sourceData = data;
41 sourceSize = size;
42 }
43
44 bool lzss::source(const string &filename) {
45 if(sourceFile.open(filename, filemap::mode::read) == false) return false;
46 sourceData = sourceFile.data();
47 sourceSize = sourceFile.size();
48 return true;
49 }
50
51 unsigned lzss::size() const {
52 unsigned size = 0;
53 if(sourceSize < 4) return size;
54 for(unsigned n = 0; n < 32; n += 8) size |= sourceData[n >> 3] << n;
55 return size;
56 }
57
58 bool lzss::compress(const string &filename) {
59 file targetFile;
60 if(targetFile.open(filename, file::mode::write) == false) return false;
61
62 for(unsigned n = 0; n < 32; n += 8) targetFile.write(sourceSize >> n);
63 for(unsigned n = 0; n < 65536; n++) tree[n] = 0;
64
65 uint8_t buffer[25];
66 unsigned sourceOffset = 0;
67
68 while(sourceOffset < sourceSize) {
69 uint8_t mask = 0x00;
70 unsigned bufferOffset = 1;
71
72 for(unsigned iteration = 0; iteration < 8; iteration++) {
73 if(sourceOffset >= sourceSize) break;
74
75 uint16_t symbol = sourceData[sourceOffset + 0];
76 if(sourceOffset < sourceSize - 1) symbol |= sourceData[sourceOffset + 1] << 8;
77 Node *node = tree[symbol];
78 unsigned maxLength = 0, maxOffset = 0;
79
80 while(node) {
81 if(node->offset < sourceOffset - 0x80000) {
82 //out-of-range: all subsequent nodes will also be, so free up their memory
83 if(node->next) { delete node->next; node->next = 0; }
84 break;
4485 }
4586
46 output[flagoffset] = flag;
87 unsigned length = 0, x = sourceOffset, y = node->offset;
88 while(length < 35 && x < sourceSize && sourceData[x++] == sourceData[y++]) length++;
89 if(length > maxLength) maxLength = length, maxOffset = node->offset;
90 if(length == 35) break;
91
92 node = node->next;
4793 }
4894
49 outlength = o;
50 return true;
95 //attach current symbol to top of tree for subsequent searches
96 node = new Node;
97 node->offset = sourceOffset;
98 node->next = tree[symbol];
99 tree[symbol] = node;
100
101 if(maxLength < 4) {
102 buffer[bufferOffset++] = sourceData[sourceOffset++];
103 } else {
104 unsigned output = ((maxLength - 4) << 19) | (sourceOffset - 1 - maxOffset);
105 for(unsigned n = 0; n < 24; n += 8) buffer[bufferOffset++] = output >> n;
106 mask |= 0x80 >> iteration;
107 sourceOffset += maxLength;
108 }
51109 }
52110
53 static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) {
54 output = new(zeromemory) uint8_t[length];
111 buffer[0] = mask;
112 targetFile.write(buffer, bufferOffset);
113 }
55114
56 unsigned i = 0, o = 0;
57 while(o < length) {
58 uint8_t flag = input[i++];
115 sourceFile.close();
116 targetFile.close();
117 return true;
118 }
59119
60 for(unsigned b = 0; b < 8 && o < length; b++) {
61 if(!(flag & (1 << b))) output[o++] = input[i++];
62 else {
63 uint16_t offset = input[i++];
64 offset += input[i++] << 8;
65 uint16_t lookuplength = (offset >> 12) + 3;
66 offset &= 4095;
67 for(unsigned index = 0; index < lookuplength && o + index < length; index++) {
68 output[o + index] = output[o + index - offset];
69 }
70 o += lookuplength;
71 }
72 }
120 bool lzss::decompress(uint8_t *targetData, unsigned targetSize) {
121 if(targetSize < size()) return false;
122
123 unsigned sourceOffset = 4, targetOffset = 0;
124 while(sourceOffset < sourceSize) {
125 uint8_t mask = sourceData[sourceOffset++];
126
127 for(unsigned iteration = 0; iteration < 8; iteration++) {
128 if(sourceOffset >= sourceSize) break;
129
130 if((mask & (0x80 >> iteration)) == 0) {
131 targetData[targetOffset++] = sourceData[sourceOffset++];
132 } else {
133 unsigned code = 0;
134 for(unsigned n = 0; n < 24; n += 8) code |= sourceData[sourceOffset++] << n;
135 unsigned length = (code >> 19) + 4;
136 unsigned offset = targetOffset - 1 - (code & 0x7ffff);
137 while(length--) targetData[targetOffset++] = targetData[offset++];
73138 }
139 }
140 }
141 }
74142
75 return true;
76 }
77 };
143 bool lzss::decompress(const string &filename) {
144 if(sourceSize < 4) return false;
145 unsigned targetSize = size();
146
147 file fp;
148 if(fp.open(filename, file::mode::write) == false) return false;
149 fp.truncate(targetSize);
150 fp.close();
151
152 filemap targetFile;
153 if(targetFile.open(filename, filemap::mode::readwrite) == false) return false;
154 uint8_t *targetData = targetFile.data();
155
156 bool result = decompress(targetData, targetSize);
157 sourceFile.close();
158 targetFile.close();
159 return result;
160 }
161
78162 }
79163
80164 #endif
00 #ifndef NALL_PLATFORM_HPP
11 #define NALL_PLATFORM_HPP
22
3 #include <nall/utf8.hpp>
3 #if defined(_WIN32)
4 //minimum version needed for _wstat64, etc
5 #undef __MSVCRT_VERSION__
6 #define __MSVCRT_VERSION__ 0x0601
7 #include <nall/windows/utf8.hpp>
8 #endif
49
510 //=========================
611 //standard platform headers
1722 #include <string.h>
1823 #include <time.h>
1924
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
2028 #if defined(_WIN32)
2129 #include <io.h>
2230 #include <direct.h>
2331 #include <shlobj.h>
32 #include <wchar.h>
2433 #undef interface
2534 #define dllexport __declspec(dllexport)
2635 #else
2736 #include <unistd.h>
2837 #include <pwd.h>
29 #include <sys/stat.h>
3038 #define dllexport
3139 #endif
3240
5260 #if defined(_WIN32)
5361 #define getcwd _getcwd
5462 #define ftruncate _chsize
63 #define mkdir(n, m) _wmkdir(nall::utf16_t(n))
5564 #define putenv _putenv
56 #define mkdir(n, m) _wmkdir(nall::utf16_t(n))
5765 #define rmdir _rmdir
66 #define usleep(n) Sleep(n / 1000)
5867 #define vsnprintf _vsnprintf
59 #define usleep(n) Sleep(n / 1000)
6068 #endif
6169
6270 //================
8694 wchar_t fn[_MAX_PATH] = L"";
8795 _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
8896 strcpy(resolvedname, nall::utf8_t(fn));
97 for(unsigned n = 0; resolvedname[n]; n++) if(resolvedname[n] == '\\') resolvedname[n] = '/';
8998 return resolvedname;
9099 }
91100
93102 wchar_t fp[_MAX_PATH] = L"";
94103 SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
95104 strcpy(path, nall::utf8_t(fp));
105 for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/';
96106 return path;
97107 }
98108
100110 wchar_t fp[_MAX_PATH] = L"";
101111 _wgetcwd(fp, _MAX_PATH);
102112 strcpy(path, nall::utf8_t(fp));
113 for(unsigned n = 0; path[n]; n++) if(path[n] == '\\') path[n] = '/';
103114 return path;
104115 }
105116 #else
0 #ifndef NALL_PNG_HPP
1 #define NALL_PNG_HPP
2
3 //PNG image decoder
4 //author: byuu
5
6 #include <nall/inflate.hpp>
7 #include <nall/string.hpp>
8
9 namespace nall {
10
11 struct png {
12 uint32_t *data;
13 unsigned size;
14
15 struct Info {
16 unsigned width;
17 unsigned height;
18 unsigned bitDepth;
19 unsigned colorType;
20 unsigned compressionMethod;
21 unsigned filterType;
22 unsigned interlaceMethod;
23
24 unsigned bytesPerPixel;
25 unsigned pitch;
26
27 uint8_t palette[256][3];
28 } info;
29
30 uint8_t *rawData;
31 unsigned rawSize;
32
33 inline bool decode(const string &filename);
34 inline bool decode(const uint8_t *sourceData, unsigned sourceSize);
35 inline void transform();
36 inline void alphaTransform(uint32_t rgb = 0xffffff);
37 inline png();
38 inline ~png();
39
40 protected:
41 enum class FourCC : unsigned {
42 IHDR = 0x49484452,
43 PLTE = 0x504c5445,
44 IDAT = 0x49444154,
45 IEND = 0x49454e44,
46 };
47
48 static const unsigned interlace[7][4];
49 unsigned bitpos;
50
51 inline unsigned inflateSize();
52 inline bool deinterlace(const uint8_t *&inputData, unsigned pass);
53 inline bool filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height);
54 inline unsigned read(const uint8_t *data, unsigned length);
55 inline unsigned decode(const uint8_t *&data);
56 inline unsigned readbits(const uint8_t *&data);
57 inline unsigned scale(unsigned n);
58 };
59
60 bool png::decode(const string &filename) {
61 uint8_t *data;
62 unsigned size;
63 if(file::read(filename, data, size) == false) return false;
64 bool result = decode(data, size);
65 delete[] data;
66 return result;
67 }
68
69 bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
70 if(sourceSize < 8) return false;
71 if(read(sourceData + 0, 4) != 0x89504e47) return false;
72 if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false;
73
74 uint8_t *compressedData = 0;
75 unsigned compressedSize = 0;
76
77 unsigned offset = 8;
78 while(offset < sourceSize) {
79 unsigned length = read(sourceData + offset + 0, 4);
80 unsigned fourCC = read(sourceData + offset + 4, 4);
81 unsigned checksum = read(sourceData + offset + 8 + length, 4);
82
83 if(fourCC == (unsigned)FourCC::IHDR) {
84 info.width = read(sourceData + offset + 8, 4);
85 info.height = read(sourceData + offset + 12, 4);
86 info.bitDepth = read(sourceData + offset + 16, 1);
87 info.colorType = read(sourceData + offset + 17, 1);
88 info.compressionMethod = read(sourceData + offset + 18, 1);
89 info.filterType = read(sourceData + offset + 19, 1);
90 info.interlaceMethod = read(sourceData + offset + 20, 1);
91
92 if(info.bitDepth == 0 || info.bitDepth > 16) return false;
93 if(info.bitDepth & (info.bitDepth - 1)) return false; //not a power of two
94 if(info.compressionMethod != 0) return false;
95 if(info.filterType != 0) return false;
96 if(info.interlaceMethod != 0 && info.interlaceMethod != 1) return false;
97
98 switch(info.colorType) {
99 case 0: info.bytesPerPixel = info.bitDepth * 1; break; //L
100 case 2: info.bytesPerPixel = info.bitDepth * 3; break; //R,G,B
101 case 3: info.bytesPerPixel = info.bitDepth * 1; break; //P
102 case 4: info.bytesPerPixel = info.bitDepth * 2; break; //L,A
103 case 6: info.bytesPerPixel = info.bitDepth * 4; break; //R,G,B,A
104 default: return false;
105 }
106
107 if(info.colorType == 2 || info.colorType == 4 || info.colorType == 6)
108 if(info.bitDepth != 8 && info.bitDepth != 16) return false;
109 if(info.colorType == 3 && info.bitDepth == 16) return false;
110
111 info.bytesPerPixel = (info.bytesPerPixel + 7) / 8;
112 info.pitch = (int)info.width * info.bytesPerPixel;
113 }
114
115 if(fourCC == (unsigned)FourCC::PLTE) {
116 if(length % 3) return false;
117 for(unsigned n = 0, p = offset + 8; n < length / 3; n++) {
118 info.palette[n][0] = sourceData[p++];
119 info.palette[n][1] = sourceData[p++];
120 info.palette[n][2] = sourceData[p++];
121 }
122 }
123
124 if(fourCC == (unsigned)FourCC::IDAT) {
125 compressedData = (uint8_t*)realloc(compressedData, compressedSize + length);
126 memcpy(compressedData + compressedSize, sourceData + offset + 8, length);
127 compressedSize += length;
128 }
129
130 if(fourCC == (unsigned)FourCC::IEND) {
131 break;
132 }
133
134 offset += 4 + 4 + length + 4;
135 }
136
137 unsigned interlacedSize = inflateSize();
138 uint8_t *interlacedData = new uint8_t[interlacedSize];
139
140 bool result = inflate(interlacedData, interlacedSize, compressedData + 2, compressedSize - 6);
141 delete[] compressedData;
142
143 if(result == false) {
144 delete[] interlacedData;
145 return false;
146 }
147
148 rawSize = info.width * info.height * info.bytesPerPixel;
149 rawData = new uint8_t[rawSize];
150
151 if(info.interlaceMethod == 0) {
152 if(filter(rawData, interlacedData, info.width, info.height) == false) {
153 delete[] interlacedData;
154 delete[] rawData;
155 rawData = 0;
156 return false;
157 }
158 } else {
159 const uint8_t *passData = interlacedData;
160 for(unsigned pass = 0; pass < 7; pass++) {
161 if(deinterlace(passData, pass) == false) {
162 delete[] interlacedData;
163 delete[] rawData;
164 rawData = 0;
165 return false;
166 }
167 }
168 }
169
170 delete[] interlacedData;
171 return true;
172 }
173
174 const unsigned png::interlace[7][4] = {
175 //x-distance, y-distance, x-origin, y-origin
176 { 8, 8, 0, 0 },
177 { 8, 8, 4, 0 },
178 { 4, 8, 0, 4 },
179 { 4, 4, 2, 0 },
180 { 2, 4, 0, 2 },
181 { 2, 2, 1, 0 },
182 { 1, 2, 0, 1 },
183 };
184
185 unsigned png::inflateSize() {
186 if(info.interlaceMethod == 0) {
187 return info.width * info.height * info.bytesPerPixel + info.height;
188 }
189
190 unsigned size = 0;
191 for(unsigned pass = 0; pass < 7; pass++) {
192 unsigned xd = interlace[pass][0], yd = interlace[pass][1];
193 unsigned xo = interlace[pass][2], yo = interlace[pass][3];
194 unsigned width = (info.width + (xd - xo - 1)) / xd;
195 unsigned height = (info.height + (yd - yo - 1)) / yd;
196 if(width == 0 || height == 0) continue;
197 size += width * height * info.bytesPerPixel + height;
198 }
199 return size;
200 }
201
202 bool png::deinterlace(const uint8_t *&inputData, unsigned pass) {
203 unsigned xd = interlace[pass][0], yd = interlace[pass][1];
204 unsigned xo = interlace[pass][2], yo = interlace[pass][3];
205 unsigned width = (info.width + (xd - xo - 1)) / xd;
206 unsigned height = (info.height + (yd - yo - 1)) / yd;
207 if(width == 0 || height == 0) return true;
208
209 unsigned outputSize = width * height * info.bytesPerPixel;
210 uint8_t *outputData = new uint8_t[outputSize];
211 bool result = filter(outputData, inputData, width, height);
212
213 const uint8_t *rd = outputData;
214 for(unsigned y = yo; y < info.height; y += yd) {
215 uint8_t *wr = rawData + y * info.pitch;
216 for(unsigned x = xo; x < info.width; x += xd) {
217 for(unsigned b = 0; b < info.bytesPerPixel; b++) {
218 wr[x * info.bytesPerPixel + b] = *rd++;
219 }
220 }
221 }
222
223 inputData += outputSize + height;
224 delete[] outputData;
225 return result;
226 }
227
228 bool png::filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height) {
229 uint8_t *wr = outputData;
230 const uint8_t *rd = inputData;
231 int bpp = info.bytesPerPixel, pitch = width * bpp;
232 for(int y = 0; y < height; y++) {
233 uint8_t filter = *rd++;
234
235 switch(filter) {
236 case 0x00: //None
237 for(int x = 0; x < pitch; x++) {
238 wr[x] = rd[x];
239 }
240 break;
241
242 case 0x01: //Subtract
243 for(int x = 0; x < pitch; x++) {
244 wr[x] = rd[x] + (x - bpp < 0 ? 0 : wr[x - bpp]);
245 }
246 break;
247
248 case 0x02: //Above
249 for(int x = 0; x < pitch; x++) {
250 wr[x] = rd[x] + (y - 1 < 0 ? 0 : wr[x - pitch]);
251 }
252 break;
253
254 case 0x03: //Average
255 for(int x = 0; x < pitch; x++) {
256 short a = x - bpp < 0 ? 0 : wr[x - bpp];
257 short b = y - 1 < 0 ? 0 : wr[x - pitch];
258
259 wr[x] = rd[x] + (uint8_t)((a + b) / 2);
260 }
261 break;
262
263 case 0x04: //Paeth
264 for(int x = 0; x < pitch; x++) {
265 short a = x - bpp < 0 ? 0 : wr[x - bpp];
266 short b = y - 1 < 0 ? 0 : wr[x - pitch];
267 short c = x - bpp < 0 || y - 1 < 0 ? 0 : wr[x - pitch - bpp];
268
269 short p = a + b - c;
270 short pa = p > a ? p - a : a - p;
271 short pb = p > b ? p - b : b - p;
272 short pc = p > c ? p - c : c - p;
273
274 uint8_t paeth = (uint8_t)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
275
276 wr[x] = rd[x] + paeth;
277 }
278 break;
279
280 default: //Invalid
281 return false;
282 }
283
284 rd += pitch;
285 wr += pitch;
286 }
287
288 return true;
289 }
290
291 unsigned png::read(const uint8_t *data, unsigned length) {
292 unsigned result = 0;
293 while(length--) result = (result << 8) | (*data++);
294 return result;
295 }
296
297 unsigned png::decode(const uint8_t *&data) {
298 unsigned p, r, g, b, a;
299
300 switch(info.colorType) {
301 case 0: //L
302 r = g = b = scale(readbits(data));
303 a = 0xff;
304 break;
305 case 2: //R,G,B
306 r = scale(readbits(data));
307 g = scale(readbits(data));
308 b = scale(readbits(data));
309 a = 0xff;
310 break;
311 case 3: //P
312 p = readbits(data);
313 r = info.palette[p][0];
314 g = info.palette[p][1];
315 b = info.palette[p][2];
316 a = 0xff;
317 break;
318 case 4: //L,A
319 r = g = b = scale(readbits(data));
320 a = scale(readbits(data));
321 break;
322 case 6: //R,G,B,A
323 r = scale(readbits(data));
324 g = scale(readbits(data));
325 b = scale(readbits(data));
326 a = scale(readbits(data));
327 break;
328 }
329
330 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
331 }
332
333 unsigned png::readbits(const uint8_t *&data) {
334 unsigned result = 0;
335 switch(info.bitDepth) {
336 case 1:
337 result = (*data >> bitpos) & 1;
338 bitpos++;
339 if(bitpos == 8) { data++; bitpos = 0; }
340 break;
341 case 2:
342 result = (*data >> bitpos) & 3;
343 bitpos += 2;
344 if(bitpos == 8) { data++; bitpos = 0; }
345 break;
346 case 4:
347 result = (*data >> bitpos) & 15;
348 bitpos += 4;
349 if(bitpos == 8) { data++; bitpos = 0; }
350 break;
351 case 8:
352 result = *data++;
353 break;
354 case 16:
355 result = (data[0] << 8) | (data[1] << 0);
356 data += 2;
357 break;
358 }
359 return result;
360 }
361
362 unsigned png::scale(unsigned n) {
363 switch(info.bitDepth) {
364 case 1: return n ? 0xff : 0x00;
365 case 2: return n * 0x55;
366 case 4: return n * 0x11;
367 case 8: return n;
368 case 16: return n >> 8;
369 }
370 return 0;
371 }
372
373 void png::transform() {
374 if(data) delete[] data;
375 data = new uint32_t[info.width * info.height];
376
377 bitpos = 0;
378 const uint8_t *rd = rawData;
379 for(unsigned y = 0; y < info.height; y++) {
380 uint32_t *wr = data + y * info.width;
381 for(unsigned x = 0; x < info.width; x++) {
382 wr[x] = decode(rd);
383 }
384 }
385 }
386
387 void png::alphaTransform(uint32_t rgb) {
388 transform();
389
390 uint8_t ir = rgb >> 16;
391 uint8_t ig = rgb >> 8;
392 uint8_t ib = rgb >> 0;
393
394 uint32_t *p = data;
395 for(unsigned y = 0; y < info.height; y++) {
396 for(unsigned x = 0; x < info.width; x++) {
397 uint32_t pixel = *p;
398 uint8_t a = pixel >> 24;
399 uint8_t r = pixel >> 16;
400 uint8_t g = pixel >> 8;
401 uint8_t b = pixel >> 0;
402
403 r = (r * a) + (ir * (255 - a)) >> 8;
404 g = (g * a) + (ig * (255 - a)) >> 8;
405 b = (b * a) + (ib * (255 - a)) >> 8;
406
407 *p++ = (255 << 24) | (r << 16) | (g << 8) | (b << 0);
408 }
409 }
410 }
411
412 png::png() : data(0), rawData(0) {
413 }
414
415 png::~png() {
416 if(data) delete[] data;
417 if(rawData) delete[] rawData;
418 }
419
420 }
421
422 #endif
0 #ifndef NALL_RESOURCE_HPP
1 #define NALL_RESOURCE_HPP
2
3 #include <nall/file.hpp>
4 #include <nall/zip.hpp>
5
6 namespace nall {
7
8 struct resource {
9 //create resource with "zip -9 resource.zip resource"
10 static bool encode(const char *outputFilename, const char *inputFilename) {
11 file fp;
12 if(fp.open(inputFilename, file::mode::read) == false) return false;
13 unsigned size = fp.size();
14 uint8_t *data = new uint8_t[size];
15 fp.read(data, size);
16 fp.close();
17
18 fp.open(outputFilename, file::mode::write);
19 fp.print("static const uint8_t data[", size, "] = {\n");
20 uint8_t *p = data;
21 while(size) {
22 fp.print(" ");
23 for(unsigned n = 0; n < 32 && size; n++, size--) {
24 fp.print((unsigned)*p++, ",");
25 }
26 fp.print("\n");
27 }
28 fp.print("};\n");
29 fp.close();
30
31 delete[] data;
32 }
33
34 uint8_t *data;
35 unsigned size;
36
37 //extract first file from ZIP archive
38 bool decode(const uint8_t *cdata, unsigned csize) {
39 if(data) delete[] data;
40
41 zip archive;
42 if(archive.open(cdata, csize) == false) return false;
43 if(archive.file.size() == 0) return false;
44 bool result = archive.extract(archive.file[0], data, size);
45 archive.close();
46
47 return result;
48 }
49
50 resource() : data(0), size(0) {
51 }
52
53 ~resource() {
54 if(data) delete[] data;
55 }
56 };
57
58 }
59
60 #endif
11 #define NALL_SHA256_HPP
22
33 //author: vladitx
4
5 #include <nall/stdint.hpp>
46
57 namespace nall {
68 #define PTR(t, a) ((t*)(a))
4850 uint64_t len;
4951 };
5052
51 void sha256_init(sha256_ctx *p) {
53 inline void sha256_init(sha256_ctx *p) {
5254 memset(p, 0, sizeof(sha256_ctx));
5355 memcpy(p->h, T_H, sizeof(T_H));
5456 }
8991 p->inlen = 0;
9092 }
9193
92 void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) {
94 inline void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) {
9395 unsigned l;
9496 p->len += len;
9597
106108 }
107109 }
108110
109 void sha256_final(sha256_ctx *p) {
111 inline void sha256_final(sha256_ctx *p) {
110112 uint64_t len;
111113 p->in[p->inlen++] = 0x80;
112114
123125 sha256_block(p);
124126 }
125127
126 void sha256_hash(sha256_ctx *p, uint8_t *s) {
128 inline void sha256_hash(sha256_ctx *p, uint8_t *s) {
127129 uint32_t *t = (uint32_t*)s;
128130 for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]);
129131 }
110110 string xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
111111
112112 if(type == TypeBsx) {
113 xml << "<cartridge/>";
113 xml.append("<cartridge/>");
114114 xmlMemoryMap = xml.transform("'", "\"");
115115 return;
116116 }
117117
118118 if(type == TypeSufamiTurbo) {
119 xml << "<cartridge/>";
119 xml.append("<cartridge/>");
120120 xmlMemoryMap = xml.transform("'", "\"");
121121 return;
122122 }
123123
124124 if(type == TypeGameBoy) {
125 xml << "<cartridge rtc='" << gameboy_has_rtc(data, size) << "'>\n";
125 xml.append("<cartridge rtc='", gameboy_has_rtc(data, size), "'>\n");
126126 if(gameboy_ram_size(data, size) > 0) {
127 xml << " <ram size='" << hex(gameboy_ram_size(data, size)) << "'/>\n";
128 }
129 xml << "</cartridge>\n";
127 xml.append(" <ram size='0x", hex(gameboy_ram_size(data, size)), "'/>\n");
128 }
129 xml.append("</cartridge>\n");
130130 xmlMemoryMap = xml.transform("'", "\"");
131131 return;
132132 }
133133
134 xml << "<cartridge";
134 xml.append("<cartridge");
135135 if(region == NTSC) {
136 xml << " region='NTSC'";
136 xml.append(" region='NTSC'");
137137 } else {
138 xml << " region='PAL'";
139 }
140 xml << ">\n";
138 xml.append(" region='PAL'");
139 }
140 xml.append(">\n");
141141
142142 if(type == TypeSuperGameBoy1Bios) {
143 xml << " <rom>\n";
144 xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
145 xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
146 xml << " </rom>\n";
147 xml << " <icd2 revision='1'>\n";
148 xml << " <map address='00-3f:6000-7fff'/>\n";
149 xml << " <map address='80-bf:6000-7fff'/>\n";
150 xml << " </icd2>\n";
143 xml.append(" <rom>\n");
144 xml.append(" <map mode='linear' address='00-7f:8000-ffff'/>\n");
145 xml.append(" <map mode='linear' address='80-ff:8000-ffff'/>\n");
146 xml.append(" </rom>\n");
147 xml.append(" <icd2 revision='1'>\n");
148 xml.append(" <map address='00-3f:6000-7fff'/>\n");
149 xml.append(" <map address='80-bf:6000-7fff'/>\n");
150 xml.append(" </icd2>\n");
151151 } else if(type == TypeSuperGameBoy2Bios) {
152 xml << " <rom>\n";
153 xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
154 xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
155 xml << " </rom>\n";
156 xml << " <icd2 revision='2'>\n";
157 xml << " <map address='00-3f:6000-7fff'/>\n";
158 xml << " <map address='80-bf:6000-7fff'/>\n";
159 xml << " </icd2>\n";
152 xml.append(" <rom>\n");
153 xml.append(" <map mode='linear' address='00-7f:8000-ffff'/>\n");
154 xml.append(" <map mode='linear' address='80-ff:8000-ffff'/>\n");
155 xml.append(" </rom>\n");
156 xml.append(" <icd2 revision='2'>\n");
157 xml.append(" <map address='00-3f:6000-7fff'/>\n");
158 xml.append(" <map address='80-bf:6000-7fff'/>\n");
159 xml.append(" </icd2>\n");
160 } else if(has_cx4) {
161 xml.append(" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.bin' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'>\n");
162 xml.append(" <rom>\n");
163 xml.append(" <map mode='linear' address='00-7f:8000-ffff'/>\n");
164 xml.append(" <map mode='linear' address='80-ff:8000-ffff'/>\n");
165 xml.append(" </rom>\n");
166 xml.append(" <mmio>\n");
167 xml.append(" <map address='00-3f:6000-7fff'/>\n");
168 xml.append(" <map address='80-bf:6000-7fff'/>\n");
169 xml.append(" </mmio>\n");
170 xml.append(" </hitachidsp>\n");
160171 } else if(has_spc7110) {
161 xml << " <rom>\n";
162 xml << " <map mode='shadow' address='00-0f:8000-ffff'/>\n";
163 xml << " <map mode='shadow' address='80-bf:8000-ffff'/>\n";
164 xml << " <map mode='linear' address='c0-cf:0000-ffff'/>\n";
165 xml << " </rom>\n";
166
167 xml << " <spc7110>\n";
168 xml << " <mcu>\n";
169 xml << " <map address='d0-ff:0000-ffff' offset='100000' size='" << hex(size - 0x100000) << "'/>\n";
170 xml << " </mcu>\n";
171 xml << " <ram size='" << hex(ram_size) << "'>\n";
172 xml << " <map mode='linear' address='00:6000-7fff'/>\n";
173 xml << " <map mode='linear' address='30:6000-7fff'/>\n";
174 xml << " </ram>\n";
175 xml << " <mmio>\n";
176 xml << " <map address='00-3f:4800-483f'/>\n";
177 xml << " <map address='80-bf:4800-483f'/>\n";
178 xml << " </mmio>\n";
172 xml.append(" <rom>\n");
173 xml.append(" <map mode='shadow' address='00-0f:8000-ffff'/>\n");
174 xml.append(" <map mode='shadow' address='80-bf:8000-ffff'/>\n");
175 xml.append(" <map mode='linear' address='c0-cf:0000-ffff'/>\n");
176 xml.append(" </rom>\n");
177
178 xml.append(" <spc7110>\n");
179 xml.append(" <mcu>\n");
180 xml.append(" <map address='d0-ff:0000-ffff' offset='0x100000' size='0x", hex(size - 0x100000), "'/>\n");
181 xml.append(" </mcu>\n");
182 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
183 xml.append(" <map mode='linear' address='00:6000-7fff'/>\n");
184 xml.append(" <map mode='linear' address='30:6000-7fff'/>\n");
185 xml.append(" </ram>\n");
186 xml.append(" <mmio>\n");
187 xml.append(" <map address='00-3f:4800-483f'/>\n");
188 xml.append(" <map address='80-bf:4800-483f'/>\n");
189 xml.append(" </mmio>\n");
179190 if(has_spc7110rtc) {
180 xml << " <rtc>\n";
181 xml << " <map address='00-3f:4840-4842'/>\n";
182 xml << " <map address='80-bf:4840-4842'/>\n";
183 xml << " </rtc>\n";
184 }
185 xml << " <dcu>\n";
186 xml << " <map address='50:0000-ffff'/>\n";
187 xml << " </dcu>\n";
188 xml << " </spc7110>\n";
191 xml.append(" <rtc>\n");
192 xml.append(" <map address='00-3f:4840-4842'/>\n");
193 xml.append(" <map address='80-bf:4840-4842'/>\n");
194 xml.append(" </rtc>\n");
195 }
196 xml.append(" <dcu>\n");
197 xml.append(" <map address='50:0000-ffff'/>\n");
198 xml.append(" </dcu>\n");
199 xml.append(" </spc7110>\n");
189200 } else if(mapper == LoROM) {
190 xml << " <rom>\n";
191 xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
192 xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
193 xml << " </rom>\n";
201 xml.append(" <rom>\n");
202 xml.append(" <map mode='linear' address='00-7f:8000-ffff'/>\n");
203 xml.append(" <map mode='linear' address='80-ff:8000-ffff'/>\n");
204 xml.append(" </rom>\n");
194205
195206 if(ram_size > 0) {
196 xml << " <ram size='" << hex(ram_size) << "'>\n";
197 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
198 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
207 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
208 xml.append(" <map mode='linear' address='20-3f:6000-7fff'/>\n");
209 xml.append(" <map mode='linear' address='a0-bf:6000-7fff'/>\n");
199210 if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
200 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
201 xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
211 xml.append(" <map mode='linear' address='70-7f:0000-7fff'/>\n");
212 xml.append(" <map mode='linear' address='f0-ff:0000-7fff'/>\n");
202213 } else {
203 xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
204 xml << " <map mode='linear' address='f0-ff:0000-ffff'/>\n";
214 xml.append(" <map mode='linear' address='70-7f:0000-ffff'/>\n");
215 xml.append(" <map mode='linear' address='f0-ff:0000-ffff'/>\n");
205216 }
206 xml << " </ram>\n";
217 xml.append(" </ram>\n");
207218 }
208219 } else if(mapper == HiROM) {
209 xml << " <rom>\n";
210 xml << " <map mode='shadow' address='00-3f:8000-ffff'/>\n";
211 xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
212 xml << " <map mode='shadow' address='80-bf:8000-ffff'/>\n";
213 xml << " <map mode='linear' address='c0-ff:0000-ffff'/>\n";
214 xml << " </rom>\n";
220 xml.append(" <rom>\n");
221 xml.append(" <map mode='shadow' address='00-3f:8000-ffff'/>\n");
222 xml.append(" <map mode='linear' address='40-7f:0000-ffff'/>\n");
223 xml.append(" <map mode='shadow' address='80-bf:8000-ffff'/>\n");
224 xml.append(" <map mode='linear' address='c0-ff:0000-ffff'/>\n");
225 xml.append(" </rom>\n");
215226
216227 if(ram_size > 0) {
217 xml << " <ram size='" << hex(ram_size) << "'>\n";
218 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
219 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
228 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
229 xml.append(" <map mode='linear' address='20-3f:6000-7fff'/>\n");
230 xml.append(" <map mode='linear' address='a0-bf:6000-7fff'/>\n");
220231 if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
221 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
232 xml.append(" <map mode='linear' address='70-7f:0000-7fff'/>\n");
222233 } else {
223 xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
234 xml.append(" <map mode='linear' address='70-7f:0000-ffff'/>\n");
224235 }
225 xml << " </ram>\n";
236 xml.append(" </ram>\n");
226237 }
227238 } else if(mapper == ExLoROM) {
228 xml << " <rom>\n";
229 xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
230 xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
231 xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
232 xml << " </rom>\n";
239 xml.append(" <rom>\n");
240 xml.append(" <map mode='linear' address='00-3f:8000-ffff'/>\n");
241 xml.append(" <map mode='linear' address='40-7f:0000-ffff'/>\n");
242 xml.append(" <map mode='linear' address='80-bf:8000-ffff'/>\n");
243 xml.append(" </rom>\n");
233244
234245 if(ram_size > 0) {
235 xml << " <ram size='" << hex(ram_size) << "'>\n";
236 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
237 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
238 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
239 xml << " </ram>\n";
246 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
247 xml.append(" <map mode='linear' address='20-3f:6000-7fff'/>\n");
248 xml.append(" <map mode='linear' address='a0-bf:6000-7fff'/>\n");
249 xml.append(" <map mode='linear' address='70-7f:0000-7fff'/>\n");
250 xml.append(" </ram>\n");
240251 }
241252 } else if(mapper == ExHiROM) {
242 xml << " <rom>\n";
243 xml << " <map mode='shadow' address='00-3f:8000-ffff' offset='400000'/>\n";
244 xml << " <map mode='linear' address='40-7f:0000-ffff' offset='400000'/>\n";
245 xml << " <map mode='shadow' address='80-bf:8000-ffff' offset='000000'/>\n";
246 xml << " <map mode='linear' address='c0-ff:0000-ffff' offset='000000'/>\n";
247 xml << " </rom>\n";
253 xml.append(" <rom>\n");
254 xml.append(" <map mode='shadow' address='00-3f:8000-ffff' offset='0x400000'/>\n");
255 xml.append(" <map mode='linear' address='40-7f:0000-ffff' offset='0x400000'/>\n");
256 xml.append(" <map mode='shadow' address='80-bf:8000-ffff' offset='0x000000'/>\n");
257 xml.append(" <map mode='linear' address='c0-ff:0000-ffff' offset='0x000000'/>\n");
258 xml.append(" </rom>\n");
248259
249260 if(ram_size > 0) {
250 xml << " <ram size='" << hex(ram_size) << "'>\n";
251 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
252 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
261 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
262 xml.append(" <map mode='linear' address='20-3f:6000-7fff'/>\n");
263 xml.append(" <map mode='linear' address='a0-bf:6000-7fff'/>\n");
253264 if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
254 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
265 xml.append(" <map mode='linear' address='70-7f:0000-7fff'/>\n");
255266 } else {
256 xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
267 xml.append(" <map mode='linear' address='70-7f:0000-ffff'/>\n");
257268 }
258 xml << " </ram>\n";
269 xml.append(" </ram>\n");
259270 }
260271 } else if(mapper == SuperFXROM) {
261 xml << " <superfx revision='2'>\n";
262 xml << " <rom>\n";
263 xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
264 xml << " <map mode='linear' address='40-5f:0000-ffff'/>\n";
265 xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
266 xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
267 xml << " </rom>\n";
268 xml << " <ram size='" << hex(ram_size) << "'>\n";
269 xml << " <map mode='linear' address='00-3f:6000-7fff' size='2000'/>\n";
270 xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
271 xml << " <map mode='linear' address='80-bf:6000-7fff' size='2000'/>\n";
272 xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
273 xml << " </ram>\n";
274 xml << " <mmio>\n";
275 xml << " <map address='00-3f:3000-32ff'/>\n";
276 xml << " <map address='80-bf:3000-32ff'/>\n";
277 xml << " </mmio>\n";
278 xml << " </superfx>\n";
272 xml.append(" <superfx revision='2'>\n");
273 xml.append(" <rom>\n");
274 xml.append(" <map mode='linear' address='00-3f:8000-ffff'/>\n");
275 xml.append(" <map mode='linear' address='40-5f:0000-ffff'/>\n");
276 xml.append(" <map mode='linear' address='80-bf:8000-ffff'/>\n");
277 xml.append(" <map mode='linear' address='c0-df:0000-ffff'/>\n");
278 xml.append(" </rom>\n");
279 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
280 xml.append(" <map mode='linear' address='00-3f:6000-7fff' size='0x2000'/>\n");
281 xml.append(" <map mode='linear' address='60-7f:0000-ffff'/>\n");
282 xml.append(" <map mode='linear' address='80-bf:6000-7fff' size='0x2000'/>\n");
283 xml.append(" <map mode='linear' address='e0-ff:0000-ffff'/>\n");
284 xml.append(" </ram>\n");
285 xml.append(" <mmio>\n");
286 xml.append(" <map address='00-3f:3000-32ff'/>\n");
287 xml.append(" <map address='80-bf:3000-32ff'/>\n");
288 xml.append(" </mmio>\n");
289 xml.append(" </superfx>\n");
279290 } else if(mapper == SA1ROM) {
280 xml << " <sa1>\n";
281 xml << " <mcu>\n";
282 xml << " <rom>\n";
283 xml << " <map mode='direct' address='00-3f:8000-ffff'/>\n";
284 xml << " <map mode='direct' address='80-bf:8000-ffff'/>\n";
285 xml << " <map mode='direct' address='c0-ff:0000-ffff'/>\n";
286 xml << " </rom>\n";
287 xml << " <ram>\n";
288 xml << " <map mode='direct' address='00-3f:6000-7fff'/>\n";
289 xml << " <map mode='direct' address='80-bf:6000-7fff'/>\n";
290 xml << " </ram>\n";
291 xml << " </mcu>\n";
292 xml << " <iram size='800'>\n";
293 xml << " <map mode='linear' address='00-3f:3000-37ff'/>\n";
294 xml << " <map mode='linear' address='80-bf:3000-37ff'/>\n";
295 xml << " </iram>\n";
296 xml << " <bwram size='" << hex(ram_size) << "'>\n";
297 xml << " <map mode='linear' address='40-4f:0000-ffff'/>\n";
298 xml << " </bwram>\n";
299 xml << " <mmio>\n";
300 xml << " <map address='00-3f:2200-23ff'/>\n";
301 xml << " <map address='80-bf:2200-23ff'/>\n";
302 xml << " </mmio>\n";
303 xml << " </sa1>\n";
291 xml.append(" <sa1>\n");
292 xml.append(" <mcu>\n");
293 xml.append(" <rom>\n");
294 xml.append(" <map mode='direct' address='00-3f:8000-ffff'/>\n");
295 xml.append(" <map mode='direct' address='80-bf:8000-ffff'/>\n");
296 xml.append(" <map mode='direct' address='c0-ff:0000-ffff'/>\n");
297 xml.append(" </rom>\n");
298 xml.append(" <ram>\n");
299 xml.append(" <map mode='direct' address='00-3f:6000-7fff'/>\n");
300 xml.append(" <map mode='direct' address='80-bf:6000-7fff'/>\n");
301 xml.append(" </ram>\n");
302 xml.append(" </mcu>\n");
303 xml.append(" <iram size='0x800'>\n");
304 xml.append(" <map mode='linear' address='00-3f:3000-37ff'/>\n");
305 xml.append(" <map mode='linear' address='80-bf:3000-37ff'/>\n");
306 xml.append(" </iram>\n");
307 xml.append(" <bwram size='0x", hex(ram_size), "'>\n");
308 xml.append(" <map mode='linear' address='40-4f:0000-ffff'/>\n");
309 xml.append(" </bwram>\n");
310 xml.append(" <mmio>\n");
311 xml.append(" <map address='00-3f:2200-23ff'/>\n");
312 xml.append(" <map address='80-bf:2200-23ff'/>\n");
313 xml.append(" </mmio>\n");
314 xml.append(" </sa1>\n");
304315 } else if(mapper == BSCLoROM) {
305 xml << " <rom>\n";
306 xml << " <map mode='linear' address='00-1f:8000-ffff' offset='000000'/>\n";
307 xml << " <map mode='linear' address='20-3f:8000-ffff' offset='100000'/>\n";
308 xml << " <map mode='linear' address='80-9f:8000-ffff' offset='200000'/>\n";
309 xml << " <map mode='linear' address='a0-bf:8000-ffff' offset='100000'/>\n";
310 xml << " </rom>\n";
311 xml << " <ram size='" << hex(ram_size) << "'>\n";
312 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
313 xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
314 xml << " </ram>\n";
315 xml << " <bsx>\n";
316 xml << " <slot>\n";
317 xml << " <map mode='linear' address='c0-ef:0000-ffff'/>\n";
318 xml << " </slot>\n";
319 xml << " </bsx>\n";
316 xml.append(" <rom>\n");
317 xml.append(" <map mode='linear' address='00-1f:8000-ffff' offset='0x000000'/>\n");
318 xml.append(" <map mode='linear' address='20-3f:8000-ffff' offset='0x100000'/>\n");
319 xml.append(" <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n");
320 xml.append(" <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\n");
321 xml.append(" </rom>\n");
322 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
323 xml.append(" <map mode='linear' address='70-7f:0000-7fff'/>\n");
324 xml.append(" <map mode='linear' address='f0-ff:0000-7fff'/>\n");
325 xml.append(" </ram>\n");
326 xml.append(" <bsx>\n");
327 xml.append(" <slot>\n");
328 xml.append(" <map mode='linear' address='c0-ef:0000-ffff'/>\n");
329 xml.append(" </slot>\n");
330 xml.append(" </bsx>\n");
320331 } else if(mapper == BSCHiROM) {
321 xml << " <rom>\n";
322 xml << " <map mode='shadow' address='00-1f:8000-ffff'/>\n";
323 xml << " <map mode='linear' address='40-5f:0000-ffff'/>\n";
324 xml << " <map mode='shadow' address='80-9f:8000-ffff'/>\n";
325 xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
326 xml << " </rom>\n";
327 xml << " <ram size='" << hex(ram_size) << "'>\n";
328 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
329 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
330 xml << " </ram>\n";
331 xml << " <bsx>\n";
332 xml << " <slot>\n";
333 xml << " <map mode='shadow' address='20-3f:8000-ffff'/>\n";
334 xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
335 xml << " <map mode='shadow' address='a0-bf:8000-ffff'/>\n";
336 xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
337 xml << " </slot>\n";
338 xml << " </bsx>\n";
332 xml.append(" <rom>\n");
333 xml.append(" <map mode='shadow' address='00-1f:8000-ffff'/>\n");
334 xml.append(" <map mode='linear' address='40-5f:0000-ffff'/>\n");
335 xml.append(" <map mode='shadow' address='80-9f:8000-ffff'/>\n");
336 xml.append(" <map mode='linear' address='c0-df:0000-ffff'/>\n");
337 xml.append(" </rom>\n");
338 xml.append(" <ram size='0x", hex(ram_size), "'>\n");
339 xml.append(" <map mode='linear' address='20-3f:6000-7fff'/>\n");
340 xml.append(" <map mode='linear' address='a0-bf:6000-7fff'/>\n");
341 xml.append(" </ram>\n");
342 xml.append(" <bsx>\n");
343 xml.append(" <slot>\n");
344 xml.append(" <map mode='shadow' address='20-3f:8000-ffff'/>\n");
345 xml.append(" <map mode='linear' address='60-7f:0000-ffff'/>\n");
346 xml.append(" <map mode='shadow' address='a0-bf:8000-ffff'/>\n");
347 xml.append(" <map mode='linear' address='e0-ff:0000-ffff'/>\n");
348 xml.append(" </slot>\n");
349 xml.append(" </bsx>\n");
339350 } else if(mapper == BSXROM) {
340 xml << " <bsx>\n";
341 xml << " <mcu>\n";
342 xml << " <map address='00-3f:8000-ffff'/>\n";
343 xml << " <map address='80-bf:8000-ffff'/>\n";
344 xml << " <map address='40-7f:0000-ffff'/>\n";
345 xml << " <map address='c0-ff:0000-ffff'/>\n";
346 xml << " <map address='20-3f:6000-7fff'/>\n";
347 xml << " </mcu>\n";
348 xml << " <mmio>\n";
349 xml << " <map address='00-3f:5000-5fff'/>\n";
350 xml << " <map address='80-bf:5000-5fff'/>\n";
351 xml << " </mmio>\n";
352 xml << " </bsx>\n";
351 xml.append(" <bsx>\n");
352 xml.append(" <mcu>\n");
353 xml.append(" <map address='00-3f:8000-ffff'/>\n");
354 xml.append(" <map address='80-bf:8000-ffff'/>\n");
355 xml.append(" <map address='40-7f:0000-ffff'/>\n");
356 xml.append(" <map address='c0-ff:0000-ffff'/>\n");
357 xml.append(" <map address='20-3f:6000-7fff'/>\n");
358 xml.append(" </mcu>\n");
359 xml.append(" <mmio>\n");
360 xml.append(" <map address='00-3f:5000-5fff'/>\n");
361 xml.append(" <map address='80-bf:5000-5fff'/>\n");
362 xml.append(" </mmio>\n");
363 xml.append(" </bsx>\n");
353364 } else if(mapper == STROM) {
354 xml << " <rom>\n";
355 xml << " <map mode='linear' address='00-1f:8000-ffff'/>\n";
356 xml << " <map mode='linear' address='80-9f:8000-ffff'/>\n";
357 xml << " </rom>\n";
358 xml << " <sufamiturbo>\n";
359 xml << " <slot id='A'>\n";
360 xml << " <rom>\n";
361 xml << " <map mode='linear' address='20-3f:8000-ffff'/>\n";
362 xml << " <map mode='linear' address='a0-bf:8000-ffff'/>\n";
363 xml << " </rom>\n";
364 xml << " <ram size='20000'>\n";
365 xml << " <map mode='linear' address='60-63:8000-ffff'/>\n";
366 xml << " <map mode='linear' address='e0-e3:8000-ffff'/>\n";
367 xml << " </ram>\n";
368 xml << " </slot>\n";
369 xml << " <slot id='B'>\n";
370 xml << " <rom>\n";
371 xml << " <map mode='linear' address='40-5f:8000-ffff'/>\n";
372 xml << " <map mode='linear' address='c0-df:8000-ffff'/>\n";
373 xml << " </rom>\n";
374 xml << " <ram size='20000'>\n";
375 xml << " <map mode='linear' address='70-73:8000-ffff'/>\n";
376 xml << " <map mode='linear' address='f0-f3:8000-ffff'/>\n";
377 xml << " </ram>\n";
378 xml << " </slot>\n";
379 xml << " </sufamiturbo>\n";
365 xml.append(" <rom>\n");
366 xml.append(" <map mode='linear' address='00-1f:8000-ffff'/>\n");
367 xml.append(" <map mode='linear' address='80-9f:8000-ffff'/>\n");
368 xml.append(" </rom>\n");
369 xml.append(" <sufamiturbo>\n");
370 xml.append(" <slot id='A'>\n");
371 xml.append(" <rom>\n");
372 xml.append(" <map mode='linear' address='20-3f:8000-ffff'/>\n");
373 xml.append(" <map mode='linear' address='a0-bf:8000-ffff'/>\n");
374 xml.append(" </rom>\n");
375 xml.append(" <ram size='0x20000'>\n");
376 xml.append(" <map mode='linear' address='60-63:8000-ffff'/>\n");
377 xml.append(" <map mode='linear' address='e0-e3:8000-ffff'/>\n");
378 xml.append(" </ram>\n");
379 xml.append(" </slot>\n");
380 xml.append(" <slot id='B'>\n");
381 xml.append(" <rom>\n");
382 xml.append(" <map mode='linear' address='40-5f:8000-ffff'/>\n");
383 xml.append(" <map mode='linear' address='c0-df:8000-ffff'/>\n");
384 xml.append(" </rom>\n");
385 xml.append(" <ram size='0x20000'>\n");
386 xml.append(" <map mode='linear' address='70-73:8000-ffff'/>\n");
387 xml.append(" <map mode='linear' address='f0-f3:8000-ffff'/>\n");
388 xml.append(" </ram>\n");
389 xml.append(" </slot>\n");
390 xml.append(" </sufamiturbo>\n");
380391 }
381392
382393 if(has_srtc) {
383 xml << " <srtc>\n";
384 xml << " <map address='00-3f:2800-2801'/>\n";
385 xml << " <map address='80-bf:2800-2801'/>\n";
386 xml << " </srtc>\n";
394 xml.append(" <srtc>\n");
395 xml.append(" <map address='00-3f:2800-2801'/>\n");
396 xml.append(" <map address='80-bf:2800-2801'/>\n");
397 xml.append(" </srtc>\n");
387398 }
388399
389400 if(has_sdd1) {
390 xml << " <sdd1>\n";
391 xml << " <mcu>\n";
392 xml << " <map address='c0-ff:0000-ffff'/>\n";
393 xml << " </mcu>\n";
394 xml << " <mmio>\n";
395 xml << " <map address='00-3f:4800-4807'/>\n";
396 xml << " <map address='80-bf:4800-4807'/>\n";
397 xml << " </mmio>\n";
398 xml << " </sdd1>\n";
399 }
400
401 if(has_cx4) {
402 xml << " <cx4>\n";
403 xml << " <map address='00-3f:6000-7fff'/>\n";
404 xml << " <map address='80-bf:6000-7fff'/>\n";
405 xml << " </cx4>\n";
401 xml.append(" <sdd1>\n");
402 xml.append(" <mcu>\n");
403 xml.append(" <map address='c0-ff:0000-ffff'/>\n");
404 xml.append(" </mcu>\n");
405 xml.append(" <mmio>\n");
406 xml.append(" <map address='00-3f:4800-4807'/>\n");
407 xml.append(" <map address='80-bf:4800-4807'/>\n");
408 xml.append(" </mmio>\n");
409 xml.append(" </sdd1>\n");
406410 }
407411
408412 if(has_dsp1) {
409 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
413 xml.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n");
410414 if(dsp1_mapper == DSP1LoROM1MB) {
411 xml << " <dr>\n";
412 xml << " <map address='20-3f:8000-bfff'/>\n";
413 xml << " <map address='a0-bf:8000-bfff'/>\n";
414 xml << " </dr>\n";
415 xml << " <sr>\n";
416 xml << " <map address='20-3f:c000-ffff'/>\n";
417 xml << " <map address='a0-bf:c000-ffff'/>\n";
418 xml << " </sr>\n";
415 xml.append(" <dr>\n");
416 xml.append(" <map address='20-3f:8000-bfff'/>\n");
417 xml.append(" <map address='a0-bf:8000-bfff'/>\n");
418 xml.append(" </dr>\n");
419 xml.append(" <sr>\n");
420 xml.append(" <map address='20-3f:c000-ffff'/>\n");
421 xml.append(" <map address='a0-bf:c000-ffff'/>\n");
422 xml.append(" </sr>\n");
419423 } else if(dsp1_mapper == DSP1LoROM2MB) {
420 xml << " <dr>\n";
421 xml << " <map address='60-6f:0000-3fff'/>\n";
422 xml << " <map address='e0-ef:0000-3fff'/>\n";
423 xml << " </dr>\n";
424 xml << " <sr>\n";
425 xml << " <map address='60-6f:4000-7fff'/>\n";
426 xml << " <map address='e0-ef:4000-7fff'/>\n";
427 xml << " </sr>\n";
424 xml.append(" <dr>\n");
425 xml.append(" <map address='60-6f:0000-3fff'/>\n");
426 xml.append(" <map address='e0-ef:0000-3fff'/>\n");
427 xml.append(" </dr>\n");
428 xml.append(" <sr>\n");
429 xml.append(" <map address='60-6f:4000-7fff'/>\n");
430 xml.append(" <map address='e0-ef:4000-7fff'/>\n");
431 xml.append(" </sr>\n");
428432 } else if(dsp1_mapper == DSP1HiROM) {
429 xml << " <dr>\n";
430 xml << " <map address='00-1f:6000-6fff'/>\n";
431 xml << " <map address='80-9f:6000-6fff'/>\n";
432 xml << " </dr>\n";
433 xml << " <sr>\n";
434 xml << " <map address='00-1f:7000-7fff'/>\n";
435 xml << " <map address='80-9f:7000-7fff'/>\n";
436 xml << " </sr>\n";
437 }
438 xml << " </necdsp>\n";
433 xml.append(" <dr>\n");
434 xml.append(" <map address='00-1f:6000-6fff'/>\n");
435 xml.append(" <map address='80-9f:6000-6fff'/>\n");
436 xml.append(" </dr>\n");
437 xml.append(" <sr>\n");
438 xml.append(" <map address='00-1f:7000-7fff'/>\n");
439 xml.append(" <map address='80-9f:7000-7fff'/>\n");
440 xml.append(" </sr>\n");
441 }
442 xml.append(" </necdsp>\n");
439443 }
440444
441445 if(has_dsp2) {
442 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
443 xml << " <dr>\n";
444 xml << " <map address='20-3f:8000-bfff'/>\n";
445 xml << " <map address='a0-bf:8000-bfff'/>\n";
446 xml << " </dr>\n";
447 xml << " <sr>\n";
448 xml << " <map address='20-3f:c000-ffff'/>\n";
449 xml << " <map address='a0-bf:c000-ffff'/>\n";
450 xml << " </sr>\n";
451 xml << " </necdsp>\n";
446 xml.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n");
447 xml.append(" <dr>\n");
448 xml.append(" <map address='20-3f:8000-bfff'/>\n");
449 xml.append(" <map address='a0-bf:8000-bfff'/>\n");
450 xml.append(" </dr>\n");
451 xml.append(" <sr>\n");
452 xml.append(" <map address='20-3f:c000-ffff'/>\n");
453 xml.append(" <map address='a0-bf:c000-ffff'/>\n");
454 xml.append(" </sr>\n");
455 xml.append(" </necdsp>\n");
452456 }
453457
454458 if(has_dsp3) {
455 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
456 xml << " <dr>\n";
457 xml << " <map address='20-3f:8000-bfff'/>\n";
458 xml << " <map address='a0-bf:8000-bfff'/>\n";
459 xml << " </dr>\n";
460 xml << " <sr>\n";
461 xml << " <map address='20-3f:c000-ffff'/>\n";
462 xml << " <map address='a0-bf:c000-ffff'/>\n";
463 xml << " </sr>\n";
464 xml << " </necdsp>\n";
459 xml.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n");
460 xml.append(" <dr>\n");
461 xml.append(" <map address='20-3f:8000-bfff'/>\n");
462 xml.append(" <map address='a0-bf:8000-bfff'/>\n");
463 xml.append(" </dr>\n");
464 xml.append(" <sr>\n");
465 xml.append(" <map address='20-3f:c000-ffff'/>\n");
466 xml.append(" <map address='a0-bf:c000-ffff'/>\n");
467 xml.append(" </sr>\n");
468 xml.append(" </necdsp>\n");
465469 }
466470
467471 if(has_dsp4) {
468 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
469 xml << " <dr>\n";
470 xml << " <map address='30-3f:8000-bfff'/>\n";
471 xml << " <map address='b0-bf:8000-bfff'/>\n";
472 xml << " </dr>\n";
473 xml << " <sr>\n";
474 xml << " <map address='30-3f:c000-ffff'/>\n";
475 xml << " <map address='b0-bf:c000-ffff'/>\n";
476 xml << " </sr>\n";
477 xml << " </necdsp>\n";
472 xml.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n");
473 xml.append(" <dr>\n");
474 xml.append(" <map address='30-3f:8000-bfff'/>\n");
475 xml.append(" <map address='b0-bf:8000-bfff'/>\n");
476 xml.append(" </dr>\n");
477 xml.append(" <sr>\n");
478 xml.append(" <map address='30-3f:c000-ffff'/>\n");
479 xml.append(" <map address='b0-bf:c000-ffff'/>\n");
480 xml.append(" </sr>\n");
481 xml.append(" </necdsp>\n");
478482 }
479483
480484 if(has_obc1) {
481 xml << " <obc1>\n";
482 xml << " <map address='00-3f:6000-7fff'/>\n";
483 xml << " <map address='80-bf:6000-7fff'/>\n";
484 xml << " </obc1>\n";
485 xml.append(" <obc1>\n");
486 xml.append(" <map address='00-3f:6000-7fff'/>\n");
487 xml.append(" <map address='80-bf:6000-7fff'/>\n");
488 xml.append(" </obc1>\n");
485489 }
486490
487491 if(has_st010) {
488 xml << " <necdsp revision='upd96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
489 xml << " <dr>\n";
490 xml << " <map address='60:0000'/>\n";
491 xml << " <map address='e0:0000'/>\n";
492 xml << " </dr>\n";
493 xml << " <sr>\n";
494 xml << " <map address='60:0001'/>\n";
495 xml << " <map address='e0:0001'/>\n";
496 xml << " </sr>\n";
497 xml << " <dp>\n";
498 xml << " <map address='68-6f:0000-0fff'/>\n";
499 xml << " <map address='e8-ef:0000-0fff'/>\n";
500 xml << " </dp>\n";
501 xml << " </necdsp>\n";
492 xml.append(" <necdsp model='uPD96050' frequency='10000000' firmware='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n");
493 xml.append(" <dr>\n");
494 xml.append(" <map address='60:0000'/>\n");
495 xml.append(" <map address='e0:0000'/>\n");
496 xml.append(" </dr>\n");
497 xml.append(" <sr>\n");
498 xml.append(" <map address='60:0001'/>\n");
499 xml.append(" <map address='e0:0001'/>\n");
500 xml.append(" </sr>\n");
501 xml.append(" <dp>\n");
502 xml.append(" <map address='68-6f:0000-0fff'/>\n");
503 xml.append(" <map address='e8-ef:0000-0fff'/>\n");
504 xml.append(" </dp>\n");
505 xml.append(" </necdsp>\n");
502506 }
503507
504508 if(has_st011) {
505 xml << " <necdsp revision='upd96050' frequency='15000000' program='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n";
506 xml << " <dr>\n";
507 xml << " <map address='60:0000'/>\n";
508 xml << " <map address='e0:0000'/>\n";
509 xml << " </dr>\n";
510 xml << " <sr>\n";
511 xml << " <map address='60:0001'/>\n";
512 xml << " <map address='e0:0001'/>\n";
513 xml << " </sr>\n";
514 xml << " <dp>\n";
515 xml << " <map address='68-6f:0000-0fff'/>\n";
516 xml << " <map address='e8-ef:0000-0fff'/>\n";
517 xml << " </dp>\n";
518 xml << " </necdsp>\n";
509 xml.append(" <necdsp model='uPD96050' frequency='15000000' firmware='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n");
510 xml.append(" <dr>\n");
511 xml.append(" <map address='60:0000'/>\n");
512 xml.append(" <map address='e0:0000'/>\n");
513 xml.append(" </dr>\n");
514 xml.append(" <sr>\n");
515 xml.append(" <map address='60:0001'/>\n");
516 xml.append(" <map address='e0:0001'/>\n");
517 xml.append(" </sr>\n");
518 xml.append(" <dp>\n");
519 xml.append(" <map address='68-6f:0000-0fff'/>\n");
520 xml.append(" <map address='e8-ef:0000-0fff'/>\n");
521 xml.append(" </dp>\n");
522 xml.append(" </necdsp>\n");
519523 }
520524
521525 if(has_st018) {
522 xml << " <setarisc program='ST-0018'>\n";
523 xml << " <map address='00-3f:3800-38ff'/>\n";
524 xml << " <map address='80-bf:3800-38ff'/>\n";
525 xml << " </setarisc>\n";
526 }
527
528 xml << "</cartridge>\n";
526 xml.append(" <setarisc firmware='ST-0018'>\n");
527 xml.append(" <map address='00-3f:3800-38ff'/>\n");
528 xml.append(" <map address='80-bf:3800-38ff'/>\n");
529 xml.append(" </setarisc>\n");
530 }
531
532 xml.append("</cartridge>\n");
529533 xmlMemoryMap = xml.transform("'", "\"");
530534 }
531535
0 #ifndef NALL_STACK_HPP
1 #define NALL_STACK_HPP
2
3 #include <nall/concept.hpp>
4 #include <nall/vector.hpp>
5
6 namespace nall {
7 template<typename T> struct stack : public linear_vector<T> {
8 void push(const T &value) {
9 linear_vector<T>::append(value);
10 }
11
12 T pull() {
13 if(linear_vector<T>::size() == 0) throw;
14 T value = linear_vector<T>::operator[](linear_vector<T>::size() - 1);
15 linear_vector<T>::remove(linear_vector<T>::size() - 1);
16 return value;
17 }
18
19 T& operator()() {
20 if(linear_vector<T>::size() == 0) throw;
21 return linear_vector<T>::operator[](linear_vector<T>::size() - 1);
22 }
23 };
24
25 template<typename T> struct has_size<stack<T>> { enum { value = true }; };
26 }
27
28 #endif
55 #include <stdlib.h>
66 #include <string.h>
77 #include <nall/concept.hpp>
8 #include <nall/function.hpp>
89 #include <nall/stdint.hpp>
9 #include <nall/utf8.hpp>
1010 #include <nall/vector.hpp>
11 #include <nall/windows/utf8.hpp>
1112
1213 namespace nall {
1314 class string;
15 class lstring;
1416 template<typename T> inline const char* to_string(T);
1517
1618 class string {
1921
2022 template<typename... Args> inline string& assign(Args&&... args);
2123 template<typename... Args> inline string& append(Args&&... args);
22 inline string& assign_(const char*);
23 inline string& append_(const char*);
2424
2525 inline bool readfile(const string&);
2626
27 inline string& replace (const char*, const char*);
28 inline string& qreplace(const char*, const char*);
27 template<unsigned Limit = 0> inline string& replace(const char*, const char*);
28 template<unsigned Limit = 0> inline string& ireplace(const char*, const char*);
29 template<unsigned Limit = 0> inline string& qreplace(const char*, const char*);
30 template<unsigned Limit = 0> inline string& iqreplace(const char*, const char*);
2931
3032 inline unsigned length() const;
3133
4244
4345 inline string& lower();
4446 inline string& upper();
47 inline string& qlower();
48 inline string& qupper();
4549 inline string& transform(const char *before, const char *after);
4650
4751 template<unsigned limit = 0> inline string& ltrim(const char *key = " ");
4852 template<unsigned limit = 0> inline string& rtrim(const char *key = " ");
49 template<unsigned limit = 0> inline string& trim (const char *key = " ");
53 template<unsigned limit = 0> inline string& trim(const char *key = " ", const char *rkey = 0);
5054
5155 inline optional<unsigned> position(const char *key) const;
56 inline optional<unsigned> iposition(const char *key) const;
5257 inline optional<unsigned> qposition(const char *key) const;
53
54 template<typename T> inline string& operator= (T value);
55 template<typename T> inline string& operator<<(T value);
58 inline optional<unsigned> iqposition(const char *key) const;
5659
5760 inline operator const char*() const;
5861 inline char* operator()();
7376 inline string(string&&);
7477 inline ~string();
7578
79 //internal functions
80 inline string& assign_(const char*);
81 inline string& append_(const char*);
82
7683 protected:
7784 char *data;
7885 unsigned size;
86
87 template<unsigned Limit, bool Insensitive, bool Quoted> inline string& ureplace(const char*, const char*);
7988
8089 #if defined(QSTRING_H)
8190 public:
8897 template<typename T> inline lstring& operator<<(T value);
8998
9099 inline optional<unsigned> find(const char*) const;
91 template<unsigned limit = 0> inline void split (const char*, const char*);
92 template<unsigned limit = 0> inline void qsplit(const char*, const char*);
100 template<unsigned Limit = 0> inline lstring& split(const char*, const char*);
101 template<unsigned Limit = 0> inline lstring& isplit(const char*, const char*);
102 template<unsigned Limit = 0> inline lstring& qsplit(const char*, const char*);
103 template<unsigned Limit = 0> inline lstring& iqsplit(const char*, const char*);
93104
94105 lstring();
95106 lstring(std::initializer_list<string>);
107
108 protected:
109 template<unsigned Limit, bool Insensitive, bool Quoted> inline lstring& usplit(const char*, const char*);
96110 };
97111
98112 //compare.hpp
99113 inline char chrlower(char c);
100114 inline char chrupper(char c);
101 inline int stricmp(const char *str1, const char *str2);
115 inline int istrcmp(const char *str1, const char *str2);
102116 inline bool wildcard(const char *str, const char *pattern);
103117 inline bool iwildcard(const char *str, const char *pattern);
104 inline bool strbegin (const char *str, const char *key);
105 inline bool stribegin(const char *str, const char *key);
106 inline bool strend (const char *str, const char *key);
107 inline bool striend(const char *str, const char *key);
118 inline bool strbegin(const char *str, const char *key);
119 inline bool istrbegin(const char *str, const char *key);
120 inline bool strend(const char *str, const char *key);
121 inline bool istrend(const char *str, const char *key);
108122
109123 //convert.hpp
110124 inline char* strlower(char *str);
111125 inline char* strupper(char *str);
126 inline char* qstrlower(char *str);
127 inline char* qstrupper(char *str);
112128 inline char* strtr(char *dest, const char *before, const char *after);
113 inline uintmax_t hex (const char *str);
114 inline intmax_t integer(const char *str);
129 inline uintmax_t hex(const char *str);
130 inline intmax_t integer(const char *str);
115131 inline uintmax_t decimal(const char *str);
116 inline uintmax_t binary (const char *str);
117 inline double fp (const char *str);
132 inline uintmax_t binary(const char *str);
133 inline double fp(const char *str);
118134
119135 //math.hpp
120 inline bool strint (const char *str, int &result);
136 inline bool strint(const char *str, int &result);
121137 inline bool strmath(const char *str, int &result);
122138
123139 //platform.hpp
131147
132148 //strpos.hpp
133149 inline optional<unsigned> strpos(const char *str, const char *key);
150 inline optional<unsigned> istrpos(const char *str, const char *key);
134151 inline optional<unsigned> qstrpos(const char *str, const char *key);
152 inline optional<unsigned> iqstrpos(const char *str, const char *key);
153 template<bool Insensitive = false, bool Quoted = false> inline optional<unsigned> ustrpos(const char *str, const char *key);
135154
136155 //trim.hpp
137156 template<unsigned limit = 0> inline char* ltrim(char *str, const char *key = " ");
138157 template<unsigned limit = 0> inline char* rtrim(char *str, const char *key = " ");
139 template<unsigned limit = 0> inline char* trim (char *str, const char *key = " ");
158 template<unsigned limit = 0> inline char* trim(char *str, const char *key = " ", const char *rkey = 0);
140159
141160 //utility.hpp
161 template<bool Insensitive> alwaysinline bool chrequal(char x, char y);
162 template<bool Quoted, typename T> alwaysinline bool quoteskip(T *&p);
163 template<bool Quoted, typename T> alwaysinline bool quotecopy(char *&t, T *&p);
142164 inline unsigned strlcpy(string &dest, const char *src, unsigned length);
143165 inline unsigned strlcat(string &dest, const char *src, unsigned length);
144 inline string substr(const char *src, unsigned start = 0, unsigned length = 0);
166 inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u);
167 inline string sha256(const uint8_t *data, unsigned size);
145168
146 inline string integer(intmax_t value);
147 template<unsigned length = 0> inline string linteger(intmax_t value);
148 template<unsigned length = 0> inline string rinteger(intmax_t value);
149 inline string decimal(uintmax_t value);
150 template<unsigned length = 0> inline string ldecimal(uintmax_t value);
151 template<unsigned length = 0> inline string rdecimal(uintmax_t value);
152 template<unsigned length = 0> inline string hex(uintmax_t value);
153 template<unsigned length = 0> inline string binary(uintmax_t value);
169 template<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value);
170 template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value);
171 template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value);
172 template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value);
173 template<unsigned length = 0, char padding = '0'> inline string hex(uintmax_t value);
174 template<unsigned length = 0, char padding = '0'> inline string binary(uintmax_t value);
154175 inline unsigned fp(char *str, double value);
155176 inline string fp(double value);
156177
55 //this is needed, as C++0x does not support explicit template specialization inside classes
66 template<> inline const char* to_string<bool> (bool v) { return v ? "true" : "false"; }
77 template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; }
8 template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
9 template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
8 template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
9 template<> inline const char* to_string<intmax_t> (intmax_t v) { static char temp[256]; snprintf(temp, 255, "%+lld", (long long)v); return temp; }
10 template<> inline const char* to_string<uintmax_t> (uintmax_t v) { static char temp[256]; snprintf(temp, 255, "%llu", (unsigned long long)v); return temp; }
11 template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
1012 template<> inline const char* to_string<char*> (char *v) { return v; }
1113 template<> inline const char* to_string<const char*> (const char *v) { return v; }
1214 template<> inline const char* to_string<string> (string v) { return v; }
1315 template<> inline const char* to_string<const string&>(const string &v) { return v; }
14
15 template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
16 template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
1716
1817 template<typename T> lstring& lstring::operator<<(T value) {
1918 operator[](size()).assign(to_string<T>(value));
1010 return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
1111 }
1212
13 int stricmp(const char *str1, const char *str2) {
13 int istrcmp(const char *str1, const char *str2) {
1414 while(*str1) {
1515 if(chrlower(*str1) != chrlower(*str2)) break;
1616 str1++, str2++;
6565 return (!memcmp(str, key, ksl));
6666 }
6767
68 bool stribegin(const char *str, const char *key) {
68 bool istrbegin(const char *str, const char *key) {
6969 int ssl = strlen(str), ksl = strlen(key);
7070
7171 if(ksl > ssl) return false;
8888 return (!memcmp(str + ssl - ksl, key, ksl));
8989 }
9090
91 bool striend(const char *str, const char *key) {
91 bool istrend(const char *str, const char *key) {
9292 int ssl = strlen(str), ksl = strlen(key);
9393
9494 if(ksl > ssl) return false;
2020 i++;
2121 }
2222 return str;
23 }
24
25 char* qstrlower(char *s) {
26 if(!s) return 0;
27 bool quoted = false;
28 while(*s) {
29 if(*s == '\"' || *s == '\'') quoted ^= 1;
30 if(quoted == false && *s >= 'A' && *s <= 'Z') *s += 0x20;
31 s++;
32 }
33 }
34
35 char* qstrupper(char *s) {
36 if(!s) return 0;
37 bool quoted = false;
38 while(*s) {
39 if(*s == '\"' || *s == '\'') quoted ^= 1;
40 if(quoted == false && *s >= 'a' && *s <= 'z') *s -= 0x20;
41 s++;
42 }
2343 }
2444
2545 char* strtr(char *dest, const char *before, const char *after) {
11 #define NALL_STRING_MATH_HPP
22
33 namespace nall {
4
5 static function<int64_t (const char *&)> eval_fallback;
46
57 static int eval_integer(const char *&s) {
68 if(!*s) throw "unrecognized_integer";
5759 }
5860
5961 static int eval(const char *&s, int depth = 0) {
60 while(*s == ' ' || *s == '\t') s++; //trim whitespace
62 while(*s == ' ' || *s == '\t') s++; //trim whitespace
6163 if(!*s) throw "unrecognized_token";
6264 int value = 0, x = *s, y = *(s + 1);
6365
7375
7476 else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
7577
78 else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing
79
7680 else throw "unrecognized_token";
7781
7882 while(true) {
79 while(*s == ' ' || *s == '\t') s++; //trim whitespace
83 while(*s == ' ' || *s == '\t') s++; //trim whitespace
8084 if(!*s) break;
8185 x = *s, y = *(s + 1);
8286
22
33 namespace nall {
44
5 string& string::replace(const char *key, const char *token) {
6 int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length();
7 unsigned int replace_count = 0, size = ssl;
8 char *buffer;
5 template<unsigned Limit, bool Insensitive, bool Quoted>
6 string& string::ureplace(const char *key, const char *token) {
7 if(!key || !*key) return *this;
8 enum : unsigned { limit = Limit ? Limit : ~0u };
99
10 if(ksl <= ssl) {
11 if(tsl > ksl) { //the new string may be longer than the old string...
12 for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
13 if(!memcmp(data + i, key, ksl)) {
14 replace_count++;
15 i += ksl;
16 } else i++;
17 }
18 size = ssl + ((tsl - ksl) * replace_count);
19 reserve(size);
10 const char *p = data;
11 unsigned counter = 0, keyLength = 0;
12
13 while(*p) {
14 if(quoteskip<Quoted>(p)) continue;
15 for(unsigned n = 0;; n++) {
16 if(key[n] == 0) { counter++; p += n; keyLength = n; break; }
17 if(!chrequal<Insensitive>(key[n], p[n])) { p++; break; }
2018 }
19 }
20 if(counter == 0) return *this;
21 if(Limit) counter = min(counter, Limit);
2122
22 buffer = new char[size + 1];
23 for(i = z = 0; i < ssl;) {
24 if(i <= ssl - ksl) {
25 if(!memcmp(data + i, key, ksl)) {
26 memcpy(buffer + z, token, tsl);
27 z += tsl;
28 i += ksl;
29 } else buffer[z++] = data[i++];
30 } else buffer[z++] = data[i++];
23 char *t = data, *base;
24 unsigned tokenLength = strlen(token);
25 if(tokenLength > keyLength) {
26 t = base = strdup(data);
27 reserve((unsigned)(p - data) + ((tokenLength - keyLength) * counter));
28 }
29 char *o = data;
30
31 while(*t && counter) {
32 if(quotecopy<Quoted>(o, t)) continue;
33 for(unsigned n = 0;; n++) {
34 if(key[n] == 0) { counter--; memcpy(o, token, tokenLength); t += keyLength; o += tokenLength; break; }
35 if(!chrequal<Insensitive>(key[n], t[n])) { *o++ = *t++; break; }
3136 }
32 buffer[z] = 0;
33
34 assign(buffer);
35 delete[] buffer;
3637 }
38 do *o++ = *t; while(*t++);
39 if(tokenLength > keyLength) free(base);
3740
3841 return *this;
3942 }
4043
41 string& string::qreplace(const char *key, const char *token) {
42 int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length();
43 unsigned int replace_count = 0, size = ssl;
44 uint8_t x;
45 char *buffer;
46
47 if(ksl <= ssl) {
48 if(tsl > ksl) {
49 for(i = 0; i <= ssl - ksl;) {
50 x = data[i];
51 if(x == '\"' || x == '\'') {
52 l = i;
53 i++;
54 while(data[i++] != x) {
55 if(i == ssl) {
56 i = l;
57 break;
58 }
59 }
60 }
61 if(!memcmp(data + i, key, ksl)) {
62 replace_count++;
63 i += ksl;
64 } else i++;
65 }
66 size = ssl + ((tsl - ksl) * replace_count);
67 reserve(size);
68 }
69
70 buffer = new char[size + 1];
71 for(i = z = 0; i < ssl;) {
72 x = data[i];
73 if(x == '\"' || x == '\'') {
74 l = i++;
75 while(data[i] != x && i < ssl)i++;
76 if(i >= ssl)i = l;
77 else {
78 memcpy(buffer + z, data + l, i - l);
79 z += i - l;
80 }
81 }
82 if(i <= ssl - ksl) {
83 if(!memcmp(data + i, key, ksl)) {
84 memcpy(buffer + z, token, tsl);
85 z += tsl;
86 i += ksl;
87 replace_count++;
88 } else buffer[z++] = data[i++];
89 } else buffer[z++] = data[i++];
90 }
91 buffer[z] = 0;
92
93 assign(buffer);
94 delete[] buffer;
95 }
96
97 return *this;
98 }
44 template<unsigned Limit> string &string::replace(const char *key, const char *token) { return ureplace<Limit, false, false>(key, token); }
45 template<unsigned Limit> string &string::ireplace(const char *key, const char *token) { return ureplace<Limit, true, false>(key, token); }
46 template<unsigned Limit> string &string::qreplace(const char *key, const char *token) { return ureplace<Limit, false, true>(key, token); }
47 template<unsigned Limit> string &string::iqreplace(const char *key, const char *token) { return ureplace<Limit, true, true>(key, token); }
9948
10049 };
10150
22
33 namespace nall {
44
5 template<unsigned Limit> void lstring::split(const char *key, const char *src) {
6 unsigned limit = Limit;
5 template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit(const char *key, const char *base) {
76 reset();
7 if(!key || !*key) return *this;
88
9 int ssl = strlen(src), ksl = strlen(key);
10 int lp = 0, split_count = 0;
9 const char *p = base;
10 unsigned counter = 0;
1111
12 for(int i = 0; i <= ssl - ksl;) {
13 if(!memcmp(src + i, key, ksl)) {
14 strlcpy(operator[](split_count++), src + lp, i - lp + 1);
15 i += ksl;
16 lp = i;
17 if(!--limit) break;
18 } else i++;
12 while(*p) {
13 if(Limit) if(counter >= Limit) break;
14 if(quoteskip<Quoted>(p)) continue;
15 for(unsigned n = 0;; n++) {
16 if(key[n] == 0) {
17 strlcpy(operator[](counter++), base, (unsigned)(p - base + 1));
18 p += n;
19 base = p;
20 break;
21 }
22 if(!chrequal<Insensitive>(key[n], p[n])) { p++; break; }
23 }
1924 }
2025
21 operator[](split_count++) = src + lp;
26 operator[](counter) = base;
27 return *this;
2228 }
2329
24 template<unsigned Limit> void lstring::qsplit(const char *key, const char *src) {
25 unsigned limit = Limit;
26 reset();
27
28 int ssl = strlen(src), ksl = strlen(key);
29 int lp = 0, split_count = 0;
30
31 for(int i = 0; i <= ssl - ksl;) {
32 uint8_t x = src[i];
33
34 if(x == '\"' || x == '\'') {
35 int z = i++; //skip opening quote
36 while(i < ssl && src[i] != x) i++;
37 if(i >= ssl) i = z; //failed match, rewind i
38 else {
39 i++; //skip closing quote
40 continue; //restart in case next char is also a quote
41 }
42 }
43
44 if(!memcmp(src + i, key, ksl)) {
45 strlcpy(operator[](split_count++), src + lp, i - lp + 1);
46 i += ksl;
47 lp = i;
48 if(!--limit) break;
49 } else i++;
50 }
51
52 operator[](split_count++) = src + lp;
53 }
30 template<unsigned Limit> lstring& lstring::split(const char *key, const char *src) { return usplit<Limit, false, false>(key, src); }
31 template<unsigned Limit> lstring& lstring::isplit(const char *key, const char *src) { return usplit<Limit, true, false>(key, src); }
32 template<unsigned Limit> lstring& lstring::qsplit(const char *key, const char *src) { return usplit<Limit, false, true>(key, src); }
33 template<unsigned Limit> lstring& lstring::iqsplit(const char *key, const char *src) { return usplit<Limit, true, true>(key, src); }
5434
5535 };
5636
11 #define NALL_STRING_STRPOS_HPP
22
33 //usage example:
4 //if(auto pos = strpos(str, key)) print(pos(), "\n");
5 //prints position of key within str, only if it is found
4 //if(auto position = strpos(str, key)) print(position(), "\n");
5 //prints position of key within str; but only if it is found
66
77 namespace nall {
88
9 optional<unsigned> strpos(const char *str, const char *key) {
10 unsigned ssl = strlen(str), ksl = strlen(key);
11 if(ksl > ssl) return { false, 0 };
9 template<bool Insensitive, bool Quoted>
10 optional<unsigned> ustrpos(const char *str, const char *key) {
11 const char *base = str;
1212
13 for(unsigned i = 0; i <= ssl - ksl; i++) {
14 if(!memcmp(str + i, key, ksl)) return { true, i };
13 while(*str) {
14 if(quoteskip<Quoted>(str)) continue;
15 for(unsigned n = 0;; n++) {
16 if(key[n] == 0) return { true, (unsigned)(str - base) };
17 if(str[n] == 0) return { false, 0 };
18 if(!chrequal<Insensitive>(str[n], key[n])) break;
19 }
20 str++;
1521 }
1622
1723 return { false, 0 };
1824 }
1925
20 optional<unsigned> qstrpos(const char *str, const char *key) {
21 unsigned ssl = strlen(str), ksl = strlen(key);
22 if(ksl > ssl) return { false, 0 };
23
24 for(unsigned i = 0; i <= ssl - ksl;) {
25 uint8_t x = str[i];
26 if(x == '\"' || x == '\'') {
27 uint8_t z = i++;
28 while(str[i] != x && i < ssl) i++;
29 if(i >= ssl) i = z;
30 }
31 if(!memcmp(str + i, key, ksl)) return { true, i };
32 i++;
33 }
34
35 return { false, 0 };
36 }
26 optional<unsigned> strpos(const char *str, const char *key) { return ustrpos<false, false>(str, key); }
27 optional<unsigned> istrpos(const char *str, const char *key) { return ustrpos<true, false>(str, key); }
28 optional<unsigned> qstrpos(const char *str, const char *key) { return ustrpos<false, true>(str, key); }
29 optional<unsigned> iqstrpos(const char *str, const char *key) { return ustrpos<true, true>(str, key); }
3730
3831 }
3932
2828 return str;
2929 }
3030
31 template<unsigned limit> char* trim(char *str, const char *key) {
31 template<unsigned limit> char* trim(char *str, const char *key, const char *rkey) {
32 if(rkey) return ltrim<limit>(rtrim<limit>(str, rkey), key);
3233 return ltrim<limit>(rtrim<limit>(str, key), key);
3334 }
3435
11 #define NALL_STRING_UTILITY_HPP
22
33 namespace nall {
4
5 template<bool Insensitive>
6 bool chrequal(char x, char y) {
7 if(Insensitive) return chrlower(x) == chrlower(y);
8 return x == y;
9 }
10
11 template<bool Quoted, typename T>
12 bool quoteskip(T *&p) {
13 if(Quoted == false) return false;
14 if(*p != '\'' && *p != '\"') return false;
15
16 while(*p == '\'' || *p == '\"') {
17 char x = *p++;
18 while(*p && *p++ != x);
19 }
20 return true;
21 }
22
23 template<bool Quoted, typename T>
24 bool quotecopy(char *&t, T *&p) {
25 if(Quoted == false) return false;
26 if(*p != '\'' && *p != '\"') return false;
27
28 while(*p == '\'' || *p == '\"') {
29 char x = *p++;
30 *t++ = x;
31 while(*p && *p != x) *t++ = *p++;
32 *t++ = *p++;
33 }
34 return true;
35 }
436
537 unsigned strlcpy(string &dest, const char *src, unsigned length) {
638 dest.reserve(length);
1446
1547 string substr(const char *src, unsigned start, unsigned length) {
1648 string dest;
17 if(length == 0) {
49 if(length == ~0u) {
1850 //copy entire string
1951 dest = src + start;
2052 } else {
2456 return dest;
2557 }
2658
59 string sha256(const uint8_t *data, unsigned size) {
60 sha256_ctx sha;
61 uint8_t hash[32];
62 sha256_init(&sha);
63 sha256_chunk(&sha, data, size);
64 sha256_final(&sha);
65 sha256_hash(&sha, hash);
66 string result;
67 foreach(byte, hash) result.append(hex<2>(byte));
68 return result;
69 }
70
2771 /* arithmetic <> string */
2872
29 string integer(intmax_t value) {
73 template<unsigned length_, char padding> string integer(intmax_t value) {
3074 bool negative = value < 0;
3175 if(negative) value = abs(value);
3276
4185 buffer[size++] = negative ? '-' : '+';
4286 buffer[size] = 0;
4387
44 char result[size + 1];
45 memset(result, '0', size);
46 result[size] = 0;
47
48 for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) {
49 result[x] = buffer[y];
50 }
51
52 return (const char*)result;
53 }
54
55 template<unsigned length_> string linteger(intmax_t value) {
88 unsigned length = (length_ == 0 ? size : length_);
89 char result[length + 1];
90 memset(result, padding, length);
91 result[length] = 0;
92
93 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
94 result[x] = buffer[y];
95 }
96
97 return (const char*)result;
98 }
99
100 template<unsigned length_, char padding> string linteger(intmax_t value) {
56101 bool negative = value < 0;
57102 if(negative) value = abs(value);
58103
69114
70115 unsigned length = (length_ == 0 ? size : length_);
71116 char result[length + 1];
72 memset(result, ' ', length);
117 memset(result, padding, length);
73118 result[length] = 0;
74119
75120 for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) {
79124 return (const char*)result;
80125 }
81126
82 template<unsigned length_> string rinteger(intmax_t value) {
83 bool negative = value < 0;
84 if(negative) value = abs(value);
85
86 char buffer[64];
87 unsigned size = 0;
88
89 do {
90 unsigned n = value % 10;
91 buffer[size++] = '0' + n;
92 value /= 10;
93 } while(value);
94 buffer[size++] = negative ? '-' : '+';
95 buffer[size] = 0;
96
97 unsigned length = (length_ == 0 ? size : length_);
98 char result[length + 1];
99 memset(result, ' ', length);
100 result[length] = 0;
101
102 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
103 result[x] = buffer[y];
104 }
105
106 return (const char*)result;
107 }
108
109 string decimal(uintmax_t value) {
110 char buffer[64];
111 unsigned size = 0;
112
113 do {
114 unsigned n = value % 10;
115 buffer[size++] = '0' + n;
116 value /= 10;
117 } while(value);
118 buffer[size] = 0;
119
120 char result[size + 1];
121 memset(result, '0', size);
122 result[size] = 0;
123
124 for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) {
125 result[x] = buffer[y];
126 }
127
128 return (const char*)result;
129 }
130
131 template<unsigned length_> string ldecimal(uintmax_t value) {
132 char buffer[64];
133 unsigned size = 0;
134
135 do {
136 unsigned n = value % 10;
137 buffer[size++] = '0' + n;
138 value /= 10;
139 } while(value);
140 buffer[size] = 0;
141
142 unsigned length = (length_ == 0 ? size : length_);
143 char result[length + 1];
144 memset(result, ' ', length);
127 template<unsigned length_, char padding> string decimal(uintmax_t value) {
128 char buffer[64];
129 unsigned size = 0;
130
131 do {
132 unsigned n = value % 10;
133 buffer[size++] = '0' + n;
134 value /= 10;
135 } while(value);
136 buffer[size] = 0;
137
138 unsigned length = (length_ == 0 ? size : length_);
139 char result[length + 1];
140 memset(result, padding, length);
141 result[length] = 0;
142
143 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
144 result[x] = buffer[y];
145 }
146
147 return (const char*)result;
148 }
149
150 template<unsigned length_, char padding> string ldecimal(uintmax_t value) {
151 char buffer[64];
152 unsigned size = 0;
153
154 do {
155 unsigned n = value % 10;
156 buffer[size++] = '0' + n;
157 value /= 10;
158 } while(value);
159 buffer[size] = 0;
160
161 unsigned length = (length_ == 0 ? size : length_);
162 char result[length + 1];
163 memset(result, padding, length);
145164 result[length] = 0;
146165
147166 for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) {
151170 return (const char*)result;
152171 }
153172
154 template<unsigned length_> string rdecimal(uintmax_t value) {
155 char buffer[64];
156 unsigned size = 0;
157
158 do {
159 unsigned n = value % 10;
160 buffer[size++] = '0' + n;
161 value /= 10;
162 } while(value);
163 buffer[size] = 0;
164
165 unsigned length = (length_ == 0 ? size : length_);
166 char result[length + 1];
167 memset(result, ' ', length);
168 result[length] = 0;
169
170 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
171 result[x] = buffer[y];
172 }
173
174 return (const char*)result;
175 }
176
177 template<unsigned length_> string hex(uintmax_t value) {
173 template<unsigned length_, char padding> string hex(uintmax_t value) {
178174 char buffer[64];
179175 unsigned size = 0;
180176
186182
187183 unsigned length = (length_ == 0 ? size : length_);
188184 char result[length + 1];
189 memset(result, '0', length);
190 result[length] = 0;
191
192 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
193 result[x] = buffer[y];
194 }
195
196 return (const char*)result;
197 }
198
199 template<unsigned length_> string binary(uintmax_t value) {
185 memset(result, padding, length);
186 result[length] = 0;
187
188 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
189 result[x] = buffer[y];
190 }
191
192 return (const char*)result;
193 }
194
195 template<unsigned length_, char padding> string binary(uintmax_t value) {
200196 char buffer[256];
201197 unsigned size = 0;
202198
208204
209205 unsigned length = (length_ == 0 ? size : length_);
210206 char result[length + 1];
211 memset(result, '0', length);
207 memset(result, padding, length);
212208 result[length] = 0;
213209
214210 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
55 unsigned string::length() const { return strlen(data); }
66
77 bool string::equals(const char *str) const { return !strcmp(data, str); }
8 bool string::iequals(const char *str) const { return !stricmp(data, str); }
8 bool string::iequals(const char *str) const { return !istrcmp(data, str); }
99
1010 bool string::wildcard(const char *str) const { return nall::wildcard(data, str); }
1111 bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); }
1212
1313 bool string::beginswith(const char *str) const { return strbegin(data, str); }
14 bool string::ibeginswith(const char *str) const { return stribegin(data, str); }
14 bool string::ibeginswith(const char *str) const { return istrbegin(data, str); }
1515
1616 bool string::endswith(const char *str) const { return strend(data, str); }
17 bool string::iendswith(const char *str) const { return striend(data, str); }
17 bool string::iendswith(const char *str) const { return istrend(data, str); }
1818
1919 string& string::lower() { nall::strlower(data); return *this; }
2020 string& string::upper() { nall::strupper(data); return *this; }
21 string& string::qlower() { nall::qstrlower(data); return *this; }
22 string& string::qupper() { nall::qstrupper(data); return *this; }
2123 string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; }
2224
2325 template<unsigned limit> string& string::ltrim(const char *key) { nall::ltrim<limit>(data, key); return *this; }
2426 template<unsigned limit> string& string::rtrim(const char *key) { nall::rtrim<limit>(data, key); return *this; }
25 template<unsigned limit> string& string::trim (const char *key) { nall::trim <limit>(data, key); return *this; }
27 template<unsigned limit> string& string::trim(const char *key, const char *rkey) { nall::trim <limit>(data, key, rkey); return *this; }
2628
2729 optional<unsigned> string::position(const char *key) const { return strpos(data, key); }
30 optional<unsigned> string::iposition(const char *key) const { return istrpos(data, key); }
2831 optional<unsigned> string::qposition(const char *key) const { return qstrpos(data, key); }
32 optional<unsigned> string::iqposition(const char *key) const { return iqstrpos(data, key); }
2933
3034 }
3135
7676 if(auto pos = strpos(source, "]]>")) {
7777 if(pos() - 9 > 0) {
7878 string cdata = substr(source, 9, pos() - 9);
79 data << cdata;
79 data.append(cdata);
8080 offset += strlen(cdata);
8181 }
8282 source += 9 + offset + 3;
11 #define NALL_STRING_HPP
22
33 #include <initializer_list>
4 #include <nall/array.hpp>
45 #include <nall/platform.hpp>
6 #include <nall/sha256.hpp>
57 #include <nall/utility.hpp>
68
79 #include <nall/string/base.hpp>
+0
-86
snespurify/nall/utf8.hpp less more
0 #ifndef NALL_UTF8_HPP
1 #define NALL_UTF8_HPP
2
3 //UTF-8 <> UTF-16 conversion
4 //used only for Win32; Linux, etc use UTF-8 internally
5
6 #if defined(_WIN32)
7
8 #undef UNICODE
9 #undef _WIN32_WINNT
10 #undef NOMINMAX
11 #define UNICODE
12 #define _WIN32_WINNT 0x0501
13 #define NOMINMAX
14 #include <windows.h>
15 #undef interface
16
17 namespace nall {
18 //UTF-8 to UTF-16
19 class utf16_t {
20 public:
21 operator wchar_t*() {
22 return buffer;
23 }
24
25 operator const wchar_t*() const {
26 return buffer;
27 }
28
29 utf16_t(const char *s = "") {
30 if(!s) s = "";
31 unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0);
32 buffer = new wchar_t[length + 1]();
33 MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length);
34 }
35
36 ~utf16_t() {
37 delete[] buffer;
38 }
39
40 private:
41 wchar_t *buffer;
42 };
43
44 //UTF-16 to UTF-8
45 class utf8_t {
46 public:
47 operator char*() {
48 return buffer;
49 }
50
51 operator const char*() const {
52 return buffer;
53 }
54
55 utf8_t(const wchar_t *s = L"") {
56 if(!s) s = L"";
57 unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0);
58 buffer = new char[length + 1]();
59 WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0);
60 }
61
62 ~utf8_t() {
63 delete[] buffer;
64 }
65
66 utf8_t(const utf8_t&) = delete;
67 utf8_t& operator=(const utf8_t&) = delete;
68
69 private:
70 char *buffer;
71 };
72
73 inline void utf8_args(int &argc, char **&argv) {
74 wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
75 argv = new char*[argc];
76 for(unsigned i = 0; i < argc; i++) {
77 argv[i] = new char[_MAX_PATH];
78 strcpy(argv[i], nall::utf8_t(wargv[i]));
79 }
80 }
81 }
82
83 #endif //if defined(_WIN32)
84
85 #endif
2525 public:
2626 inline operator bool() const { return valid; }
2727 inline const T& operator()() const { if(!valid) throw; return value; }
28 inline optional<T>& operator=(const optional<T> &source) { valid = source.valid; value = source.value; return *this; }
2829 inline optional(bool valid, const T &value) : valid(valid), value(value) {}
2930 };
3031
9393 else resize(objectsize - count);
9494 }
9595
96 inline T& operator[](unsigned index) {
97 if(index >= objectsize) resize(index + 1);
98 return pool[index];
99 }
100
101 inline const T& operator[](unsigned index) const {
102 if(index >= objectsize) throw "vector[] out of bounds";
103 return pool[index];
96 linear_vector() : pool(0), poolsize(0), objectsize(0) {
97 }
98
99 linear_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
100 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
101 }
102
103 ~linear_vector() {
104 reset();
104105 }
105106
106107 //copy
131132 operator=(std::move(source));
132133 }
133134
134 //construction
135 linear_vector() : pool(0), poolsize(0), objectsize(0) {
136 }
137
138 linear_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
139 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
140 }
141
142 ~linear_vector() {
143 reset();
144 }
135 //index
136 inline T& operator[](unsigned index) {
137 if(index >= objectsize) resize(index + 1);
138 return pool[index];
139 }
140
141 inline const T& operator[](unsigned index) const {
142 if(index >= objectsize) throw "vector[] out of bounds";
143 return pool[index];
144 }
145
146 //iteration
147 T* begin() { return &pool[0]; }
148 T* end() { return &pool[objectsize]; }
149 const T* begin() const { return &pool[0]; }
150 const T* end() const { return &pool[objectsize]; }
145151 };
146152
147153 //pointer_vector
221227 else resize(objectsize - count);
222228 }
223229
224 inline T& operator[](unsigned index) {
225 if(index >= objectsize) resize(index + 1);
226 if(!pool[index]) pool[index] = new T;
227 return *pool[index];
228 }
229
230 inline const T& operator[](unsigned index) const {
231 if(index >= objectsize || !pool[index]) throw "vector[] out of bounds";
232 return *pool[index];
230 pointer_vector() : pool(0), poolsize(0), objectsize(0) {
231 }
232
233 pointer_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
234 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
235 }
236
237 ~pointer_vector() {
238 reset();
233239 }
234240
235241 //copy
260266 operator=(std::move(source));
261267 }
262268
263 //construction
264 pointer_vector() : pool(0), poolsize(0), objectsize(0) {
265 }
266
267 pointer_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
268 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
269 }
270
271 ~pointer_vector() {
272 reset();
273 }
269 //index
270 inline T& operator[](unsigned index) {
271 if(index >= objectsize) resize(index + 1);
272 if(!pool[index]) pool[index] = new T;
273 return *pool[index];
274 }
275
276 inline const T& operator[](unsigned index) const {
277 if(index >= objectsize || !pool[index]) throw "vector[] out of bounds";
278 return *pool[index];
279 }
280
281 //iteration
282 struct iterator {
283 bool operator!=(const iterator &source) const { return index != source.index; }
284 T& operator*() { return vector.operator[](index); }
285 iterator& operator++() { index++; return *this; }
286 iterator(pointer_vector &vector, unsigned index) : vector(vector), index(index) {}
287 private:
288 pointer_vector &vector;
289 unsigned index;
290 };
291
292 iterator begin() { return iterator(*this, 0); }
293 iterator end() { return iterator(*this, objectsize); }
274294 };
275295
276296 template<typename T> struct has_size<linear_vector<T>> { enum { value = true }; };
0 #ifndef NALL_WINDOWS_DETOUR_HPP
1 #define NALL_WINDOWS_DETOUR_HPP
2
3 #include <nall/foreach.hpp>
4 #include <nall/platform.hpp>
5 #include <nall/stdint.hpp>
6 #include <nall/string.hpp>
7 #include <nall/utf8.hpp>
8
9 namespace nall {
10
11 #define Copy 0
12 #define RelNear 1
13
14 struct detour {
15 static bool insert(const string &moduleName, const string &functionName, void *&source, void *target);
16 static bool remove(const string &moduleName, const string &functionName, void *&source);
17
18 protected:
19 static unsigned length(const uint8_t *function);
20 static unsigned mirror(uint8_t *target, const uint8_t *source);
21
22 struct opcode {
23 uint16_t prefix;
24 unsigned length;
25 unsigned mode;
26 uint16_t modify;
27 };
28 static opcode opcodes[];
29 };
30
31 //TODO:
32 //* fs:, gs: should force another opcode copy
33 //* conditional branches within +5-byte range should fail
34 detour::opcode detour::opcodes[] = {
35 { 0x50, 1 }, //push eax
36 { 0x51, 1 }, //push ecx
37 { 0x52, 1 }, //push edx
38 { 0x53, 1 }, //push ebx
39 { 0x54, 1 }, //push esp
40 { 0x55, 1 }, //push ebp
41 { 0x56, 1 }, //push esi
42 { 0x57, 1 }, //push edi
43 { 0x58, 1 }, //pop eax
44 { 0x59, 1 }, //pop ecx
45 { 0x5a, 1 }, //pop edx
46 { 0x5b, 1 }, //pop ebx
47 { 0x5c, 1 }, //pop esp
48 { 0x5d, 1 }, //pop ebp
49 { 0x5e, 1 }, //pop esi
50 { 0x5f, 1 }, //pop edi
51 { 0x64, 1 }, //fs:
52 { 0x65, 1 }, //gs:
53 { 0x68, 5 }, //push dword
54 { 0x6a, 2 }, //push byte
55 { 0x74, 2, RelNear, 0x0f84 }, //je near -> je far
56 { 0x75, 2, RelNear, 0x0f85 }, //jne near -> jne far
57 { 0x89, 2 }, //mov reg,reg
58 { 0x8b, 2 }, //mov reg,reg
59 { 0x90, 1 }, //nop
60 { 0xa1, 5 }, //mov eax,[dword]
61 { 0xeb, 2, RelNear, 0xe9 }, //jmp near -> jmp far
62 };
63
64 bool detour::insert(const string &moduleName, const string &functionName, void *&source, void *target) {
65 HMODULE module = GetModuleHandleW(utf16_t(moduleName));
66 if(!module) return false;
67
68 uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName);
69 if(!sourceData) return false;
70
71 unsigned sourceLength = detour::length(sourceData);
72 if(sourceLength < 5) {
73 //unable to clone enough bytes to insert hook
74 #if 1
75 string output = { "detour::insert(", moduleName, "::", functionName, ") failed: " };
76 for(unsigned n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " ");
77 output.rtrim<1>(" ");
78 MessageBoxA(0, output, "nall::detour", MB_OK);
79 #endif
80 return false;
81 }
82
83 uint8_t *mirrorData = new uint8_t[512]();
84 detour::mirror(mirrorData, sourceData);
85
86 DWORD privileges;
87 VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges);
88 VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges);
89 uintmax_t address = (uintmax_t)target - ((uintmax_t)sourceData + 5);
90 sourceData[0] = 0xe9; //jmp target
91 sourceData[1] = address >> 0;
92 sourceData[2] = address >> 8;
93 sourceData[3] = address >> 16;
94 sourceData[4] = address >> 24;
95 VirtualProtect((void*)sourceData, 256, privileges, &privileges);
96
97 source = (void*)mirrorData;
98 return true;
99 }
100
101 bool detour::remove(const string &moduleName, const string &functionName, void *&source) {
102 HMODULE module = GetModuleHandleW(utf16_t(moduleName));
103 if(!module) return false;
104
105 uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName);
106 if(!sourceData) return false;
107
108 uint8_t *mirrorData = (uint8_t*)source;
109 if(mirrorData == sourceData) return false; //hook was never installed
110
111 unsigned length = detour::length(256 + mirrorData);
112 if(length < 5) return false;
113
114 DWORD privileges;
115 VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges);
116 for(unsigned n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n];
117 VirtualProtect((void*)sourceData, 256, privileges, &privileges);
118
119 source = (void*)sourceData;
120 delete[] mirrorData;
121 return true;
122 }
123
124 unsigned detour::length(const uint8_t *function) {
125 unsigned length = 0;
126 while(length < 5) {
127 detour::opcode *opcode = 0;
128 foreach(op, detour::opcodes) {
129 if(function[length] == op.prefix) {
130 opcode = &op;
131 break;
132 }
133 }
134 if(opcode == 0) break;
135 length += opcode->length;
136 }
137 return length;
138 }
139
140 unsigned detour::mirror(uint8_t *target, const uint8_t *source) {
141 const uint8_t *entryPoint = source;
142 for(unsigned n = 0; n < 256; n++) target[256 + n] = source[n];
143
144 unsigned size = detour::length(source);
145 while(size) {
146 detour::opcode *opcode = 0;
147 foreach(op, detour::opcodes) {
148 if(*source == op.prefix) {
149 opcode = &op;
150 break;
151 }
152 }
153
154 switch(opcode->mode) {
155 case Copy:
156 for(unsigned n = 0; n < opcode->length; n++) *target++ = *source++;
157 break;
158 case RelNear: {
159 source++;
160 uintmax_t sourceAddress = (uintmax_t)source + 1 + (int8_t)*source;
161 *target++ = opcode->modify;
162 if(opcode->modify >> 8) *target++ = opcode->modify >> 8;
163 uintmax_t targetAddress = (uintmax_t)target + 4;
164 uintmax_t address = sourceAddress - targetAddress;
165 *target++ = address >> 0;
166 *target++ = address >> 8;
167 *target++ = address >> 16;
168 *target++ = address >> 24;
169 source += 2;
170 } break;
171 }
172
173 size -= opcode->length;
174 }
175
176 uintmax_t address = (entryPoint + detour::length(entryPoint)) - (target + 5);
177 *target++ = 0xe9; //jmp entryPoint
178 *target++ = address >> 0;
179 *target++ = address >> 8;
180 *target++ = address >> 16;
181 *target++ = address >> 24;
182
183 return source - entryPoint;
184 }
185
186 #undef Implied
187 #undef RelNear
188
189 }
190
191 #endif
0 #ifndef NALL_WINDOWS_LAUNCHER_HPP
1 #define NALL_WINDOWS_LAUNCHER_HPP
2
3 namespace nall {
4
5 //launch a new process and inject specified DLL into it
6
7 bool launch(const char *applicationName, const char *libraryName, uint32_t entryPoint) {
8 //if a launcher does not send at least one message, a wait cursor will appear
9 PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
10 MSG msg;
11 GetMessage(&msg, 0, 0, 0);
12
13 STARTUPINFOW si;
14 PROCESS_INFORMATION pi;
15
16 memset(&si, 0, sizeof(STARTUPINFOW));
17 BOOL result = CreateProcessW(
18 utf16_t(applicationName), GetCommandLineW(), NULL, NULL, TRUE,
19 DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, //do not break if application creates its own processes
20 NULL, NULL, &si, &pi
21 );
22 if(result == false) return false;
23
24 uint8_t entryData[1024], entryHook[1024] = {
25 0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName
26 0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW
27 0xff, 0xd0, //call eax
28 0xcd, 0x03, //int 3
29 };
30
31 entryHook[1] = (uint8_t)((entryPoint + 14) >> 0);
32 entryHook[2] = (uint8_t)((entryPoint + 14) >> 8);
33 entryHook[3] = (uint8_t)((entryPoint + 14) >> 16);
34 entryHook[4] = (uint8_t)((entryPoint + 14) >> 24);
35
36 uint32_t pLoadLibraryW = (uint32_t)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW");
37 entryHook[6] = pLoadLibraryW >> 0;
38 entryHook[7] = pLoadLibraryW >> 8;
39 entryHook[8] = pLoadLibraryW >> 16;
40 entryHook[9] = pLoadLibraryW >> 24;
41
42 utf16_t buffer = utf16_t(libraryName);
43 memcpy(entryHook + 14, buffer, 2 * wcslen(buffer) + 2);
44
45 while(true) {
46 DEBUG_EVENT event;
47 WaitForDebugEvent(&event, INFINITE);
48
49 if(event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
50
51 if(event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) {
52 if(event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) {
53 if(event.u.Exception.ExceptionRecord.ExceptionAddress == (void*)(entryPoint + 14 - 1)) {
54 HANDLE hProcess = OpenProcess(0, FALSE, event.dwProcessId);
55 HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, event.dwThreadId);
56
57 CONTEXT context;
58 context.ContextFlags = CONTEXT_FULL;
59 GetThreadContext(hThread, &context);
60
61 WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL);
62 context.Eip = entryPoint;
63 SetThreadContext(hThread, &context);
64
65 CloseHandle(hThread);
66 CloseHandle(hProcess);
67 }
68
69 ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
70 continue;
71 }
72
73 ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
74 continue;
75 }
76
77 if(event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
78 ReadProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL);
79 WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryHook, sizeof entryHook, NULL);
80
81 ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
82 continue;
83 }
84
85 ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE);
86 }
87
88 return true;
89 }
90
91 }
92
93 #endif
0 #ifndef NALL_UTF8_HPP
1 #define NALL_UTF8_HPP
2
3 //UTF-8 <> UTF-16 conversion
4 //used only for Win32; Linux, etc use UTF-8 internally
5
6 #if defined(_WIN32)
7
8 #undef UNICODE
9 #undef _WIN32_WINNT
10 #undef NOMINMAX
11 #define UNICODE
12 #define _WIN32_WINNT 0x0501
13 #define NOMINMAX
14 #include <windows.h>
15 #undef interface
16
17 namespace nall {
18 //UTF-8 to UTF-16
19 class utf16_t {
20 public:
21 operator wchar_t*() {
22 return buffer;
23 }
24
25 operator const wchar_t*() const {
26 return buffer;
27 }
28
29 utf16_t(const char *s = "") {
30 if(!s) s = "";
31 unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0);
32 buffer = new wchar_t[length + 1]();
33 MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length);
34 }
35
36 ~utf16_t() {
37 delete[] buffer;
38 }
39
40 private:
41 wchar_t *buffer;
42 };
43
44 //UTF-16 to UTF-8
45 class utf8_t {
46 public:
47 operator char*() {
48 return buffer;
49 }
50
51 operator const char*() const {
52 return buffer;
53 }
54
55 utf8_t(const wchar_t *s = L"") {
56 if(!s) s = L"";
57 unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0);
58 buffer = new char[length + 1]();
59 WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0);
60 }
61
62 ~utf8_t() {
63 delete[] buffer;
64 }
65
66 utf8_t(const utf8_t&) = delete;
67 utf8_t& operator=(const utf8_t&) = delete;
68
69 private:
70 char *buffer;
71 };
72
73 inline void utf8_args(int &argc, char **&argv) {
74 wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
75 argv = new char*[argc];
76 for(unsigned i = 0; i < argc; i++) {
77 argv[i] = new char[_MAX_PATH];
78 strcpy(argv[i], nall::utf8_t(wargv[i]));
79 }
80 }
81 }
82
83 #endif //if defined(_WIN32)
84
85 #endif
0 #ifndef NALL_UNZIP_HPP
1 #define NALL_UNZIP_HPP
2
3 #include <nall/filemap.hpp>
4 #include <nall/inflate.hpp>
5 #include <nall/string.hpp>
6 #include <nall/vector.hpp>
7
8 namespace nall {
9
10 struct zip {
11 struct File {
12 string name;
13 const uint8_t *data;
14 unsigned size;
15 unsigned csize;
16 unsigned cmode; //0 = uncompressed, 8 = deflate
17 unsigned crc32;
18 };
19
20 inline bool open(const string &filename) {
21 close();
22 if(fm.open(filename, filemap::mode::read) == false) return false;
23 if(open(fm.data(), fm.size()) == false) {
24 fm.close();
25 return false;
26 }
27 return true;
28 }
29
30 inline bool open(const uint8_t *data, unsigned size) {
31 if(size < 22) return false;
32
33 filedata = data;
34 filesize = size;
35
36 file.reset();
37
38 const uint8_t *footer = data + size - 22;
39 const uint8_t *directory = data + read(footer + 16, 4);
40
41 while(true) {
42 unsigned signature = read(directory + 0, 4);
43 if(signature != 0x02014b50) break;
44
45 File file;
46 file.cmode = read(directory + 10, 2);
47 file.crc32 = read(directory + 16, 4);
48 file.csize = read(directory + 20, 4);
49 file.size = read(directory + 24, 4);
50
51 unsigned namelength = read(directory + 28, 2);
52 unsigned extralength = read(directory + 30, 2);
53 unsigned commentlength = read(directory + 32, 2);
54
55 char *filename = new char[namelength + 1];
56 memcpy(filename, directory + 46, namelength);
57 filename[namelength] = 0;
58 file.name = filename;
59 delete[] filename;
60
61 unsigned offset = read(directory + 42, 4);
62 unsigned offsetNL = read(data + offset + 26, 2);
63 unsigned offsetEL = read(data + offset + 28, 2);
64 file.data = data + offset + 30 + offsetNL + offsetEL;
65
66 directory += 46 + namelength + extralength + commentlength;
67
68 this->file.append(file);
69 }
70
71 return true;
72 }
73
74 inline bool extract(File &file, uint8_t *&data, unsigned &size) {
75 data = 0, size = 0;
76
77 if(file.cmode == 0) {
78 size = file.size;
79 data = new uint8_t[size];
80 memcpy(data, file.data, size);
81 return true;
82 }
83
84 if(file.cmode == 8) {
85 size = file.size;
86 data = new uint8_t[size];
87 if(inflate(data, size, file.data, file.csize) == false) {
88 delete[] data;
89 size = 0;
90 return false;
91 }
92 return true;
93 }
94
95 return false;
96 }
97
98 inline void close() {
99 if(fm.open()) fm.close();
100 }
101
102 ~zip() {
103 close();
104 }
105
106 protected:
107 filemap fm;
108 const uint8_t *filedata;
109 unsigned filesize;
110
111 unsigned read(const uint8_t *data, unsigned size) {
112 unsigned result = 0, shift = 0;
113 while(size--) { result |= *data++ << shift; shift += 8; }
114 return result;
115 }
116
117 public:
118 linear_vector<File> file;
119 };
120
121 }
122
123 #endif
3333 void Font::setUnderline(bool underline) { state.underline = underline; return p.setUnderline(underline); }
3434 Font::Font() : state(*new State), p(*new pFont(*this)) { p.constructor(); }
3535
36 void Timer::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); }
37 void Timer::setInterval(unsigned milliseconds) { state.milliseconds = milliseconds; return p.setInterval(milliseconds); }
38 Timer::Timer() : state(*new State), p(*new pTimer(*this)) { p.constructor(); }
39
3640 MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::information(parent, text, buttons); }
3741 MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::question(parent, text, buttons); }
3842 MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::warning(parent, text, buttons); }
4246 void Window::append(Layout &layout) { state.layout.append(layout); return p.append(layout); }
4347 void Window::append(Menu &menu) { state.menu.append(menu); ((Action&)menu).state.parent = this; return p.append(menu); }
4448 void Window::append(Widget &widget) { state.widget.append(widget); return p.append(widget); }
49 Color Window::backgroundColor() { return p.backgroundColor(); }
4550 Geometry Window::frameGeometry() { Geometry geometry = p.geometry(), margin = p.frameMargin(); return { geometry.x - margin.x, geometry.y - margin.y, geometry.width + margin.width, geometry.height + margin.height }; }
4651 Geometry Window::frameMargin() { return p.frameMargin(); }
4752 bool Window::focused() { return p.focused(); }
4853 Geometry Window::geometry() { return p.geometry(); }
49 void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { state.backgroundColor = true; state.backgroundColorRed = red; state.backgroundColorGreen = green; state.backgroundColorBlue = blue; return p.setBackgroundColor(red, green, blue); }
54 void Window::setBackgroundColor(const Color &color) { state.backgroundColorOverride = true; state.backgroundColor = color; return p.setBackgroundColor(color); }
5055 void Window::setFrameGeometry(const Geometry &geometry) { Geometry margin = p.frameMargin(); return setGeometry({ geometry.x + margin.x, geometry.y + margin.y, geometry.width - margin.width, geometry.height - margin.height }); }
5156 void Window::setFocused() { return p.setFocused(); }
5257 void Window::setFullScreen(bool fullScreen) { state.fullScreen = fullScreen; return p.setFullScreen(fullScreen); }
8893
8994 bool Widget::enabled() { return state.enabled; }
9095 Font& Widget::font() { return p.font(); }
96 Geometry Widget::geometry() { return state.geometry; }
9197 Geometry Widget::minimumGeometry() { return p.minimumGeometry(); }
9298 void Widget::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); }
9399 void Widget::setFocused() { return p.setFocused(); }
122128 void HexEdit::setRows(unsigned rows) { state.rows = rows; return p.setRows(rows); }
123129 void HexEdit::update() { return p.update(); }
124130 HexEdit::HexEdit() : state(*new State), base_from_member<pHexEdit&>(*new pHexEdit(*this)), Widget(base_from_member<pHexEdit&>::value), p(base_from_member<pHexEdit&>::value) { p.constructor(); }
131
132 unsigned HorizontalScrollBar::position() { return p.position(); }
133 void HorizontalScrollBar::setLength(unsigned length) { state.length = length; return p.setLength(length); }
134 void HorizontalScrollBar::setPosition(unsigned position) { state.position = position; return p.setPosition(position); }
135 HorizontalScrollBar::HorizontalScrollBar() : state(*new State), base_from_member<pHorizontalScrollBar&>(*new pHorizontalScrollBar(*this)), Widget(base_from_member<pHorizontalScrollBar&>::value), p(base_from_member<pHorizontalScrollBar&>::value) { p.constructor(); }
125136
126137 unsigned HorizontalSlider::position() { return p.position(); }
127138 void HorizontalSlider::setLength(unsigned length) { state.length = length; return p.setLength(length); }
167178 string TextEdit::text() { return p.text(); }
168179 TextEdit::TextEdit() : state(*new State), base_from_member<pTextEdit&>(*new pTextEdit(*this)), Widget(base_from_member<pTextEdit&>::value), p(base_from_member<pTextEdit&>::value) { p.constructor(); }
169180
181 unsigned VerticalScrollBar::position() { return p.position(); }
182 void VerticalScrollBar::setLength(unsigned length) { state.length = length; return p.setLength(length); }
183 void VerticalScrollBar::setPosition(unsigned position) { state.position = position; return p.setPosition(position); }
184 VerticalScrollBar::VerticalScrollBar() : state(*new State), base_from_member<pVerticalScrollBar&>(*new pVerticalScrollBar(*this)), Widget(base_from_member<pVerticalScrollBar&>::value), p(base_from_member<pVerticalScrollBar&>::value) { p.constructor(); }
185
170186 unsigned VerticalSlider::position() { return p.position(); }
171187 void VerticalSlider::setLength(unsigned length) { state.length = length; return p.setLength(length); }
172188 void VerticalSlider::setPosition(unsigned position) { state.position = position; return p.setPosition(position); }
55
66 struct pOS;
77 struct pFont;
8 struct pTimer;
89 struct pWindow;
910 struct pAction;
1011 struct pMenu;
1920 struct pCheckBox;
2021 struct pComboBox;
2122 struct pHexEdit;
23 struct pHorizontalScrollBar;
2224 struct pHorizontalSlider;
2325 struct pLabel;
2426 struct pLineEdit;
2628 struct pProgressBar;
2729 struct pRadioBox;
2830 struct pTextEdit;
31 struct pVerticalScrollBar;
2932 struct pVerticalSlider;
3033 struct pViewport;
3134
3942 unsigned width, height;
4043 inline Geometry() : x(0), y(0), width(0), height(0) {}
4144 inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
45 };
46
47 struct Color {
48 uint8_t red, green, blue, alpha;
49 inline Color() : red(0), green(0), blue(0), alpha(255) {}
50 inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {}
4251 };
4352
4453 struct Object {
8190 pFont &p;
8291 };
8392
93 struct Timer : Object {
94 nall::function<void ()> onTimeout;
95
96 void setEnabled(bool enabled = true);
97 void setInterval(unsigned milliseconds);
98
99 Timer();
100 struct State;
101 State &state;
102 pTimer &p;
103 };
104
84105 struct MessageWindow : Object {
85106 enum class Buttons : unsigned {
86107 Ok,
110131 void append(Layout &layout);
111132 void append(Menu &menu);
112133 void append(Widget &widget);
134 Color backgroundColor();
113135 Geometry frameGeometry();
114136 Geometry frameMargin();
115137 bool focused();
116138 Geometry geometry();
117 void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
139 void setBackgroundColor(const Color &color);
118140 void setFrameGeometry(const Geometry &geometry);
119141 void setFocused();
120142 void setFullScreen(bool fullScreen = true);
209231 struct Widget : Object {
210232 bool enabled();
211233 Font& font();
234 Geometry geometry();
212235 Geometry minimumGeometry();
213236 void setEnabled(bool enabled = true);
214237 void setFocused();
284307 struct State;
285308 State &state;
286309 pHexEdit &p;
310 };
311
312 struct HorizontalScrollBar : private nall::base_from_member<pHorizontalScrollBar&>, Widget {
313 nall::function<void ()> onChange;
314
315 unsigned position();
316 void setLength(unsigned length);
317 void setPosition(unsigned position);
318
319 HorizontalScrollBar();
320 struct State;
321 State &state;
322 pHorizontalScrollBar &p;
287323 };
288324
289325 struct HorizontalSlider : private nall::base_from_member<pHorizontalSlider&>, Widget {
392428 pTextEdit &p;
393429 };
394430
395 struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget {
431 struct VerticalScrollBar : private nall::base_from_member<pVerticalScrollBar&>, Widget {
396432 nall::function<void ()> onChange;
397433
398434 unsigned position();
399435 void setLength(unsigned length);
400436 void setPosition(unsigned position);
401437
438 VerticalScrollBar();
439 struct State;
440 State &state;
441 pVerticalScrollBar &p;
442 };
443
444 struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget {
445 nall::function<void ()> onChange;
446
447 unsigned position();
448 void setLength(unsigned length);
449 void setPosition(unsigned position);
450
402451 VerticalSlider();
403452 struct State;
404453 State &state;
1212 }
1313 };
1414
15 struct Timer::State {
16 bool enabled;
17 unsigned milliseconds;
18
19 State() {
20 enabled = false;
21 milliseconds = 0;
22 }
23 };
24
1525 struct Window::State {
16 bool backgroundColor;
17 unsigned backgroundColorRed, backgroundColorGreen, backgroundColorBlue;
26 bool backgroundColorOverride;
27 Color backgroundColor;
1828 bool fullScreen;
1929 Geometry geometry;
2030 reference_array<Layout&> layout;
3141 Font *widgetFont;
3242
3343 State() {
34 backgroundColor = false;
35 backgroundColorRed = 0;
36 backgroundColorGreen = 0;
37 backgroundColorBlue = 0;
44 backgroundColorOverride = false;
45 backgroundColor = { 0, 0, 0, 255 };
3846 fullScreen = false;
3947 geometry = { 128, 128, 256, 256 };
4048 menuFont = 0;
141149 }
142150 };
143151
152 struct HorizontalScrollBar::State {
153 unsigned length;
154 unsigned position;
155
156 State() {
157 length = 101;
158 position = 0;
159 }
160 };
161
144162 struct HorizontalSlider::State {
145163 unsigned length;
146164 unsigned position;
212230 }
213231 };
214232
233 struct VerticalScrollBar::State {
234 unsigned length;
235 unsigned position;
236
237 State() {
238 length = 101;
239 position = 0;
240 }
241 };
242
215243 struct VerticalSlider::State {
216244 unsigned length;
217245 unsigned position;
2828 gtkFont = pango_font_description_new();
2929 PangoContext *context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
3030 gtkLayout = pango_layout_new(context);
31 font.setFamily("Sans");
32 font.setSize(8);
3133 }
11
22 #include "settings.cpp"
33 #include "font.cpp"
4 #include "timer.cpp"
45 #include "message-window.cpp"
56 #include "window.cpp"
67
1718 #include "widget/check-box.cpp"
1819 #include "widget/combo-box.cpp"
1920 #include "widget/hex-edit.cpp"
21 #include "widget/horizontal-scroll-bar.cpp"
2022 #include "widget/horizontal-slider.cpp"
2123 #include "widget/label.cpp"
2224 #include "widget/line-edit.cpp"
2426 #include "widget/progress-bar.cpp"
2527 #include "widget/radio-box.cpp"
2628 #include "widget/text-edit.cpp"
29 #include "widget/vertical-scroll-bar.cpp"
2730 #include "widget/vertical-slider.cpp"
2831 #include "widget/viewport.cpp"
2932
3033 Font pOS::defaultFont;
3134
3235 Geometry pOS::availableGeometry() {
33 //TODO: is there a GTK+ function for this?
34 //should return desktopGeometry() sans panels, toolbars, docks, etc.
35 Geometry geometry = desktopGeometry();
36 return { geometry.x + 64, geometry.y + 64, geometry.width - 128, geometry.height - 128 };
36 Display *display = XOpenDisplay(0);
37 int screen = DefaultScreen(display);
38
39 static Atom atom = X11None;
40 if(atom == X11None) atom = XInternAtom(display, "_NET_WORKAREA", True);
41
42 int format;
43 unsigned char *data = 0;
44 unsigned long items, after;
45 Atom returnAtom;
46
47 int result = XGetWindowProperty(
48 display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data
49 );
50
51 XCloseDisplay(display);
52
53 if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) {
54 unsigned long *workarea = (unsigned long*)data;
55 return { (signed)workarea[0], (signed)workarea[1], (unsigned)workarea[2], (unsigned)workarea[3] };
56 }
57
58 return desktopGeometry();
3759 }
3860
3961 Geometry pOS::desktopGeometry() {
148170 " GtkComboBox::appears-as-list = 1\n"
149171 " GtkTreeView::vertical-separator = 0\n"
150172 "}\n"
151 "class \"GtkComboBox\" style \"phoenix-gtk\"\n"
173 //"class \"GtkComboBox\" style \"phoenix-gtk\"\n"
152174 "class \"GtkTreeView\" style \"phoenix-gtk\"\n"
153175 );
154176 }
5656 void constructor();
5757 };
5858
59 struct pTimer : public pObject {
60 Timer &timer;
61
62 void setEnabled(bool enabled);
63 void setInterval(unsigned milliseconds);
64
65 pTimer(Timer &timer) : timer(timer) {}
66 void constructor();
67 };
68
5969 struct pMessageWindow : public pObject {
6070 static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
6171 static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
7181 GtkWidget *statusContainer;
7282 GtkWidget *menu;
7383 GtkWidget *status;
84 GdkEventConfigure lastConfigure;
7485
7586 void append(Layout &layout);
7687 void append(Menu &menu);
7788 void append(Widget &widget);
89 Color backgroundColor();
7890 bool focused();
7991 Geometry frameMargin();
8092 Geometry geometry();
81 void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
93 void setBackgroundColor(const Color &color);
8294 void setFocused();
8395 void setFullScreen(bool fullScreen);
8496 void setGeometry(const Geometry &geometry);
191203
192204 struct pCanvas : public pWidget {
193205 Canvas &canvas;
194 uint32_t *bufferRGB;
195 uint32_t *bufferBGR;
206 cairo_surface_t *surface;
196207
197208 uint32_t* buffer();
198209 void setGeometry(const Geometry &geometry);
200211
201212 pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
202213 void constructor();
203 void redraw();
204214 };
205215
206216 struct pCheckBox : public pWidget {
251261 void setCursorPosition(unsigned position);
252262 void setScroll();
253263 void updateScroll();
264 };
265
266 struct pHorizontalScrollBar : public pWidget {
267 HorizontalScrollBar &horizontalScrollBar;
268
269 Geometry minimumGeometry();
270 unsigned position();
271 void setLength(unsigned length);
272 void setPosition(unsigned position);
273
274 pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {}
275 void constructor();
254276 };
255277
256278 struct pHorizontalSlider : public pWidget {
357379 void constructor();
358380 };
359381
360 struct pVerticalSlider : public pWidget {
361 VerticalSlider &verticalSlider;
382 struct pVerticalScrollBar : public pWidget {
383 VerticalScrollBar &verticalScrollBar;
362384
363385 Geometry minimumGeometry();
364386 unsigned position();
365387 void setLength(unsigned length);
366388 void setPosition(unsigned position);
367389
390 pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {}
391 void constructor();
392 };
393
394 struct pVerticalSlider : public pWidget {
395 VerticalSlider &verticalSlider;
396
397 Geometry minimumGeometry();
398 unsigned position();
399 void setLength(unsigned length);
400 void setPosition(unsigned position);
401
368402 pVerticalSlider(VerticalSlider &verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {}
369403 void constructor();
370404 };
0 static guint Timer_trigger(pTimer *self) {
1 //timer may have been disabled prior to triggering, so check state
2 if(self->timer.state.enabled) {
3 if(self->timer.onTimeout) self->timer.onTimeout();
4 }
5 //callback may have disabled timer, so check state again
6 if(self->timer.state.enabled) {
7 g_timeout_add(self->timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)self);
8 }
9 //kill this timer instance (it is spawned above if needed again)
10 return false;
11 }
12
13 void pTimer::setEnabled(bool enabled) {
14 if(enabled) {
15 g_timeout_add(timer.state.milliseconds, (GSourceFunc)Timer_trigger, (gpointer)this);
16 }
17 }
18
19 void pTimer::setInterval(unsigned milliseconds) {
20 }
21
22 void pTimer::constructor() {
23 }
44 Geometry pButton::minimumGeometry() {
55 Font &font = pWidget::font();
66 Geometry geometry = font.geometry(button.state.text);
7 return { 0, 0, geometry.width + 24, geometry.height + 14 };
7 return { 0, 0, geometry.width + 24, geometry.height + 12 };
88 }
99
1010 void pButton::setText(const string &text) {
0 static void Canvas_expose(pCanvas *self) {
1 self->redraw();
0 static gboolean Canvas_expose(GtkWidget *widget, GdkEvent *event, pCanvas *self) {
1 cairo_t *context = gdk_cairo_create(gtk_widget_get_window(widget));
2 cairo_set_source_surface(context, self->surface, 0, 0);
3 cairo_paint(context);
4 cairo_destroy(context);
5 return true;
26 }
37
48 uint32_t* pCanvas::buffer() {
5 return bufferRGB;
9 return (uint32_t*)cairo_image_surface_get_data(surface);
610 }
711
812 void pCanvas::setGeometry(const Geometry &geometry) {
9 delete[] bufferRGB;
10 delete[] bufferBGR;
13 if(geometry.width == cairo_image_surface_get_width(surface)
14 && geometry.height == cairo_image_surface_get_height(surface)) return;
1115
12 bufferRGB = new uint32_t[geometry.width * geometry.height]();
13 bufferBGR = new uint32_t[geometry.width * geometry.height]();
16 cairo_surface_destroy(surface);
17 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, geometry.width, geometry.height);
1418
1519 pWidget::setGeometry(geometry);
1620 update();
1822
1923 void pCanvas::update() {
2024 if(gtk_widget_get_realized(gtkWidget) == false) return;
21 GdkRectangle rect;
22 rect.x = 0;
23 rect.y = 0;
24 rect.width = gtkWidget->allocation.width;
25 rect.height = gtkWidget->allocation.height;
26 gdk_window_invalidate_rect(gtkWidget->window, &rect, true);
25 gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), 0, true);
2726 }
2827
2928 void pCanvas::constructor() {
30 bufferRGB = new uint32_t[256 * 256]();
31 bufferBGR = new uint32_t[256 * 256]();
32
29 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 256, 256);
3330 gtkWidget = gtk_drawing_area_new();
3431 GdkColor color;
3532 color.pixel = color.red = color.green = color.blue = 0;
3633 gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color);
3734 gtk_widget_set_double_buffered(gtkWidget, false);
3835 gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK);
39 g_signal_connect_swapped(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
36 g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
4037 }
41
42 void pCanvas::redraw() {
43 if(gtk_widget_get_realized(gtkWidget) == false) return;
44 uint32_t *rgb = bufferRGB, *bgr = bufferBGR;
45 for(unsigned y = gtkWidget->allocation.height; y; y--) {
46 for(unsigned x = gtkWidget->allocation.width; x; x--) {
47 uint32_t pixel = *rgb++;
48 *bgr++ = ((pixel << 16) & 0xff0000) | (pixel & 0x00ff00) | ((pixel >> 16) & 0x0000ff);
49 }
50 }
51
52 gdk_draw_rgb_32_image(
53 gtkWidget->window,
54 gtkWidget->style->fg_gc[GTK_WIDGET_STATE(gtkWidget)],
55 0, 0, gtkWidget->allocation.width, gtkWidget->allocation.height,
56 GDK_RGB_DITHER_NONE, (guchar*)bufferBGR, sizeof(uint32_t) * gtkWidget->allocation.width
57 );
58 }
1212 foreach(item, comboBox.state.text) maximumWidth = max(maximumWidth, font.geometry(item).width);
1313
1414 Geometry geometry = font.geometry(" ");
15 return { 0, 0, maximumWidth + 44, geometry.height + 10 };
15 return { 0, 0, maximumWidth + 44, geometry.height + 12 };
1616 }
1717
1818 void pComboBox::reset() {
1919 locked = true;
20 for(signed n = itemCounter - 1; n >= 0; n--) {
21 gtk_combo_box_remove_text(GTK_COMBO_BOX(gtkWidget), n);
22 }
20 gtk_list_store_clear(GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(gtkWidget))));
2321 itemCounter = 0;
2422 locked = false;
2523 }
111111 unsigned cursorY = position / lineWidth;
112112 unsigned cursorX = position % lineWidth;
113113
114 if(scancode == GDK_Home) {
114 if(scancode == GDK_KEY_Home) {
115115 setCursorPosition(cursorY * lineWidth + 10);
116116 return true;
117117 }
118118
119 if(scancode == GDK_End) {
119 if(scancode == GDK_KEY_End) {
120120 setCursorPosition(cursorY * lineWidth + 10 + (hexEdit.state.columns * 3 - 1));
121121 return true;
122122 }
123123
124 if(scancode == GDK_Up) {
124 if(scancode == GDK_KEY_Up) {
125125 if(cursorY != 0) return false;
126126
127127 signed newOffset = hexEdit.state.offset - hexEdit.state.columns;
132132 return true;
133133 }
134134
135 if(scancode == GDK_Down) {
135 if(scancode == GDK_KEY_Down) {
136136 if(cursorY != hexEdit.state.rows - 1) return false;
137137
138138 signed newOffset = hexEdit.state.offset + hexEdit.state.columns;
143143 return true;
144144 }
145145
146 if(scancode == GDK_Page_Up) {
146 if(scancode == GDK_KEY_Page_Up) {
147147 signed newOffset = hexEdit.state.offset - hexEdit.state.columns * hexEdit.state.rows;
148148 if(newOffset >= 0) {
149149 hexEdit.setOffset(newOffset);
154154 return true;
155155 }
156156
157 if(scancode == GDK_Page_Down) {
157 if(scancode == GDK_KEY_Page_Down) {
158158 signed newOffset = hexEdit.state.offset + hexEdit.state.columns * hexEdit.state.rows;
159159 for(unsigned n = 0; n < hexEdit.state.rows; n++) {
160160 if(newOffset + hexEdit.state.columns * hexEdit.state.rows - (hexEdit.state.columns - 1) <= hexEdit.state.length) {
0 static void HorizontalScrollBar_change(HorizontalScrollBar *self) {
1 if(self->state.position == self->position()) return;
2 self->state.position = self->position();
3 if(self->onChange) self->onChange();
4 }
5
6 Geometry pHorizontalScrollBar::minimumGeometry() {
7 return { 0, 0, 0, 20 };
8 }
9
10 unsigned pHorizontalScrollBar::position() {
11 return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget));
12 }
13
14 void pHorizontalScrollBar::setLength(unsigned length) {
15 length += length == 0;
16 gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
17 gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
18 }
19
20 void pHorizontalScrollBar::setPosition(unsigned position) {
21 gtk_range_set_value(GTK_RANGE(gtkWidget), position);
22 }
23
24 void pHorizontalScrollBar::constructor() {
25 gtkWidget = gtk_hscrollbar_new(0);
26 setLength(101);
27 g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalScrollBar_change), (gpointer)&horizontalScrollBar);
28 }
1414 void pHorizontalSlider::setLength(unsigned length) {
1515 length += length == 0;
1616 gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
17 gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
1718 }
1819
1920 void pHorizontalSlider::setPosition(unsigned position) {
2324 void pHorizontalSlider::constructor() {
2425 gtkWidget = gtk_hscale_new_with_range(0, 100, 1);
2526 gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false);
27 setLength(101);
2628 g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)&horizontalSlider);
2729 }
1212 }
1313
1414 void pLineEdit::setEditable(bool editable) {
15 gtk_entry_set_editable(GTK_ENTRY(gtkWidget), editable);
15 gtk_editable_set_editable(GTK_EDITABLE(gtkWidget), editable);
1616 }
1717
1818 void pLineEdit::setText(const string &text) {
0 static void VerticalScrollBar_change(VerticalScrollBar *self) {
1 if(self->state.position == self->position()) return;
2 self->state.position = self->position();
3 if(self->onChange) self->onChange();
4 }
5
6 Geometry pVerticalScrollBar::minimumGeometry() {
7 return { 0, 0, 20, 0 };
8 }
9
10 unsigned pVerticalScrollBar::position() {
11 return (unsigned)gtk_range_get_value(GTK_RANGE(gtkWidget));
12 }
13
14 void pVerticalScrollBar::setLength(unsigned length) {
15 length += length == 0;
16 gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
17 gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
18 }
19
20 void pVerticalScrollBar::setPosition(unsigned position) {
21 gtk_range_set_value(GTK_RANGE(gtkWidget), position);
22 }
23
24 void pVerticalScrollBar::constructor() {
25 gtkWidget = gtk_vscrollbar_new(0);
26 setLength(101);
27 g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalScrollBar_change), (gpointer)&verticalScrollBar);
28 }
1414 void pVerticalSlider::setLength(unsigned length) {
1515 length += length == 0;
1616 gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
17 gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
1718 }
1819
1920 void pVerticalSlider::setPosition(unsigned position) {
2324 void pVerticalSlider::constructor() {
2425 gtkWidget = gtk_vscale_new_with_range(0, 100, 1);
2526 gtk_scale_set_draw_value(GTK_SCALE(gtkWidget), false);
27 setLength(101);
2628 g_signal_connect_swapped(G_OBJECT(gtkWidget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)&verticalSlider);
2729 }
00 uintptr_t pViewport::handle() {
1 return GDK_WINDOW_XID(gtkWidget->window);
1 return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget));
22 }
33
44 void pViewport::constructor() {
00 static void Action_setFont(GtkWidget *widget, gpointer font);
11 static void Widget_setFont(GtkWidget *widget, gpointer font);
22
3 static gint Window_close(Window *window) {
3 static gint Window_close(GtkWidget *widget, GdkEvent *event, Window *window) {
44 if(window->onClose) window->onClose();
55 window->setVisible(false);
66 return true;
77 }
88
9 static gboolean Window_configure(Window *window) {
9 static gboolean Window_expose(GtkWidget *widget, GdkEvent *event, Window *window) {
10 cairo_t *context = gdk_cairo_create(widget->window);
11
12 Color color = window->backgroundColor();
13 double red = (double)color.red / 255.0;
14 double green = (double)color.green / 255.0;
15 double blue = (double)color.blue / 255.0;
16 double alpha = (double)color.alpha / 255.0;
17
18 if(gdk_screen_is_composited(gdk_screen_get_default())) {
19 cairo_set_source_rgba(context, red, green, blue, alpha);
20 } else {
21 cairo_set_source_rgb(context, red, green, blue);
22 }
23
24 cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
25 cairo_paint(context);
26 cairo_destroy(context);
27
28 return false;
29 }
30
31 static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *window) {
1032 if(gtk_widget_get_realized(window->p.widget) == false) return false;
33 GdkWindow *gdkWindow = gtk_widget_get_window(widget);
1134
1235 //update geometry settings
13 Display *display = XOpenDisplay(0);
14 XWindowAttributes attributes, parentAttributes;
15 XGetWindowAttributes(display, GDK_WINDOW_XID(window->p.widget->window), &attributes);
16 X11Window rootWindow, parentWindow, *childWindow = 0;
17 unsigned int childCount;
18 XQueryTree(display, GDK_WINDOW_XID(window->p.widget->window), &rootWindow, &parentWindow, &childWindow, &childCount);
19 XGetWindowAttributes(display, parentWindow, &parentAttributes);
20 if(childWindow) XFree(childWindow);
21 XCloseDisplay(display);
22
23 settings.frameGeometryX = attributes.x;
24 settings.frameGeometryY = attributes.y;
25 settings.frameGeometryWidth = parentAttributes.width - attributes.width;
26 settings.frameGeometryHeight = parentAttributes.height - attributes.height;
27
28 GtkAllocation menuAllocation, statusAllocation;
29 gtk_widget_get_allocation(window->p.menu, &menuAllocation);
30 gtk_widget_get_allocation(window->p.status, &statusAllocation);
31
32 if(menuAllocation.height > 1) settings.menuGeometryHeight = menuAllocation.height;
33 if(statusAllocation.height > 1) settings.statusGeometryHeight = statusAllocation.height;
34
35 //calculate current window position
36 signed eventX = parentAttributes.x + attributes.x;
37 signed eventY = parentAttributes.y + attributes.y + window->p.menuHeight();
38 unsigned eventWidth = attributes.width;
39 unsigned eventHeight = attributes.height - window->p.menuHeight() - window->p.statusHeight();
36 GdkRectangle border, client;
37 gdk_window_get_frame_extents(gdkWindow, &border);
38 gdk_window_get_geometry(gdkWindow, 0, 0, &client.width, &client.height, 0);
39 gdk_window_get_origin(gdkWindow, &client.x, &client.y);
40
41 settings.frameGeometryX = client.x - border.x;
42 settings.frameGeometryY = client.y - border.y;
43 settings.frameGeometryWidth = border.width - client.width;
44 settings.frameGeometryHeight = border.height - client.height;
4045
4146 //move
42 if(window->p.locked == false && window->state.fullScreen == false) {
43 if(window->state.geometry.x != eventX || window->state.geometry.y != eventY) {
44 window->state.geometry.x = eventX;
45 window->state.geometry.y = eventY;
46 }
47 }
48
49 if(window->onMove) window->onMove();
47 if(event->configure.x != window->p.lastConfigure.x
48 || event->configure.y != window->p.lastConfigure.y
49 ) {
50 if(window->state.fullScreen == false) {
51 window->state.geometry.x = client.x;
52 window->state.geometry.y = client.y + window->p.menuHeight();
53 }
54 if(window->p.locked == false && window->onMove) window->onMove();
55 }
5056
5157 //size
52 if(window->p.locked == false && window->state.fullScreen == false) {
53 if(window->state.geometry.width != eventWidth || window->state.geometry.height != eventHeight) {
54 window->state.geometry.width = eventWidth;
55 window->state.geometry.height = eventHeight;
56 }
57 }
58
59 foreach(layout, window->state.layout) {
60 Geometry geometry = window->geometry();
61 geometry.x = geometry.y = 0;
62 layout.setGeometry(geometry);
63 }
64
65 if(window->onSize) window->onSize();
66
58 if(event->configure.width != window->p.lastConfigure.width
59 || event->configure.height != window->p.lastConfigure.height
60 ) {
61 if(window->state.fullScreen == false) {
62 window->state.geometry.width = client.width;
63 window->state.geometry.height = client.height - window->p.menuHeight() - window->p.statusHeight();
64 }
65
66 foreach(layout, window->state.layout) {
67 Geometry geometry = window->geometry();
68 geometry.x = geometry.y = 0;
69 layout.setGeometry(geometry);
70 }
71
72 if(window->p.locked == false && window->onSize) window->onSize();
73 }
74
75 window->p.lastConfigure = event->configure;
6776 return false;
6877 }
6978
7685
7786 void pWindow::append(Menu &subMenu) {
7887 if(window.state.menuFont) subMenu.p.setFont(*window.state.menuFont);
79 gtk_menu_bar_append(menu, subMenu.p.widget);
88 gtk_menu_shell_append(GTK_MENU_SHELL(menu), subMenu.p.widget);
8089 gtk_widget_show(subMenu.p.widget);
8190 }
8291
8796 }
8897 gtk_fixed_put(GTK_FIXED(formContainer), widget.p.gtkWidget, 0, 0);
8998 widget.setVisible();
99 }
100
101 Color pWindow::backgroundColor() {
102 if(window.state.backgroundColorOverride) return window.state.backgroundColor;
103 GdkColor color = widget->style->bg[GTK_STATE_NORMAL];
104 return { (uint8_t)(color.red >> 8), (uint8_t)(color.green >> 8), (uint8_t)(color.blue >> 8), 255 };
90105 }
91106
92107 Geometry pWindow::frameMargin() {
110125 return window.state.geometry;
111126 }
112127
113 void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
114 GdkColor color;
115 color.pixel = (red << 16) | (green << 8) | (blue << 0);
116 color.red = (red << 8) | (red << 0);
117 color.green = (green << 8) | (green << 0);
118 color.blue = (blue << 8) | (blue << 0);
119 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &color);
128 void pWindow::setBackgroundColor(const Color &color) {
129 GdkColor gdkColor;
130 gdkColor.pixel = (color.red << 16) | (color.green << 8) | (color.blue << 0);
131 gdkColor.red = (color.red << 8) | (color.red << 0);
132 gdkColor.green = (color.green << 8) | (color.green << 0);
133 gdkColor.blue = (color.blue << 8) | (color.blue << 0);
134 gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &gdkColor);
120135 }
121136
122137 void pWindow::setFocused() {
128143 gtk_window_unfullscreen(GTK_WINDOW(widget));
129144 gtk_window_set_resizable(GTK_WINDOW(widget), window.state.resizable);
130145 gtk_window_set_decorated(GTK_WINDOW(widget), true);
131 locked = true;
132146 for(unsigned n = 0; n < 4; n++) {
133147 setGeometry(window.state.geometry);
134148 gtk_widget_set_size_request(widget, -1, -1);
135149 OS::processEvents();
136150 usleep(2000);
137151 }
138 locked = false;
139152 } else {
140153 gtk_window_fullscreen(GTK_WINDOW(widget));
141154 gtk_window_set_decorated(GTK_WINDOW(widget), false);
197210 }
198211
199212 void pWindow::constructor() {
213 memset(&lastConfigure, 0, sizeof(GdkEventConfigure));
200214 widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
215
216 if(gdk_screen_is_composited(gdk_screen_get_default())) {
217 gtk_widget_set_colormap(widget, gdk_screen_get_rgba_colormap(gdk_screen_get_default()));
218 } else {
219 gtk_widget_set_colormap(widget, gdk_screen_get_rgb_colormap(gdk_screen_get_default()));
220 }
221
201222 gtk_window_set_resizable(GTK_WINDOW(widget), true);
202223 gtk_widget_set_app_paintable(widget, true);
203224 gtk_widget_add_events(widget, GDK_CONFIGURE);
223244 setTitle("");
224245 setGeometry(window.state.geometry);
225246
226 g_signal_connect_swapped(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
227 g_signal_connect_swapped(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
247 g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
248 g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window);
249 g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
228250 }
229251
230252 unsigned pWindow::menuHeight() {
+0
-109
snespurify/phoenix/nall/Makefile less more
0 # Makefile
1 # author: byuu
2 # license: public domain
3
4 [A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
5 [a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z
6 [0-9] = 0 1 2 3 4 5 6 7 8 9
7 [markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ?
8 [all] = $([A-Z]) $([a-z]) $([0-9]) $([markup])
9 [space] :=
10 [space] +=
11
12 #####
13 # platform detection
14 #####
15
16 ifeq ($(platform),)
17 uname := $(shell uname -a)
18 ifeq ($(uname),)
19 platform := win
20 delete = del $(subst /,\,$1)
21 else ifneq ($(findstring Darwin,$(uname)),)
22 platform := osx
23 delete = rm -f $1
24 else
25 platform := x
26 delete = rm -f $1
27 endif
28 endif
29
30 ifeq ($(compiler),)
31 ifeq ($(platform),win)
32 compiler := gcc
33 else ifeq ($(platform),osx)
34 compiler := gcc-mp-4.5
35 else
36 compiler := gcc-4.5
37 endif
38 endif
39
40 ifeq ($(prefix),)
41 prefix := /usr/local
42 endif
43
44 #####
45 # function rwildcard(directory, pattern)
46 #####
47 rwildcard = \
48 $(strip \
49 $(filter $(if $2,$2,%), \
50 $(foreach f, \
51 $(wildcard $1*), \
52 $(eval t = $(call rwildcard,$f/)) \
53 $(if $t,$t,$f) \
54 ) \
55 ) \
56 )
57
58 #####
59 # function strtr(source, from, to)
60 #####
61 strtr = \
62 $(eval __temp := $1) \
63 $(strip \
64 $(foreach c, \
65 $(join $(addsuffix :,$2),$3), \
66 $(eval __temp := \
67 $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \
68 ) \
69 ) \
70 $(__temp) \
71 )
72
73 #####
74 # function strupper(source)
75 #####
76 strupper = $(call strtr,$1,$([a-z]),$([A-Z]))
77
78 #####
79 # function strlower(source)
80 #####
81 strlower = $(call strtr,$1,$([A-Z]),$([a-z]))
82
83 #####
84 # function strlen(source)
85 #####
86 strlen = \
87 $(eval __temp := $(subst $([space]),_,$1)) \
88 $(words \
89 $(strip \
90 $(foreach c, \
91 $([all]), \
92 $(eval __temp := \
93 $(subst $c,$c ,$(__temp)) \
94 ) \
95 ) \
96 $(__temp) \
97 ) \
98 )
99
100 #####
101 # function streq(source)
102 #####
103 streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1)
104
105 #####
106 # function strne(source)
107 #####
108 strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,)
+0
-17
snespurify/phoenix/nall/algorithm.hpp less more
0 #ifndef NALL_ALGORITHM_HPP
1 #define NALL_ALGORITHM_HPP
2
3 #undef min
4 #undef max
5
6 namespace nall {
7 template<typename T, typename U> T min(const T &t, const U &u) {
8 return t < u ? t : u;
9 }
10
11 template<typename T, typename U> T max(const T &t, const U &u) {
12 return t > u ? t : u;
13 }
14 }
15
16 #endif
+0
-74
snespurify/phoenix/nall/any.hpp less more
0 #ifndef NALL_ANY_HPP
1 #define NALL_ANY_HPP
2
3 #include <typeinfo>
4 #include <type_traits>
5 #include <nall/static.hpp>
6
7 namespace nall {
8 class any {
9 public:
10 bool empty() const { return container; }
11 const std::type_info& type() const { return container ? container->type() : typeid(void); }
12
13 template<typename T> any& operator=(const T& value_) {
14 typedef typename static_if<
15 std::is_array<T>::value,
16 typename std::remove_extent<typename std::add_const<T>::type>::type*,
17 T
18 >::type auto_t;
19
20 if(type() == typeid(auto_t)) {
21 static_cast<holder<auto_t>*>(container)->value = (auto_t)value_;
22 } else {
23 if(container) delete container;
24 container = new holder<auto_t>((auto_t)value_);
25 }
26
27 return *this;
28 }
29
30 any() : container(0) {}
31 template<typename T> any(const T& value_) : container(0) { operator=(value_); }
32
33 private:
34 struct placeholder {
35 virtual const std::type_info& type() const = 0;
36 } *container;
37
38 template<typename T> struct holder : placeholder {
39 T value;
40 const std::type_info& type() const { return typeid(T); }
41 holder(const T& value_) : value(value_) {}
42 };
43
44 template<typename T> friend T any_cast(any&);
45 template<typename T> friend T any_cast(const any&);
46 template<typename T> friend T* any_cast(any*);
47 template<typename T> friend const T* any_cast(const any*);
48 };
49
50 template<typename T> T any_cast(any &value) {
51 typedef typename std::remove_reference<T>::type nonref;
52 if(value.type() != typeid(nonref)) throw;
53 return static_cast<any::holder<nonref>*>(value.container)->value;
54 }
55
56 template<typename T> T any_cast(const any &value) {
57 typedef const typename std::remove_reference<T>::type nonref;
58 if(value.type() != typeid(nonref)) throw;
59 return static_cast<any::holder<nonref>*>(value.container)->value;
60 }
61
62 template<typename T> T* any_cast(any *value) {
63 if(!value || value->type() != typeid(T)) return 0;
64 return &static_cast<any::holder<T>*>(value->container)->value;
65 }
66
67 template<typename T> const T* any_cast(const any *value) {
68 if(!value || value->type() != typeid(T)) return 0;
69 return &static_cast<any::holder<T>*>(value->container)->value;
70 }
71 }
72
73 #endif
+0
-141
snespurify/phoenix/nall/array.hpp less more
0 #ifndef NALL_ARRAY_HPP
1 #define NALL_ARRAY_HPP
2
3 #include <stdlib.h>
4 #include <initializer_list>
5 #include <type_traits>
6 #include <utility>
7 #include <nall/algorithm.hpp>
8 #include <nall/bit.hpp>
9 #include <nall/concept.hpp>
10 #include <nall/foreach.hpp>
11 #include <nall/utility.hpp>
12
13 namespace nall {
14 //dynamic vector array
15 //neither constructor nor destructor is ever invoked;
16 //thus, this should only be used for POD objects.
17 template<typename T> class array {
18 protected:
19 T *pool;
20 unsigned poolsize, buffersize;
21
22 public:
23 unsigned size() const { return buffersize; }
24 unsigned capacity() const { return poolsize; }
25
26 void reset() {
27 if(pool) free(pool);
28 pool = 0;
29 poolsize = 0;
30 buffersize = 0;
31 }
32
33 void reserve(unsigned newsize) {
34 if(newsize == poolsize) return;
35
36 pool = (T*)realloc(pool, newsize * sizeof(T));
37 poolsize = newsize;
38 buffersize = min(buffersize, newsize);
39 }
40
41 void resize(unsigned newsize) {
42 if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2
43 buffersize = newsize;
44 }
45
46 T* get(unsigned minsize = 0) {
47 if(minsize > buffersize) resize(minsize);
48 if(minsize > buffersize) throw "array[] out of bounds";
49 return pool;
50 }
51
52 void append(const T data) {
53 operator[](buffersize) = data;
54 }
55
56 template<typename U> void insert(unsigned index, const U list) {
57 unsigned listsize = container_size(list);
58 resize(buffersize + listsize);
59 memmove(pool + index + listsize, pool + index, (buffersize - index) * sizeof(T));
60 foreach(item, list) pool[index++] = item;
61 }
62
63 void insert(unsigned index, const T item) {
64 insert(index, array<T>{ item });
65 }
66
67 void remove(unsigned index, unsigned count = 1) {
68 for(unsigned i = index; count + i < buffersize; i++) {
69 pool[i] = pool[count + i];
70 }
71 if(count + index >= buffersize) resize(index); //every element >= index was removed
72 else resize(buffersize - count);
73 }
74
75 optional<unsigned> find(const T data) {
76 for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return { true, i };
77 return { false, 0 };
78 }
79
80 void clear() {
81 memset(pool, 0, buffersize * sizeof(T));
82 }
83
84 array() : pool(0), poolsize(0), buffersize(0) {
85 }
86
87 array(std::initializer_list<T> list) : pool(0), poolsize(0), buffersize(0) {
88 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
89 }
90
91 ~array() {
92 reset();
93 }
94
95 //copy
96 array& operator=(const array &source) {
97 if(pool) free(pool);
98 buffersize = source.buffersize;
99 poolsize = source.poolsize;
100 pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size,
101 memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects
102 return *this;
103 }
104
105 array(const array &source) : pool(0), poolsize(0), buffersize(0) {
106 operator=(source);
107 }
108
109 //move
110 array& operator=(array &&source) {
111 if(pool) free(pool);
112 pool = source.pool;
113 poolsize = source.poolsize;
114 buffersize = source.buffersize;
115 source.pool = 0;
116 source.reset();
117 return *this;
118 }
119
120 array(array &&source) : pool(0), poolsize(0), buffersize(0) {
121 operator=(std::move(source));
122 }
123
124 //index
125 inline T& operator[](unsigned index) {
126 if(index >= buffersize) resize(index + 1);
127 if(index >= buffersize) throw "array[] out of bounds";
128 return pool[index];
129 }
130
131 inline const T& operator[](unsigned index) const {
132 if(index >= buffersize) throw "array[] out of bounds";
133 return pool[index];
134 }
135 };
136
137 template<typename T> struct has_size<array<T>> { enum { value = true }; };
138 }
139
140 #endif
+0
-90
snespurify/phoenix/nall/base64.hpp less more
0 #ifndef NALL_BASE64_HPP
1 #define NALL_BASE64_HPP
2
3 #include <string.h>
4 #include <nall/stdint.hpp>
5
6 namespace nall {
7 class base64 {
8 public:
9 static bool encode(char *&output, const uint8_t* input, unsigned inlength) {
10 output = new char[inlength * 8 / 6 + 6]();
11
12 unsigned i = 0, o = 0;
13 while(i < inlength) {
14 switch(i % 3) {
15 case 0: {
16 output[o++] = enc(input[i] >> 2);
17 output[o] = enc((input[i] & 3) << 4);
18 } break;
19
20 case 1: {
21 uint8_t prev = dec(output[o]);
22 output[o++] = enc(prev + (input[i] >> 4));
23 output[o] = enc((input[i] & 15) << 2);
24 } break;
25
26 case 2: {
27 uint8_t prev = dec(output[o]);
28 output[o++] = enc(prev + (input[i] >> 6));
29 output[o++] = enc(input[i] & 63);
30 } break;
31 }
32
33 i++;
34 }
35
36 return true;
37 }
38
39 static bool decode(uint8_t *&output, unsigned &outlength, const char *input) {
40 unsigned inlength = strlen(input), infix = 0;
41 output = new uint8_t[inlength]();
42
43 unsigned i = 0, o = 0;
44 while(i < inlength) {
45 uint8_t x = dec(input[i]);
46
47 switch(i++ & 3) {
48 case 0: {
49 output[o] = x << 2;
50 } break;
51
52 case 1: {
53 output[o++] |= x >> 4;
54 output[o] = (x & 15) << 4;
55 } break;
56
57 case 2: {
58 output[o++] |= x >> 2;
59 output[o] = (x & 3) << 6;
60 } break;
61
62 case 3: {
63 output[o++] |= x;
64 } break;
65 }
66 }
67
68 outlength = o;
69 return true;
70 }
71
72 private:
73 static char enc(uint8_t n) {
74 static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
75 return lookup_table[n & 63];
76 }
77
78 static uint8_t dec(char n) {
79 if(n >= 'A' && n <= 'Z') return n - 'A';
80 if(n >= 'a' && n <= 'z') return n - 'a' + 26;
81 if(n >= '0' && n <= '9') return n - '0' + 52;
82 if(n == '-') return 62;
83 if(n == '_') return 63;
84 return 0;
85 }
86 };
87 }
88
89 #endif
+0
-51
snespurify/phoenix/nall/bit.hpp less more
0 #ifndef NALL_BIT_HPP
1 #define NALL_BIT_HPP
2
3 namespace nall {
4 template<int bits> inline unsigned uclamp(const unsigned x) {
5 enum { y = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) };
6 return y + ((x - y) & -(x < y)); //min(x, y);
7 }
8
9 template<int bits> inline unsigned uclip(const unsigned x) {
10 enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) };
11 return (x & m);
12 }
13
14 template<int bits> inline signed sclamp(const signed x) {
15 enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 };
16 return (x > m) ? m : (x < -b) ? -b : x;
17 }
18
19 template<int bits> inline signed sclip(const signed x) {
20 enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
21 return ((x & m) ^ b) - b;
22 }
23
24 namespace bit {
25 //lowest(0b1110) == 0b0010
26 template<typename T> inline T lowest(const T x) {
27 return x & -x;
28 }
29
30 //clear_lowest(0b1110) == 0b1100
31 template<typename T> inline T clear_lowest(const T x) {
32 return x & (x - 1);
33 }
34
35 //set_lowest(0b0101) == 0b0111
36 template<typename T> inline T set_lowest(const T x) {
37 return x | (x + 1);
38 }
39
40 //round up to next highest single bit:
41 //round(15) == 16, round(16) == 16, round(17) == 32
42 inline unsigned round(unsigned x) {
43 if((x & (x - 1)) == 0) return x;
44 while(x & (x - 1)) x &= x - 1;
45 return x << 1;
46 }
47 }
48 }
49
50 #endif
+0
-34
snespurify/phoenix/nall/concept.hpp less more
0 #ifndef NALL_CONCEPT_HPP
1 #define NALL_CONCEPT_HPP
2
3 #include <nall/static.hpp>
4 #include <nall/utility.hpp>
5
6 namespace nall {
7 //unsigned count() const;
8 template<typename T> struct has_count { enum { value = false }; };
9
10 //unsigned length() const;
11 template<typename T> struct has_length { enum { value = false }; };
12
13 //unsigned size() const;
14 template<typename T> struct has_size { enum { value = false }; };
15
16 template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_count<T>>::type = 0) {
17 return object.count();
18 }
19
20 template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_length<T>>::type = 0) {
21 return object.length();
22 }
23
24 template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_size<T>>::type = 0) {
25 return object.size();
26 }
27
28 template<typename T> unsigned container_size(const T& object, typename mp_enable_if<std::is_array<T>>::type = 0) {
29 return sizeof(T) / sizeof(typename std::remove_extent<T>::type);
30 }
31 }
32
33 #endif
+0
-123
snespurify/phoenix/nall/config.hpp less more
0 #ifndef NALL_CONFIG_HPP
1 #define NALL_CONFIG_HPP
2
3 #include <nall/file.hpp>
4 #include <nall/string.hpp>
5 #include <nall/vector.hpp>
6
7 namespace nall {
8 namespace configuration_traits {
9 template<typename T> struct is_boolean { enum { value = false }; };
10 template<> struct is_boolean<bool> { enum { value = true }; };
11
12 template<typename T> struct is_signed { enum { value = false }; };
13 template<> struct is_signed<signed> { enum { value = true }; };
14
15 template<typename T> struct is_unsigned { enum { value = false }; };
16 template<> struct is_unsigned<unsigned> { enum { value = true }; };
17
18 template<typename T> struct is_double { enum { value = false }; };
19 template<> struct is_double<double> { enum { value = true }; };
20
21 template<typename T> struct is_string { enum { value = false }; };
22 template<> struct is_string<string> { enum { value = true }; };
23 }
24
25 class configuration {
26 public:
27 enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t };
28 struct item_t {
29 uintptr_t data;
30 string name;
31 string desc;
32 type_t type;
33
34 string get() const {
35 switch(type) {
36 case boolean_t: return string() << *(bool*)data;
37 case signed_t: return string() << *(signed*)data;
38 case unsigned_t: return string() << *(unsigned*)data;
39 case double_t: return string() << *(double*)data;
40 case string_t: return string() << "\"" << *(string*)data << "\"";
41 }
42 return "???";
43 }
44
45 void set(string s) {
46 switch(type) {
47 case boolean_t: *(bool*)data = (s == "true"); break;
48 case signed_t: *(signed*)data = integer(s); break;
49 case unsigned_t: *(unsigned*)data = decimal(s); break;
50 case double_t: *(double*)data = fp(s); break;
51 case string_t: s.trim("\""); *(string*)data = s; break;
52 }
53 }
54 };
55 linear_vector<item_t> list;
56
57 template<typename T>
58 void attach(T &data, const char *name, const char *desc = "") {
59 unsigned n = list.size();
60 list[n].data = (uintptr_t)&data;
61 list[n].name = name;
62 list[n].desc = desc;
63
64 if(configuration_traits::is_boolean<T>::value) list[n].type = boolean_t;
65 else if(configuration_traits::is_signed<T>::value) list[n].type = signed_t;
66 else if(configuration_traits::is_unsigned<T>::value) list[n].type = unsigned_t;
67 else if(configuration_traits::is_double<T>::value) list[n].type = double_t;
68 else if(configuration_traits::is_string<T>::value) list[n].type = string_t;
69 else list[n].type = unknown_t;
70 }
71
72 virtual bool load(const char *filename) {
73 string data;
74 if(data.readfile(filename) == true) {
75 data.replace("\r", "");
76 lstring line;
77 line.split("\n", data);
78
79 for(unsigned i = 0; i < line.size(); i++) {
80 if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0;
81 if(!qstrpos(line[i], " = ")) continue;
82
83 lstring part;
84 part.qsplit(" = ", line[i]);
85 part[0].trim();
86 part[1].trim();
87
88 for(unsigned n = 0; n < list.size(); n++) {
89 if(part[0] == list[n].name) {
90 list[n].set(part[1]);
91 break;
92 }
93 }
94 }
95
96 return true;
97 } else {
98 return false;
99 }
100 }
101
102 virtual bool save(const char *filename) const {
103 file fp;
104 if(fp.open(filename, file::mode::write)) {
105 for(unsigned i = 0; i < list.size(); i++) {
106 string output;
107 output << list[i].name << " = " << list[i].get();
108 if(list[i].desc != "") output << " # " << list[i].desc;
109 output << "\r\n";
110 fp.print(output);
111 }
112
113 fp.close();
114 return true;
115 } else {
116 return false;
117 }
118 }
119 };
120 }
121
122 #endif
+0
-66
snespurify/phoenix/nall/crc32.hpp less more
0 #ifndef NALL_CRC32_HPP
1 #define NALL_CRC32_HPP
2
3 #include <nall/stdint.hpp>
4
5 namespace nall {
6 const uint32_t crc32_table[256] = {
7 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
8 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
9 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
10 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
11 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
12 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
13 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
14 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
15 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
16 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
17 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
18 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
19 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
20 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
21 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
22 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
23 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
24 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
25 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
26 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
27 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
28 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
29 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
30 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
31 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
32 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
33 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
34 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
35 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
36 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
37 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
38 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
39 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
40 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
41 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
42 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
43 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
44 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
45 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
46 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
47 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
48 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
49 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
50 };
51
52 inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) {
53 return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff];
54 }
55
56 inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) {
57 uint32_t crc32 = ~0;
58 for(unsigned i = 0; i < length; i++) {
59 crc32 = crc32_adjust(crc32, data[i]);
60 }
61 return ~crc32;
62 }
63 }
64
65 #endif
+0
-30
snespurify/phoenix/nall/detect.hpp less more
0 #ifndef NALL_DETECT_HPP
1 #define NALL_DETECT_HPP
2
3 /* Compiler detection */
4
5 #if defined(__GNUC__)
6 #define COMPILER_GCC
7 #elif defined(_MSC_VER)
8 #define COMPILER_VISUALC
9 #endif
10
11 /* Platform detection */
12
13 #if defined(_WIN32)
14 #define PLATFORM_WIN
15 #elif defined(__APPLE__)
16 #define PLATFORM_OSX
17 #elif defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
18 #define PLATFORM_X
19 #endif
20
21 /* Endian detection */
22
23 #if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64)
24 #define ARCH_LSB
25 #elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__)
26 #define ARCH_MSB
27 #endif
28
29 #endif
+0
-75
snespurify/phoenix/nall/dictionary.hpp less more
0 #ifndef NALL_DICTIONARY_HPP
1 #define NALL_DICTIONARY_HPP
2
3 #include <nall/array.hpp>
4 #include <nall/string.hpp>
5 #include <nall/utility.hpp>
6
7 namespace nall {
8 class dictionary {
9 public:
10 string operator[](const char *input) {
11 for(unsigned i = 0; i < index_input.size(); i++) {
12 if(index_input[i] == input) return index_output[i];
13 }
14
15 //no match, use input; remove input identifier, if one exists
16 if(strbegin(input, "{{")) {
17 if(auto pos = strpos(input, "}}")) {
18 string temp = substr(input, pos() + 2);
19 return temp;
20 }
21 }
22
23 return input;
24 }
25
26 bool import(const char *filename) {
27 string data;
28 if(data.readfile(filename) == false) return false;
29 data.ltrim<1>("\xef\xbb\xbf"); //remove UTF-8 marker, if it exists
30 data.replace("\r", "");
31
32 lstring line;
33 line.split("\n", data);
34 for(unsigned i = 0; i < line.size(); i++) {
35 lstring part;
36 //format: "Input" = "Output"
37 part.qsplit("=", line[i]);
38 if(part.size() != 2) continue;
39
40 //remove whitespace
41 part[0].trim();
42 part[1].trim();
43
44 //remove quotes
45 part[0].trim<1>("\"");
46 part[1].trim<1>("\"");
47
48 unsigned n = index_input.size();
49 index_input[n] = part[0];
50 index_output[n] = part[1];
51 }
52
53 return true;
54 }
55
56 void reset() {
57 index_input.reset();
58 index_output.reset();
59 }
60
61 ~dictionary() {
62 reset();
63 }
64
65 dictionary& operator=(const dictionary&) = delete;
66 dictionary(const dictionary&) = delete;
67
68 protected:
69 lstring index_input;
70 lstring index_output;
71 };
72 }
73
74 #endif
+0
-151
snespurify/phoenix/nall/directory.hpp less more
0 #ifndef NALL_DIRECTORY_HPP
1 #define NALL_DIRECTORY_HPP
2
3 #include <nall/foreach.hpp>
4 #include <nall/sort.hpp>
5 #include <nall/string.hpp>
6
7 #if defined(_WIN32)
8 #include <nall/utf8.hpp>
9 #else
10 #include <dirent.h>
11 #include <stdio.h>
12 #include <sys/types.h>
13 #endif
14
15 namespace nall {
16
17 struct directory {
18 static bool exists(const string &pathname);
19 static lstring folders(const string &pathname, const string &pattern = "*");
20 static lstring files(const string &pathname, const string &pattern = "*");
21 static lstring contents(const string &pathname, const string &pattern = "*");
22 };
23
24 #if defined(_WIN32)
25 inline bool directory::exists(const string &pathname) {
26 DWORD result = GetFileAttributes(utf16_t(pathname));
27 if(result == INVALID_FILE_ATTRIBUTES) return false;
28 return (result & FILE_ATTRIBUTE_DIRECTORY);
29 }
30
31 inline lstring directory::folders(const string &pathname, const string &pattern) {
32 lstring list;
33 string path = pathname;
34 path.transform("/", "\\");
35 if(!strend(path, "\\")) path.append("\\");
36 path.append("*");
37 HANDLE handle;
38 WIN32_FIND_DATA data;
39 handle = FindFirstFile(utf16_t(path), &data);
40 if(handle != INVALID_HANDLE_VALUE) {
41 if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
42 if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
43 string name = utf8_t(data.cFileName);
44 if(wildcard(name, pattern)) list.append(string(name, "/"));
45 }
46 }
47 while(FindNextFile(handle, &data) != false) {
48 if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
49 if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
50 string name = utf8_t(data.cFileName);
51 if(wildcard(name, pattern)) list.append(string(name, "/"));
52 }
53 }
54 }
55 FindClose(handle);
56 }
57 if(list.size() > 0) sort(&list[0], list.size());
58 return list;
59 }
60
61 inline lstring directory::files(const string &pathname, const string &pattern) {
62 lstring list;
63 string path = pathname;
64 path.transform("/", "\\");
65 if(!strend(path, "\\")) path.append("\\");
66 path.append("*");
67 HANDLE handle;
68 WIN32_FIND_DATA data;
69 handle = FindFirstFile(utf16_t(path), &data);
70 if(handle != INVALID_HANDLE_VALUE) {
71 if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
72 string name = utf8_t(data.cFileName);
73 if(wildcard(name, pattern)) list.append(name);
74 }
75 while(FindNextFile(handle, &data) != false) {
76 if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
77 string name = utf8_t(data.cFileName);
78 if(wildcard(name, pattern)) list.append(name);
79 }
80 }
81 FindClose(handle);
82 }
83 if(list.size() > 0) sort(&list[0], list.size());
84 return list;
85 }
86
87 inline lstring directory::contents(const string &pathname, const string &pattern) {
88 lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files
89 lstring files = directory::files(pathname, pattern);
90 foreach(file, files) folders.append(file);
91 return folders;
92 }
93 #else
94 inline bool directory::exists(const string &pathname) {
95 DIR *dp = opendir(pathname);
96 if(!dp) return false;
97 closedir(dp);
98 return true;
99 }
100
101 inline lstring directory::folders(const string &pathname, const string &pattern) {
102 lstring list;
103 DIR *dp;
104 struct dirent *ep;
105 dp = opendir(pathname);
106 if(dp) {
107 while(ep = readdir(dp)) {
108 if(!strcmp(ep->d_name, ".")) continue;
109 if(!strcmp(ep->d_name, "..")) continue;
110 if(ep->d_type & DT_DIR) {
111 if(wildcard(ep->d_name, pattern)) list.append(string(ep->d_name, "/"));
112 }
113 }
114 closedir(dp);
115 }
116 if(list.size() > 0) sort(&list[0], list.size());
117 return list;
118
119 }
120
121 inline lstring directory::files(const string &pathname, const string &pattern) {
122 lstring list;
123 DIR *dp;
124 struct dirent *ep;
125 dp = opendir(pathname);
126 if(dp) {
127 while(ep = readdir(dp)) {
128 if(!strcmp(ep->d_name, ".")) continue;
129 if(!strcmp(ep->d_name, "..")) continue;
130 if((ep->d_type & DT_DIR) == 0) {
131 if(wildcard(ep->d_name, pattern)) list.append(ep->d_name);
132 }
133 }
134 closedir(dp);
135 }
136 if(list.size() > 0) sort(&list[0], list.size());
137 return list;
138 }
139
140 inline lstring directory::contents(const string &pathname, const string &pattern) {
141 lstring folders = directory::folders(pathname); //pattern search of contents() should only filter files
142 lstring files = directory::files(pathname, pattern);
143 foreach(file, files) folders.append(file);
144 return folders;
145 }
146 #endif
147
148 }
149
150 #endif
+0
-115
snespurify/phoenix/nall/dl.hpp less more
0 #ifndef NALL_DL_HPP
1 #define NALL_DL_HPP
2
3 //dynamic linking support
4
5 #include <nall/detect.hpp>
6 #include <nall/stdint.hpp>
7 #include <nall/string.hpp>
8 #include <nall/utility.hpp>
9
10 #if defined(PLATFORM_X) || defined(PLATFORM_OSX)
11 #include <dlfcn.h>
12 #elif defined(PLATFORM_WIN)
13 #include <windows.h>
14 #include <nall/utf8.hpp>
15 #endif
16
17 namespace nall {
18 struct library {
19 bool opened() const { return handle; }
20 bool open(const char*, const char* = "");
21 bool open_absolute(const char*);
22 void* sym(const char*);
23 void close();
24
25 library() : handle(0) {}
26 ~library() { close(); }
27
28 library& operator=(const library&) = delete;
29 library(const library&) = delete;
30
31 private:
32 uintptr_t handle;
33 };
34
35 #if defined(PLATFORM_X)
36 inline bool library::open(const char *name, const char *path) {
37 if(handle) close();
38 handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY);
39 if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY);
40 return handle;
41 }
42
43 inline bool library::open_absolute(const char *name) {
44 if(handle) close();
45 handle = (uintptr_t)dlopen(name, RTLD_LAZY);
46 return handle;
47 }
48
49 inline void* library::sym(const char *name) {
50 if(!handle) return 0;
51 return dlsym((void*)handle, name);
52 }
53
54 inline void library::close() {
55 if(!handle) return;
56 dlclose((void*)handle);
57 handle = 0;
58 }
59 #elif defined(PLATFORM_OSX)
60 inline bool library::open(const char *name, const char *path) {
61 if(handle) close();
62 handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY);
63 if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
64 return handle;
65 }
66
67 inline bool library::open_absolute(const char *name) {
68 if(handle) close();
69 handle = (uintptr_t)dlopen(name, RTLD_LAZY);
70 return handle;
71 }
72
73 inline void* library::sym(const char *name) {
74 if(!handle) return 0;
75 return dlsym((void*)handle, name);
76 }
77
78 inline void library::close() {
79 if(!handle) return;
80 dlclose((void*)handle);
81 handle = 0;
82 }
83 #elif defined(PLATFORM_WIN)
84 inline bool library::open(const char *name, const char *path) {
85 if(handle) close();
86 string filepath(path, *path && !strend(path, "/") && !strend(path, "\\") ? "\\" : "", name, ".dll");
87 handle = (uintptr_t)LoadLibraryW(utf16_t(filepath));
88 return handle;
89 }
90
91 inline bool library::open_absolute(const char *name) {
92 if(handle) close();
93 handle = (uintptr_t)LoadLibraryW(utf16_t(name));
94 return handle;
95 }
96
97 inline void* library::sym(const char *name) {
98 if(!handle) return 0;
99 return (void*)GetProcAddress((HMODULE)handle, name);
100 }
101
102 inline void library::close() {
103 if(!handle) return;
104 FreeLibrary((HMODULE)handle);
105 handle = 0;
106 }
107 #else
108 inline bool library::open(const char*, const char*) { return false; }
109 inline void* library::sym(const char*) { return 0; }
110 inline void library::close() {}
111 #endif
112 };
113
114 #endif
+0
-38
snespurify/phoenix/nall/endian.hpp less more
0 #ifndef NALL_ENDIAN_HPP
1 #define NALL_ENDIAN_HPP
2
3 #if !defined(ARCH_MSB)
4 //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201
5 #define order_lsb2(a,b) a,b
6 #define order_lsb3(a,b,c) a,b,c
7 #define order_lsb4(a,b,c,d) a,b,c,d
8 #define order_lsb5(a,b,c,d,e) a,b,c,d,e
9 #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f
10 #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
11 #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
12 #define order_msb2(a,b) b,a
13 #define order_msb3(a,b,c) c,b,a
14 #define order_msb4(a,b,c,d) d,c,b,a
15 #define order_msb5(a,b,c,d,e) e,d,c,b,a
16 #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a
17 #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
18 #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
19 #else
20 //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304
21 #define order_lsb2(a,b) b,a
22 #define order_lsb3(a,b,c) c,b,a
23 #define order_lsb4(a,b,c,d) d,c,b,a
24 #define order_lsb5(a,b,c,d,e) e,d,c,b,a
25 #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a
26 #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
27 #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
28 #define order_msb2(a,b) a,b
29 #define order_msb3(a,b,c) a,b,c
30 #define order_msb4(a,b,c,d) a,b,c,d
31 #define order_msb5(a,b,c,d,e) a,b,c,d,e
32 #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f
33 #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
34 #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
35 #endif
36
37 #endif
+0
-261
snespurify/phoenix/nall/file.hpp less more
0 #ifndef NALL_FILE_HPP
1 #define NALL_FILE_HPP
2
3 #include <stdio.h>
4 #include <string.h>
5
6 #if !defined(_WIN32)
7 #include <unistd.h>
8 #else
9 #include <io.h>
10 #endif
11
12 #include <nall/stdint.hpp>
13 #include <nall/string.hpp>
14 #include <nall/utf8.hpp>
15 #include <nall/utility.hpp>
16
17 namespace nall {
18 inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) {
19 #if !defined(_WIN32)
20 return fopen(utf8_filename, mode);
21 #else
22 return _wfopen(utf16_t(utf8_filename), utf16_t(mode));
23 #endif
24 }
25
26 class file {
27 public:
28 enum class mode : unsigned { read, write, readwrite, writeread };
29 enum class index : unsigned { absolute, relative };
30
31 uint8_t read() {
32 if(!fp) return 0xff; //file not open
33 if(file_mode == mode::write) return 0xff; //reads not permitted
34 if(file_offset >= file_size) return 0xff; //cannot read past end of file
35 buffer_sync();
36 return buffer[(file_offset++) & buffer_mask];
37 }
38
39 uintmax_t readl(unsigned length = 1) {
40 uintmax_t data = 0;
41 for(int i = 0; i < length; i++) {
42 data |= (uintmax_t)read() << (i << 3);
43 }
44 return data;
45 }
46
47 uintmax_t readm(unsigned length = 1) {
48 uintmax_t data = 0;
49 while(length--) {
50 data <<= 8;
51 data |= read();
52 }
53 return data;
54 }
55
56 void read(uint8_t *buffer, unsigned length) {
57 while(length--) *buffer++ = read();
58 }
59
60 void write(uint8_t data) {
61 if(!fp) return; //file not open
62 if(file_mode == mode::read) return; //writes not permitted
63 buffer_sync();
64 buffer[(file_offset++) & buffer_mask] = data;
65 buffer_dirty = true;
66 if(file_offset > file_size) file_size = file_offset;
67 }
68
69 void writel(uintmax_t data, unsigned length = 1) {
70 while(length--) {
71 write(data);
72 data >>= 8;
73 }
74 }
75
76 void writem(uintmax_t data, unsigned length = 1) {
77 for(int i = length - 1; i >= 0; i--) {
78 write(data >> (i << 3));
79 }
80 }
81
82 void write(const uint8_t *buffer, unsigned length) {
83 while(length--) write(*buffer++);
84 }
85
86 template<typename... Args> void print(Args... args) {
87 string data(args...);
88 const char *p = data;
89 while(*p) write(*p++);
90 }
91
92 void flush() {
93 buffer_flush();
94 fflush(fp);
95 }
96
97 void seek(int offset, index index_ = index::absolute) {
98 if(!fp) return; //file not open
99 buffer_flush();
100
101 uintmax_t req_offset = file_offset;
102 switch(index_) {
103 case index::absolute: req_offset = offset; break;
104 case index::relative: req_offset += offset; break;
105 }
106
107 if(req_offset < 0) req_offset = 0; //cannot seek before start of file
108 if(req_offset > file_size) {
109 if(file_mode == mode::read) { //cannot seek past end of file
110 req_offset = file_size;
111 } else { //pad file to requested location
112 file_offset = file_size;
113 while(file_size < req_offset) write(0x00);
114 }
115 }
116
117 file_offset = req_offset;
118 }
119
120 int offset() {
121 if(!fp) return -1; //file not open
122 return file_offset;
123 }
124
125 int size() {
126 if(!fp) return -1; //file not open
127 return file_size;
128 }
129
130 bool truncate(unsigned size) {
131 if(!fp) return false; //file not open
132 #if !defined(_WIN32)
133 return ftruncate(fileno(fp), size) == 0;
134 #else
135 return _chsize(fileno(fp), size) == 0;
136 #endif
137 }
138
139 bool end() {
140 if(!fp) return true; //file not open
141 return file_offset >= file_size;
142 }
143
144 static bool exists(const char *fn) {
145 #if !defined(_WIN32)
146 FILE *fp = fopen(fn, "rb");
147 #else
148 FILE *fp = _wfopen(utf16_t(fn), L"rb");
149 #endif
150 if(fp) {
151 fclose(fp);
152 return true;
153 }
154 return false;
155 }
156
157 static unsigned size(const char *fn) {
158 #if !defined(_WIN32)
159 FILE *fp = fopen(fn, "rb");
160 #else
161 FILE *fp = _wfopen(utf16_t(fn), L"rb");
162 #endif
163 unsigned filesize = 0;
164 if(fp) {
165 fseek(fp, 0, SEEK_END);
166 filesize = ftell(fp);
167 fclose(fp);
168 }
169 return filesize;
170 }
171
172 bool open() {
173 return fp;
174 }
175
176 bool open(const char *fn, mode mode_) {
177 if(fp) return false;
178
179 switch(file_mode = mode_) {
180 #if !defined(_WIN32)
181 case mode::read: fp = fopen(fn, "rb"); break;
182 case mode::write: fp = fopen(fn, "wb+"); break; //need read permission for buffering
183 case mode::readwrite: fp = fopen(fn, "rb+"); break;
184 case mode::writeread: fp = fopen(fn, "wb+"); break;
185 #else
186 case mode::read: fp = _wfopen(utf16_t(fn), L"rb"); break;
187 case mode::write: fp = _wfopen(utf16_t(fn), L"wb+"); break;
188 case mode::readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break;
189 case mode::writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break;
190 #endif
191 }
192 if(!fp) return false;
193 buffer_offset = -1; //invalidate buffer
194 file_offset = 0;
195 fseek(fp, 0, SEEK_END);
196 file_size = ftell(fp);
197 fseek(fp, 0, SEEK_SET);
198 return true;
199 }
200
201 void close() {
202 if(!fp) return;
203 buffer_flush();
204 fclose(fp);
205 fp = 0;
206 }
207
208 file() {
209 memset(buffer, 0, sizeof buffer);
210 buffer_offset = -1;
211 buffer_dirty = false;
212 fp = 0;
213 file_offset = 0;
214 file_size = 0;
215 file_mode = mode::read;
216 }
217
218 ~file() {
219 close();
220 }
221
222 file& operator=(const file&) = delete;
223 file(const file&) = delete;
224
225 private:
226 enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 };
227 char buffer[buffer_size];
228 int buffer_offset;
229 bool buffer_dirty;
230 FILE *fp;
231 unsigned file_offset;
232 unsigned file_size;
233 mode file_mode;
234
235 void buffer_sync() {
236 if(!fp) return; //file not open
237 if(buffer_offset != (file_offset & ~buffer_mask)) {
238 buffer_flush();
239 buffer_offset = file_offset & ~buffer_mask;
240 fseek(fp, buffer_offset, SEEK_SET);
241 unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
242 if(length) unsigned unused = fread(buffer, 1, length, fp);
243 }
244 }
245
246 void buffer_flush() {
247 if(!fp) return; //file not open
248 if(file_mode == mode::read) return; //buffer cannot be written to
249 if(buffer_offset < 0) return; //buffer unused
250 if(buffer_dirty == false) return; //buffer unmodified since read
251 fseek(fp, buffer_offset, SEEK_SET);
252 unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
253 if(length) unsigned unused = fwrite(buffer, 1, length, fp);
254 buffer_offset = -1; //invalidate buffer
255 buffer_dirty = false;
256 }
257 };
258 }
259
260 #endif
+0
-200
snespurify/phoenix/nall/filemap.hpp less more
0 #ifndef NALL_FILEMAP_HPP
1 #define NALL_FILEMAP_HPP
2
3 #include <nall/stdint.hpp>
4 #include <nall/utf8.hpp>
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #if defined(_WIN32)
9 #include <windows.h>
10 #else
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #endif
17
18 namespace nall {
19 class filemap {
20 public:
21 enum class mode : unsigned { read, write, readwrite, writeread };
22
23 bool opened() const { return p_opened(); }
24 bool open(const char *filename, mode mode_) { return p_open(filename, mode_); }
25 void close() { return p_close(); }
26 unsigned size() const { return p_size; }
27 uint8_t* data() { return p_handle; }
28 const uint8_t* data() const { return p_handle; }
29 filemap() : p_size(0), p_handle(0) { p_ctor(); }
30 filemap(const char *filename, mode mode_) : p_size(0), p_handle(0) { p_ctor(); p_open(filename, mode_); }
31 ~filemap() { p_dtor(); }
32
33 private:
34 unsigned p_size;
35 uint8_t *p_handle;
36
37 #if defined(_WIN32)
38 //=============
39 //MapViewOfFile
40 //=============
41
42 HANDLE p_filehandle, p_maphandle;
43
44 bool p_opened() const {
45 return p_handle;
46 }
47
48 bool p_open(const char *filename, mode mode_) {
49 int desired_access, creation_disposition, flprotect, map_access;
50
51 switch(mode_) {
52 default: return false;
53 case mode::read:
54 desired_access = GENERIC_READ;
55 creation_disposition = OPEN_EXISTING;
56 flprotect = PAGE_READONLY;
57 map_access = FILE_MAP_READ;
58 break;
59 case mode::write:
60 //write access requires read access
61 desired_access = GENERIC_WRITE;
62 creation_disposition = CREATE_ALWAYS;
63 flprotect = PAGE_READWRITE;
64 map_access = FILE_MAP_ALL_ACCESS;
65 break;
66 case mode::readwrite:
67 desired_access = GENERIC_READ | GENERIC_WRITE;
68 creation_disposition = OPEN_EXISTING;
69 flprotect = PAGE_READWRITE;
70 map_access = FILE_MAP_ALL_ACCESS;
71 break;
72 case mode::writeread:
73 desired_access = GENERIC_READ | GENERIC_WRITE;
74 creation_disposition = CREATE_NEW;
75 flprotect = PAGE_READWRITE;
76 map_access = FILE_MAP_ALL_ACCESS;
77 break;
78 }
79
80 p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL,
81 creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
82 if(p_filehandle == INVALID_HANDLE_VALUE) return false;
83
84 p_size = GetFileSize(p_filehandle, NULL);
85
86 p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL);
87 if(p_maphandle == INVALID_HANDLE_VALUE) {
88 CloseHandle(p_filehandle);
89 p_filehandle = INVALID_HANDLE_VALUE;
90 return false;
91 }
92
93 p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size);
94 return p_handle;
95 }
96
97 void p_close() {
98 if(p_handle) {
99 UnmapViewOfFile(p_handle);
100 p_handle = 0;
101 }
102
103 if(p_maphandle != INVALID_HANDLE_VALUE) {
104 CloseHandle(p_maphandle);
105 p_maphandle = INVALID_HANDLE_VALUE;
106 }
107
108 if(p_filehandle != INVALID_HANDLE_VALUE) {
109 CloseHandle(p_filehandle);
110 p_filehandle = INVALID_HANDLE_VALUE;
111 }
112 }
113
114 void p_ctor() {
115 p_filehandle = INVALID_HANDLE_VALUE;
116 p_maphandle = INVALID_HANDLE_VALUE;
117 }
118
119 void p_dtor() {
120 close();
121 }
122
123 #else
124 //====
125 //mmap
126 //====
127
128 int p_fd;
129
130 bool p_opened() const {
131 return p_handle;
132 }
133
134 bool p_open(const char *filename, mode mode_) {
135 int open_flags, mmap_flags;
136
137 switch(mode_) {
138 default: return false;
139 case mode::read:
140 open_flags = O_RDONLY;
141 mmap_flags = PROT_READ;
142 break;
143 case mode::write:
144 open_flags = O_RDWR | O_CREAT; //mmap() requires read access
145 mmap_flags = PROT_WRITE;
146 break;
147 case mode::readwrite:
148 open_flags = O_RDWR;
149 mmap_flags = PROT_READ | PROT_WRITE;
150 break;
151 case mode::writeread:
152 open_flags = O_RDWR | O_CREAT;
153 mmap_flags = PROT_READ | PROT_WRITE;
154 break;
155 }
156
157 p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
158 if(p_fd < 0) return false;
159
160 struct stat p_stat;
161 fstat(p_fd, &p_stat);
162 p_size = p_stat.st_size;
163
164 p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0);
165 if(p_handle == MAP_FAILED) {
166 p_handle = 0;
167 ::close(p_fd);
168 p_fd = -1;
169 return false;
170 }
171
172 return p_handle;
173 }
174
175 void p_close() {
176 if(p_handle) {
177 munmap(p_handle, p_size);
178 p_handle = 0;
179 }
180
181 if(p_fd >= 0) {
182 ::close(p_fd);
183 p_fd = -1;
184 }
185 }
186
187 void p_ctor() {
188 p_fd = -1;
189 }
190
191 void p_dtor() {
192 p_close();
193 }
194
195 #endif
196 };
197 }
198
199 #endif
+0
-18
snespurify/phoenix/nall/foreach.hpp less more
0 #ifndef NALL_FOREACH_HPP
1 #define NALL_FOREACH_HPP
2
3 #include <type_traits>
4 #include <nall/concept.hpp>
5
6 #undef foreach
7
8 #define foreach2(iter, object) foreach3(iter, object, foreach_counter)
9 #define foreach3(iter, object, foreach_counter) \
10 for(unsigned foreach_counter = 0, foreach_limit = container_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \
11 for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0)
12
13 #define foreach_impl(...) foreach_decl(__VA_ARGS__, foreach3(__VA_ARGS__), foreach2(__VA_ARGS__), foreach_too_few_arguments)
14 #define foreach_decl(_1, _2, _3, N, ...) N
15 #define foreach(...) foreach_impl(__VA_ARGS__)
16
17 #endif
+0
-60
snespurify/phoenix/nall/function.hpp less more
0 #ifndef NALL_FUNCTION_HPP
1 #define NALL_FUNCTION_HPP
2
3 namespace nall {
4 template<typename T> class function;
5
6 template<typename R, typename... P> class function<R (P...)> {
7 struct container {
8 virtual R operator()(P... p) const = 0;
9 virtual container* copy() const = 0;
10 virtual ~container() {}
11 } *callback;
12
13 struct global : container {
14 R (*function)(P...);
15 R operator()(P... p) const { return function(std::forward<P>(p)...); }
16 container* copy() const { return new global(function); }
17 global(R (*function)(P...)) : function(function) {}
18 };
19
20 template<typename C> struct member : container {
21 R (C::*function)(P...);
22 C *object;
23 R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); }
24 container* copy() const { return new member(function, object); }
25 member(R (C::*function)(P...), C *object) : function(function), object(object) {}
26 };
27
28 template<typename L> struct lambda : container {
29 mutable L object;
30 R operator()(P... p) const { return object(std::forward<P>(p)...); }
31 container* copy() const { return new lambda(object); }
32 lambda(const L& object) : object(object) {}
33 };
34
35 public:
36 operator bool() const { return callback; }
37 R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); }
38 void reset() { if(callback) { delete callback; callback = 0; } }
39
40 function& operator=(const function &source) {
41 if(this != &source) {
42 if(callback) { delete callback; callback = 0; }
43 if(source.callback) callback = source.callback->copy();
44 }
45 return *this;
46 }
47
48 function(const function &source) : callback(0) { operator=(source); }
49 function() : callback(0) {}
50 function(void *function) : callback(0) { if(function) callback = new global((R (*)(P...))function); }
51 function(R (*function)(P...)) { callback = new global(function); }
52 template<typename C> function(R (C::*function)(P...), C *object) { callback = new member<C>(function, object); }
53 template<typename C> function(R (C::*function)(P...) const, C *object) { callback = new member<C>((R (C::*)(P...))function, object); }
54 template<typename L> function(const L& object) { callback = new lambda<L>(object); }
55 ~function() { if(callback) delete callback; }
56 };
57 }
58
59 #endif
+0
-105
snespurify/phoenix/nall/gameboy/cartridge.hpp less more
0 #ifndef NALL_GAMEBOY_CARTRIDGE_HPP
1 #define NALL_GAMEBOY_CARTRIDGE_HPP
2
3 namespace nall {
4
5 class GameBoyCartridge {
6 public:
7 string xml;
8 inline GameBoyCartridge(const uint8_t *data, unsigned size);
9
10 //private:
11 struct Information {
12 string mapper;
13 bool ram;
14 bool battery;
15 bool rtc;
16 bool rumble;
17
18 unsigned romsize;
19 unsigned ramsize;
20 } info;
21 };
22
23 GameBoyCartridge::GameBoyCartridge(const uint8_t *romdata, unsigned romsize) {
24 xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
25 if(romsize < 0x4000) return;
26
27 info.mapper = "unknown";
28 info.ram = false;
29 info.battery = false;
30 info.rtc = false;
31 info.rumble = false;
32
33 info.romsize = 0;
34 info.ramsize = 0;
35
36 switch(romdata[0x0147]) {
37 case 0x00: info.mapper = "none"; break;
38 case 0x01: info.mapper = "MBC1"; break;
39 case 0x02: info.mapper = "MBC1"; info.ram = true; break;
40 case 0x03: info.mapper = "MBC1"; info.ram = true; info.battery = true; break;
41 case 0x05: info.mapper = "MBC2"; info.ram = true; break;
42 case 0x06: info.mapper = "MBC2"; info.ram = true; info.battery = true; break;
43 case 0x08: info.mapper = "none"; info.ram = true; break;
44 case 0x09: info.mapper = "MBC0"; info.ram = true; info.battery = true; break;
45 case 0x0b: info.mapper = "MMM01"; break;
46 case 0x0c: info.mapper = "MMM01"; info.ram = true; break;
47 case 0x0d: info.mapper = "MMM01"; info.ram = true; info.battery = true; break;
48 case 0x0f: info.mapper = "MBC3"; info.rtc = true; info.battery = true; break;
49 case 0x10: info.mapper = "MBC3"; info.rtc = true; info.ram = true; info.battery = true; break;
50 case 0x11: info.mapper = "MBC3"; break;
51 case 0x12: info.mapper = "MBC3"; info.ram = true; break;
52 case 0x13: info.mapper = "MBC3"; info.ram = true; info.battery = true; break;
53 case 0x19: info.mapper = "MBC5"; break;
54 case 0x1a: info.mapper = "MBC5"; info.ram = true; break;
55 case 0x1b: info.mapper = "MBC5"; info.ram = true; info.battery = true; break;
56 case 0x1c: info.mapper = "MBC5"; info.rumble = true; break;
57 case 0x1d: info.mapper = "MBC5"; info.rumble = true; info.ram = true; break;
58 case 0x1e: info.mapper = "MBC5"; info.rumble = true; info.ram = true; info.battery = true; break;
59 case 0xfc: break; //Pocket Camera
60 case 0xfd: break; //Bandai TAMA5
61 case 0xfe: info.mapper = "HuC3"; break;
62 case 0xff: info.mapper = "HuC1"; info.ram = true; info.battery = true; break;
63 }
64
65 switch(romdata[0x0148]) { default:
66 case 0x00: info.romsize = 2 * 16 * 1024; break;
67 case 0x01: info.romsize = 4 * 16 * 1024; break;
68 case 0x02: info.romsize = 8 * 16 * 1024; break;
69 case 0x03: info.romsize = 16 * 16 * 1024; break;
70 case 0x04: info.romsize = 32 * 16 * 1024; break;
71 case 0x05: info.romsize = 64 * 16 * 1024; break;
72 case 0x06: info.romsize = 128 * 16 * 1024; break;
73 case 0x07: info.romsize = 256 * 16 * 1024; break;
74 case 0x52: info.romsize = 72 * 16 * 1024; break;
75 case 0x53: info.romsize = 80 * 16 * 1024; break;
76 case 0x54: info.romsize = 96 * 16 * 1024; break;
77 }
78
79 switch(romdata[0x0149]) { default:
80 case 0x00: info.ramsize = 0 * 1024; break;
81 case 0x01: info.ramsize = 2 * 1024; break;
82 case 0x02: info.ramsize = 8 * 1024; break;
83 case 0x03: info.ramsize = 32 * 1024; break;
84 }
85
86 if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
87
88 xml << "<cartridge mapper='" << info.mapper << "'";
89 if(info.rtc) xml << " rtc='true'";
90 if(info.rumble) xml << " rumble='true'";
91 xml << ">\n";
92
93 xml << " <rom size='" << hex(romsize) << "'/>\n"; //TODO: trust/check info.romsize?
94
95 if(info.ramsize > 0)
96 xml << " <ram size='" << hex(info.ramsize) << "' battery='" << info.battery << "'/>\n";
97
98 xml << "</cartridge>\n";
99 xml.transform("'", "\"");
100 }
101
102 }
103
104 #endif
+0
-386
snespurify/phoenix/nall/input.hpp less more
0 #ifndef NALL_INPUT_HPP
1 #define NALL_INPUT_HPP
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include <nall/stdint.hpp>
8 #include <nall/string.hpp>
9
10 namespace nall {
11
12 struct Keyboard;
13 Keyboard& keyboard(unsigned = 0);
14
15 static const char KeyboardScancodeName[][64] = {
16 "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
17 "PrintScreen", "ScrollLock", "Pause", "Tilde",
18 "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0",
19 "Dash", "Equal", "Backspace",
20 "Insert", "Delete", "Home", "End", "PageUp", "PageDown",
21 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
22 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
23 "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash",
24 "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0",
25 "Point", "Enter", "Add", "Subtract", "Multiply", "Divide",
26 "NumLock", "CapsLock",
27 "Up", "Down", "Left", "Right",
28 "Tab", "Return", "Spacebar", "Menu",
29 "Shift", "Control", "Alt", "Super",
30 };
31
32 struct Keyboard {
33 const unsigned ID;
34 enum { Base = 1 };
35 enum { Count = 8, Size = 128 };
36
37 enum Scancode {
38 Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
39 PrintScreen, ScrollLock, Pause, Tilde,
40 Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
41 Dash, Equal, Backspace,
42 Insert, Delete, Home, End, PageUp, PageDown,
43 A, B, C, D, E, F, G, H, I, J, K, L, M,
44 N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
45 LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
46 Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
47 Point, Enter, Add, Subtract, Multiply, Divide,
48 NumLock, CapsLock,
49 Up, Down, Left, Right,
50 Tab, Return, Spacebar, Menu,
51 Shift, Control, Alt, Super,
52 Limit,
53 };
54
55 static signed numberDecode(uint16_t scancode) {
56 for(unsigned i = 0; i < Count; i++) {
57 if(keyboard(i).belongsTo(scancode)) return i;
58 }
59 return -1;
60 }
61
62 static signed keyDecode(uint16_t scancode) {
63 for(unsigned i = 0; i < Count; i++) {
64 if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape);
65 }
66 return -1;
67 }
68
69 static signed modifierDecode(uint16_t scancode) {
70 for(unsigned i = 0; i < Count; i++) {
71 if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift);
72 }
73 return -1;
74 }
75
76 static bool isAnyKey(uint16_t scancode) {
77 for(unsigned i = 0; i < Count; i++) {
78 if(keyboard(i).isKey(scancode)) return true;
79 }
80 return false;
81 }
82
83 static bool isAnyModifier(uint16_t scancode) {
84 for(unsigned i = 0; i < Count; i++) {
85 if(keyboard(i).isModifier(scancode)) return true;
86 }
87 return false;
88 }
89
90 static uint16_t decode(const char *name) {
91 string s(name);
92 if(!strbegin(name, "KB")) return 0;
93 s.ltrim("KB");
94 unsigned id = decimal(s);
95 auto pos = strpos(s, "::");
96 if(!pos) return 0;
97 s = substr(s, pos() + 2);
98 for(unsigned i = 0; i < Limit; i++) {
99 if(s == KeyboardScancodeName[i]) return Base + Size * id + i;
100 }
101 return 0;
102 }
103
104 string encode(uint16_t code) const {
105 unsigned index = 0;
106 for(unsigned i = 0; i < Count; i++) {
107 if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
108 index = code - (Base + Size * i);
109 break;
110 }
111 }
112 return string() << "KB" << ID << "::" << KeyboardScancodeName[index];
113 }
114
115 uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
116 uint16_t key(unsigned id) const { return Base + Size * ID + id; }
117 bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); }
118 bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); }
119 bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); }
120
121 Keyboard(unsigned ID_) : ID(ID_) {}
122 };
123
124 inline Keyboard& keyboard(unsigned id) {
125 static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
126 switch(id) { default:
127 case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
128 case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
129 }
130 }
131
132 static const char MouseScancodeName[][64] = {
133 "Xaxis", "Yaxis", "Zaxis",
134 "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
135 };
136
137 struct Mouse;
138 Mouse& mouse(unsigned = 0);
139
140 struct Mouse {
141 const unsigned ID;
142 enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count };
143 enum { Count = 8, Size = 16 };
144 enum { Axes = 3, Buttons = 8 };
145
146 enum Scancode {
147 Xaxis, Yaxis, Zaxis,
148 Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7,
149 Limit,
150 };
151
152 static signed numberDecode(uint16_t scancode) {
153 for(unsigned i = 0; i < Count; i++) {
154 if(mouse(i).belongsTo(scancode)) return i;
155 }
156 return -1;
157 }
158
159 static signed axisDecode(uint16_t scancode) {
160 for(unsigned i = 0; i < Count; i++) {
161 if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0);
162 }
163 return -1;
164 }
165
166 static signed buttonDecode(uint16_t scancode) {
167 for(unsigned i = 0; i < Count; i++) {
168 if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0);
169 }
170 return -1;
171 }
172
173 static bool isAnyAxis(uint16_t scancode) {
174 for(unsigned i = 0; i < Count; i++) {
175 if(mouse(i).isAxis(scancode)) return true;
176 }
177 return false;
178 }
179
180 static bool isAnyButton(uint16_t scancode) {
181 for(unsigned i = 0; i < Count; i++) {
182 if(mouse(i).isButton(scancode)) return true;
183 }
184 return false;
185 }
186
187 static uint16_t decode(const char *name) {
188 string s(name);
189 if(!strbegin(name, "MS")) return 0;
190 s.ltrim("MS");
191 unsigned id = decimal(s);
192 auto pos = strpos(s, "::");
193 if(!pos) return 0;
194 s = substr(s, pos() + 2);
195 for(unsigned i = 0; i < Limit; i++) {
196 if(s == MouseScancodeName[i]) return Base + Size * id + i;
197 }
198 return 0;
199 }
200
201 string encode(uint16_t code) const {
202 unsigned index = 0;
203 for(unsigned i = 0; i < Count; i++) {
204 if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
205 index = code - (Base + Size * i);
206 break;
207 }
208 }
209 return string() << "MS" << ID << "::" << MouseScancodeName[index];
210 }
211
212 uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
213 uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; }
214 uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; }
215 bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); }
216 bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); }
217 bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); }
218
219 Mouse(unsigned ID_) : ID(ID_) {}
220 };
221
222 inline Mouse& mouse(unsigned id) {
223 static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
224 switch(id) { default:
225 case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
226 case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
227 }
228 }
229
230 static const char JoypadScancodeName[][64] = {
231 "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7",
232 "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7",
233 "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15",
234 "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
235 "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15",
236 "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23",
237 "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31",
238 };
239
240 struct Joypad;
241 Joypad& joypad(unsigned = 0);
242
243 struct Joypad {
244 const unsigned ID;
245 enum { Base = Mouse::Base + Mouse::Size * Mouse::Count };
246 enum { Count = 8, Size = 64 };
247 enum { Hats = 8, Axes = 16, Buttons = 32 };
248
249 enum Scancode {
250 Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7,
251 Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7,
252 Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15,
253 Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7,
254 Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15,
255 Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23,
256 Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31,
257 Limit,
258 };
259
260 enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 };
261
262 static signed numberDecode(uint16_t scancode) {
263 for(unsigned i = 0; i < Count; i++) {
264 if(joypad(i).belongsTo(scancode)) return i;
265 }
266 return -1;
267 }
268
269 static signed hatDecode(uint16_t scancode) {
270 for(unsigned i = 0; i < Count; i++) {
271 if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0);
272 }
273 return -1;
274 }
275
276 static signed axisDecode(uint16_t scancode) {
277 for(unsigned i = 0; i < Count; i++) {
278 if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0);
279 }
280 return -1;
281 }
282
283 static signed buttonDecode(uint16_t scancode) {
284 for(unsigned i = 0; i < Count; i++) {
285 if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0);
286 }
287 return -1;
288 }
289
290 static bool isAnyHat(uint16_t scancode) {
291 for(unsigned i = 0; i < Count; i++) {
292 if(joypad(i).isHat(scancode)) return true;
293 }
294 return false;
295 }
296
297 static bool isAnyAxis(uint16_t scancode) {
298 for(unsigned i = 0; i < Count; i++) {
299 if(joypad(i).isAxis(scancode)) return true;
300 }
301 return false;
302 }
303
304 static bool isAnyButton(uint16_t scancode) {
305 for(unsigned i = 0; i < Count; i++) {
306 if(joypad(i).isButton(scancode)) return true;
307 }
308 return false;
309 }
310
311 static uint16_t decode(const char *name) {
312 string s(name);
313 if(!strbegin(name, "JP")) return 0;
314 s.ltrim("JP");
315 unsigned id = decimal(s);
316 auto pos = strpos(s, "::");
317 if(!pos) return 0;
318 s = substr(s, pos() + 2);
319 for(unsigned i = 0; i < Limit; i++) {
320 if(s == JoypadScancodeName[i]) return Base + Size * id + i;
321 }
322 return 0;
323 }
324
325 string encode(uint16_t code) const {
326 unsigned index = 0;
327 for(unsigned i = 0; i < Count; i++) {
328 if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
329 index = code - (Base + Size * i);
330 }
331 }
332 return string() << "JP" << ID << "::" << JoypadScancodeName[index];
333 }
334
335 uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
336 uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; }
337 uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; }
338 uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; }
339 bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); }
340 bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); }
341 bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); }
342 bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); }
343
344 Joypad(unsigned ID_) : ID(ID_) {}
345 };
346
347 inline Joypad& joypad(unsigned id) {
348 static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
349 switch(id) { default:
350 case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
351 case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
352 }
353 }
354
355 struct Scancode {
356 enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count };
357
358 static uint16_t decode(const char *name) {
359 uint16_t code;
360 code = Keyboard::decode(name);
361 if(code) return code;
362 code = Mouse::decode(name);
363 if(code) return code;
364 code = Joypad::decode(name);
365 if(code) return code;
366 return None;
367 }
368
369 static string encode(uint16_t code) {
370 for(unsigned i = 0; i < Keyboard::Count; i++) {
371 if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code);
372 }
373 for(unsigned i = 0; i < Mouse::Count; i++) {
374 if(mouse(i).belongsTo(code)) return mouse(i).encode(code);
375 }
376 for(unsigned i = 0; i < Joypad::Count; i++) {
377 if(joypad(i).belongsTo(code)) return joypad(i).encode(code);
378 }
379 return "None";
380 }
381 };
382
383 }
384
385 #endif
+0
-81
snespurify/phoenix/nall/lzss.hpp less more
0 #ifndef NALL_LZSS_HPP
1 #define NALL_LZSS_HPP
2
3 #include <nall/array.hpp>
4 #include <nall/new.hpp>
5 #include <nall/stdint.hpp>
6
7 namespace nall {
8 class lzss {
9 public:
10 static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) {
11 output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9];
12
13 unsigned i = 0, o = 0;
14 while(i < inlength) {
15 unsigned flagoffset = o++;
16 uint8_t flag = 0x00;
17
18 for(unsigned b = 0; b < 8 && i < inlength; b++) {
19 unsigned longest = 0, pointer;
20 for(unsigned index = 1; index < 4096; index++) {
21 unsigned count = 0;
22 while(true) {
23 if(count >= 15 + 3) break; //verify pattern match is not longer than max length
24 if(i + count >= inlength) break; //verify pattern match does not read past end of input
25 if(i + count < index) break; //verify read is not before start of input
26 if(input[i + count] != input[i + count - index]) break; //verify pattern still matches
27 count++;
28 }
29
30 if(count > longest) {
31 longest = count;
32 pointer = index;
33 }
34 }
35
36 if(longest < 3) output[o++] = input[i++];
37 else {
38 flag |= 1 << b;
39 uint16_t x = ((longest - 3) << 12) + pointer;
40 output[o++] = x;
41 output[o++] = x >> 8;
42 i += longest;
43 }
44 }
45
46 output[flagoffset] = flag;
47 }
48
49 outlength = o;
50 return true;
51 }
52
53 static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) {
54 output = new(zeromemory) uint8_t[length];
55
56 unsigned i = 0, o = 0;
57 while(o < length) {
58 uint8_t flag = input[i++];
59
60 for(unsigned b = 0; b < 8 && o < length; b++) {
61 if(!(flag & (1 << b))) output[o++] = input[i++];
62 else {
63 uint16_t offset = input[i++];
64 offset += input[i++] << 8;
65 uint16_t lookuplength = (offset >> 12) + 3;
66 offset &= 4095;
67 for(unsigned index = 0; index < lookuplength && o + index < length; index++) {
68 output[o + index] = output[o + index - offset];
69 }
70 o += lookuplength;
71 }
72 }
73 }
74
75 return true;
76 }
77 };
78 }
79
80 #endif
+0
-40
snespurify/phoenix/nall/moduloarray.hpp less more
0 #ifndef NALL_MODULO_HPP
1 #define NALL_MODULO_HPP
2
3 #include <nall/serializer.hpp>
4
5 namespace nall {
6 template<typename T, int size> class modulo_array {
7 public:
8 inline T operator[](int index) const {
9 return buffer[size + index];
10 }
11
12 inline T read(int index) const {
13 return buffer[size + index];
14 }
15
16 inline void write(unsigned index, const T value) {
17 buffer[index] =
18 buffer[index + size] =
19 buffer[index + size + size] = value;
20 }
21
22 void serialize(serializer &s) {
23 s.array(buffer, size * 3);
24 }
25
26 modulo_array() {
27 buffer = new T[size * 3]();
28 }
29
30 ~modulo_array() {
31 delete[] buffer;
32 }
33
34 private:
35 T *buffer;
36 };
37 }
38
39 #endif
+0
-122
snespurify/phoenix/nall/platform.hpp less more
0 #ifndef NALL_PLATFORM_HPP
1 #define NALL_PLATFORM_HPP
2
3 #include <nall/utf8.hpp>
4
5 //=========================
6 //standard platform headers
7 //=========================
8
9 #include <limits>
10
11 #include <assert.h>
12 #include <limits.h>
13 #include <math.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <time.h>
19
20 #if defined(_WIN32)
21 #include <io.h>
22 #include <direct.h>
23 #include <shlobj.h>
24 #undef interface
25 #define dllexport __declspec(dllexport)
26 #else
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <sys/stat.h>
30 #define dllexport
31 #endif
32
33 //==================
34 //warning supression
35 //==================
36
37 //Visual C++
38 #if defined(_MSC_VER)
39 //disable libc "deprecation" warnings
40 #pragma warning(disable:4996)
41 #endif
42
43 //================
44 //POSIX compliance
45 //================
46
47 #if defined(_MSC_VER)
48 #define PATH_MAX _MAX_PATH
49 #define va_copy(dest, src) ((dest) = (src))
50 #endif
51
52 #if defined(_WIN32)
53 #define getcwd _getcwd
54 #define ftruncate _chsize
55 #define putenv _putenv
56 #define mkdir(n, m) _wmkdir(nall::utf16_t(n))
57 #define rmdir _rmdir
58 #define vsnprintf _vsnprintf
59 #define usleep(n) Sleep(n / 1000)
60 #endif
61
62 //================
63 //inline expansion
64 //================
65
66 #if defined(__GNUC__)
67 #define noinline __attribute__((noinline))
68 #define inline inline
69 #define alwaysinline inline __attribute__((always_inline))
70 #elif defined(_MSC_VER)
71 #define noinline __declspec(noinline)
72 #define inline inline
73 #define alwaysinline inline __forceinline
74 #else
75 #define noinline
76 #define inline inline
77 #define alwaysinline inline
78 #endif
79
80 //=========================
81 //file system functionality
82 //=========================
83
84 #if defined(_WIN32)
85 inline char* realpath(const char *filename, char *resolvedname) {
86 wchar_t fn[_MAX_PATH] = L"";
87 _wfullpath(fn, nall::utf16_t(filename), _MAX_PATH);
88 strcpy(resolvedname, nall::utf8_t(fn));
89 return resolvedname;
90 }
91
92 inline char* userpath(char *path) {
93 wchar_t fp[_MAX_PATH] = L"";
94 SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, fp);
95 strcpy(path, nall::utf8_t(fp));
96 return path;
97 }
98
99 inline char* getcwd(char *path) {
100 wchar_t fp[_MAX_PATH] = L"";
101 _wgetcwd(fp, _MAX_PATH);
102 strcpy(path, nall::utf8_t(fp));
103 return path;
104 }
105 #else
106 //realpath() already exists
107
108 inline char* userpath(char *path) {
109 *path = 0;
110 struct passwd *userinfo = getpwuid(getuid());
111 if(userinfo) strcpy(path, userinfo->pw_dir);
112 return path;
113 }
114
115 inline char *getcwd(char *path) {
116 return getcwd(path, PATH_MAX);
117 }
118 #endif
119
120 #endif
121
+0
-109
snespurify/phoenix/nall/priorityqueue.hpp less more
0 #ifndef NALL_PRIORITYQUEUE_HPP
1 #define NALL_PRIORITYQUEUE_HPP
2
3 #include <limits>
4 #include <nall/function.hpp>
5 #include <nall/serializer.hpp>
6 #include <nall/utility.hpp>
7
8 namespace nall {
9 template<typename type_t> void priority_queue_nocallback(type_t) {}
10
11 //priority queue implementation using binary min-heap array;
12 //does not require normalize() function.
13 //O(1) find (tick)
14 //O(log n) insert (enqueue)
15 //O(log n) remove (dequeue)
16 template<typename type_t> class priority_queue {
17 public:
18 inline void tick(unsigned ticks) {
19 basecounter += ticks;
20 while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue());
21 }
22
23 //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks);
24 //counter cannot exceed std::numeric_limits<unsigned>::max() >> 1.
25 void enqueue(unsigned counter, type_t event) {
26 unsigned child = heapsize++;
27 counter += basecounter;
28
29 while(child) {
30 unsigned parent = (child - 1) >> 1;
31 if(gte(counter, heap[parent].counter)) break;
32
33 heap[child].counter = heap[parent].counter;
34 heap[child].event = heap[parent].event;
35 child = parent;
36 }
37
38 heap[child].counter = counter;
39 heap[child].event = event;
40 }
41
42 type_t dequeue() {
43 type_t event(heap[0].event);
44 unsigned parent = 0;
45 unsigned counter = heap[--heapsize].counter;
46
47 while(true) {
48 unsigned child = (parent << 1) + 1;
49 if(child >= heapsize) break;
50 if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++;
51 if(gte(heap[child].counter, counter)) break;
52
53 heap[parent].counter = heap[child].counter;
54 heap[parent].event = heap[child].event;
55 parent = child;
56 }
57
58 heap[parent].counter = counter;
59 heap[parent].event = heap[heapsize].event;
60 return event;
61 }
62
63 void reset() {
64 basecounter = 0;
65 heapsize = 0;
66 }
67
68 void serialize(serializer &s) {
69 s.integer(basecounter);
70 s.integer(heapsize);
71 for(unsigned n = 0; n < heapcapacity; n++) {
72 s.integer(heap[n].counter);
73 s.integer(heap[n].event);
74 }
75 }
76
77 priority_queue(unsigned size, function<void (type_t)> callback_ = &priority_queue_nocallback<type_t>)
78 : callback(callback_) {
79 heap = new heap_t[size];
80 heapcapacity = size;
81 reset();
82 }
83
84 ~priority_queue() {
85 delete[] heap;
86 }
87
88 priority_queue& operator=(const priority_queue&) = delete;
89 priority_queue(const priority_queue&) = delete;
90
91 private:
92 function<void (type_t)> callback;
93 unsigned basecounter;
94 unsigned heapsize;
95 unsigned heapcapacity;
96 struct heap_t {
97 unsigned counter;
98 type_t event;
99 } *heap;
100
101 //return true if x is greater than or equal to y
102 inline bool gte(unsigned x, unsigned y) {
103 return x - y < (std::numeric_limits<unsigned>::max() >> 1);
104 }
105 };
106 }
107
108 #endif
+0
-91
snespurify/phoenix/nall/property.hpp less more
0 #ifndef NALL_PROPERTY_HPP
1 #define NALL_PROPERTY_HPP
2
3 //nall::property implements ownership semantics into container classes
4 //example: property<owner>::readonly<type> implies that only owner has full
5 //access to type; and all other code has readonly access.
6 //
7 //this code relies on extended friend semantics from C++0x to work, as it
8 //declares a friend class via a template paramter. it also exploits a bug in
9 //G++ 4.x to work even in C++98 mode.
10 //
11 //if compiling elsewhere, simply remove the friend class and private semantics
12
13 //property can be used either of two ways:
14 //struct foo {
15 // property<foo>::readonly<bool> x;
16 // property<foo>::readwrite<int> y;
17 //};
18 //-or-
19 //struct foo : property<foo> {
20 // readonly<bool> x;
21 // readwrite<int> y;
22 //};
23
24 //return types are const T& (byref) instead fo T (byval) to avoid major speed
25 //penalties for objects with expensive copy constructors
26
27 //operator-> provides access to underlying object type:
28 //readonly<Object> foo;
29 //foo->bar();
30 //... will call Object::bar();
31
32 //operator='s reference is constant so as to avoid leaking a reference handle
33 //that could bypass access restrictions
34
35 //both constant and non-constant operators are provided, though it may be
36 //necessary to cast first, for instance:
37 //struct foo : property<foo> { readonly<int> bar; } object;
38 //int main() { int value = const_cast<const foo&>(object); }
39
40 //writeonly is useful for objects that have non-const reads, but const writes.
41 //however, to avoid leaking handles, the interface is very restricted. the only
42 //way to write is via operator=, which requires conversion via eg copy
43 //constructor. example:
44 //struct foo {
45 // foo(bool value) { ... }
46 //};
47 //writeonly<foo> bar;
48 //bar = true;
49
50 namespace nall {
51 template<typename C> struct property {
52 template<typename T> struct traits { typedef T type; };
53
54 template<typename T> struct readonly {
55 const T* operator->() const { return &value; }
56 const T& operator()() const { return value; }
57 operator const T&() const { return value; }
58 private:
59 T* operator->() { return &value; }
60 operator T&() { return value; }
61 const T& operator=(const T& value_) { return value = value_; }
62 T value;
63 friend class traits<C>::type;
64 };
65
66 template<typename T> struct writeonly {
67 void operator=(const T& value_) { value = value_; }
68 private:
69 const T* operator->() const { return &value; }
70 const T& operator()() const { return value; }
71 operator const T&() const { return value; }
72 T* operator->() { return &value; }
73 operator T&() { return value; }
74 T value;
75 friend class traits<C>::type;
76 };
77
78 template<typename T> struct readwrite {
79 const T* operator->() const { return &value; }
80 const T& operator()() const { return value; }
81 operator const T&() const { return value; }
82 T* operator->() { return &value; }
83 operator T&() { return value; }
84 const T& operator=(const T& value_) { return value = value_; }
85 T value;
86 };
87 };
88 }
89
90 #endif
+0
-32
snespurify/phoenix/nall/public_cast.hpp less more
0 #ifndef NALL_PUBLIC_CAST_HPP
1 #define NALL_PUBLIC_CAST_HPP
2
3 //this is a proof-of-concept-*only* C++ access-privilege elevation exploit.
4 //this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8:
5 //"access checking rules do not apply to names in explicit instantiations."
6 //usage example:
7
8 //struct N { typedef void (Class::*)(); };
9 //template class public_cast<N, &Class::Reference>;
10 //(class.*public_cast<N>::value);
11
12 //Class::Reference may be public, protected or private
13 //Class::Reference may be a function, object or variable
14
15 namespace nall {
16 template<typename T, typename T::type... P> struct public_cast;
17
18 template<typename T> struct public_cast<T> {
19 static typename T::type value;
20 };
21
22 template<typename T> typename T::type public_cast<T>::value;
23
24 template<typename T, typename T::type P> struct public_cast<T, P> {
25 static typename T::type value;
26 };
27
28 template<typename T, typename T::type P> typename T::type public_cast<T, P>::value = public_cast<T>::value = P;
29 }
30
31 #endif
+0
-20
snespurify/phoenix/nall/random.hpp less more
0 #ifndef NALL_RANDOM_HPP
1 #define NALL_RANDOM_HPP
2
3 namespace nall {
4 //pseudo-random number generator
5 inline unsigned prng() {
6 static unsigned n = 0;
7 return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
8 }
9
10 struct random_cyclic {
11 unsigned seed;
12 inline unsigned operator()() {
13 return seed = (seed >> 1) ^ (((seed & 1) - 1) & 0xedb88320);
14 }
15 random_cyclic() : seed(0) {}
16 };
17 }
18
19 #endif
+0
-103
snespurify/phoenix/nall/reference_array.hpp less more
0 #ifndef NALL_REFERENCE_ARRAY_HPP
1 #define NALL_REFERENCE_ARRAY_HPP
2
3 #include <type_traits>
4 #include <nall/bit.hpp>
5 #include <nall/concept.hpp>
6
7 namespace nall {
8 template<typename T> struct reference_array {
9 protected:
10 typedef typename std::remove_reference<T>::type *Tptr;
11 Tptr *pool;
12 unsigned poolsize, buffersize;
13
14 public:
15 unsigned size() const { return buffersize; }
16 unsigned capacity() const { return poolsize; }
17
18 void reset() {
19 if(pool) free(pool);
20 pool = 0;
21 poolsize = 0;
22 buffersize = 0;
23 }
24
25 void reserve(unsigned newsize) {
26 if(newsize == poolsize) return;
27
28 pool = (Tptr*)realloc(pool, newsize * sizeof(T));
29 poolsize = newsize;
30 buffersize = min(buffersize, newsize);
31 }
32
33 void resize(unsigned newsize) {
34 if(newsize > poolsize) reserve(bit::round(newsize));
35 buffersize = newsize;
36 }
37
38 void append(const T data) {
39 unsigned index = buffersize++;
40 if(index >= poolsize) resize(index + 1);
41 pool[index] = &data;
42 }
43
44 template<typename... Args> reference_array(Args&... args) : pool(0), poolsize(0), buffersize(0) {
45 construct(args...);
46 }
47
48 ~reference_array() {
49 reset();
50 }
51
52 reference_array& operator=(const reference_array &source) {
53 if(pool) free(pool);
54 buffersize = source.buffersize;
55 poolsize = source.poolsize;
56 pool = (Tptr*)malloc(sizeof(T) * poolsize);
57 memcpy(pool, source.pool, sizeof(T) * buffersize);
58 return *this;
59 }
60
61 reference_array& operator=(const reference_array &&source) {
62 if(pool) free(pool);
63 pool = source.pool;
64 poolsize = source.poolsize;
65 buffersize = source.buffersize;
66 source.pool = 0;
67 source.reset();
68 return *this;
69 }
70
71 inline T operator[](unsigned index) {
72 if(index >= buffersize) throw "reference_array[] out of bounds";
73 return *pool[index];
74 }
75
76 inline const T operator[](unsigned index) const {
77 if(index >= buffersize) throw "reference_array[] out of bounds";
78 return *pool[index];
79 }
80
81 private:
82 void construct() {
83 }
84
85 void construct(const reference_array &source) {
86 operator=(source);
87 }
88
89 void construct(const reference_array &&source) {
90 operator=(std::move(source));
91 }
92
93 template<typename... Args> void construct(T data, Args&... args) {
94 append(data);
95 construct(args...);
96 }
97 };
98
99 template<typename T> struct has_size<reference_array<T>> { enum { value = true }; };
100 }
101
102 #endif
+0
-85
snespurify/phoenix/nall/serial.hpp less more
0 #ifndef NALL_SERIAL_HPP
1 #define NALL_SERIAL_HPP
2
3 #include <sys/ioctl.h>
4 #include <fcntl.h>
5 #include <termios.h>
6 #include <unistd.h>
7
8 #include <nall/stdint.hpp>
9
10 namespace nall {
11 class serial {
12 public:
13 //-1 on error, otherwise return bytes read
14 int read(uint8_t *data, unsigned length) {
15 if(port_open == false) return -1;
16 return ::read(port, (void*)data, length);
17 }
18
19 //-1 on error, otherwise return bytes written
20 int write(const uint8_t *data, unsigned length) {
21 if(port_open == false) return -1;
22 return ::write(port, (void*)data, length);
23 }
24
25 bool open(const char *portname, unsigned rate, bool flowcontrol) {
26 close();
27
28 port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
29 if(port == -1) return false;
30
31 if(ioctl(port, TIOCEXCL) == -1) { close(); return false; }
32 if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; }
33 if(tcgetattr(port, &original_attr) == -1) { close(); return false; }
34
35 termios attr = original_attr;
36 cfmakeraw(&attr);
37 cfsetspeed(&attr, rate);
38
39 attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN);
40 attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
41 attr.c_iflag |= (IGNBRK | IGNPAR);
42 attr.c_oflag &=~ (OPOST);
43 attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL);
44 attr.c_cflag |= (CS8 | CREAD);
45 if(flowcontrol == false) {
46 attr.c_cflag &= ~CRTSCTS;
47 } else {
48 attr.c_cflag |= CRTSCTS;
49 }
50 attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0;
51
52 if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; }
53 return port_open = true;
54 }
55
56 void close() {
57 if(port != -1) {
58 tcdrain(port);
59 if(port_open == true) {
60 tcsetattr(port, TCSANOW, &original_attr);
61 port_open = false;
62 }
63 ::close(port);
64 port = -1;
65 }
66 }
67
68 serial() {
69 port = -1;
70 port_open = false;
71 }
72
73 ~serial() {
74 close();
75 }
76
77 private:
78 int port;
79 bool port_open;
80 termios original_attr;
81 };
82 }
83
84 #endif
+0
-146
snespurify/phoenix/nall/serializer.hpp less more
0 #ifndef NALL_SERIALIZER_HPP
1 #define NALL_SERIALIZER_HPP
2
3 #include <type_traits>
4 #include <utility>
5 #include <nall/stdint.hpp>
6 #include <nall/utility.hpp>
7
8 namespace nall {
9 //serializer: a class designed to save and restore the state of classes.
10 //
11 //benefits:
12 //- data() will be portable in size (it is not necessary to specify type sizes.)
13 //- data() will be portable in endianness (always stored internally as little-endian.)
14 //- one serialize function can both save and restore class states.
15 //
16 //caveats:
17 //- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
18 //- floating-point usage is not portable across platforms
19
20 class serializer {
21 public:
22 enum mode_t { Load, Save, Size };
23
24 mode_t mode() const {
25 return imode;
26 }
27
28 const uint8_t* data() const {
29 return idata;
30 }
31
32 unsigned size() const {
33 return isize;
34 }
35
36 unsigned capacity() const {
37 return icapacity;
38 }
39
40 template<typename T> void floatingpoint(T &value) {
41 enum { size = sizeof(T) };
42 //this is rather dangerous, and not cross-platform safe;
43 //but there is no standardized way to export FP-values
44 uint8_t *p = (uint8_t*)&value;
45 if(imode == Save) {
46 for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
47 } else if(imode == Load) {
48 for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
49 } else {
50 isize += size;
51 }
52 }
53
54 template<typename T> void integer(T &value) {
55 enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
56 if(imode == Save) {
57 for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
58 } else if(imode == Load) {
59 value = 0;
60 for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3);
61 } else if(imode == Size) {
62 isize += size;
63 }
64 }
65
66 template<typename T> void array(T &array) {
67 enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
68 for(unsigned n = 0; n < size; n++) integer(array[n]);
69 }
70
71 template<typename T> void array(T array, unsigned size) {
72 for(unsigned n = 0; n < size; n++) integer(array[n]);
73 }
74
75 //copy
76 serializer& operator=(const serializer &s) {
77 if(idata) delete[] idata;
78
79 imode = s.imode;
80 idata = new uint8_t[s.icapacity];
81 isize = s.isize;
82 icapacity = s.icapacity;
83
84 memcpy(idata, s.idata, s.icapacity);
85 return *this;
86 }
87
88 serializer(const serializer &s) : idata(0) {
89 operator=(s);
90 }
91
92 //move
93 serializer& operator=(serializer &&s) {
94 if(idata) delete[] idata;
95
96 imode = s.imode;
97 idata = s.idata;
98 isize = s.isize;
99 icapacity = s.icapacity;
100
101 s.idata = 0;
102 return *this;
103 }
104
105 serializer(serializer &&s) {
106 operator=(std::move(s));
107 }
108
109 //construction
110 serializer() {
111 imode = Size;
112 idata = 0;
113 isize = 0;
114 icapacity = 0;
115 }
116
117 serializer(unsigned capacity) {
118 imode = Save;
119 idata = new uint8_t[capacity]();
120 isize = 0;
121 icapacity = capacity;
122 }
123
124 serializer(const uint8_t *data, unsigned capacity) {
125 imode = Load;
126 idata = new uint8_t[capacity];
127 isize = 0;
128 icapacity = capacity;
129 memcpy(idata, data, capacity);
130 }
131
132 ~serializer() {
133 if(idata) delete[] idata;
134 }
135
136 private:
137 mode_t imode;
138 uint8_t *idata;
139 unsigned isize;
140 unsigned icapacity;
141 };
142
143 };
144
145 #endif
+0
-143
snespurify/phoenix/nall/sha256.hpp less more
0 #ifndef NALL_SHA256_HPP
1 #define NALL_SHA256_HPP
2
3 //author: vladitx
4
5 namespace nall {
6 #define PTR(t, a) ((t*)(a))
7
8 #define SWAP32(x) ((uint32_t)( \
9 (((uint32_t)(x) & 0x000000ff) << 24) | \
10 (((uint32_t)(x) & 0x0000ff00) << 8) | \
11 (((uint32_t)(x) & 0x00ff0000) >> 8) | \
12 (((uint32_t)(x) & 0xff000000) >> 24) \
13 ))
14
15 #define ST32(a, d) *PTR(uint32_t, a) = (d)
16 #define ST32BE(a, d) ST32(a, SWAP32(d))
17
18 #define LD32(a) *PTR(uint32_t, a)
19 #define LD32BE(a) SWAP32(LD32(a))
20
21 #define LSL32(x, n) ((uint32_t)(x) << (n))
22 #define LSR32(x, n) ((uint32_t)(x) >> (n))
23 #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n)))
24
25 //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19
26 static const uint32_t T_H[8] = {
27 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
28 };
29
30 //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311
31 static const uint32_t T_K[64] = {
32 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
33 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
34 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
35 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
36 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
37 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
38 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
39 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
40 };
41
42 struct sha256_ctx {
43 uint8_t in[64];
44 unsigned inlen;
45
46 uint32_t w[64];
47 uint32_t h[8];
48 uint64_t len;
49 };
50
51 void sha256_init(sha256_ctx *p) {
52 memset(p, 0, sizeof(sha256_ctx));
53 memcpy(p->h, T_H, sizeof(T_H));
54 }
55
56 static void sha256_block(sha256_ctx *p) {
57 unsigned i;
58 uint32_t s0, s1;
59 uint32_t a, b, c, d, e, f, g, h;
60 uint32_t t1, t2, maj, ch;
61
62 for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4);
63
64 for(i = 16; i < 64; i++) {
65 s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3);
66 s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10);
67 p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1;
68 }
69
70 a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3];
71 e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7];
72
73 for(i = 0; i < 64; i++) {
74 s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22);
75 maj = (a & b) ^ (a & c) ^ (b & c);
76 t2 = s0 + maj;
77 s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25);
78 ch = (e & f) ^ (~e & g);
79 t1 = h + s1 + ch + T_K[i] + p->w[i];
80
81 h = g; g = f; f = e; e = d + t1;
82 d = c; c = b; b = a; a = t1 + t2;
83 }
84
85 p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d;
86 p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h;
87
88 //next block
89 p->inlen = 0;
90 }
91
92 void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) {
93 unsigned l;
94 p->len += len;
95
96 while(len) {
97 l = 64 - p->inlen;
98 l = (len < l) ? len : l;
99
100 memcpy(p->in + p->inlen, s, l);
101 s += l;
102 p->inlen += l;
103 len -= l;
104
105 if(p->inlen == 64) sha256_block(p);
106 }
107 }
108
109 void sha256_final(sha256_ctx *p) {
110 uint64_t len;
111 p->in[p->inlen++] = 0x80;
112
113 if(p->inlen > 56) {
114 memset(p->in + p->inlen, 0, 64 - p->inlen);
115 sha256_block(p);
116 }
117
118 memset(p->in + p->inlen, 0, 56 - p->inlen);
119
120 len = p->len << 3;
121 ST32BE(p->in + 56, len >> 32);
122 ST32BE(p->in + 60, len);
123 sha256_block(p);
124 }
125
126 void sha256_hash(sha256_ctx *p, uint8_t *s) {
127 uint32_t *t = (uint32_t*)s;
128 for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]);
129 }
130
131 #undef PTR
132 #undef SWAP32
133 #undef ST32
134 #undef ST32BE
135 #undef LD32
136 #undef LD32BE
137 #undef LSL32
138 #undef LSR32
139 #undef ROR32
140 }
141
142 #endif
+0
-878
snespurify/phoenix/nall/snes/cartridge.hpp less more
0 #ifndef NALL_SNES_CARTRIDGE_HPP
1 #define NALL_SNES_CARTRIDGE_HPP
2
3 namespace nall {
4
5 class SNESCartridge {
6 public:
7 string xmlMemoryMap;
8 inline SNESCartridge(const uint8_t *data, unsigned size);
9
10 //private:
11 inline void read_header(const uint8_t *data, unsigned size);
12 inline unsigned find_header(const uint8_t *data, unsigned size);
13 inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
14 inline unsigned gameboy_ram_size(const uint8_t *data, unsigned size);
15 inline bool gameboy_has_rtc(const uint8_t *data, unsigned size);
16
17 enum HeaderField {
18 CartName = 0x00,
19 Mapper = 0x15,
20 RomType = 0x16,
21 RomSize = 0x17,
22 RamSize = 0x18,
23 CartRegion = 0x19,
24 Company = 0x1a,
25 Version = 0x1b,
26 Complement = 0x1c, //inverse checksum
27 Checksum = 0x1e,
28 ResetVector = 0x3c,
29 };
30
31 enum Mode {
32 ModeNormal,
33 ModeBsxSlotted,
34 ModeBsx,
35 ModeSufamiTurbo,
36 ModeSuperGameBoy,
37 };
38
39 enum Type {
40 TypeNormal,
41 TypeBsxSlotted,
42 TypeBsxBios,
43 TypeBsx,
44 TypeSufamiTurboBios,
45 TypeSufamiTurbo,
46 TypeSuperGameBoy1Bios,
47 TypeSuperGameBoy2Bios,
48 TypeGameBoy,
49 TypeUnknown,
50 };
51
52 enum Region {
53 NTSC,
54 PAL,
55 };
56
57 enum MemoryMapper {
58 LoROM,
59 HiROM,
60 ExLoROM,
61 ExHiROM,
62 SuperFXROM,
63 SA1ROM,
64 SPC7110ROM,
65 BSCLoROM,
66 BSCHiROM,
67 BSXROM,
68 STROM,
69 };
70
71 enum DSP1MemoryMapper {
72 DSP1Unmapped,
73 DSP1LoROM1MB,
74 DSP1LoROM2MB,
75 DSP1HiROM,
76 };
77
78 bool loaded; //is a base cartridge inserted?
79 unsigned crc32; //crc32 of all cartridges (base+slot(s))
80 unsigned rom_size;
81 unsigned ram_size;
82
83 Mode mode;
84 Type type;
85 Region region;
86 MemoryMapper mapper;
87 DSP1MemoryMapper dsp1_mapper;
88
89 bool has_bsx_slot;
90 bool has_superfx;
91 bool has_sa1;
92 bool has_srtc;
93 bool has_sdd1;
94 bool has_spc7110;
95 bool has_spc7110rtc;
96 bool has_cx4;
97 bool has_dsp1;
98 bool has_dsp2;
99 bool has_dsp3;
100 bool has_dsp4;
101 bool has_obc1;
102 bool has_st010;
103 bool has_st011;
104 bool has_st018;
105 };
106
107 SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
108 read_header(data, size);
109
110 string xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
111
112 if(type == TypeBsx) {
113 xml << "<cartridge/>";
114 xmlMemoryMap = xml.transform("'", "\"");
115 return;
116 }
117
118 if(type == TypeSufamiTurbo) {
119 xml << "<cartridge/>";
120 xmlMemoryMap = xml.transform("'", "\"");
121 return;
122 }
123
124 if(type == TypeGameBoy) {
125 xml << "<cartridge rtc='" << gameboy_has_rtc(data, size) << "'>\n";
126 if(gameboy_ram_size(data, size) > 0) {
127 xml << " <ram size='" << hex(gameboy_ram_size(data, size)) << "'/>\n";
128 }
129 xml << "</cartridge>\n";
130 xmlMemoryMap = xml.transform("'", "\"");
131 return;
132 }
133
134 xml << "<cartridge";
135 if(region == NTSC) {
136 xml << " region='NTSC'";
137 } else {
138 xml << " region='PAL'";
139 }
140 xml << ">\n";
141
142 if(type == TypeSuperGameBoy1Bios) {
143 xml << " <rom>\n";
144 xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
145 xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
146 xml << " </rom>\n";
147 xml << " <icd2 revision='1'>\n";
148 xml << " <map address='00-3f:6000-7fff'/>\n";
149 xml << " <map address='80-bf:6000-7fff'/>\n";
150 xml << " </icd2>\n";
151 } else if(type == TypeSuperGameBoy2Bios) {
152 xml << " <rom>\n";
153 xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
154 xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
155 xml << " </rom>\n";
156 xml << " <icd2 revision='2'>\n";
157 xml << " <map address='00-3f:6000-7fff'/>\n";
158 xml << " <map address='80-bf:6000-7fff'/>\n";
159 xml << " </icd2>\n";
160 } else if(has_spc7110) {
161 xml << " <rom>\n";
162 xml << " <map mode='shadow' address='00-0f:8000-ffff'/>\n";
163 xml << " <map mode='shadow' address='80-bf:8000-ffff'/>\n";
164 xml << " <map mode='linear' address='c0-cf:0000-ffff'/>\n";
165 xml << " </rom>\n";
166
167 xml << " <spc7110>\n";
168 xml << " <mcu>\n";
169 xml << " <map address='d0-ff:0000-ffff' offset='100000' size='" << hex(size - 0x100000) << "'/>\n";
170 xml << " </mcu>\n";
171 xml << " <ram size='" << hex(ram_size) << "'>\n";
172 xml << " <map mode='linear' address='00:6000-7fff'/>\n";
173 xml << " <map mode='linear' address='30:6000-7fff'/>\n";
174 xml << " </ram>\n";
175 xml << " <mmio>\n";
176 xml << " <map address='00-3f:4800-483f'/>\n";
177 xml << " <map address='80-bf:4800-483f'/>\n";
178 xml << " </mmio>\n";
179 if(has_spc7110rtc) {
180 xml << " <rtc>\n";
181 xml << " <map address='00-3f:4840-4842'/>\n";
182 xml << " <map address='80-bf:4840-4842'/>\n";
183 xml << " </rtc>\n";
184 }
185 xml << " <dcu>\n";
186 xml << " <map address='50:0000-ffff'/>\n";
187 xml << " </dcu>\n";
188 xml << " </spc7110>\n";
189 } else if(mapper == LoROM) {
190 xml << " <rom>\n";
191 xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
192 xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
193 xml << " </rom>\n";
194
195 if(ram_size > 0) {
196 xml << " <ram size='" << hex(ram_size) << "'>\n";
197 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
198 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
199 if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
200 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
201 xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
202 } else {
203 xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
204 xml << " <map mode='linear' address='f0-ff:0000-ffff'/>\n";
205 }
206 xml << " </ram>\n";
207 }
208 } else if(mapper == HiROM) {
209 xml << " <rom>\n";
210 xml << " <map mode='shadow' address='00-3f:8000-ffff'/>\n";
211 xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
212 xml << " <map mode='shadow' address='80-bf:8000-ffff'/>\n";
213 xml << " <map mode='linear' address='c0-ff:0000-ffff'/>\n";
214 xml << " </rom>\n";
215
216 if(ram_size > 0) {
217 xml << " <ram size='" << hex(ram_size) << "'>\n";
218 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
219 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
220 if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
221 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
222 } else {
223 xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
224 }
225 xml << " </ram>\n";
226 }
227 } else if(mapper == ExLoROM) {
228 xml << " <rom>\n";
229 xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
230 xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
231 xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
232 xml << " </rom>\n";
233
234 if(ram_size > 0) {
235 xml << " <ram size='" << hex(ram_size) << "'>\n";
236 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
237 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
238 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
239 xml << " </ram>\n";
240 }
241 } else if(mapper == ExHiROM) {
242 xml << " <rom>\n";
243 xml << " <map mode='shadow' address='00-3f:8000-ffff' offset='400000'/>\n";
244 xml << " <map mode='linear' address='40-7f:0000-ffff' offset='400000'/>\n";
245 xml << " <map mode='shadow' address='80-bf:8000-ffff' offset='000000'/>\n";
246 xml << " <map mode='linear' address='c0-ff:0000-ffff' offset='000000'/>\n";
247 xml << " </rom>\n";
248
249 if(ram_size > 0) {
250 xml << " <ram size='" << hex(ram_size) << "'>\n";
251 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
252 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
253 if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
254 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
255 } else {
256 xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
257 }
258 xml << " </ram>\n";
259 }
260 } else if(mapper == SuperFXROM) {
261 xml << " <superfx revision='2'>\n";
262 xml << " <rom>\n";
263 xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
264 xml << " <map mode='linear' address='40-5f:0000-ffff'/>\n";
265 xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
266 xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
267 xml << " </rom>\n";
268 xml << " <ram size='" << hex(ram_size) << "'>\n";
269 xml << " <map mode='linear' address='00-3f:6000-7fff' size='2000'/>\n";
270 xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
271 xml << " <map mode='linear' address='80-bf:6000-7fff' size='2000'/>\n";
272 xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
273 xml << " </ram>\n";
274 xml << " <mmio>\n";
275 xml << " <map address='00-3f:3000-32ff'/>\n";
276 xml << " <map address='80-bf:3000-32ff'/>\n";
277 xml << " </mmio>\n";
278 xml << " </superfx>\n";
279 } else if(mapper == SA1ROM) {
280 xml << " <sa1>\n";
281 xml << " <mcu>\n";
282 xml << " <rom>\n";
283 xml << " <map mode='direct' address='00-3f:8000-ffff'/>\n";
284 xml << " <map mode='direct' address='80-bf:8000-ffff'/>\n";
285 xml << " <map mode='direct' address='c0-ff:0000-ffff'/>\n";
286 xml << " </rom>\n";
287 xml << " <ram>\n";
288 xml << " <map mode='direct' address='00-3f:6000-7fff'/>\n";
289 xml << " <map mode='direct' address='80-bf:6000-7fff'/>\n";
290 xml << " </ram>\n";
291 xml << " </mcu>\n";
292 xml << " <iram size='800'>\n";
293 xml << " <map mode='linear' address='00-3f:3000-37ff'/>\n";
294 xml << " <map mode='linear' address='80-bf:3000-37ff'/>\n";
295 xml << " </iram>\n";
296 xml << " <bwram size='" << hex(ram_size) << "'>\n";
297 xml << " <map mode='linear' address='40-4f:0000-ffff'/>\n";
298 xml << " </bwram>\n";
299 xml << " <mmio>\n";
300 xml << " <map address='00-3f:2200-23ff'/>\n";
301 xml << " <map address='80-bf:2200-23ff'/>\n";
302 xml << " </mmio>\n";
303 xml << " </sa1>\n";
304 } else if(mapper == BSCLoROM) {
305 xml << " <rom>\n";
306 xml << " <map mode='linear' address='00-1f:8000-ffff' offset='000000'/>\n";
307 xml << " <map mode='linear' address='20-3f:8000-ffff' offset='100000'/>\n";
308 xml << " <map mode='linear' address='80-9f:8000-ffff' offset='200000'/>\n";
309 xml << " <map mode='linear' address='a0-bf:8000-ffff' offset='100000'/>\n";
310 xml << " </rom>\n";
311 xml << " <ram size='" << hex(ram_size) << "'>\n";
312 xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
313 xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
314 xml << " </ram>\n";
315 xml << " <bsx>\n";
316 xml << " <slot>\n";
317 xml << " <map mode='linear' address='c0-ef:0000-ffff'/>\n";
318 xml << " </slot>\n";
319 xml << " </bsx>\n";
320 } else if(mapper == BSCHiROM) {
321 xml << " <rom>\n";
322 xml << " <map mode='shadow' address='00-1f:8000-ffff'/>\n";
323 xml << " <map mode='linear' address='40-5f:0000-ffff'/>\n";
324 xml << " <map mode='shadow' address='80-9f:8000-ffff'/>\n";
325 xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
326 xml << " </rom>\n";
327 xml << " <ram size='" << hex(ram_size) << "'>\n";
328 xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
329 xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
330 xml << " </ram>\n";
331 xml << " <bsx>\n";
332 xml << " <slot>\n";
333 xml << " <map mode='shadow' address='20-3f:8000-ffff'/>\n";
334 xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
335 xml << " <map mode='shadow' address='a0-bf:8000-ffff'/>\n";
336 xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
337 xml << " </slot>\n";
338 xml << " </bsx>\n";
339 } else if(mapper == BSXROM) {
340 xml << " <bsx>\n";
341 xml << " <mcu>\n";
342 xml << " <map address='00-3f:8000-ffff'/>\n";
343 xml << " <map address='80-bf:8000-ffff'/>\n";
344 xml << " <map address='40-7f:0000-ffff'/>\n";
345 xml << " <map address='c0-ff:0000-ffff'/>\n";
346 xml << " <map address='20-3f:6000-7fff'/>\n";
347 xml << " </mcu>\n";
348 xml << " <mmio>\n";
349 xml << " <map address='00-3f:5000-5fff'/>\n";
350 xml << " <map address='80-bf:5000-5fff'/>\n";
351 xml << " </mmio>\n";
352 xml << " </bsx>\n";
353 } else if(mapper == STROM) {
354 xml << " <rom>\n";
355 xml << " <map mode='linear' address='00-1f:8000-ffff'/>\n";
356 xml << " <map mode='linear' address='80-9f:8000-ffff'/>\n";
357 xml << " </rom>\n";
358 xml << " <sufamiturbo>\n";
359 xml << " <slot id='A'>\n";
360 xml << " <rom>\n";
361 xml << " <map mode='linear' address='20-3f:8000-ffff'/>\n";
362 xml << " <map mode='linear' address='a0-bf:8000-ffff'/>\n";
363 xml << " </rom>\n";
364 xml << " <ram size='20000'>\n";
365 xml << " <map mode='linear' address='60-63:8000-ffff'/>\n";
366 xml << " <map mode='linear' address='e0-e3:8000-ffff'/>\n";
367 xml << " </ram>\n";
368 xml << " </slot>\n";
369 xml << " <slot id='B'>\n";
370 xml << " <rom>\n";
371 xml << " <map mode='linear' address='40-5f:8000-ffff'/>\n";
372 xml << " <map mode='linear' address='c0-df:8000-ffff'/>\n";
373 xml << " </rom>\n";
374 xml << " <ram size='20000'>\n";
375 xml << " <map mode='linear' address='70-73:8000-ffff'/>\n";
376 xml << " <map mode='linear' address='f0-f3:8000-ffff'/>\n";
377 xml << " </ram>\n";
378 xml << " </slot>\n";
379 xml << " </sufamiturbo>\n";
380 }
381
382 if(has_srtc) {
383 xml << " <srtc>\n";
384 xml << " <map address='00-3f:2800-2801'/>\n";
385 xml << " <map address='80-bf:2800-2801'/>\n";
386 xml << " </srtc>\n";
387 }
388
389 if(has_sdd1) {
390 xml << " <sdd1>\n";
391 xml << " <mcu>\n";
392 xml << " <map address='c0-ff:0000-ffff'/>\n";
393 xml << " </mcu>\n";
394 xml << " <mmio>\n";
395 xml << " <map address='00-3f:4800-4807'/>\n";
396 xml << " <map address='80-bf:4800-4807'/>\n";
397 xml << " </mmio>\n";
398 xml << " </sdd1>\n";
399 }
400
401 if(has_cx4) {
402 xml << " <cx4>\n";
403 xml << " <map address='00-3f:6000-7fff'/>\n";
404 xml << " <map address='80-bf:6000-7fff'/>\n";
405 xml << " </cx4>\n";
406 }
407
408 if(has_dsp1) {
409 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
410 if(dsp1_mapper == DSP1LoROM1MB) {
411 xml << " <dr>\n";
412 xml << " <map address='20-3f:8000-bfff'/>\n";
413 xml << " <map address='a0-bf:8000-bfff'/>\n";
414 xml << " </dr>\n";
415 xml << " <sr>\n";
416 xml << " <map address='20-3f:c000-ffff'/>\n";
417 xml << " <map address='a0-bf:c000-ffff'/>\n";
418 xml << " </sr>\n";
419 } else if(dsp1_mapper == DSP1LoROM2MB) {
420 xml << " <dr>\n";
421 xml << " <map address='60-6f:0000-3fff'/>\n";
422 xml << " <map address='e0-ef:0000-3fff'/>\n";
423 xml << " </dr>\n";
424 xml << " <sr>\n";
425 xml << " <map address='60-6f:4000-7fff'/>\n";
426 xml << " <map address='e0-ef:4000-7fff'/>\n";
427 xml << " </sr>\n";
428 } else if(dsp1_mapper == DSP1HiROM) {
429 xml << " <dr>\n";
430 xml << " <map address='00-1f:6000-6fff'/>\n";
431 xml << " <map address='80-9f:6000-6fff'/>\n";
432 xml << " </dr>\n";
433 xml << " <sr>\n";
434 xml << " <map address='00-1f:7000-7fff'/>\n";
435 xml << " <map address='80-9f:7000-7fff'/>\n";
436 xml << " </sr>\n";
437 }
438 xml << " </necdsp>\n";
439 }
440
441 if(has_dsp2) {
442 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
443 xml << " <dr>\n";
444 xml << " <map address='20-3f:8000-bfff'/>\n";
445 xml << " <map address='a0-bf:8000-bfff'/>\n";
446 xml << " </dr>\n";
447 xml << " <sr>\n";
448 xml << " <map address='20-3f:c000-ffff'/>\n";
449 xml << " <map address='a0-bf:c000-ffff'/>\n";
450 xml << " </sr>\n";
451 xml << " </necdsp>\n";
452 }
453
454 if(has_dsp3) {
455 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
456 xml << " <dr>\n";
457 xml << " <map address='20-3f:8000-bfff'/>\n";
458 xml << " <map address='a0-bf:8000-bfff'/>\n";
459 xml << " </dr>\n";
460 xml << " <sr>\n";
461 xml << " <map address='20-3f:c000-ffff'/>\n";
462 xml << " <map address='a0-bf:c000-ffff'/>\n";
463 xml << " </sr>\n";
464 xml << " </necdsp>\n";
465 }
466
467 if(has_dsp4) {
468 xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
469 xml << " <dr>\n";
470 xml << " <map address='30-3f:8000-bfff'/>\n";
471 xml << " <map address='b0-bf:8000-bfff'/>\n";
472 xml << " </dr>\n";
473 xml << " <sr>\n";
474 xml << " <map address='30-3f:c000-ffff'/>\n";
475 xml << " <map address='b0-bf:c000-ffff'/>\n";
476 xml << " </sr>\n";
477 xml << " </necdsp>\n";
478 }
479
480 if(has_obc1) {
481 xml << " <obc1>\n";
482 xml << " <map address='00-3f:6000-7fff'/>\n";
483 xml << " <map address='80-bf:6000-7fff'/>\n";
484 xml << " </obc1>\n";
485 }
486
487 if(has_st010) {
488 xml << " <necdsp revision='upd96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
489 xml << " <dr>\n";
490 xml << " <map address='60:0000'/>\n";
491 xml << " <map address='e0:0000'/>\n";
492 xml << " </dr>\n";
493 xml << " <sr>\n";
494 xml << " <map address='60:0001'/>\n";
495 xml << " <map address='e0:0001'/>\n";
496 xml << " </sr>\n";
497 xml << " <dp>\n";
498 xml << " <map address='68-6f:0000-0fff'/>\n";
499 xml << " <map address='e8-ef:0000-0fff'/>\n";
500 xml << " </dp>\n";
501 xml << " </necdsp>\n";
502 }
503
504 if(has_st011) {
505 xml << " <necdsp revision='upd96050' frequency='15000000' program='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n";
506 xml << " <dr>\n";
507 xml << " <map address='60:0000'/>\n";
508 xml << " <map address='e0:0000'/>\n";
509 xml << " </dr>\n";
510 xml << " <sr>\n";
511 xml << " <map address='60:0001'/>\n";
512 xml << " <map address='e0:0001'/>\n";
513 xml << " </sr>\n";
514 xml << " <dp>\n";
515 xml << " <map address='68-6f:0000-0fff'/>\n";
516 xml << " <map address='e8-ef:0000-0fff'/>\n";
517 xml << " </dp>\n";
518 xml << " </necdsp>\n";
519 }
520
521 if(has_st018) {
522 xml << " <setarisc program='ST-0018'>\n";
523 xml << " <map address='00-3f:3800-38ff'/>\n";
524 xml << " <map address='80-bf:3800-38ff'/>\n";
525 xml << " </setarisc>\n";
526 }
527
528 xml << "</cartridge>\n";
529 xmlMemoryMap = xml.transform("'", "\"");
530 }
531
532 void SNESCartridge::read_header(const uint8_t *data, unsigned size) {
533 type = TypeUnknown;
534 mapper = LoROM;
535 dsp1_mapper = DSP1Unmapped;
536 region = NTSC;
537 rom_size = size;
538 ram_size = 0;
539
540 has_bsx_slot = false;
541 has_superfx = false;
542 has_sa1 = false;
543 has_srtc = false;
544 has_sdd1 = false;
545 has_spc7110 = false;
546 has_spc7110rtc = false;
547 has_cx4 = false;
548 has_dsp1 = false;
549 has_dsp2 = false;
550 has_dsp3 = false;
551 has_dsp4 = false;
552 has_obc1 = false;
553 has_st010 = false;
554 has_st011 = false;
555 has_st018 = false;
556
557 //=====================
558 //detect Game Boy carts
559 //=====================
560
561 if(size >= 0x0140) {
562 if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
563 && data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
564 type = TypeGameBoy;
565 return;
566 }
567 }
568
569 if(size < 32768) {
570 type = TypeUnknown;
571 return;
572 }
573
574 const unsigned index = find_header(data, size);
575 const uint8_t mapperid = data[index + Mapper];
576 const uint8_t rom_type = data[index + RomType];
577 const uint8_t rom_size = data[index + RomSize];
578 const uint8_t company = data[index + Company];
579 const uint8_t regionid = data[index + CartRegion] & 0x7f;
580
581 ram_size = 1024 << (data[index + RamSize] & 7);
582 if(ram_size == 1024) ram_size = 0; //no RAM present
583
584 //0, 1, 13 = NTSC; 2 - 12 = PAL
585 region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;
586
587 //=======================
588 //detect BS-X flash carts
589 //=======================
590
591 if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
592 if(data[index + 0x14] == 0x00) {
593 const uint8_t n15 = data[index + 0x15];
594 if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
595 if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
596 type = TypeBsx;
597 mapper = BSXROM;
598 region = NTSC; //BS-X only released in Japan
599 return;
600 }
601 }
602 }
603 }
604
605 //=========================
606 //detect Sufami Turbo carts
607 //=========================
608
609 if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
610 if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
611 type = TypeSufamiTurboBios;
612 } else {
613 type = TypeSufamiTurbo;
614 }
615 mapper = STROM;
616 region = NTSC; //Sufami Turbo only released in Japan
617 return; //RAM size handled outside this routine
618 }
619
620 //==========================
621 //detect Super Game Boy BIOS
622 //==========================
623
624 if(!memcmp(data + index, "Super GAMEBOY2", 14)) {
625 type = TypeSuperGameBoy2Bios;
626 return;
627 }
628
629 if(!memcmp(data + index, "Super GAMEBOY", 13)) {
630 type = TypeSuperGameBoy1Bios;
631 return;
632 }
633
634 //=====================
635 //detect standard carts
636 //=====================
637
638 //detect presence of BS-X flash cartridge connector (reads extended header information)
639 if(data[index - 14] == 'Z') {
640 if(data[index - 11] == 'J') {
641 uint8_t n13 = data[index - 13];
642 if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
643 if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
644 has_bsx_slot = true;
645 }
646 }
647 }
648 }
649
650 if(has_bsx_slot) {
651 if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
652 //BS-X base cart
653 type = TypeBsxBios;
654 mapper = BSXROM;
655 region = NTSC; //BS-X only released in Japan
656 return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
657 } else {
658 type = TypeBsxSlotted;
659 mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
660 region = NTSC; //BS-X slotted cartridges only released in Japan
661 }
662 } else {
663 //standard cart
664 type = TypeNormal;
665
666 if(index == 0x7fc0 && size >= 0x401000) {
667 mapper = ExLoROM;
668 } else if(index == 0x7fc0 && mapperid == 0x32) {
669 mapper = ExLoROM;
670 } else if(index == 0x7fc0) {
671 mapper = LoROM;
672 } else if(index == 0xffc0) {
673 mapper = HiROM;
674 } else { //index == 0x40ffc0
675 mapper = ExHiROM;
676 }
677 }
678
679 if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
680 has_superfx = true;
681 mapper = SuperFXROM;
682 ram_size = 1024 << (data[index - 3] & 7);
683 if(ram_size == 1024) ram_size = 0;
684 }
685
686 if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
687 has_sa1 = true;
688 mapper = SA1ROM;
689 }
690
691 if(mapperid == 0x35 && rom_type == 0x55) {
692 has_srtc = true;
693 }
694
695 if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
696 has_sdd1 = true;
697 }
698
699 if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
700 has_spc7110 = true;
701 has_spc7110rtc = (rom_type == 0xf9);
702 mapper = SPC7110ROM;
703 }
704
705 if(mapperid == 0x20 && rom_type == 0xf3) {
706 has_cx4 = true;
707 }
708
709 if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) {
710 has_dsp1 = true;
711 }
712
713 if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) {
714 has_dsp1 = true;
715 }
716
717 if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
718 has_dsp1 = true;
719 }
720
721 if(has_dsp1 == true) {
722 if((mapperid & 0x2f) == 0x20 && size <= 0x100000) {
723 dsp1_mapper = DSP1LoROM1MB;
724 } else if((mapperid & 0x2f) == 0x20) {
725 dsp1_mapper = DSP1LoROM2MB;
726 } else if((mapperid & 0x2f) == 0x21) {
727 dsp1_mapper = DSP1HiROM;
728 }
729 }
730
731 if(mapperid == 0x20 && rom_type == 0x05) {
732 has_dsp2 = true;
733 }
734
735 if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) {
736 has_dsp3 = true;
737 }
738
739 if(mapperid == 0x30 && rom_type == 0x03) {
740 has_dsp4 = true;
741 }
742
743 if(mapperid == 0x30 && rom_type == 0x25) {
744 has_obc1 = true;
745 }
746
747 if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
748 has_st010 = true;
749 }
750
751 if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) {
752 has_st011 = true;
753 }
754
755 if(mapperid == 0x30 && rom_type == 0xf5) {
756 has_st018 = true;
757 }
758 }
759
760 unsigned SNESCartridge::find_header(const uint8_t *data, unsigned size) {
761 unsigned score_lo = score_header(data, size, 0x007fc0);
762 unsigned score_hi = score_header(data, size, 0x00ffc0);
763 unsigned score_ex = score_header(data, size, 0x40ffc0);
764 if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
765
766 if(score_lo >= score_hi && score_lo >= score_ex) {
767 return 0x007fc0;
768 } else if(score_hi >= score_ex) {
769 return 0x00ffc0;
770 } else {
771 return 0x40ffc0;
772 }
773 }
774
775 unsigned SNESCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) {
776 if(size < addr + 64) return 0; //image too small to contain header at this location?
777 int score = 0;
778
779 uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
780 uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
781 uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
782
783 uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
784 uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
785
786 //$00:[000-7fff] contains uninitialized RAM and MMIO.
787 //reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
788 if(resetvector < 0x8000) return 0;
789
790 //some images duplicate the header in multiple locations, and others have completely
791 //invalid header information that cannot be relied upon.
792 //below code will analyze the first opcode executed at the specified reset vector to
793 //determine the probability that this is the correct header.
794
795 //most likely opcodes
796 if(resetop == 0x78 //sei
797 || resetop == 0x18 //clc (clc; xce)
798 || resetop == 0x38 //sec (sec; xce)
799 || resetop == 0x9c //stz $nnnn (stz $4200)
800 || resetop == 0x4c //jmp $nnnn
801 || resetop == 0x5c //jml $nnnnnn
802 ) score += 8;
803
804 //plausible opcodes
805 if(resetop == 0xc2 //rep #$nn
806 || resetop == 0xe2 //sep #$nn
807 || resetop == 0xad //lda $nnnn
808 || resetop == 0xae //ldx $nnnn
809 || resetop == 0xac //ldy $nnnn
810 || resetop == 0xaf //lda $nnnnnn
811 || resetop == 0xa9 //lda #$nn
812 || resetop == 0xa2 //ldx #$nn
813 || resetop == 0xa0 //ldy #$nn
814 || resetop == 0x20 //jsr $nnnn
815 || resetop == 0x22 //jsl $nnnnnn
816 ) score += 4;
817
818 //implausible opcodes
819 if(resetop == 0x40 //rti
820 || resetop == 0x60 //rts
821 || resetop == 0x6b //rtl
822 || resetop == 0xcd //cmp $nnnn
823 || resetop == 0xec //cpx $nnnn
824 || resetop == 0xcc //cpy $nnnn
825 ) score -= 4;
826
827 //least likely opcodes
828 if(resetop == 0x00 //brk #$nn
829 || resetop == 0x02 //cop #$nn
830 || resetop == 0xdb //stp
831 || resetop == 0x42 //wdm
832 || resetop == 0xff //sbc $nnnnnn,x
833 ) score -= 8;
834
835 //at times, both the header and reset vector's first opcode will match ...
836 //fallback and rely on info validity in these cases to determine more likely header.
837
838 //a valid checksum is the biggest indicator of a valid header.
839 if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4;
840
841 if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
842 if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
843 if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
844 if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
845
846 if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header
847 if(data[addr + RomType] < 0x08) score++;
848 if(data[addr + RomSize] < 0x10) score++;
849 if(data[addr + RamSize] < 0x08) score++;
850 if(data[addr + CartRegion] < 14) score++;
851
852 if(score < 0) score = 0;
853 return score;
854 }
855
856 unsigned SNESCartridge::gameboy_ram_size(const uint8_t *data, unsigned size) {
857 if(size < 512) return 0;
858 switch(data[0x0149]) {
859 case 0x00: return 0 * 1024;
860 case 0x01: return 8 * 1024;
861 case 0x02: return 8 * 1024;
862 case 0x03: return 32 * 1024;
863 case 0x04: return 128 * 1024;
864 case 0x05: return 128 * 1024;
865 default: return 128 * 1024;
866 }
867 }
868
869 bool SNESCartridge::gameboy_has_rtc(const uint8_t *data, unsigned size) {
870 if(size < 512) return false;
871 if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true;
872 return false;
873 }
874
875 }
876
877 #endif
+0
-458
snespurify/phoenix/nall/snes/cpu.hpp less more
0 #ifndef NALL_SNES_CPU_HPP
1 #define NALL_SNES_CPU_HPP
2
3 namespace nall {
4
5 struct SNESCPU {
6 enum : unsigned {
7 Implied, //
8 Constant, //#$00
9 AccumConstant, //#$00
10 IndexConstant, //#$00
11 Direct, //$00
12 DirectX, //$00,x
13 DirectY, //$00,y
14 IDirect, //($00)
15 IDirectX, //($00,x)
16 IDirectY, //($00),y
17 ILDirect, //[$00]
18 ILDirectY, //[$00],y
19 Address, //$0000
20 AddressX, //$0000,x
21 AddressY, //$0000,y
22 IAddressX, //($0000,x)
23 ILAddress, //[$0000]
24 PAddress, //PBR:$0000
25 PIAddress, //PBR:($0000)
26 Long, //$000000
27 LongX, //$000000,x
28 Stack, //$00,s
29 IStackY, //($00,s),y
30 BlockMove, //$00,$00
31 RelativeShort, //+/- $00
32 RelativeLong, //+/- $0000
33 };
34
35 struct OpcodeInfo {
36 char name[4];
37 unsigned mode;
38 };
39
40 static const OpcodeInfo opcodeInfo[256];
41
42 static unsigned getOpcodeLength(bool accum, bool index, uint8_t opcode);
43 static string disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb);
44 };
45
46 const SNESCPU::OpcodeInfo SNESCPU::opcodeInfo[256] = {
47 //0x00 - 0x0f
48 { "brk", Constant },
49 { "ora", IDirectX },
50 { "cop", Constant },
51 { "ora", Stack },
52
53 { "tsb", Direct },
54 { "ora", Direct },
55 { "asl", Direct },
56 { "ora", ILDirect },
57
58 { "php", Implied },
59 { "ora", AccumConstant },
60 { "asl", Implied },
61 { "phd", Implied },
62
63 { "tsb", Address },
64 { "ora", Address },
65 { "asl", Address },
66 { "ora", Long },
67
68 //0x10 - 0x1f
69 { "bpl", RelativeShort },
70 { "ora", IDirectY },
71 { "ora", IDirect },
72 { "ora", IStackY },
73
74 { "trb", Direct },
75 { "ora", DirectX },
76 { "asl", DirectX },
77 { "ora", ILDirectY },
78
79 { "clc", Implied },
80 { "ora", AddressY },
81 { "inc", Implied },
82 { "tcs", Implied },
83
84 { "trb", Address },
85 { "ora", AddressX },
86 { "asl", AddressX },
87 { "ora", LongX },
88
89 //0x20 - 0x2f
90 { "jsr", Address },
91 { "and", IDirectX },
92 { "jsl", Long },
93 { "and", Stack },
94
95 { "bit", Direct },
96 { "and", Direct },
97 { "rol", Direct },
98 { "and", ILDirect },
99
100 { "plp", Implied },
101 { "and", AccumConstant },
102 { "rol", Implied },
103 { "pld", Implied },
104
105 { "bit", Address },
106 { "and", Address },
107 { "rol", Address },
108 { "and", Long },
109
110 //0x30 - 0x3f
111 { "bmi", RelativeShort },
112 { "and", IDirectY },
113 { "and", IDirect },
114 { "and", IStackY },
115
116 { "bit", DirectX },
117 { "and", DirectX },
118 { "rol", DirectX },
119 { "and", ILDirectY },
120
121 { "sec", Implied },
122 { "and", AddressY },
123 { "dec", Implied },
124 { "tsc", Implied },
125
126 { "bit", AddressX },
127 { "and", AddressX },
128 { "rol", AddressX },
129 { "and", LongX },
130
131 //0x40 - 0x4f
132 { "rti", Implied },
133 { "eor", IDirectX },
134 { "wdm", Constant },
135 { "eor", Stack },
136
137 { "mvp", BlockMove },
138 { "eor", Direct },
139 { "lsr", Direct },
140 { "eor", ILDirect },
141
142 { "pha", Implied },
143 { "eor", AccumConstant },
144 { "lsr", Implied },
145 { "phk", Implied },
146
147 { "jmp", PAddress },
148 { "eor", Address },
149 { "lsr", Address },
150 { "eor", Long },
151
152 //0x50 - 0x5f
153 { "bvc", RelativeShort },
154 { "eor", IDirectY },
155 { "eor", IDirect },
156 { "eor", IStackY },
157
158 { "mvn", BlockMove },
159 { "eor", DirectX },
160 { "lsr", DirectX },
161 { "eor", ILDirectY },
162
163 { "cli", Implied },
164 { "eor", AddressY },
165 { "phy", Implied },
166 { "tcd", Implied },
167
168 { "jml", Long },
169 { "eor", AddressX },
170 { "lsr", AddressX },
171 { "eor", LongX },
172
173 //0x60 - 0x6f
174 { "rts", Implied },
175 { "adc", IDirectX },
176 { "per", Address },
177 { "adc", Stack },
178
179 { "stz", Direct },
180 { "adc", Direct },
181 { "ror", Direct },
182 { "adc", ILDirect },
183
184 { "pla", Implied },
185 { "adc", AccumConstant },
186 { "ror", Implied },
187 { "rtl", Implied },
188
189 { "jmp", PIAddress },
190 { "adc", Address },
191 { "ror", Address },
192 { "adc", Long },
193
194 //0x70 - 0x7f
195 { "bvs", RelativeShort },
196 { "adc", IDirectY },
197 { "adc", IDirect },
198 { "adc", IStackY },
199
200 { "stz", DirectX },
201 { "adc", DirectX },
202 { "ror", DirectX },
203 { "adc", ILDirectY },
204
205 { "sei", Implied },
206 { "adc", AddressY },
207 { "ply", Implied },
208 { "tdc", Implied },
209
210 { "jmp", IAddressX },
211 { "adc", AddressX },
212 { "ror", AddressX },
213 { "adc", LongX },
214
215 //0x80 - 0x8f
216 { "bra", RelativeShort },
217 { "sta", IDirectX },
218 { "brl", RelativeLong },
219 { "sta", Stack },
220
221 { "sty", Direct },
222 { "sta", Direct },
223 { "stx", Direct },
224 { "sta", ILDirect },
225
226 { "dey", Implied },
227 { "bit", AccumConstant },
228 { "txa", Implied },
229 { "phb", Implied },
230
231 { "sty", Address },
232 { "sta", Address },
233 { "stx", Address },
234 { "sta", Long },
235
236 //0x90 - 0x9f
237 { "bcc", RelativeShort },
238 { "sta", IDirectY },
239 { "sta", IDirect },
240 { "sta", IStackY },
241
242 { "sty", DirectX },
243 { "sta", DirectX },
244 { "stx", DirectY },
245 { "sta", ILDirectY },
246
247 { "tya", Implied },
248 { "sta", AddressY },
249 { "txs", Implied },
250 { "txy", Implied },
251
252 { "stz", Address },
253 { "sta", AddressX },
254 { "stz", AddressX },
255 { "sta", LongX },
256
257 //0xa0 - 0xaf
258 { "ldy", IndexConstant },
259 { "lda", IDirectX },
260 { "ldx", IndexConstant },
261 { "lda", Stack },
262
263 { "ldy", Direct },
264 { "lda", Direct },
265 { "ldx", Direct },
266 { "lda", ILDirect },
267
268 { "tay", Implied },
269 { "lda", AccumConstant },
270 { "tax", Implied },
271 { "plb", Implied },
272
273 { "ldy", Address },
274 { "lda", Address },
275 { "ldx", Address },
276 { "lda", Long },
277
278 //0xb0 - 0xbf
279 { "bcs", RelativeShort },
280 { "lda", IDirectY },
281 { "lda", IDirect },
282 { "lda", IStackY },
283
284 { "ldy", DirectX },
285 { "lda", DirectX },
286 { "ldx", DirectY },
287 { "lda", ILDirectY },
288
289 { "clv", Implied },
290 { "lda", AddressY },
291 { "tsx", Implied },
292 { "tyx", Implied },
293
294 { "ldy", AddressX },
295 { "lda", AddressX },
296 { "ldx", AddressY },
297 { "lda", LongX },
298
299 //0xc0 - 0xcf
300 { "cpy", IndexConstant },
301 { "cmp", IDirectX },
302 { "rep", Constant },
303 { "cmp", Stack },
304
305 { "cpy", Direct },
306 { "cmp", Direct },
307 { "dec", Direct },
308 { "cmp", ILDirect },
309
310 { "iny", Implied },
311 { "cmp", AccumConstant },
312 { "dex", Implied },
313 { "wai", Implied },
314
315 { "cpy", Address },
316 { "cmp", Address },
317 { "dec", Address },
318 { "cmp", Long },
319
320 //0xd0 - 0xdf
321 { "bne", RelativeShort },
322 { "cmp", IDirectY },
323 { "cmp", IDirect },
324 { "cmp", IStackY },
325
326 { "pei", IDirect },
327 { "cmp", DirectX },
328 { "dec", DirectX },
329 { "cmp", ILDirectY },
330
331 { "cld", Implied },
332 { "cmp", AddressY },
333 { "phx", Implied },
334 { "stp", Implied },
335
336 { "jmp", ILAddress },
337 { "cmp", AddressX },
338 { "dec", AddressX },
339 { "cmp", LongX },
340
341 //0xe0 - 0xef
342 { "cpx", IndexConstant },
343 { "sbc", IDirectX },
344 { "sep", Constant },
345 { "sbc", Stack },
346
347 { "cpx", Direct },
348 { "sbc", Direct },
349 { "inc", Direct },
350 { "sbc", ILDirect },
351
352 { "inx", Implied },
353 { "sbc", AccumConstant },
354 { "nop", Implied },
355 { "xba", Implied },
356
357 { "cpx", Address },
358 { "sbc", Address },
359 { "inc", Address },
360 { "sbc", Long },
361
362 //0xf0 - 0xff
363 { "beq", RelativeShort },
364 { "sbc", IDirectY },
365 { "sbc", IDirect },
366 { "sbc", IStackY },
367
368 { "pea", Address },
369 { "sbc", DirectX },
370 { "inc", DirectX },
371 { "sbc", ILDirectY },
372
373 { "sed", Implied },
374 { "sbc", AddressY },
375 { "plx", Implied },
376 { "xce", Implied },
377
378 { "jsr", IAddressX },
379 { "sbc", AddressX },
380 { "inc", AddressX },
381 { "sbc", LongX },
382 };
383
384 inline unsigned SNESCPU::getOpcodeLength(bool accum, bool index, uint8_t opcode) {
385 switch(opcodeInfo[opcode].mode) { default:
386 case Implied: return 1;
387 case Constant: return 2;
388 case AccumConstant: return 3 - accum;
389 case IndexConstant: return 3 - index;
390 case Direct: return 2;
391 case DirectX: return 2;
392 case DirectY: return 2;
393 case IDirect: return 2;
394 case IDirectX: return 2;
395 case IDirectY: return 2;
396 case ILDirect: return 2;
397 case ILDirectY: return 2;
398 case Address: return 3;
399 case AddressX: return 3;
400 case AddressY: return 3;
401 case IAddressX: return 3;
402 case ILAddress: return 3;
403 case PAddress: return 3;
404 case PIAddress: return 3;
405 case Long: return 4;
406 case LongX: return 4;
407 case Stack: return 2;
408 case IStackY: return 2;
409 case BlockMove: return 3;
410 case RelativeShort: return 2;
411 case RelativeLong: return 3;
412 }
413 }
414
415 inline string SNESCPU::disassemble(unsigned pc, bool accum, bool index, uint8_t opcode, uint8_t pl, uint8_t ph, uint8_t pb) {
416 string name = opcodeInfo[opcode].name;
417 unsigned mode = opcodeInfo[opcode].mode;
418
419 if(mode == Implied) return name;
420 if(mode == Constant) return { name, " #$", hex<2>(pl) };
421 if(mode == AccumConstant) return { name, " #$", accum ? "" : hex<2>(ph), hex<2>(pl) };
422 if(mode == IndexConstant) return { name, " #$", index ? "" : hex<2>(ph), hex<2>(pl) };
423 if(mode == Direct) return { name, " $", hex<2>(pl) };
424 if(mode == DirectX) return { name, " $", hex<2>(pl), ",x" };
425 if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" };
426 if(mode == IDirect) return { name, " ($", hex<2>(pl), ")" };
427 if(mode == IDirectX) return { name, " ($", hex<2>(pl), ",x)" };
428 if(mode == IDirectY) return { name, " ($", hex<2>(pl), "),y" };
429 if(mode == ILDirect) return { name, " [$", hex<2>(pl), "]" };
430 if(mode == ILDirectY) return { name, " [$", hex<2>(pl), "],y" };
431 if(mode == Address) return { name, " $", hex<2>(ph), hex<2>(pl) };
432 if(mode == AddressX) return { name, " $", hex<2>(ph), hex<2>(pl), ",x" };
433 if(mode == AddressY) return { name, " $", hex<2>(ph), hex<2>(pl), ",y" };
434 if(mode == IAddressX) return { name, " ($", hex<2>(ph), hex<2>(pl), ",x)" };
435 if(mode == ILAddress) return { name, " [$", hex<2>(ph), hex<2>(pl), "]" };
436 if(mode == PAddress) return { name, " $", hex<2>(ph), hex<2>(pl) };
437 if(mode == PIAddress) return { name, " ($", hex<2>(ph), hex<2>(pl), ")" };
438 if(mode == Long) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl) };
439 if(mode == LongX) return { name, " $", hex<2>(pb), hex<2>(ph), hex<2>(pl), ",x" };
440 if(mode == Stack) return { name, " $", hex<2>(pl), ",s" };
441 if(mode == IStackY) return { name, " ($", hex<2>(pl), ",s),y" };
442 if(mode == BlockMove) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) };
443 if(mode == RelativeShort) {
444 unsigned addr = (pc + 2) + (int8_t)(pl << 0);
445 return { name, " $", hex<4>(addr) };
446 }
447 if(mode == RelativeLong) {
448 unsigned addr = (pc + 3) + (int16_t)((ph << 8) + (pl << 0));
449 return { name, " $", hex<4>(addr) };
450 }
451
452 return "";
453 }
454
455 }
456
457 #endif
+0
-639
snespurify/phoenix/nall/snes/smp.hpp less more
0 #ifndef NALL_SNES_SMP_HPP
1 #define NALL_SNES_SMP_HPP
2
3 namespace nall {
4
5 struct SNESSMP {
6 enum : unsigned {
7 Implied, //
8 TVector, //0
9 Direct, //$00
10 DirectRelative, //$00,+/-$00
11 ADirect, //a,$00
12 AAbsolute, //a,$0000
13 AIX, //a,(x)
14 AIDirectX, //a,($00+x)
15 AConstant, //a,#$00
16 DirectDirect, //$00,$00
17 CAbsoluteBit, //c,$0000:0
18 Absolute, //$0000
19 P, //p
20 AbsoluteA, //$0000,a
21 Relative, //+/-$00
22 ADirectX, //a,$00+x
23 AAbsoluteX, //a,$0000+x
24 AAbsoluteY, //a,$0000+y
25 AIDirectY, //a,($00)+y
26 DirectConstant, //$00,#$00
27 IXIY, //(x),(y)
28 DirectX, //$00+x
29 A, //a
30 X, //x
31 XAbsolute, //x,$0000
32 IAbsoluteX, //($0000+x)
33 CNAbsoluteBit, //c,!$0000:0
34 XDirect, //x,$00
35 PVector, //$ff00
36 YaDirect, //ya,$00
37 XA, //x,a
38 YAbsolute, //y,$0000
39 Y, //y
40 AX, //a,x
41 YDirect, //y,$00
42 YConstant, //y,#$00
43 XSp, //x,sp
44 YaX, //ya,x
45 IXPA, //(x)+,a
46 SpX, //sp,x
47 AIXP, //a,(x)+
48 DirectA, //$00,a
49 IXA, //(x),a
50 IDirectXA, //($00+x),a
51 XConstant, //x,#$00
52 AbsoluteX, //$0000,x
53 AbsoluteBitC, //$0000:0,c
54 DirectY, //$00,y
55 AbsoluteY, //$0000,y
56 Ya, //ya
57 DirectXA, //$00+x,a
58 AbsoluteXA, //$0000+x,a
59 AbsoluteYA, //$0000+y,a
60 IDirectYA, //($00)+y,a
61 DirectYX, //$00+y,x
62 DirectYa, //$00,ya
63 DirectXY, //$00+x,y
64 AY, //a,y
65 DirectXRelative, //$00+x,+/-$00
66 XDirectY, //x,$00+y
67 YDirectX, //y,$00+x
68 YA, //y,a
69 YRelative, //y,+/-$00
70 };
71
72 struct OpcodeInfo {
73 char name[6];
74 unsigned mode;
75 };
76
77 static const OpcodeInfo opcodeInfo[256];
78
79 static unsigned getOpcodeLength(uint8_t opcode);
80 static string disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph);
81 static string disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph);
82 };
83
84 const SNESSMP::OpcodeInfo SNESSMP::opcodeInfo[256] = {
85 //0x00 - 0x0f
86 { "nop ", Implied },
87 { "tcall", TVector },
88 { "set0 ", Direct },
89 { "bbs0 ", DirectRelative },
90
91 { "or ", ADirect },
92 { "or ", AAbsolute },
93 { "or ", AIX },
94 { "or ", AIDirectX },
95
96 { "or ", AConstant },
97 { "or ", DirectDirect },
98 { "or1 ", CAbsoluteBit },
99 { "asl ", Direct },
100
101 { "asl ", Absolute },
102 { "push ", P },
103 { "tset ", AbsoluteA },
104 { "brk ", Implied },
105
106 //0x10 - 0x1f
107 { "bpl ", Relative },
108 { "tcall", TVector },
109 { "clr0 ", Direct },
110 { "bbc0 ", DirectRelative },
111
112 { "or ", ADirectX },
113 { "or ", AAbsoluteX },
114 { "or ", AAbsoluteY },
115 { "or ", AIDirectY },
116
117 { "or ", DirectConstant },
118 { "or ", IXIY },
119 { "decw ", Direct },
120 { "asl ", DirectX },
121
122 { "asl ", A },
123 { "dec ", X },
124 { "cmp ", XAbsolute },
125 { "jmp ", IAbsoluteX },
126
127 //0x20 - 0x2f
128 { "clrp ", Implied },
129 { "tcall", TVector },
130 { "set1 ", Direct },
131 { "bbs1 ", DirectRelative },
132
133 { "and ", ADirect },
134 { "and ", AAbsolute },
135 { "and ", AIX },
136 { "and ", AIDirectX },
137
138 { "and ", AConstant },
139 { "and ", DirectDirect },
140 { "or1 ", CNAbsoluteBit },
141 { "rol ", Direct },
142
143 { "rol ", Absolute },
144 { "push ", A },
145 { "cbne ", DirectRelative },
146 { "bra ", Relative },
147
148 //0x30 - 0x3f
149 { "bmi ", Relative },
150 { "tcall", TVector },
151 { "clr1 ", Direct },
152 { "bbc1 ", DirectRelative },
153
154 { "and ", ADirectX },
155 { "and ", AAbsoluteX },
156 { "and ", AAbsoluteY },
157 { "and ", AIDirectY },
158
159 { "and ", DirectConstant },
160 { "and ", IXIY },
161 { "incw ", Direct },
162 { "rol ", DirectX },
163
164 { "rol ", A },
165 { "inc ", X },
166 { "cmp ", XDirect },
167 { "call ", Absolute },
168
169 //0x40 - 0x4f
170 { "setp ", Implied },
171 { "tcall", TVector },
172 { "set2 ", Direct },
173 { "bbs2 ", DirectRelative },
174
175 { "eor ", ADirect },
176 { "eor ", AAbsolute },
177 { "eor ", AIX },
178 { "eor ", AIDirectX },
179
180 { "eor ", AConstant },
181 { "eor ", DirectDirect },
182 { "and1 ", CAbsoluteBit },
183 { "lsr ", Direct },
184
185 { "lsr ", Absolute },
186 { "push ", X },
187 { "tclr ", AbsoluteA },
188 { "pcall", PVector },
189
190 //0x50 - 0x5f
191 { "bvc ", Relative },
192 { "tcall", TVector },
193 { "clr2 ", Direct },
194 { "bbc2 ", DirectRelative },
195
196 { "eor ", ADirectX },
197 { "eor ", AAbsoluteX },
198 { "eor ", AAbsoluteY },
199 { "eor ", AIDirectY },
200
201 { "eor ", DirectConstant },
202 { "eor ", IXIY },
203 { "cmpw ", YaDirect },
204 { "lsr ", DirectX },
205
206 { "lsr ", A },
207 { "mov ", XA },
208 { "cmp ", YAbsolute },
209 { "jmp ", Absolute },
210
211 //0x60 - 0x6f
212 { "clrc ", Implied },
213 { "tcall", TVector },
214 { "set3 ", Direct },
215 { "bbs3 ", DirectRelative },
216
217 { "cmp ", ADirect },
218 { "cmp ", AAbsolute },
219 { "cmp ", AIX },
220 { "cmp ", AIDirectX },
221
222 { "cmp ", AConstant },
223 { "cmp ", DirectDirect },
224 { "and1 ", CNAbsoluteBit },
225 { "ror ", Direct },
226
227 { "ror ", Absolute },
228 { "push ", Y },
229 { "dbnz ", DirectRelative },
230 { "ret ", Implied },
231
232 //0x70 - 0x7f
233 { "bvs ", Relative },
234 { "tcall", TVector },
235 { "clr3 ", Direct },
236 { "bbc3 ", DirectRelative },
237
238 { "cmp ", ADirectX },
239 { "cmp ", AAbsoluteX },
240 { "cmp ", AAbsoluteY },
241 { "cmp ", AIDirectY },
242
243 { "cmp ", DirectConstant },
244 { "cmp ", IXIY },
245 { "addw ", YaDirect },
246 { "ror ", DirectX },
247
248 { "ror ", A },
249 { "mov ", AX },
250 { "cmp ", YDirect },
251 { "reti ", Implied },
252
253 //0x80 - 0x8f
254 { "setc ", Implied },
255 { "tcall", TVector },
256 { "set4 ", Direct },
257 { "bbs4 ", DirectRelative },
258
259 { "adc ", ADirect },
260 { "adc ", AAbsolute },
261 { "adc ", AIX },
262 { "adc ", AIDirectX },
263
264 { "adc ", AConstant },
265 { "adc ", DirectDirect },
266 { "eor1 ", CAbsoluteBit },
267 { "dec ", Direct },
268
269 { "dec ", Absolute },
270 { "mov ", YConstant },
271 { "pop ", P },
272 { "mov ", DirectConstant },
273
274 //0x90 - 0x9f
275 { "bcc ", Relative },
276 { "tcall", TVector },
277 { "clr4 ", Direct },
278 { "bbc4 ", DirectRelative },
279
280 { "adc ", ADirectX },
281 { "adc ", AAbsoluteX },
282 { "adc ", AAbsoluteY },
283 { "adc ", AIDirectY },
284
285 { "adc ", DirectRelative },
286 { "adc ", IXIY },
287 { "subw ", YaDirect },
288 { "dec ", DirectX },
289
290 { "dec ", A },
291 { "mov ", XSp },
292 { "div ", YaX },
293 { "xcn ", A },
294
295 //0xa0 - 0xaf
296 { "ei ", Implied },
297 { "tcall", TVector },
298 { "set5 ", Direct },
299 { "bbs5 ", DirectRelative },
300
301 { "sbc ", ADirect },
302 { "sbc ", AAbsolute },
303 { "sbc ", AIX },
304 { "sbc ", AIDirectX },
305
306 { "sbc ", AConstant },
307 { "sbc ", DirectDirect },
308 { "mov1 ", CAbsoluteBit },
309 { "inc ", Direct },
310
311 { "inc ", Absolute },
312 { "cmp ", YConstant },
313 { "pop ", A },
314 { "mov ", IXPA },
315
316 //0xb0 - 0xbf
317 { "bcs ", Relative },
318 { "tcall", TVector },
319 { "clr5 ", Direct },
320 { "bbc5 ", DirectRelative },
321
322 { "sbc ", ADirectX },
323 { "sbc ", AAbsoluteX },
324 { "sbc ", AAbsoluteY },
325 { "sbc ", AIDirectY },
326
327 { "sbc ", DirectConstant },
328 { "sbc ", IXIY },
329 { "movw ", YaDirect },
330 { "inc ", DirectX },
331
332 { "inc ", A },
333 { "mov ", SpX },
334 { "das ", A },
335 { "mov ", AIXP },
336
337 //0xc0 - 0xcf
338 { "di ", Implied },
339 { "tcall", TVector },
340 { "set6 ", Direct },
341 { "bbs6 ", DirectRelative },
342
343 { "mov ", DirectA },
344 { "mov ", AbsoluteA },
345 { "mov ", IXA },
346 { "mov ", IDirectXA },
347
348 { "cmp ", XConstant },
349 { "mov ", AbsoluteX },
350 { "mov1 ", AbsoluteBitC },
351 { "mov ", DirectY },
352
353 { "mov ", AbsoluteY },
354 { "mov ", XConstant },
355 { "pop ", X },
356 { "mul ", Ya },
357
358 //0xd0 - 0xdf
359 { "bne ", Relative },
360 { "tcall", TVector },
361 { "clr6 ", Relative },
362 { "bbc6 ", DirectRelative },
363
364 { "mov ", DirectXA },
365 { "mov ", AbsoluteXA },
366 { "mov ", AbsoluteYA },
367 { "mov ", IDirectYA },
368
369 { "mov ", DirectX },
370 { "mov ", DirectYX },
371 { "movw ", DirectYa },
372 { "mov ", DirectXY },
373
374 { "dec ", Y },
375 { "mov ", AY },
376 { "cbne ", DirectXRelative },
377 { "daa ", A },
378
379 //0xe0 - 0xef
380 { "clrv ", Implied },
381 { "tcall", TVector },
382 { "set7 ", Direct },
383 { "bbs7 ", DirectRelative },
384
385 { "mov ", ADirect },
386 { "mov ", AAbsolute },
387 { "mov ", AIX },
388 { "mov ", AIDirectX },
389
390 { "mov ", AConstant },
391 { "mov ", XAbsolute },
392 { "not1 ", CAbsoluteBit },
393 { "mov ", YDirect },
394
395 { "mov ", YAbsolute },
396 { "notc ", Implied },
397 { "pop ", Y },
398 { "sleep", Implied },
399
400 //0xf0 - 0xff
401 { "beq ", Relative },
402 { "tcall", TVector },
403 { "clr7 ", Direct },
404 { "bbc7 ", DirectRelative },
405
406 { "mov ", ADirectX },
407 { "mov ", AAbsoluteX },
408 { "mov ", AAbsoluteY },
409 { "mov ", AIDirectY },
410
411 { "mov ", XDirect },
412 { "mov ", XDirectY },
413 { "mov ", DirectDirect },
414 { "mov ", YDirectX },
415
416 { "inc ", Y },
417 { "mov ", YA },
418 { "dbz ", YRelative },
419 { "stop ", Implied },
420 };
421
422 inline unsigned SNESSMP::getOpcodeLength(uint8_t opcode) {
423 switch(opcodeInfo[opcode].mode) { default:
424 case Implied: return 1; //
425 case TVector: return 1; //0
426 case Direct: return 2; //$00
427 case DirectRelative: return 3; //$00,+/-$00
428 case ADirect: return 2; //a,$00
429 case AAbsolute: return 3; //a,$0000
430 case AIX: return 1; //a,(x)
431 case AIDirectX: return 2; //a,($00+x)
432 case AConstant: return 2; //a,#$00
433 case DirectDirect: return 3; //$00,$00
434 case CAbsoluteBit: return 3; //c,$0000:0
435 case Absolute: return 3; //$0000
436 case P: return 1; //p
437 case AbsoluteA: return 3; //$0000,a
438 case Relative: return 2; //+/-$00
439 case ADirectX: return 2; //a,$00+x
440 case AAbsoluteX: return 3; //a,$0000+x
441 case AAbsoluteY: return 3; //a,$0000+y
442 case AIDirectY: return 2; //a,($00)+y
443 case DirectConstant: return 3; //$00,#$00
444 case IXIY: return 1; //(x),(y)
445 case DirectX: return 2; //$00+x
446 case A: return 1; //a
447 case X: return 1; //x
448 case XAbsolute: return 3; //x,$0000
449 case IAbsoluteX: return 3; //($0000+x)
450 case CNAbsoluteBit: return 3; //c,!$0000:0
451 case XDirect: return 2; //x,$00
452 case PVector: return 2; //$ff00
453 case YaDirect: return 2; //ya,$00
454 case XA: return 1; //x,a
455 case YAbsolute: return 3; //y,$0000
456 case Y: return 1; //y
457 case AX: return 1; //a,x
458 case YDirect: return 2; //y,$00
459 case YConstant: return 2; //y,#$00
460 case XSp: return 1; //x,sp
461 case YaX: return 1; //ya,x
462 case IXPA: return 1; //(x)+,a
463 case SpX: return 1; //sp,x
464 case AIXP: return 1; //a,(x)+
465 case DirectA: return 2; //$00,a
466 case IXA: return 1; //(x),a
467 case IDirectXA: return 2; //($00+x),a
468 case XConstant: return 2; //x,#$00
469 case AbsoluteX: return 3; //$0000,x
470 case AbsoluteBitC: return 3; //$0000:0,c
471 case DirectY: return 2; //$00,y
472 case AbsoluteY: return 3; //$0000,y
473 case Ya: return 1; //ya
474 case DirectXA: return 2; //$00+x,a
475 case AbsoluteXA: return 3; //$0000+x,a
476 case AbsoluteYA: return 3; //$0000+y,a
477 case IDirectYA: return 2; //($00)+y,a
478 case DirectYX: return 2; //$00+y,x
479 case DirectYa: return 2; //$00,ya
480 case DirectXY: return 2; //$00+x,y
481 case AY: return 1; //a,y
482 case DirectXRelative: return 3; //$00+x,+/-$00
483 case XDirectY: return 2; //x,$00+y
484 case YDirectX: return 2; //y,$00+x
485 case YA: return 1; //y,a
486 case YRelative: return 2; //y,+/-$00
487 }
488 }
489
490 inline string SNESSMP::disassemble(uint16_t pc, uint8_t opcode, uint8_t pl, uint8_t ph) {
491 string name = opcodeInfo[opcode].name;
492 unsigned mode = opcodeInfo[opcode].mode;
493 unsigned pa = (ph << 8) + pl;
494
495 if(mode == Implied) return name;
496 if(mode == TVector) return { name, " ", opcode >> 4 };
497 if(mode == Direct) return { name, " $", hex<2>(pl) };
498 if(mode == DirectRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
499 if(mode == ADirect) return { name, " a,$", hex<2>(pl) };
500 if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) };
501 if(mode == AIX) return { name, "a,(x)" };
502 if(mode == AIDirectX) return { name, " a,($", hex<2>(pl), "+x)" };
503 if(mode == AConstant) return { name, " a,#$", hex<2>(pl) };
504 if(mode == DirectDirect) return { name, " $", hex<2>(ph), ",$", hex<2>(pl) };
505 if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
506 if(mode == Absolute) return { name, " $", hex<4>(pa) };
507 if(mode == P) return { name, " p" };
508 if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" };
509 if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) };
510 if(mode == ADirectX) return { name, " a,$", hex<2>(pl), "+x" };
511 if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" };
512 if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" };
513 if(mode == AIDirectY) return { name, " a,($", hex<2>(pl), ")+y" };
514 if(mode == DirectConstant) return { name, " $", hex<2>(ph), ",#$", hex<2>(pl) };
515 if(mode == IXIY) return { name, " (x),(y)" };
516 if(mode == DirectX) return { name, " $", hex<2>(pl), "+x" };
517 if(mode == A) return { name, " a" };
518 if(mode == X) return { name, " x" };
519 if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) };
520 if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" };
521 if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
522 if(mode == XDirect) return { name, " x,$", hex<2>(pl) };
523 if(mode == PVector) return { name, " $ff", hex<2>(pl) };
524 if(mode == YaDirect) return { name, " ya,$", hex<2>(pl) };
525 if(mode == XA) return { name, " x,a" };
526 if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) };
527 if(mode == Y) return { name, " y" };
528 if(mode == AX) return { name, " a,x" };
529 if(mode == YDirect) return { name, " y,$", hex<2>(pl) };
530 if(mode == YConstant) return { name, " y,#$", hex<2>(pl) };
531 if(mode == XSp) return { name, " x,sp" };
532 if(mode == YaX) return { name, " ya,x" };
533 if(mode == IXPA) return { name, " (x)+,a" };
534 if(mode == SpX) return { name, " sp,x" };
535 if(mode == AIXP) return { name, " a,(x)+" };
536 if(mode == DirectA) return { name, " $", hex<2>(pl), ",a" };
537 if(mode == IXA) return { name, " (x),a" };
538 if(mode == IDirectXA) return { name, " ($", hex<2>(pl), "+x),a" };
539 if(mode == XConstant) return { name, " x,#$", hex<2>(pl) };
540 if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" };
541 if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" };
542 if(mode == DirectY) return { name, " $", hex<2>(pl), ",y" };
543 if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" };
544 if(mode == Ya) return { name, " ya" };
545 if(mode == DirectXA) return { name, " $", hex<2>(pl), "+x,a" };
546 if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" };
547 if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" };
548 if(mode == IDirectYA) return { name, " ($", hex<2>(pl), ")+y,a" };
549 if(mode == DirectYX) return { name, " $", hex<2>(pl), "+y,x" };
550 if(mode == DirectYa) return { name, " $", hex<2>(pl), ",ya" };
551 if(mode == DirectXY) return { name, " $", hex<2>(pl), "+x,y" };
552 if(mode == AY) return { name, " a,y" };
553 if(mode == DirectXRelative) return { name, " $", hex<2>(pl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
554 if(mode == XDirectY) return { name, " x,$", hex<2>(pl), "+y" };
555 if(mode == YDirectX) return { name, " y,$", hex<2>(pl), "+x" };
556 if(mode == YA) return { name, " y,a" };
557 if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) };
558
559 return "";
560 }
561
562 inline string SNESSMP::disassemble(uint16_t pc, bool p, uint8_t opcode, uint8_t pl, uint8_t ph) {
563 string name = opcodeInfo[opcode].name;
564 unsigned mode = opcodeInfo[opcode].mode;
565 unsigned pdl = (p << 8) + pl;
566 unsigned pdh = (p << 8) + ph;
567 unsigned pa = (ph << 8) + pl;
568
569 if(mode == Implied) return name;
570 if(mode == TVector) return { name, " ", opcode >> 4 };
571 if(mode == Direct) return { name, " $", hex<3>(pdl) };
572 if(mode == DirectRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
573 if(mode == ADirect) return { name, " a,$", hex<3>(pdl) };
574 if(mode == AAbsolute) return { name, " a,$", hex<4>(pa) };
575 if(mode == AIX) return { name, "a,(x)" };
576 if(mode == AIDirectX) return { name, " a,($", hex<3>(pdl), "+x)" };
577 if(mode == AConstant) return { name, " a,#$", hex<2>(pl) };
578 if(mode == DirectDirect) return { name, " $", hex<3>(pdh), ",$", hex<3>(pdl) };
579 if(mode == CAbsoluteBit) return { name, " c,$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
580 if(mode == Absolute) return { name, " $", hex<4>(pa) };
581 if(mode == P) return { name, " p" };
582 if(mode == AbsoluteA) return { name, " $", hex<4>(pa), ",a" };
583 if(mode == Relative) return { name, " $", hex<4>(pc + 2 + (int8_t)pl) };
584 if(mode == ADirectX) return { name, " a,$", hex<3>(pdl), "+x" };
585 if(mode == AAbsoluteX) return { name, " a,$", hex<4>(pa), "+x" };
586 if(mode == AAbsoluteY) return { name, " a,$", hex<4>(pa), "+y" };
587 if(mode == AIDirectY) return { name, " a,($", hex<3>(pdl), ")+y" };
588 if(mode == DirectConstant) return { name, " $", hex<3>(pdh), ",#$", hex<2>(pl) };
589 if(mode == IXIY) return { name, " (x),(y)" };
590 if(mode == DirectX) return { name, " $", hex<3>(pdl), "+x" };
591 if(mode == A) return { name, " a" };
592 if(mode == X) return { name, " x" };
593 if(mode == XAbsolute) return { name, " x,$", hex<4>(pa) };
594 if(mode == IAbsoluteX) return { name, " ($", hex<4>(pa), "+x)" };
595 if(mode == CNAbsoluteBit) return { name, " c,!$", hex<4>(pa & 0x1fff), ":", pa >> 13 };
596 if(mode == XDirect) return { name, " x,$", hex<3>(pdl) };
597 if(mode == PVector) return { name, " $ff", hex<2>(pl) };
598 if(mode == YaDirect) return { name, " ya,$", hex<3>(pdl) };
599 if(mode == XA) return { name, " x,a" };
600 if(mode == YAbsolute) return { name, " y,$", hex<4>(pa) };
601 if(mode == Y) return { name, " y" };
602 if(mode == AX) return { name, " a,x" };
603 if(mode == YDirect) return { name, " y,$", hex<3>(pdl) };
604 if(mode == YConstant) return { name, " y,#$", hex<2>(pl) };
605 if(mode == XSp) return { name, " x,sp" };
606 if(mode == YaX) return { name, " ya,x" };
607 if(mode == IXPA) return { name, " (x)+,a" };
608 if(mode == SpX) return { name, " sp,x" };
609 if(mode == AIXP) return { name, " a,(x)+" };
610 if(mode == DirectA) return { name, " $", hex<3>(pdl), ",a" };
611 if(mode == IXA) return { name, " (x),a" };
612 if(mode == IDirectXA) return { name, " ($", hex<3>(pdl), "+x),a" };
613 if(mode == XConstant) return { name, " x,#$", hex<2>(pl) };
614 if(mode == AbsoluteX) return { name, " $", hex<4>(pa), ",x" };
615 if(mode == AbsoluteBitC) return { name, " $", hex<4>(pa & 0x1fff), ":", pa >> 13, ",c" };
616 if(mode == DirectY) return { name, " $", hex<3>(pdl), ",y" };
617 if(mode == AbsoluteY) return { name, " $", hex<4>(pa), ",y" };
618 if(mode == Ya) return { name, " ya" };
619 if(mode == DirectXA) return { name, " $", hex<3>(pdl), "+x,a" };
620 if(mode == AbsoluteXA) return { name, " $", hex<4>(pa), "+x,a" };
621 if(mode == AbsoluteYA) return { name, " $", hex<4>(pa), "+y,a" };
622 if(mode == IDirectYA) return { name, " ($", hex<3>(pdl), ")+y,a" };
623 if(mode == DirectYX) return { name, " $", hex<3>(pdl), "+y,x" };
624 if(mode == DirectYa) return { name, " $", hex<3>(pdl), ",ya" };
625 if(mode == DirectXY) return { name, " $", hex<3>(pdl), "+x,y" };
626 if(mode == AY) return { name, " a,y" };
627 if(mode == DirectXRelative) return { name, " $", hex<3>(pdl), ",$", hex<4>(pc + 3 + (int8_t)ph) };
628 if(mode == XDirectY) return { name, " x,$", hex<3>(pdl), "+y" };
629 if(mode == YDirectX) return { name, " y,$", hex<3>(pdl), "+x" };
630 if(mode == YA) return { name, " y,a" };
631 if(mode == YRelative) return { name, " y,$", hex<4>(pc + 2 + (int8_t)pl) };
632
633 return "";
634 }
635
636 }
637
638 #endif
+0
-62
snespurify/phoenix/nall/sort.hpp less more
0 #ifndef NALL_SORT_HPP
1 #define NALL_SORT_HPP
2
3 #include <nall/utility.hpp>
4
5 //class: merge sort
6 //average: O(n log n)
7 //worst: O(n log n)
8 //memory: O(n)
9 //stack: O(log n)
10 //stable?: yes
11
12 //notes:
13 //there are two primary reasons for choosing merge sort
14 //over the (usually) faster quick sort*:
15 //1: it is a stable sort.
16 //2: it lacks O(n^2) worst-case overhead.
17 //(* which is also O(n log n) in the average case.)
18
19 namespace nall {
20 template<typename T>
21 void sort(T list[], unsigned length) {
22 if(length <= 1) return; //nothing to sort
23
24 //use insertion sort to quickly sort smaller blocks
25 if(length < 64) {
26 for(unsigned i = 0; i < length; i++) {
27 unsigned min = i;
28 for(unsigned j = i + 1; j < length; j++) {
29 if(list[j] < list[min]) min = j;
30 }
31 if(min != i) swap(list[i], list[min]);
32 }
33 return;
34 }
35
36 //split list in half and recursively sort both
37 unsigned middle = length / 2;
38 sort(list, middle);
39 sort(list + middle, length - middle);
40
41 //left and right are sorted here; perform merge sort
42 T *buffer = new T[length];
43 unsigned offset = 0;
44 unsigned left = 0;
45 unsigned right = middle;
46 while(left < middle && right < length) {
47 if(list[left] < list[right]) {
48 buffer[offset++] = list[left++];
49 } else {
50 buffer[offset++] = list[right++];
51 }
52 }
53 while(left < middle) buffer[offset++] = list[left++];
54 while(right < length) buffer[offset++] = list[right++];
55
56 for(unsigned i = 0; i < length; i++) list[i] = buffer[i];
57 delete[] buffer;
58 }
59 }
60
61 #endif
+0
-20
snespurify/phoenix/nall/static.hpp less more
0 #ifndef NALL_STATIC_HPP
1 #define NALL_STATIC_HPP
2
3 namespace nall {
4 template<bool C, typename T, typename F> struct static_if { typedef T type; };
5 template<typename T, typename F> struct static_if<false, T, F> { typedef F type; };
6 template<typename C, typename T, typename F> struct mp_static_if { typedef typename static_if<C::type, T, F>::type type; };
7
8 template<bool A, bool B> struct static_and { enum { value = false }; };
9 template<> struct static_and<true, true> { enum { value = true }; };
10 template<typename A, typename B> struct mp_static_and { enum { value = static_and<A::value, B::value>::value }; };
11
12 template<bool A, bool B> struct static_or { enum { value = false }; };
13 template<> struct static_or<false, true> { enum { value = true }; };
14 template<> struct static_or<true, false> { enum { value = true }; };
15 template<> struct static_or<true, true> { enum { value = true }; };
16 template<typename A, typename B> struct mp_static_or { enum { value = static_or<A::value, B::value>::value }; };
17 }
18
19 #endif
+0
-44
snespurify/phoenix/nall/stdint.hpp less more
0 #ifndef NALL_STDINT_HPP
1 #define NALL_STDINT_HPP
2
3 #include <nall/static.hpp>
4
5 #if defined(_MSC_VER)
6 typedef signed char int8_t;
7 typedef signed short int16_t;
8 typedef signed int int32_t;
9 typedef signed long long int64_t;
10 typedef int64_t intmax_t;
11 #if defined(_WIN64)
12 typedef int64_t intptr_t;
13 #else
14 typedef int32_t intptr_t;
15 #endif
16
17 typedef unsigned char uint8_t;
18 typedef unsigned short uint16_t;
19 typedef unsigned int uint32_t;
20 typedef unsigned long long uint64_t;
21 typedef uint64_t uintmax_t;
22 #if defined(_WIN64)
23 typedef uint64_t uintptr_t;
24 #else
25 typedef uint32_t uintptr_t;
26 #endif
27 #else
28 #include <stdint.h>
29 #endif
30
31 namespace nall {
32 static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" );
33 static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
34 static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
35 static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");
36
37 static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" );
38 static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size");
39 static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size");
40 static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size");
41 }
42
43 #endif
+0
-162
snespurify/phoenix/nall/string/base.hpp less more
0 #ifndef NALL_STRING_BASE_HPP
1 #define NALL_STRING_BASE_HPP
2
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <nall/concept.hpp>
8 #include <nall/stdint.hpp>
9 #include <nall/utf8.hpp>
10 #include <nall/vector.hpp>
11
12 namespace nall {
13 class string;
14 template<typename T> inline const char* to_string(T);
15
16 class string {
17 public:
18 inline void reserve(unsigned);
19
20 template<typename... Args> inline string& assign(Args&&... args);
21 template<typename... Args> inline string& append(Args&&... args);
22 inline string& assign_(const char*);
23 inline string& append_(const char*);
24
25 inline bool readfile(const string&);
26
27 inline string& replace (const char*, const char*);
28 inline string& qreplace(const char*, const char*);
29
30 inline unsigned length() const;
31
32 inline bool equals(const char*) const;
33 inline bool iequals(const char*) const;
34
35 inline bool wildcard(const char*) const;
36 inline bool iwildcard(const char*) const;
37
38 inline bool beginswith(const char*) const;
39 inline bool ibeginswith(const char*) const;
40 inline bool endswith(const char*) const;
41 inline bool iendswith(const char*) const;
42
43 inline string& lower();
44 inline string& upper();
45 inline string& transform(const char *before, const char *after);
46
47 template<unsigned limit = 0> inline string& ltrim(const char *key = " ");
48 template<unsigned limit = 0> inline string& rtrim(const char *key = " ");
49 template<unsigned limit = 0> inline string& trim (const char *key = " ");
50
51 inline optional<unsigned> position(const char *key) const;
52 inline optional<unsigned> qposition(const char *key) const;
53
54 template<typename T> inline string& operator= (T value);
55 template<typename T> inline string& operator<<(T value);
56
57 inline operator const char*() const;
58 inline char* operator()();
59 inline char& operator[](int);
60
61 inline bool operator==(const char*) const;
62 inline bool operator!=(const char*) const;
63 inline bool operator< (const char*) const;
64 inline bool operator<=(const char*) const;
65 inline bool operator> (const char*) const;
66 inline bool operator>=(const char*) const;
67
68 inline string& operator=(const string&);
69 inline string& operator=(string&&);
70
71 template<typename... Args> inline string(Args&&... args);
72 inline string(const string&);
73 inline string(string&&);
74 inline ~string();
75
76 protected:
77 char *data;
78 unsigned size;
79
80 #if defined(QSTRING_H)
81 public:
82 inline operator QString() const;
83 #endif
84 };
85
86 class lstring : public linear_vector<string> {
87 public:
88 template<typename T> inline lstring& operator<<(T value);
89
90 inline optional<unsigned> find(const char*) const;
91 template<unsigned limit = 0> inline void split (const char*, const char*);
92 template<unsigned limit = 0> inline void qsplit(const char*, const char*);
93
94 lstring();
95 lstring(std::initializer_list<string>);
96 };
97
98 //compare.hpp
99 inline char chrlower(char c);
100 inline char chrupper(char c);
101 inline int stricmp(const char *str1, const char *str2);
102 inline bool wildcard(const char *str, const char *pattern);
103 inline bool iwildcard(const char *str, const char *pattern);
104 inline bool strbegin (const char *str, const char *key);
105 inline bool stribegin(const char *str, const char *key);
106 inline bool strend (const char *str, const char *key);
107 inline bool striend(const char *str, const char *key);
108
109 //convert.hpp
110 inline char* strlower(char *str);
111 inline char* strupper(char *str);
112 inline char* strtr(char *dest, const char *before, const char *after);
113 inline uintmax_t hex (const char *str);
114 inline intmax_t integer(const char *str);
115 inline uintmax_t decimal(const char *str);
116 inline uintmax_t binary (const char *str);
117 inline double fp (const char *str);
118
119 //math.hpp
120 inline bool strint (const char *str, int &result);
121 inline bool strmath(const char *str, int &result);
122
123 //platform.hpp
124 inline string realpath(const char *name);
125 inline string userpath();
126 inline string currentpath();
127
128 //strl.hpp
129 inline unsigned strlcpy(char *dest, const char *src, unsigned length);
130 inline unsigned strlcat(char *dest, const char *src, unsigned length);
131
132 //strpos.hpp
133 inline optional<unsigned> strpos(const char *str, const char *key);
134 inline optional<unsigned> qstrpos(const char *str, const char *key);
135
136 //trim.hpp
137 template<unsigned limit = 0> inline char* ltrim(char *str, const char *key = " ");
138 template<unsigned limit = 0> inline char* rtrim(char *str, const char *key = " ");
139 template<unsigned limit = 0> inline char* trim (char *str, const char *key = " ");
140
141 //utility.hpp
142 inline unsigned strlcpy(string &dest, const char *src, unsigned length);
143 inline unsigned strlcat(string &dest, const char *src, unsigned length);
144 inline string substr(const char *src, unsigned start = 0, unsigned length = 0);
145
146 inline string integer(intmax_t value);
147 template<unsigned length = 0> inline string linteger(intmax_t value);
148 template<unsigned length = 0> inline string rinteger(intmax_t value);
149 inline string decimal(uintmax_t value);
150 template<unsigned length = 0> inline string ldecimal(uintmax_t value);
151 template<unsigned length = 0> inline string rdecimal(uintmax_t value);
152 template<unsigned length = 0> inline string hex(uintmax_t value);
153 template<unsigned length = 0> inline string binary(uintmax_t value);
154 inline unsigned fp(char *str, double value);
155 inline string fp(double value);
156
157 //variadic.hpp
158 template<typename... Args> inline void print(Args&&... args);
159 };
160
161 #endif
+0
-75
snespurify/phoenix/nall/string/bsv.hpp less more
0 #ifndef NALL_STRING_BSV_HPP
1 #define NALL_STRING_BSV_HPP
2
3 //BSV parser
4 //version 0.01
5
6 namespace nall {
7
8 inline string bsv_decode(const char *input) {
9 string output;
10 unsigned offset = 0;
11 while(*input) {
12 //illegal characters
13 if(*input == '}' ) return "";
14 if(*input == '\r') return "";
15 if(*input == '\n') return "";
16
17 //normal characters
18 if(*input != '{') { output[offset++] = *input++; continue; }
19
20 //entities
21 if(strbegin(input, "{lf}")) { output[offset++] = '\n'; input += 4; continue; }
22 if(strbegin(input, "{lb}")) { output[offset++] = '{'; input += 4; continue; }
23 if(strbegin(input, "{rb}")) { output[offset++] = '}'; input += 4; continue; }
24
25 //illegal entities
26 return "";
27 }
28 output[offset] = 0;
29 return output;
30 }
31
32 inline string bsv_encode(const char *input) {
33 string output;
34 unsigned offset = 0;
35 while(*input) {
36 //illegal characters
37 if(*input == '\r') return "";
38
39 if(*input == '\n') {
40 output[offset++] = '{';
41 output[offset++] = 'l';
42 output[offset++] = 'f';
43 output[offset++] = '}';
44 input++;
45 continue;
46 }
47
48 if(*input == '{') {
49 output[offset++] = '{';
50 output[offset++] = 'l';
51 output[offset++] = 'b';
52 output[offset++] = '}';
53 input++;
54 continue;
55 }
56
57 if(*input == '}') {
58 output[offset++] = '{';
59 output[offset++] = 'r';
60 output[offset++] = 'b';
61 output[offset++] = '}';
62 input++;
63 continue;
64 }
65
66 output[offset++] = *input++;
67 }
68 output[offset] = 0;
69 return output;
70 }
71
72 }
73
74 #endif
+0
-32
snespurify/phoenix/nall/string/cast.hpp less more
0 #ifndef NALL_STRING_CAST_HPP
1 #define NALL_STRING_CAST_HPP
2
3 namespace nall {
4
5 //this is needed, as C++0x does not support explicit template specialization inside classes
6 template<> inline const char* to_string<bool> (bool v) { return v ? "true" : "false"; }
7 template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; snprintf(temp, 255, "%+d", v); return temp; }
8 template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; snprintf(temp, 255, "%u", v); return temp; }
9 template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
10 template<> inline const char* to_string<char*> (char *v) { return v; }
11 template<> inline const char* to_string<const char*> (const char *v) { return v; }
12 template<> inline const char* to_string<string> (string v) { return v; }
13 template<> inline const char* to_string<const string&>(const string &v) { return v; }
14
15 template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
16 template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
17
18 template<typename T> lstring& lstring::operator<<(T value) {
19 operator[](size()).assign(to_string<T>(value));
20 return *this;
21 }
22
23 #if defined(QSTRING_H)
24 template<> inline const char* to_string<QString>(QString v) { return v.toUtf8().constData(); }
25 template<> inline const char* to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
26 string::operator QString() const { return QString::fromUtf8(*this); }
27 #endif
28
29 }
30
31 #endif
+0
-110
snespurify/phoenix/nall/string/compare.hpp less more
0 #ifndef NALL_STRING_COMPARE_HPP
1 #define NALL_STRING_COMPARE_HPP
2
3 namespace nall {
4
5 char chrlower(char c) {
6 return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
7 }
8
9 char chrupper(char c) {
10 return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
11 }
12
13 int stricmp(const char *str1, const char *str2) {
14 while(*str1) {
15 if(chrlower(*str1) != chrlower(*str2)) break;
16 str1++, str2++;
17 }
18 return (int)chrlower(*str1) - (int)chrlower(*str2);
19 }
20
21 bool wildcard(const char *s, const char *p) {
22 const char *cp = 0, *mp = 0;
23 while(*s && *p != '*') {
24 if(*p != '?' && *s != *p) return false;
25 p++, s++;
26 }
27 while(*s) {
28 if(*p == '*') {
29 if(!*++p) return true;
30 mp = p, cp = s + 1;
31 } else if(*p == '?' || *p == *s) {
32 p++, s++;
33 } else {
34 p = mp, s = cp++;
35 }
36 }
37 while(*p == '*') p++;
38 return !*p;
39 }
40
41 bool iwildcard(const char *s, const char *p) {
42 const char *cp = 0, *mp = 0;
43 while(*s && *p != '*') {
44 if(*p != '?' && chrlower(*s) != chrlower(*p)) return false;
45 p++, s++;
46 }
47 while(*s) {
48 if(*p == '*') {
49 if(!*++p) return true;
50 mp = p, cp = s + 1;
51 } else if(*p == '?' || chrlower(*p) == chrlower(*s)) {
52 p++, s++;
53 } else {
54 p = mp, s = cp++;
55 }
56 }
57 while(*p == '*') p++;
58 return !*p;
59 }
60
61 bool strbegin(const char *str, const char *key) {
62 int i, ssl = strlen(str), ksl = strlen(key);
63
64 if(ksl > ssl) return false;
65 return (!memcmp(str, key, ksl));
66 }
67
68 bool stribegin(const char *str, const char *key) {
69 int ssl = strlen(str), ksl = strlen(key);
70
71 if(ksl > ssl) return false;
72 for(int i = 0; i < ksl; i++) {
73 if(str[i] >= 'A' && str[i] <= 'Z') {
74 if(str[i] != key[i] && str[i]+0x20 != key[i])return false;
75 } else if(str[i] >= 'a' && str[i] <= 'z') {
76 if(str[i] != key[i] && str[i]-0x20 != key[i])return false;
77 } else {
78 if(str[i] != key[i])return false;
79 }
80 }
81 return true;
82 }
83
84 bool strend(const char *str, const char *key) {
85 int ssl = strlen(str), ksl = strlen(key);
86
87 if(ksl > ssl) return false;
88 return (!memcmp(str + ssl - ksl, key, ksl));
89 }
90
91 bool striend(const char *str, const char *key) {
92 int ssl = strlen(str), ksl = strlen(key);
93
94 if(ksl > ssl) return false;
95 for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) {
96 if(str[i] >= 'A' && str[i] <= 'Z') {
97 if(str[i] != key[z] && str[i]+0x20 != key[z])return false;
98 } else if(str[i] >= 'a' && str[i] <= 'z') {
99 if(str[i] != key[z] && str[i]-0x20 != key[z])return false;
100 } else {
101 if(str[i] != key[z])return false;
102 }
103 }
104 return true;
105 }
106
107 }
108
109 #endif
+0
-125
snespurify/phoenix/nall/string/convert.hpp less more
0 #ifndef NALL_STRING_CONVERT_HPP
1 #define NALL_STRING_CONVERT_HPP
2
3 namespace nall {
4
5 char* strlower(char *str) {
6 if(!str) return 0;
7 int i = 0;
8 while(str[i]) {
9 str[i] = chrlower(str[i]);
10 i++;
11 }
12 return str;
13 }
14
15 char* strupper(char *str) {
16 if(!str) return 0;
17 int i = 0;
18 while(str[i]) {
19 str[i] = chrupper(str[i]);
20 i++;
21 }
22 return str;
23 }
24
25 char* strtr(char *dest, const char *before, const char *after) {
26 if(!dest || !before || !after) return dest;
27 int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
28
29 if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace
30 for(unsigned i = 0; i < sl; i++) {
31 for(unsigned l = 0; l < bsl; l++) {
32 if(dest[i] == before[l]) {
33 dest[i] = after[l];
34 break;
35 }
36 }
37 }
38
39 return dest;
40 }
41
42 uintmax_t hex(const char *str) {
43 if(!str) return 0;
44 uintmax_t result = 0;
45
46 //skip hex identifiers 0x and $, if present
47 if(*str == '0' && (*(str + 1) == 'X' || *(str + 1) == 'x')) str += 2;
48 else if(*str == '$') str++;
49
50 while(*str) {
51 uint8_t x = *str++;
52 if(x >= '0' && x <= '9') x -= '0';
53 else if(x >= 'A' && x <= 'F') x -= 'A' - 10;
54 else if(x >= 'a' && x <= 'f') x -= 'a' - 10;
55 else break; //stop at first invalid character
56 result = result * 16 + x;
57 }
58
59 return result;
60 }
61
62 intmax_t integer(const char *str) {
63 if(!str) return 0;
64 intmax_t result = 0;
65 bool negate = false;
66
67 //check for sign
68 if(*str == '+') {
69 negate = false;
70 str++;
71 } else if(*str == '-') {
72 negate = true;
73 str++;
74 }
75
76 while(*str) {
77 uint8_t x = *str++;
78 if(x >= '0' && x <= '9') x -= '0';
79 else break; //stop at first invalid character
80 result = result * 10 + x;
81 }
82
83 return !negate ? result : -result;
84 }
85
86 uintmax_t decimal(const char *str) {
87 if(!str) return 0;
88 uintmax_t result = 0;
89
90 while(*str) {
91 uint8_t x = *str++;
92 if(x >= '0' && x <= '9') x -= '0';
93 else break; //stop at first invalid character
94 result = result * 10 + x;
95 }
96
97 return result;
98 }
99
100 uintmax_t binary(const char *str) {
101 if(!str) return 0;
102 uintmax_t result = 0;
103
104 //skip bin identifiers 0b and %, if present
105 if(*str == '0' && (*(str + 1) == 'B' || *(str + 1) == 'b')) str += 2;
106 else if(*str == '%') str++;
107
108 while(*str) {
109 uint8_t x = *str++;
110 if(x == '0' || x == '1') x -= '0';
111 else break; //stop at first invalid character
112 result = result * 2 + x;
113 }
114
115 return result;
116 }
117
118 double fp(const char *str) {
119 return atof(str);
120 }
121
122 }
123
124 #endif
+0
-145
snespurify/phoenix/nall/string/core.hpp less more
0 #ifndef NALL_STRING_CORE_HPP
1 #define NALL_STRING_CORE_HPP
2
3 namespace nall {
4
5 static void istring(string &output) {
6 }
7
8 template<typename T, typename... Args>
9 static void istring(string &output, const T &value, Args&&... args) {
10 output.append_(to_string(value));
11 istring(output, std::forward<Args>(args)...);
12 }
13
14 void string::reserve(unsigned size_) {
15 if(size_ > size) {
16 size = size_;
17 data = (char*)realloc(data, size + 1);
18 data[size] = 0;
19 }
20 }
21
22 template<typename... Args> string& string::assign(Args&&... args) {
23 *data = 0;
24 istring(*this, std::forward<Args>(args)...);
25 return *this;
26 }
27
28 template<typename... Args> string& string::append(Args&&... args) {
29 istring(*this, std::forward<Args>(args)...);
30 return *this;
31 }
32
33 string& string::assign_(const char *s) {
34 unsigned length = strlen(s);
35 reserve(length);
36 strcpy(data, s);
37 return *this;
38 }
39
40 string& string::append_(const char *s) {
41 unsigned length = strlen(data) + strlen(s);
42 reserve(length);
43 strcat(data, s);
44 return *this;
45 }
46
47 string::operator const char*() const {
48 return data;
49 }
50
51 char* string::operator()() {
52 return data;
53 }
54
55 char& string::operator[](int index) {
56 reserve(index);
57 return data[index];
58 }
59
60 bool string::operator==(const char *str) const { return strcmp(data, str) == 0; }
61 bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; }
62 bool string::operator< (const char *str) const { return strcmp(data, str) < 0; }
63 bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; }
64 bool string::operator> (const char *str) const { return strcmp(data, str) > 0; }
65 bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; }
66
67 string& string::operator=(const string &value) {
68 assign(value);
69 return *this;
70 }
71
72 string& string::operator=(string &&source) {
73 if(data) free(data);
74 size = source.size;
75 data = source.data;
76 source.data = 0;
77 source.size = 0;
78 return *this;
79 }
80
81 template<typename... Args> string::string(Args&&... args) {
82 size = 64;
83 data = (char*)malloc(size + 1);
84 *data = 0;
85 istring(*this, std::forward<Args>(args)...);
86 }
87
88 string::string(const string &value) {
89 size = strlen(value);
90 data = strdup(value);
91 }
92
93 string::string(string &&source) {
94 size = source.size;
95 data = source.data;
96 source.data = 0;
97 }
98
99 string::~string() {
100 if(data) free(data);
101 }
102
103 bool string::readfile(const string &filename) {
104 assign("");
105
106 #if !defined(_WIN32)
107 FILE *fp = fopen(filename, "rb");
108 #else
109 FILE *fp = _wfopen(utf16_t(filename), L"rb");
110 #endif
111 if(!fp) return false;
112
113 fseek(fp, 0, SEEK_END);
114 unsigned size = ftell(fp);
115 rewind(fp);
116 char *fdata = new char[size + 1];
117 unsigned unused = fread(fdata, 1, size, fp);
118 fclose(fp);
119 fdata[size] = 0;
120 assign(fdata);
121 delete[] fdata;
122
123 return true;
124 }
125
126 optional<unsigned> lstring::find(const char *key) const {
127 for(unsigned i = 0; i < size(); i++) {
128 if(operator[](i) == key) return { true, i };
129 }
130 return { false, 0 };
131 }
132
133 inline lstring::lstring() {
134 }
135
136 inline lstring::lstring(std::initializer_list<string> list) {
137 for(const string *s = list.begin(); s != list.end(); ++s) {
138 operator<<(*s);
139 }
140 }
141
142 }
143
144 #endif
+0
-63
snespurify/phoenix/nall/string/filename.hpp less more
0 #ifndef NALL_FILENAME_HPP
1 #define NALL_FILENAME_HPP
2
3 namespace nall {
4
5 // "foo/bar.c" -> "foo/"
6 // "foo/" -> "foo/"
7 // "bar.c" -> "./"
8 inline string dir(char const *name) {
9 string result = name;
10 for(signed i = strlen(result); i >= 0; i--) {
11 if(result[i] == '/' || result[i] == '\\') {
12 result[i + 1] = 0;
13 break;
14 }
15 if(i == 0) result = "./";
16 }
17 return result;
18 }
19
20 // "foo/bar.c" -> "bar.c"
21 inline string notdir(char const *name) {
22 for(signed i = strlen(name); i >= 0; i--) {
23 if(name[i] == '/' || name[i] == '\\') {
24 name += i + 1;
25 break;
26 }
27 }
28 string result = name;
29 return result;
30 }
31
32 // "foo/bar.c" -> "foo/bar"
33 inline string basename(char const *name) {
34 string result = name;
35 for(signed i = strlen(result); i >= 0; i--) {
36 if(result[i] == '/' || result[i] == '\\') {
37 //file has no extension
38 break;
39 }
40 if(result[i] == '.') {
41 result[i] = 0;
42 break;
43 }
44 }
45 return result;
46 }
47
48 // "foo/bar.c" -> "c"
49 inline string extension(char const *name) {
50 for(signed i = strlen(name); i >= 0; i--) {
51 if(name[i] == '.') {
52 name += i + 1;
53 break;
54 }
55 }
56 string result = name;
57 return result;
58 }
59
60 }
61
62 #endif
+0
-164
snespurify/phoenix/nall/string/math.hpp less more
0 #ifndef NALL_STRING_MATH_HPP
1 #define NALL_STRING_MATH_HPP
2
3 namespace nall {
4
5 static int eval_integer(const char *&s) {
6 if(!*s) throw "unrecognized_integer";
7 int value = 0, x = *s, y = *(s + 1);
8
9 //hexadecimal
10 if(x == '0' && (y == 'X' || y == 'x')) {
11 s += 2;
12 while(true) {
13 if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; }
14 if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; }
15 if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; }
16 return value;
17 }
18 }
19
20 //binary
21 if(x == '0' && (y == 'B' || y == 'b')) {
22 s += 2;
23 while(true) {
24 if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; }
25 return value;
26 }
27 }
28
29 //octal (or decimal '0')
30 if(x == '0') {
31 s += 1;
32 while(true) {
33 if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; }
34 return value;
35 }
36 }
37
38 //decimal
39 if(x >= '0' && x <= '9') {
40 while(true) {
41 if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; }
42 return value;
43 }
44 }
45
46 //char
47 if(x == '\'' && y != '\'') {
48 s += 1;
49 while(true) {
50 value = value * 256 + *s++;
51 if(*s == '\'') { s += 1; return value; }
52 if(!*s) throw "mismatched_char";
53 }
54 }
55
56 throw "unrecognized_integer";
57 }
58
59 static int eval(const char *&s, int depth = 0) {
60 while(*s == ' ' || *s == '\t') s++; //trim whitespace
61 if(!*s) throw "unrecognized_token";
62 int value = 0, x = *s, y = *(s + 1);
63
64 if(*s == '(') {
65 value = eval(++s, 1);
66 if(*s++ != ')') throw "mismatched_group";
67 }
68
69 else if(x == '!') value = !eval(++s, 13);
70 else if(x == '~') value = ~eval(++s, 13);
71 else if(x == '+') value = +eval(++s, 13);
72 else if(x == '-') value = -eval(++s, 13);
73
74 else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
75
76 else throw "unrecognized_token";
77
78 while(true) {
79 while(*s == ' ' || *s == '\t') s++; //trim whitespace
80 if(!*s) break;
81 x = *s, y = *(s + 1);
82
83 if(depth >= 13) break;
84 if(x == '*') { value *= eval(++s, 13); continue; }
85 if(x == '/') { value /= eval(++s, 13); continue; }
86 if(x == '%') { value %= eval(++s, 13); continue; }
87
88 if(depth >= 12) break;
89 if(x == '+') { value += eval(++s, 12); continue; }
90 if(x == '-') { value -= eval(++s, 12); continue; }
91
92 if(depth >= 11) break;
93 if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; }
94 if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; }
95
96 if(depth >= 10) break;
97 if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; }
98 if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; }
99 if(x == '<') { value = value < eval(++s, 10); continue; }
100 if(x == '>') { value = value > eval(++s, 10); continue; }
101
102 if(depth >= 9) break;
103 if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; }
104 if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; }
105
106 if(depth >= 8) break;
107 if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; }
108
109 if(depth >= 7) break;
110 if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; }
111
112 if(depth >= 6) break;
113 if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; }
114
115 if(depth >= 5) break;
116 if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; }
117
118 if(depth >= 4) break;
119 if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; }
120
121 if(depth >= 3) break;
122 if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; }
123
124 if(x == '?') {
125 int lhs = eval(++s, 2);
126 if(*s != ':') throw "mismatched_ternary";
127 int rhs = eval(++s, 2);
128 value = value ? lhs : rhs;
129 continue;
130 }
131 if(depth >= 2) break;
132
133 if(depth > 0 && x == ')') break;
134
135 throw "unrecognized_token";
136 }
137
138 return value;
139 }
140
141 bool strint(const char *s, int &result) {
142 try {
143 result = eval_integer(s);
144 return true;
145 } catch(const char*) {
146 result = 0;
147 return false;
148 }
149 }
150
151 bool strmath(const char *s, int &result) {
152 try {
153 result = eval(s);
154 return true;
155 } catch(const char*) {
156 result = 0;
157 return false;
158 }
159 }
160
161 }
162
163 #endif
+0
-40
snespurify/phoenix/nall/string/platform.hpp less more
0 #ifndef NALL_STRING_PLATFORM_HPP
1 #define NALL_STRING_PLATFORM_HPP
2
3 namespace nall {
4
5 string currentpath() {
6 char path[PATH_MAX];
7 if(::getcwd(path)) {
8 string result(path);
9 result.transform("\\", "/");
10 if(result.endswith("/") == false) result.append("/");
11 return result;
12 }
13 return "./";
14 }
15
16 string userpath() {
17 char path[PATH_MAX];
18 if(::userpath(path)) {
19 string result(path);
20 result.transform("\\", "/");
21 if(result.endswith("/") == false) result.append("/");
22 return result;
23 }
24 return currentpath();
25 }
26
27 string realpath(const char *name) {
28 char path[PATH_MAX];
29 if(::realpath(name, path)) {
30 string result(path);
31 result.transform("\\", "/");
32 return result;
33 }
34 return userpath();
35 }
36
37 }
38
39 #endif
+0
-103
snespurify/phoenix/nall/string/replace.hpp less more
0 #ifndef NALL_STRING_REPLACE_HPP
1 #define NALL_STRING_REPLACE_HPP
2
3 namespace nall {
4
5 string& string::replace(const char *key, const char *token) {
6 int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length();
7 unsigned int replace_count = 0, size = ssl;
8 char *buffer;
9
10 if(ksl <= ssl) {
11 if(tsl > ksl) { //the new string may be longer than the old string...
12 for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
13 if(!memcmp(data + i, key, ksl)) {
14 replace_count++;
15 i += ksl;
16 } else i++;
17 }
18 size = ssl + ((tsl - ksl) * replace_count);
19 reserve(size);
20 }
21
22 buffer = new char[size + 1];
23 for(i = z = 0; i < ssl;) {
24 if(i <= ssl - ksl) {
25 if(!memcmp(data + i, key, ksl)) {
26 memcpy(buffer + z, token, tsl);
27 z += tsl;
28 i += ksl;
29 } else buffer[z++] = data[i++];
30 } else buffer[z++] = data[i++];
31 }
32 buffer[z] = 0;
33
34 assign(buffer);
35 delete[] buffer;
36 }
37
38 return *this;
39 }
40
41 string& string::qreplace(const char *key, const char *token) {
42 int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length();
43 unsigned int replace_count = 0, size = ssl;
44 uint8_t x;
45 char *buffer;
46
47 if(ksl <= ssl) {
48 if(tsl > ksl) {
49 for(i = 0; i <= ssl - ksl;) {
50 x = data[i];
51 if(x == '\"' || x == '\'') {
52 l = i;
53 i++;
54 while(data[i++] != x) {
55 if(i == ssl) {
56 i = l;
57 break;
58 }
59 }
60 }
61 if(!memcmp(data + i, key, ksl)) {
62 replace_count++;
63 i += ksl;
64 } else i++;
65 }
66 size = ssl + ((tsl - ksl) * replace_count);
67 reserve(size);
68 }
69
70 buffer = new char[size + 1];
71 for(i = z = 0; i < ssl;) {
72 x = data[i];
73 if(x == '\"' || x == '\'') {
74 l = i++;
75 while(data[i] != x && i < ssl)i++;
76 if(i >= ssl)i = l;
77 else {
78 memcpy(buffer + z, data + l, i - l);
79 z += i - l;
80 }
81 }
82 if(i <= ssl - ksl) {
83 if(!memcmp(data + i, key, ksl)) {
84 memcpy(buffer + z, token, tsl);
85 z += tsl;
86 i += ksl;
87 replace_count++;
88 } else buffer[z++] = data[i++];
89 } else buffer[z++] = data[i++];
90 }
91 buffer[z] = 0;
92
93 assign(buffer);
94 delete[] buffer;
95 }
96
97 return *this;
98 }
99
100 };
101
102 #endif
+0
-58
snespurify/phoenix/nall/string/split.hpp less more
0 #ifndef NALL_STRING_SPLIT_HPP
1 #define NALL_STRING_SPLIT_HPP
2
3 namespace nall {
4
5 template<unsigned Limit> void lstring::split(const char *key, const char *src) {
6 unsigned limit = Limit;
7 reset();
8
9 int ssl = strlen(src), ksl = strlen(key);
10 int lp = 0, split_count = 0;
11
12 for(int i = 0; i <= ssl - ksl;) {
13 if(!memcmp(src + i, key, ksl)) {
14 strlcpy(operator[](split_count++), src + lp, i - lp + 1);
15 i += ksl;
16 lp = i;
17 if(!--limit) break;
18 } else i++;
19 }
20
21 operator[](split_count++) = src + lp;
22 }
23
24 template<unsigned Limit> void lstring::qsplit(const char *key, const char *src) {
25 unsigned limit = Limit;
26 reset();
27
28 int ssl = strlen(src), ksl = strlen(key);
29 int lp = 0, split_count = 0;
30
31 for(int i = 0; i <= ssl - ksl;) {
32 uint8_t x = src[i];
33
34 if(x == '\"' || x == '\'') {
35 int z = i++; //skip opening quote
36 while(i < ssl && src[i] != x) i++;
37 if(i >= ssl) i = z; //failed match, rewind i
38 else {
39 i++; //skip closing quote
40 continue; //restart in case next char is also a quote
41 }
42 }
43
44 if(!memcmp(src + i, key, ksl)) {
45 strlcpy(operator[](split_count++), src + lp, i - lp + 1);
46 i += ksl;
47 lp = i;
48 if(!--limit) break;
49 } else i++;
50 }
51
52 operator[](split_count++) = src + lp;
53 }
54
55 };
56
57 #endif
+0
-52
snespurify/phoenix/nall/string/strl.hpp less more
0 #ifndef NALL_STRING_STRL_HPP
1 #define NALL_STRING_STRL_HPP
2
3 namespace nall {
4
5 //strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
6
7 //return = strlen(src)
8 unsigned strlcpy(char *dest, const char *src, unsigned length) {
9 char *d = dest;
10 const char *s = src;
11 unsigned n = length;
12
13 if(n) {
14 while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached
15 }
16
17 if(!n) {
18 if(length) *d = 0;
19 while(*s++); //traverse rest of s, so that s - src == strlen(src)
20 }
21
22 return (s - src - 1); //return length of copied string, sans null terminator
23 }
24
25 //return = strlen(src) + min(length, strlen(dest))
26 unsigned strlcat(char *dest, const char *src, unsigned length) {
27 char *d = dest;
28 const char *s = src;
29 unsigned n = length;
30
31 while(n-- && *d) d++; //find end of dest
32 unsigned dlength = d - dest;
33 n = length - dlength; //subtract length of dest from maximum string length
34
35 if(!n) return dlength + strlen(s);
36
37 while(*s) {
38 if(n != 1) {
39 *d++ = *s;
40 n--;
41 }
42 s++;
43 }
44 *d = 0;
45
46 return dlength + (s - src); //return length of resulting string, sans null terminator
47 }
48
49 }
50
51 #endif
+0
-41
snespurify/phoenix/nall/string/strpos.hpp less more
0 #ifndef NALL_STRING_STRPOS_HPP
1 #define NALL_STRING_STRPOS_HPP
2
3 //usage example:
4 //if(auto pos = strpos(str, key)) print(pos(), "\n");
5 //prints position of key within str, only if it is found
6
7 namespace nall {
8
9 optional<unsigned> strpos(const char *str, const char *key) {
10 unsigned ssl = strlen(str), ksl = strlen(key);
11 if(ksl > ssl) return { false, 0 };
12
13 for(unsigned i = 0; i <= ssl - ksl; i++) {
14 if(!memcmp(str + i, key, ksl)) return { true, i };
15 }
16
17 return { false, 0 };
18 }
19
20 optional<unsigned> qstrpos(const char *str, const char *key) {
21 unsigned ssl = strlen(str), ksl = strlen(key);
22 if(ksl > ssl) return { false, 0 };
23
24 for(unsigned i = 0; i <= ssl - ksl;) {
25 uint8_t x = str[i];
26 if(x == '\"' || x == '\'') {
27 uint8_t z = i++;
28 while(str[i] != x && i < ssl) i++;
29 if(i >= ssl) i = z;
30 }
31 if(!memcmp(str + i, key, ksl)) return { true, i };
32 i++;
33 }
34
35 return { false, 0 };
36 }
37
38 }
39
40 #endif
+0
-38
snespurify/phoenix/nall/string/trim.hpp less more
0 #ifndef NALL_STRING_TRIM_HPP
1 #define NALL_STRING_TRIM_HPP
2
3 namespace nall {
4
5 //limit defaults to zero, which will underflow on first compare; equivalent to no limit
6 template<unsigned Limit> char* ltrim(char *str, const char *key) {
7 unsigned limit = Limit;
8 if(!key || !*key) return str;
9 while(strbegin(str, key)) {
10 char *dest = str, *src = str + strlen(key);
11 while(true) {
12 *dest = *src++;
13 if(!*dest) break;
14 dest++;
15 }
16 if(--limit == 0) break;
17 }
18 return str;
19 }
20
21 template<unsigned Limit> char* rtrim(char *str, const char *key) {
22 unsigned limit = Limit;
23 if(!key || !*key) return str;
24 while(strend(str, key)) {
25 str[strlen(str) - strlen(key)] = 0;
26 if(--limit == 0) break;
27 }
28 return str;
29 }
30
31 template<unsigned limit> char* trim(char *str, const char *key) {
32 return ltrim<limit>(rtrim<limit>(str, key), key);
33 }
34
35 }
36
37 #endif
+0
-255
snespurify/phoenix/nall/string/utility.hpp less more
0 #ifndef NALL_STRING_UTILITY_HPP
1 #define NALL_STRING_UTILITY_HPP
2
3 namespace nall {
4
5 unsigned strlcpy(string &dest, const char *src, unsigned length) {
6 dest.reserve(length);
7 return strlcpy(dest(), src, length);
8 }
9
10 unsigned strlcat(string &dest, const char *src, unsigned length) {
11 dest.reserve(length);
12 return strlcat(dest(), src, length);
13 }
14
15 string substr(const char *src, unsigned start, unsigned length) {
16 string dest;
17 if(length == 0) {
18 //copy entire string
19 dest = src + start;
20 } else {
21 //copy partial string
22 strlcpy(dest, src + start, length + 1);
23 }
24 return dest;
25 }
26
27 /* arithmetic <> string */
28
29 string integer(intmax_t value) {
30 bool negative = value < 0;
31 if(negative) value = abs(value);
32
33 char buffer[64];
34 unsigned size = 0;
35
36 do {
37 unsigned n = value % 10;
38 buffer[size++] = '0' + n;
39 value /= 10;
40 } while(value);
41 buffer[size++] = negative ? '-' : '+';
42 buffer[size] = 0;
43
44 char result[size + 1];
45 memset(result, '0', size);
46 result[size] = 0;
47
48 for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) {
49 result[x] = buffer[y];
50 }
51
52 return (const char*)result;
53 }
54
55 template<unsigned length_> string linteger(intmax_t value) {
56 bool negative = value < 0;
57 if(negative) value = abs(value);
58
59 char buffer[64];
60 unsigned size = 0;
61
62 do {
63 unsigned n = value % 10;
64 buffer[size++] = '0' + n;
65 value /= 10;
66 } while(value);
67 buffer[size++] = negative ? '-' : '+';
68 buffer[size] = 0;
69
70 unsigned length = (length_ == 0 ? size : length_);
71 char result[length + 1];
72 memset(result, ' ', length);
73 result[length] = 0;
74
75 for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) {
76 result[x] = buffer[y];
77 }
78
79 return (const char*)result;
80 }
81
82 template<unsigned length_> string rinteger(intmax_t value) {
83 bool negative = value < 0;
84 if(negative) value = abs(value);
85
86 char buffer[64];
87 unsigned size = 0;
88
89 do {
90 unsigned n = value % 10;
91 buffer[size++] = '0' + n;
92 value /= 10;
93 } while(value);
94 buffer[size++] = negative ? '-' : '+';
95 buffer[size] = 0;
96
97 unsigned length = (length_ == 0 ? size : length_);
98 char result[length + 1];
99 memset(result, ' ', length);
100 result[length] = 0;
101
102 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
103 result[x] = buffer[y];
104 }
105
106 return (const char*)result;
107 }
108
109 string decimal(uintmax_t value) {
110 char buffer[64];
111 unsigned size = 0;
112
113 do {
114 unsigned n = value % 10;
115 buffer[size++] = '0' + n;
116 value /= 10;
117 } while(value);
118 buffer[size] = 0;
119
120 char result[size + 1];
121 memset(result, '0', size);
122 result[size] = 0;
123
124 for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) {
125 result[x] = buffer[y];
126 }
127
128 return (const char*)result;
129 }
130
131 template<unsigned length_> string ldecimal(uintmax_t value) {
132 char buffer[64];
133 unsigned size = 0;
134
135 do {
136 unsigned n = value % 10;
137 buffer[size++] = '0' + n;
138 value /= 10;
139 } while(value);
140 buffer[size] = 0;
141
142 unsigned length = (length_ == 0 ? size : length_);
143 char result[length + 1];
144 memset(result, ' ', length);
145 result[length] = 0;
146
147 for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) {
148 result[x] = buffer[y];
149 }
150
151 return (const char*)result;
152 }
153
154 template<unsigned length_> string rdecimal(uintmax_t value) {
155 char buffer[64];
156 unsigned size = 0;
157
158 do {
159 unsigned n = value % 10;
160 buffer[size++] = '0' + n;
161 value /= 10;
162 } while(value);
163 buffer[size] = 0;
164
165 unsigned length = (length_ == 0 ? size : length_);
166 char result[length + 1];
167 memset(result, ' ', length);
168 result[length] = 0;
169
170 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
171 result[x] = buffer[y];
172 }
173
174 return (const char*)result;
175 }
176
177 template<unsigned length_> string hex(uintmax_t value) {
178 char buffer[64];
179 unsigned size = 0;
180
181 do {
182 unsigned n = value & 15;
183 buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10;
184 value >>= 4;
185 } while(value);
186
187 unsigned length = (length_ == 0 ? size : length_);
188 char result[length + 1];
189 memset(result, '0', length);
190 result[length] = 0;
191
192 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
193 result[x] = buffer[y];
194 }
195
196 return (const char*)result;
197 }
198
199 template<unsigned length_> string binary(uintmax_t value) {
200 char buffer[256];
201 unsigned size = 0;
202
203 do {
204 unsigned n = value & 1;
205 buffer[size++] = '0' + n;
206 value >>= 1;
207 } while(value);
208
209 unsigned length = (length_ == 0 ? size : length_);
210 char result[length + 1];
211 memset(result, '0', length);
212 result[length] = 0;
213
214 for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) {
215 result[x] = buffer[y];
216 }
217
218 return (const char*)result;
219 }
220
221 //using sprintf is certainly not the most ideal method to convert
222 //a double to a string ... but attempting to parse a double by
223 //hand, digit-by-digit, results in subtle rounding errors.
224 unsigned fp(char *str, double value) {
225 char buffer[256];
226 sprintf(buffer, "%f", value);
227
228 //remove excess 0's in fraction (2.500000 -> 2.5)
229 for(char *p = buffer; *p; p++) {
230 if(*p == '.') {
231 char *p = buffer + strlen(buffer) - 1;
232 while(*p == '0') {
233 if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1.
234 p--;
235 }
236 break;
237 }
238 }
239
240 unsigned length = strlen(buffer);
241 if(str) strcpy(str, buffer);
242 return length + 1;
243 }
244
245 string fp(double value) {
246 string temp;
247 temp.reserve(fp(0, value));
248 fp(temp(), value);
249 return temp;
250 }
251
252 }
253
254 #endif
+0
-12
snespurify/phoenix/nall/string/variadic.hpp less more
0 #ifndef NALL_STRING_VARIADIC_HPP
1 #define NALL_STRING_VARIADIC_HPP
2
3 namespace nall {
4
5 template<typename... Args> inline void print(Args&&... args) {
6 printf("%s", (const char*)string(std::forward<Args>(args)...));
7 }
8
9 }
10
11 #endif
+0
-33
snespurify/phoenix/nall/string/wrapper.hpp less more
0 #ifndef NALL_STRING_WRAPPER_HPP
1 #define NALL_STRING_WRAPPER_HPP
2
3 namespace nall {
4
5 unsigned string::length() const { return strlen(data); }
6
7 bool string::equals(const char *str) const { return !strcmp(data, str); }
8 bool string::iequals(const char *str) const { return !stricmp(data, str); }
9
10 bool string::wildcard(const char *str) const { return nall::wildcard(data, str); }
11 bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); }
12
13 bool string::beginswith(const char *str) const { return strbegin(data, str); }
14 bool string::ibeginswith(const char *str) const { return stribegin(data, str); }
15
16 bool string::endswith(const char *str) const { return strend(data, str); }
17 bool string::iendswith(const char *str) const { return striend(data, str); }
18
19 string& string::lower() { nall::strlower(data); return *this; }
20 string& string::upper() { nall::strupper(data); return *this; }
21 string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; }
22
23 template<unsigned limit> string& string::ltrim(const char *key) { nall::ltrim<limit>(data, key); return *this; }
24 template<unsigned limit> string& string::rtrim(const char *key) { nall::rtrim<limit>(data, key); return *this; }
25 template<unsigned limit> string& string::trim (const char *key) { nall::trim <limit>(data, key); return *this; }
26
27 optional<unsigned> string::position(const char *key) const { return strpos(data, key); }
28 optional<unsigned> string::qposition(const char *key) const { return qstrpos(data, key); }
29
30 }
31
32 #endif
+0
-266
snespurify/phoenix/nall/string/xml.hpp less more
0 #ifndef NALL_STRING_XML_HPP
1 #define NALL_STRING_XML_HPP
2
3 //XML subset parser
4 //version 0.05
5
6 namespace nall {
7
8 struct xml_attribute {
9 string name;
10 string content;
11 virtual string parse() const;
12 };
13
14 struct xml_element : xml_attribute {
15 string parse() const;
16 linear_vector<xml_attribute> attribute;
17 linear_vector<xml_element> element;
18
19 protected:
20 void parse_doctype(const char *&data);
21 bool parse_head(string data);
22 bool parse_body(const char *&data);
23 friend xml_element xml_parse(const char *data);
24 };
25
26 inline string xml_attribute::parse() const {
27 string data;
28 unsigned offset = 0;
29
30 const char *source = content;
31 while(*source) {
32 if(*source == '&') {
33 if(strbegin(source, "&lt;")) { data[offset++] = '<'; source += 4; continue; }
34 if(strbegin(source, "&gt;")) { data[offset++] = '>'; source += 4; continue; }
35 if(strbegin(source, "&amp;")) { data[offset++] = '&'; source += 5; continue; }
36 if(strbegin(source, "&apos;")) { data[offset++] = '\''; source += 6; continue; }
37 if(strbegin(source, "&quot;")) { data[offset++] = '"'; source += 6; continue; }
38 }
39
40 //reject illegal characters
41 if(*source == '&') return "";
42 if(*source == '<') return "";
43 if(*source == '>') return "";
44
45 data[offset++] = *source++;
46 }
47
48 data[offset] = 0;
49 return data;
50 }
51
52 inline string xml_element::parse() const {
53 string data;
54 unsigned offset = 0;
55
56 const char *source = content;
57 while(*source) {
58 if(*source == '&') {
59 if(strbegin(source, "&lt;")) { data[offset++] = '<'; source += 4; continue; }
60 if(strbegin(source, "&gt;")) { data[offset++] = '>'; source += 4; continue; }
61 if(strbegin(source, "&amp;")) { data[offset++] = '&'; source += 5; continue; }
62 if(strbegin(source, "&apos;")) { data[offset++] = '\''; source += 6; continue; }
63 if(strbegin(source, "&quot;")) { data[offset++] = '"'; source += 6; continue; }
64 }
65
66 if(strbegin(source, "<!--")) {
67 if(auto pos = strpos(source, "-->")) {
68 source += pos() + 3;
69 continue;
70 } else {
71 return "";
72 }
73 }
74
75 if(strbegin(source, "<![CDATA[")) {
76 if(auto pos = strpos(source, "]]>")) {
77 if(pos() - 9 > 0) {
78 string cdata = substr(source, 9, pos() - 9);
79 data << cdata;
80 offset += strlen(cdata);
81 }
82 source += 9 + offset + 3;
83 continue;
84 } else {
85 return "";
86 }
87 }
88
89 //reject illegal characters
90 if(*source == '&') return "";
91 if(*source == '<') return "";
92 if(*source == '>') return "";
93
94 data[offset++] = *source++;
95 }
96
97 data[offset] = 0;
98 return data;
99 }
100
101 inline void xml_element::parse_doctype(const char *&data) {
102 name = "!DOCTYPE";
103 const char *content_begin = data;
104
105 signed counter = 0;
106 while(*data) {
107 char value = *data++;
108 if(value == '<') counter++;
109 if(value == '>') counter--;
110 if(counter < 0) {
111 content = substr(content_begin, 0, data - content_begin - 1);
112 return;
113 }
114 }
115 throw "...";
116 }
117
118 inline bool xml_element::parse_head(string data) {
119 data.qreplace("\t", " ");
120 data.qreplace("\r", " ");
121 data.qreplace("\n", " ");
122 while(qstrpos(data, " ")) data.qreplace(" ", " ");
123 data.qreplace(" =", "=");
124 data.qreplace("= ", "=");
125 data.rtrim();
126
127 lstring part;
128 part.qsplit(" ", data);
129
130 name = part[0];
131 if(name == "") throw "...";
132
133 for(unsigned i = 1; i < part.size(); i++) {
134 lstring side;
135 side.qsplit("=", part[i]);
136 if(side.size() != 2) throw "...";
137
138 xml_attribute attr;
139 attr.name = side[0];
140 attr.content = side[1];
141 if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim<1>("\"");
142 else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim<1>("'");
143 else throw "...";
144 attribute.append(attr);
145 }
146 }
147
148 inline bool xml_element::parse_body(const char *&data) {
149 while(true) {
150 if(!*data) return false;
151 if(*data++ != '<') continue;
152 if(*data == '/') return false;
153
154 if(strbegin(data, "!DOCTYPE") == true) {
155 parse_doctype(data);
156 return true;
157 }
158
159 if(strbegin(data, "!--")) {
160 if(auto offset = strpos(data, "-->")) {
161 data += offset() + 3;
162 continue;
163 } else {
164 throw "...";
165 }
166 }
167
168 if(strbegin(data, "![CDATA[")) {
169 if(auto offset = strpos(data, "]]>")) {
170 data += offset() + 3;
171 continue;
172 } else {
173 throw "...";
174 }
175 }
176
177 auto offset = strpos(data, ">");
178 if(!offset) throw "...";
179
180 string tag = substr(data, 0, offset());
181 data += offset() + 1;
182 const char *content_begin = data;
183
184 bool self_terminating = false;
185
186 if(strend(tag, "?") == true) {
187 self_terminating = true;
188 tag.rtrim<1>("?");
189 } else if(strend(tag, "/") == true) {
190 self_terminating = true;
191 tag.rtrim<1>("/");
192 }
193
194 parse_head(tag);
195 if(self_terminating) return true;
196
197 while(*data) {
198 unsigned index = element.size();
199 xml_element node;
200 if(node.parse_body(data) == false) {
201 if(*data == '/') {
202 signed length = data - content_begin - 1;
203 if(length > 0) content = substr(content_begin, 0, length);
204
205 data++;
206 auto offset = strpos(data, ">");
207 if(!offset) throw "...";
208
209 tag = substr(data, 0, offset());
210 data += offset() + 1;
211
212 tag.replace("\t", " ");
213 tag.replace("\r", " ");
214 tag.replace("\n", " ");
215 while(strpos(tag, " ")) tag.replace(" ", " ");
216 tag.rtrim();
217
218 if(name != tag) throw "...";
219 return true;
220 }
221 } else {
222 element.append(node);
223 }
224 }
225 }
226 }
227
228 //ensure there is only one root element
229 inline bool xml_validate(xml_element &document) {
230 unsigned root_counter = 0;
231
232 for(unsigned i = 0; i < document.element.size(); i++) {
233 string &name = document.element[i].name;
234 if(strbegin(name, "?")) continue;
235 if(strbegin(name, "!")) continue;
236 if(++root_counter > 1) return false;
237 }
238
239 return true;
240 }
241
242 inline xml_element xml_parse(const char *data) {
243 xml_element self;
244
245 try {
246 while(*data) {
247 xml_element node;
248 if(node.parse_body(data) == false) {
249 break;
250 } else {
251 self.element.append(node);
252 }
253 }
254
255 if(xml_validate(self) == false) throw "...";
256 return self;
257 } catch(const char*) {
258 xml_element empty;
259 return empty;
260 }
261 }
262
263 }
264
265 #endif
+0
-32
snespurify/phoenix/nall/string.hpp less more
0 #ifndef NALL_STRING_HPP
1 #define NALL_STRING_HPP
2
3 #include <initializer_list>
4 #include <nall/platform.hpp>
5 #include <nall/utility.hpp>
6
7 #include <nall/string/base.hpp>
8 #include <nall/string/bsv.hpp>
9 #include <nall/string/core.hpp>
10 #include <nall/string/cast.hpp>
11 #include <nall/string/compare.hpp>
12 #include <nall/string/convert.hpp>
13 #include <nall/string/filename.hpp>
14 #include <nall/string/math.hpp>
15 #include <nall/string/platform.hpp>
16 #include <nall/string/strl.hpp>
17 #include <nall/string/strpos.hpp>
18 #include <nall/string/trim.hpp>
19 #include <nall/string/replace.hpp>
20 #include <nall/string/split.hpp>
21 #include <nall/string/utility.hpp>
22 #include <nall/string/variadic.hpp>
23 #include <nall/string/wrapper.hpp>
24 #include <nall/string/xml.hpp>
25
26 namespace nall {
27 template<> struct has_length<string> { enum { value = true }; };
28 template<> struct has_size<lstring> { enum { value = true }; };
29 }
30
31 #endif
+0
-223
snespurify/phoenix/nall/ups.hpp less more
0 #ifndef NALL_UPS_HPP
1 #define NALL_UPS_HPP
2
3 #include <nall/crc32.hpp>
4 #include <nall/file.hpp>
5 #include <nall/function.hpp>
6 #include <nall/stdint.hpp>
7
8 namespace nall {
9
10 struct ups {
11 enum class result : unsigned {
12 unknown,
13 success,
14 patch_unwritable,
15 patch_invalid,
16 source_invalid,
17 target_invalid,
18 target_too_small,
19 patch_checksum_invalid,
20 source_checksum_invalid,
21 target_checksum_invalid,
22 };
23
24 function<void (unsigned offset, unsigned length)> progress;
25
26 result create(
27 const uint8_t *sourcedata, unsigned sourcelength,
28 const uint8_t *targetdata, unsigned targetlength,
29 const char *patchfilename
30 ) {
31 source_data = (uint8_t*)sourcedata, target_data = (uint8_t*)targetdata;
32 source_length = sourcelength, target_length = targetlength;
33 source_offset = target_offset = 0;
34 source_checksum = target_checksum = patch_checksum = ~0;
35
36 if(patch_file.open(patchfilename, file::mode::write) == false) return result::patch_unwritable;
37
38 patch_write('U');
39 patch_write('P');
40 patch_write('S');
41 patch_write('1');
42 encode(source_length);
43 encode(target_length);
44
45 unsigned output_length = source_length > target_length ? source_length : target_length;
46 unsigned relative = 0;
47 for(unsigned offset = 0; offset < output_length;) {
48 uint8_t x = source_read();
49 uint8_t y = target_read();
50
51 if(x == y) {
52 offset++;
53 continue;
54 }
55
56 encode(offset++ - relative);
57 patch_write(x ^ y);
58
59 while(true) {
60 if(offset >= output_length) {
61 patch_write(0x00);
62 break;
63 }
64
65 x = source_read();
66 y = target_read();
67 offset++;
68 patch_write(x ^ y);
69 if(x == y) break;
70 }
71
72 relative = offset;
73 }
74
75 source_checksum = ~source_checksum;
76 target_checksum = ~target_checksum;
77 for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8));
78 for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8));
79 uint32_t patch_result_checksum = ~patch_checksum;
80 for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8));
81
82 patch_file.close();
83 return result::success;
84 }
85
86 result apply(
87 const uint8_t *patchdata, unsigned patchlength,
88 const uint8_t *sourcedata, unsigned sourcelength,
89 uint8_t *targetdata, unsigned &targetlength
90 ) {
91 patch_data = (uint8_t*)patchdata, source_data = (uint8_t*)sourcedata, target_data = targetdata;
92 patch_length = patchlength, source_length = sourcelength, target_length = targetlength;
93 patch_offset = source_offset = target_offset = 0;
94 patch_checksum = source_checksum = target_checksum = ~0;
95
96 if(patch_length < 18) return result::patch_invalid;
97 if(patch_read() != 'U') return result::patch_invalid;
98 if(patch_read() != 'P') return result::patch_invalid;
99 if(patch_read() != 'S') return result::patch_invalid;
100 if(patch_read() != '1') return result::patch_invalid;
101
102 unsigned source_read_length = decode();
103 unsigned target_read_length = decode();
104
105 if(source_length != source_read_length && source_length != target_read_length) return result::source_invalid;
106 targetlength = (source_length == source_read_length ? target_read_length : source_read_length);
107 if(target_length < targetlength) return result::target_too_small;
108 target_length = targetlength;
109
110 while(patch_offset < patch_length - 12) {
111 unsigned length = decode();
112 while(length--) target_write(source_read());
113 while(true) {
114 uint8_t patch_xor = patch_read();
115 target_write(patch_xor ^ source_read());
116 if(patch_xor == 0) break;
117 }
118 }
119 while(source_offset < source_length) target_write(source_read());
120 while(target_offset < target_length) target_write(source_read());
121
122 uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0;
123 for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8);
124 for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8);
125 uint32_t patch_result_checksum = ~patch_checksum;
126 source_checksum = ~source_checksum;
127 target_checksum = ~target_checksum;
128 for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8);
129
130 if(patch_result_checksum != patch_read_checksum) return result::patch_invalid;
131 if(source_checksum == source_read_checksum && source_length == source_read_length) {
132 if(target_checksum == target_read_checksum && target_length == target_read_length) return result::success;
133 return result::target_invalid;
134 } else if(source_checksum == target_read_checksum && source_length == target_read_length) {
135 if(target_checksum == source_read_checksum && target_length == source_read_length) return result::success;
136 return result::target_invalid;
137 } else {
138 return result::source_invalid;
139 }
140 }
141
142 private:
143 uint8_t *patch_data, *source_data, *target_data;
144 unsigned patch_length, source_length, target_length;
145 unsigned patch_offset, source_offset, target_offset;
146 unsigned patch_checksum, source_checksum, target_checksum;
147 file patch_file;
148
149 uint8_t patch_read() {
150 if(patch_offset < patch_length) {
151 uint8_t n = patch_data[patch_offset++];
152 patch_checksum = crc32_adjust(patch_checksum, n);
153 return n;
154 }
155 return 0x00;
156 }
157
158 uint8_t source_read() {
159 if(source_offset < source_length) {
160 uint8_t n = source_data[source_offset++];
161 source_checksum = crc32_adjust(source_checksum, n);
162 return n;
163 }
164 return 0x00;
165 }
166
167 uint8_t target_read() {
168 uint8_t result = 0x00;
169 if(target_offset < target_length) {
170 result = target_data[target_offset];
171 target_checksum = crc32_adjust(target_checksum, result);
172 }
173 if(((target_offset++ & 255) == 0) && progress) {
174 progress(target_offset, source_length > target_length ? source_length : target_length);
175 }
176 return result;
177 }
178
179 void patch_write(uint8_t n) {
180 patch_file.write(n);
181 patch_checksum = crc32_adjust(patch_checksum, n);
182 }
183
184 void target_write(uint8_t n) {
185 if(target_offset < target_length) {
186 target_data[target_offset] = n;
187 target_checksum = crc32_adjust(target_checksum, n);
188 }
189 if(((target_offset++ & 255) == 0) && progress) {
190 progress(target_offset, source_length > target_length ? source_length : target_length);
191 }
192 }
193
194 void encode(uint64_t offset) {
195 while(true) {
196 uint64_t x = offset & 0x7f;
197 offset >>= 7;
198 if(offset == 0) {
199 patch_write(0x80 | x);
200 break;
201 }
202 patch_write(x);
203 offset--;
204 }
205 }
206
207 uint64_t decode() {
208 uint64_t offset = 0, shift = 1;
209 while(true) {
210 uint8_t x = patch_read();
211 offset += (x & 0x7f) * shift;
212 if(x & 0x80) break;
213 shift <<= 7;
214 offset += shift;
215 }
216 return offset;
217 }
218 };
219
220 }
221
222 #endif
+0
-86
snespurify/phoenix/nall/utf8.hpp less more
0 #ifndef NALL_UTF8_HPP
1 #define NALL_UTF8_HPP
2
3 //UTF-8 <> UTF-16 conversion
4 //used only for Win32; Linux, etc use UTF-8 internally
5
6 #if defined(_WIN32)
7
8 #undef UNICODE
9 #undef _WIN32_WINNT
10 #undef NOMINMAX
11 #define UNICODE
12 #define _WIN32_WINNT 0x0501
13 #define NOMINMAX
14 #include <windows.h>
15 #undef interface
16
17 namespace nall {
18 //UTF-8 to UTF-16
19 class utf16_t {
20 public:
21 operator wchar_t*() {
22 return buffer;
23 }
24
25 operator const wchar_t*() const {
26 return buffer;
27 }
28
29 utf16_t(const char *s = "") {
30 if(!s) s = "";
31 unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0);
32 buffer = new wchar_t[length + 1]();
33 MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length);
34 }
35
36 ~utf16_t() {
37 delete[] buffer;
38 }
39
40 private:
41 wchar_t *buffer;
42 };
43
44 //UTF-16 to UTF-8
45 class utf8_t {
46 public:
47 operator char*() {
48 return buffer;
49 }
50
51 operator const char*() const {
52 return buffer;
53 }
54
55 utf8_t(const wchar_t *s = L"") {
56 if(!s) s = L"";
57 unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0);
58 buffer = new char[length + 1]();
59 WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0);
60 }
61
62 ~utf8_t() {
63 delete[] buffer;
64 }
65
66 utf8_t(const utf8_t&) = delete;
67 utf8_t& operator=(const utf8_t&) = delete;
68
69 private:
70 char *buffer;
71 };
72
73 inline void utf8_args(int &argc, char **&argv) {
74 wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
75 argv = new char*[argc];
76 for(unsigned i = 0; i < argc; i++) {
77 argv[i] = new char[_MAX_PATH];
78 strcpy(argv[i], nall::utf8_t(wargv[i]));
79 }
80 }
81 }
82
83 #endif //if defined(_WIN32)
84
85 #endif
+0
-39
snespurify/phoenix/nall/utility.hpp less more
0 #ifndef NALL_UTILITY_HPP
1 #define NALL_UTILITY_HPP
2
3 #include <type_traits>
4 #include <utility>
5
6 namespace nall {
7 template<bool C, typename T = bool> struct enable_if { typedef T type; };
8 template<typename T> struct enable_if<false, T> {};
9 template<typename C, typename T = bool> struct mp_enable_if : enable_if<C::value, T> {};
10
11 template<typename T> inline void swap(T &x, T &y) {
12 T temp(std::move(x));
13 x = std::move(y);
14 y = std::move(temp);
15 }
16
17 template<typename T> struct base_from_member {
18 T value;
19 base_from_member(T value_) : value(value_) {}
20 };
21
22 template<typename T> class optional {
23 bool valid;
24 T value;
25 public:
26 inline operator bool() const { return valid; }
27 inline const T& operator()() const { if(!valid) throw; return value; }
28 inline optional(bool valid, const T &value) : valid(valid), value(value) {}
29 };
30
31 template<typename T> inline T* allocate(unsigned size, const T &value) {
32 T *array = new T[size];
33 for(unsigned i = 0; i < size; i++) array[i] = value;
34 return array;
35 }
36 }
37
38 #endif
+0
-118
snespurify/phoenix/nall/varint.hpp less more
0 #ifndef NALL_VARINT_HPP
1 #define NALL_VARINT_HPP
2
3 #include <type_traits>
4 #include <nall/bit.hpp>
5 #include <nall/static.hpp>
6
7 namespace nall {
8 template<unsigned bits> class uint_t {
9 private:
10 unsigned data;
11
12 public:
13 inline operator unsigned() const { return data; }
14 inline unsigned operator ++(int) { unsigned r = data; data = uclip<bits>(data + 1); return r; }
15 inline unsigned operator --(int) { unsigned r = data; data = uclip<bits>(data - 1); return r; }
16 inline unsigned operator ++() { return data = uclip<bits>(data + 1); }
17 inline unsigned operator --() { return data = uclip<bits>(data - 1); }
18 inline unsigned operator =(const unsigned i) { return data = uclip<bits>(i); }
19 inline unsigned operator |=(const unsigned i) { return data = uclip<bits>(data | i); }
20 inline unsigned operator ^=(const unsigned i) { return data = uclip<bits>(data ^ i); }
21 inline unsigned operator &=(const unsigned i) { return data = uclip<bits>(data & i); }
22 inline unsigned operator<<=(const unsigned i) { return data = uclip<bits>(data << i); }
23 inline unsigned operator>>=(const unsigned i) { return data = uclip<bits>(data >> i); }
24 inline unsigned operator +=(const unsigned i) { return data = uclip<bits>(data + i); }
25 inline unsigned operator -=(const unsigned i) { return data = uclip<bits>(data - i); }
26 inline unsigned operator *=(const unsigned i) { return data = uclip<bits>(data * i); }
27 inline unsigned operator /=(const unsigned i) { return data = uclip<bits>(data / i); }
28 inline unsigned operator %=(const unsigned i) { return data = uclip<bits>(data % i); }
29
30 inline uint_t() : data(0) {}
31 inline uint_t(const unsigned i) : data(uclip<bits>(i)) {}
32 };
33
34 template<unsigned bits> class int_t {
35 private:
36 signed data;
37
38 public:
39 inline operator signed() const { return data; }
40 inline signed operator ++(int) { signed r = data; data = sclip<bits>(data + 1); return r; }
41 inline signed operator --(int) { signed r = data; data = sclip<bits>(data - 1); return r; }
42 inline signed operator ++() { return data = sclip<bits>(data + 1); }
43 inline signed operator --() { return data = sclip<bits>(data - 1); }
44 inline signed operator =(const signed i) { return data = sclip<bits>(i); }
45 inline signed operator |=(const signed i) { return data = sclip<bits>(data | i); }
46 inline signed operator ^=(const signed i) { return data = sclip<bits>(data ^ i); }
47 inline signed operator &=(const signed i) { return data = sclip<bits>(data & i); }
48 inline signed operator<<=(const signed i) { return data = sclip<bits>(data << i); }
49 inline signed operator>>=(const signed i) { return data = sclip<bits>(data >> i); }
50 inline signed operator +=(const signed i) { return data = sclip<bits>(data + i); }
51 inline signed operator -=(const signed i) { return data = sclip<bits>(data - i); }
52 inline signed operator *=(const signed i) { return data = sclip<bits>(data * i); }
53 inline signed operator /=(const signed i) { return data = sclip<bits>(data / i); }
54 inline signed operator %=(const signed i) { return data = sclip<bits>(data % i); }
55
56 inline int_t() : data(0) {}
57 inline int_t(const signed i) : data(sclip<bits>(i)) {}
58 };
59
60 class varuint_t {
61 private:
62 unsigned data;
63 unsigned mask;
64
65 public:
66 inline operator unsigned() const { return data; }
67 inline unsigned operator ++(int) { unsigned r = data; data = (data + 1) & mask; return r; }
68 inline unsigned operator --(int) { unsigned r = data; data = (data - 1) & mask; return r; }
69 inline unsigned operator ++() { return data = (data + 1) & mask; }
70 inline unsigned operator --() { return data = (data - 1) & mask; }
71 inline unsigned operator =(const unsigned i) { return data = (i) & mask; }
72 inline unsigned operator |=(const unsigned i) { return data = (data | i) & mask; }
73 inline unsigned operator ^=(const unsigned i) { return data = (data ^ i) & mask; }
74 inline unsigned operator &=(const unsigned i) { return data = (data & i) & mask; }
75 inline unsigned operator<<=(const unsigned i) { return data = (data << i) & mask; }
76 inline unsigned operator>>=(const unsigned i) { return data = (data >> i) & mask; }
77 inline unsigned operator +=(const unsigned i) { return data = (data + i) & mask; }
78 inline unsigned operator -=(const unsigned i) { return data = (data - i) & mask; }
79 inline unsigned operator *=(const unsigned i) { return data = (data * i) & mask; }
80 inline unsigned operator /=(const unsigned i) { return data = (data / i) & mask; }
81 inline unsigned operator %=(const unsigned i) { return data = (data % i) & mask; }
82
83 inline void bits(unsigned bits) { mask = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1); data &= mask; }
84 inline varuint_t() : data(0), mask(~0U) {}
85 inline varuint_t(const unsigned i) : data(i), mask(~0U) {}
86 };
87
88 class varuintmax_t {
89 private:
90 uintmax_t data;
91 uintmax_t mask;
92
93 public:
94 inline operator uintmax_t() const { return data; }
95 inline uintmax_t operator ++(int) { uintmax_t r = data; data = (data + 1) & mask; return r; }
96 inline uintmax_t operator --(int) { uintmax_t r = data; data = (data - 1) & mask; return r; }
97 inline uintmax_t operator ++() { return data = (data + 1) & mask; }
98 inline uintmax_t operator --() { return data = (data - 1) & mask; }
99 inline uintmax_t operator =(const uintmax_t i) { return data = (i) & mask; }
100 inline uintmax_t operator |=(const uintmax_t i) { return data = (data | i) & mask; }
101 inline uintmax_t operator ^=(const uintmax_t i) { return data = (data ^ i) & mask; }
102 inline uintmax_t operator &=(const uintmax_t i) { return data = (data & i) & mask; }
103 inline uintmax_t operator<<=(const uintmax_t i) { return data = (data << i) & mask; }
104 inline uintmax_t operator>>=(const uintmax_t i) { return data = (data >> i) & mask; }
105 inline uintmax_t operator +=(const uintmax_t i) { return data = (data + i) & mask; }
106 inline uintmax_t operator -=(const uintmax_t i) { return data = (data - i) & mask; }
107 inline uintmax_t operator *=(const uintmax_t i) { return data = (data * i) & mask; }
108 inline uintmax_t operator /=(const uintmax_t i) { return data = (data / i) & mask; }
109 inline uintmax_t operator %=(const uintmax_t i) { return data = (data % i) & mask; }
110
111 inline void bits(unsigned bits) { mask = (1ULL << (bits - 1)) + ((1ULL << (bits - 1)) - 1); data &= mask; }
112 inline varuintmax_t() : data(0), mask(~0ULL) {}
113 inline varuintmax_t(const uintmax_t i) : data(i), mask(~0ULL) {}
114 };
115 }
116
117 #endif
+0
-281
snespurify/phoenix/nall/vector.hpp less more
0 #ifndef NALL_VECTOR_HPP
1 #define NALL_VECTOR_HPP
2
3 #include <initializer_list>
4 #include <new>
5 #include <type_traits>
6 #include <utility>
7 #include <nall/algorithm.hpp>
8 #include <nall/bit.hpp>
9 #include <nall/concept.hpp>
10 #include <nall/foreach.hpp>
11 #include <nall/utility.hpp>
12
13 namespace nall {
14 //linear_vector
15 //memory: O(capacity * 2)
16 //
17 //linear_vector uses placement new + manual destructor calls to create a
18 //contiguous block of memory for all objects. accessing individual elements
19 //is fast, though resizing the array incurs significant overhead.
20 //reserve() overhead is reduced from quadratic time to amortized constant time
21 //by resizing twice as much as requested.
22 //
23 //if objects hold memory address references to themselves (introspection), a
24 //valid copy constructor will be needed to keep pointers valid.
25
26 template<typename T> class linear_vector {
27 protected:
28 T *pool;
29 unsigned poolsize, objectsize;
30
31 public:
32 unsigned size() const { return objectsize; }
33 unsigned capacity() const { return poolsize; }
34
35 void reset() {
36 if(pool) {
37 for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
38 free(pool);
39 }
40 pool = 0;
41 poolsize = 0;
42 objectsize = 0;
43 }
44
45 void reserve(unsigned newsize) {
46 newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
47
48 T *poolcopy = (T*)calloc(newsize, sizeof(T));
49 for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]);
50 for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
51 free(pool);
52 pool = poolcopy;
53 poolsize = newsize;
54 objectsize = min(objectsize, newsize);
55 }
56
57 void resize(unsigned newsize) {
58 if(newsize > poolsize) reserve(newsize);
59
60 if(newsize < objectsize) {
61 //vector is shrinking; destroy excess objects
62 for(unsigned i = newsize; i < objectsize; i++) pool[i].~T();
63 } else if(newsize > objectsize) {
64 //vector is expanding; allocate new objects
65 for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T;
66 }
67
68 objectsize = newsize;
69 }
70
71 void append(const T data) {
72 if(objectsize + 1 > poolsize) reserve(objectsize + 1);
73 new(pool + objectsize++) T(data);
74 }
75
76 template<typename U> void insert(unsigned index, const U list) {
77 linear_vector<T> merged;
78 for(unsigned i = 0; i < index; i++) merged.append(pool[i]);
79 foreach(item, list) merged.append(item);
80 for(unsigned i = index; i < objectsize; i++) merged.append(pool[i]);
81 operator=(merged);
82 }
83
84 void insert(unsigned index, const T item) {
85 insert(index, linear_vector<T>{ item });
86 }
87
88 void remove(unsigned index, unsigned count = 1) {
89 for(unsigned i = index; count + i < objectsize; i++) {
90 pool[i] = pool[count + i];
91 }
92 if(count + index >= objectsize) resize(index); //every element >= index was removed
93 else resize(objectsize - count);
94 }
95
96 inline T& operator[](unsigned index) {
97 if(index >= objectsize) resize(index + 1);
98 return pool[index];
99 }
100
101 inline const T& operator[](unsigned index) const {
102 if(index >= objectsize) throw "vector[] out of bounds";
103 return pool[index];
104 }
105
106 //copy
107 inline linear_vector<T>& operator=(const linear_vector<T> &source) {
108 reset();
109 reserve(source.capacity());
110 resize(source.size());
111 for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
112 return *this;
113 }
114
115 linear_vector(const linear_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
116 operator=(source);
117 }
118
119 //move
120 inline linear_vector<T>& operator=(linear_vector<T> &&source) {
121 reset();
122 pool = source.pool;
123 poolsize = source.poolsize;
124 objectsize = source.objectsize;
125 source.pool = 0;
126 source.reset();
127 return *this;
128 }
129
130 linear_vector(linear_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
131 operator=(std::move(source));
132 }
133
134 //construction
135 linear_vector() : pool(0), poolsize(0), objectsize(0) {
136 }
137
138 linear_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
139 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
140 }
141
142 ~linear_vector() {
143 reset();
144 }
145 };
146
147 //pointer_vector
148 //memory: O(1)
149 //
150 //pointer_vector keeps an array of pointers to each vector object. this adds
151 //significant overhead to individual accesses, but allows for optimal memory
152 //utilization.
153 //
154 //by guaranteeing that the base memory address of each objects never changes,
155 //this avoids the need for an object to have a valid copy constructor.
156
157 template<typename T> class pointer_vector {
158 protected:
159 T **pool;
160 unsigned poolsize, objectsize;
161
162 public:
163 unsigned size() const { return objectsize; }
164 unsigned capacity() const { return poolsize; }
165
166 void reset() {
167 if(pool) {
168 for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; }
169 free(pool);
170 }
171 pool = 0;
172 poolsize = 0;
173 objectsize = 0;
174 }
175
176 void reserve(unsigned newsize) {
177 newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
178
179 for(unsigned i = newsize; i < objectsize; i++) {
180 if(pool[i]) { delete pool[i]; pool[i] = 0; }
181 }
182
183 pool = (T**)realloc(pool, newsize * sizeof(T*));
184 for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0;
185 poolsize = newsize;
186 objectsize = min(objectsize, newsize);
187 }
188
189 void resize(unsigned newsize) {
190 if(newsize > poolsize) reserve(newsize);
191
192 for(unsigned i = newsize; i < objectsize; i++) {
193 if(pool[i]) { delete pool[i]; pool[i] = 0; }
194 }
195
196 objectsize = newsize;
197 }
198
199 void append(const T data) {
200 if(objectsize + 1 > poolsize) reserve(objectsize + 1);
201 pool[objectsize++] = new T(data);
202 }
203
204 template<typename U> void insert(unsigned index, const U list) {
205 pointer_vector<T> merged;
206 for(unsigned i = 0; i < index; i++) merged.append(*pool[i]);
207 foreach(item, list) merged.append(item);
208 for(unsigned i = index; i < objectsize; i++) merged.append(*pool[i]);
209 operator=(merged);
210 }
211
212 void insert(unsigned index, const T item) {
213 insert(index, pointer_vector<T>{ item });
214 }
215
216 void remove(unsigned index, unsigned count = 1) {
217 for(unsigned i = index; count + i < objectsize; i++) {
218 *pool[i] = *pool[count + i];
219 }
220 if(count + index >= objectsize) resize(index); //every element >= index was removed
221 else resize(objectsize - count);
222 }
223
224 inline T& operator[](unsigned index) {
225 if(index >= objectsize) resize(index + 1);
226 if(!pool[index]) pool[index] = new T;
227 return *pool[index];
228 }
229
230 inline const T& operator[](unsigned index) const {
231 if(index >= objectsize || !pool[index]) throw "vector[] out of bounds";
232 return *pool[index];
233 }
234
235 //copy
236 inline pointer_vector<T>& operator=(const pointer_vector<T> &source) {
237 reset();
238 reserve(source.capacity());
239 resize(source.size());
240 for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
241 return *this;
242 }
243
244 pointer_vector(const pointer_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
245 operator=(source);
246 }
247
248 //move
249 inline pointer_vector<T>& operator=(pointer_vector<T> &&source) {
250 reset();
251 pool = source.pool;
252 poolsize = source.poolsize;
253 objectsize = source.objectsize;
254 source.pool = 0;
255 source.reset();
256 return *this;
257 }
258
259 pointer_vector(pointer_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
260 operator=(std::move(source));
261 }
262
263 //construction
264 pointer_vector() : pool(0), poolsize(0), objectsize(0) {
265 }
266
267 pointer_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
268 for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
269 }
270
271 ~pointer_vector() {
272 reset();
273 }
274 };
275
276 template<typename T> struct has_size<linear_vector<T>> { enum { value = true }; };
277 template<typename T> struct has_size<pointer_vector<T>> { enum { value = true }; };
278 }
279
280 #endif
0 #ifndef PHOENIX_CPP
1 #define PHOENIX_CPP
2
03 #if defined(PHOENIX_WINDOWS)
14 #define UNICODE
25 #define WINVER 0x0501
1316 #include <QApplication>
1417 #include <QtGui>
1518 #elif defined(PHOENIX_GTK)
16 #define None X11None
19 #define None
1720 #define Window X11Window
21 #define X11None 0L
1822
1923 #include <gtk/gtk.h>
24 #include <gdk/gdk.h>
2025 #include <gdk/gdkx.h>
2126 #include <cairo.h>
2227 #include <gdk/gdkkeysyms.h>
28 #include <X11/Xatom.h>
2329
2430 #undef None
2531 #undef Window
3440 namespace phoenix {
3541 #include "core/core.cpp"
3642 }
43
44 #endif
0 #ifndef PHOENIX_HPP
1 #define PHOENIX_HPP
2
03 #include <nall/array.hpp>
14 #include <nall/config.hpp>
25 #include <nall/foreach.hpp>
1013 namespace phoenix {
1114 #include "core/core.hpp"
1215 }
16
17 #endif
1919
2020 void pFont::constructor() {
2121 qtFont = new QFont;
22 font.setFamily("Sans");
23 font.setSize(8);
2224 }
2325
2426 void pFont::update() {
22
33 #include "settings.cpp"
44 #include "font.cpp"
5 #include "timer.cpp"
56 #include "message-window.cpp"
67 #include "window.cpp"
78
1819 #include "widget/check-box.cpp"
1920 #include "widget/combo-box.cpp"
2021 #include "widget/hex-edit.cpp"
22 #include "widget/horizontal-scroll-bar.cpp"
2123 #include "widget/horizontal-slider.cpp"
2224 #include "widget/label.cpp"
2325 #include "widget/line-edit.cpp"
2527 #include "widget/progress-bar.cpp"
2628 #include "widget/radio-box.cpp"
2729 #include "widget/text-edit.cpp"
30 #include "widget/vertical-scroll-bar.cpp"
2831 #include "widget/vertical-slider.cpp"
2932 #include "widget/viewport.cpp"
3033
00 /****************************************************************************
11 ** Meta object code from reading C++ file 'qt.moc.hpp'
22 **
3 ** Created: Tue Mar 29 11:11:59 2011
3 ** Created: Mon Aug 8 04:51:19 2011
44 ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
55 **
66 ** WARNING! All changes made in this file will be lost!
1515 #endif
1616
1717 QT_BEGIN_MOC_NAMESPACE
18 static const uint qt_meta_data_pTimer[] = {
19
20 // content:
21 5, // revision
22 0, // classname
23 0, 0, // classinfo
24 1, 14, // methods
25 0, 0, // properties
26 0, 0, // enums/sets
27 0, 0, // constructors
28 0, // flags
29 0, // signalCount
30
31 // slots: signature, parameters, type, tag, flags
32 8, 7, 7, 7, 0x0a,
33
34 0 // eod
35 };
36
37 static const char qt_meta_stringdata_pTimer[] = {
38 "pTimer\0\0onTimeout()\0"
39 };
40
41 const QMetaObject pTimer::staticMetaObject = {
42 { &QObject::staticMetaObject, qt_meta_stringdata_pTimer,
43 qt_meta_data_pTimer, 0 }
44 };
45
46 #ifdef Q_NO_DATA_RELOCATION
47 const QMetaObject &pTimer::getStaticMetaObject() { return staticMetaObject; }
48 #endif //Q_NO_DATA_RELOCATION
49
50 const QMetaObject *pTimer::metaObject() const
51 {
52 return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
53 }
54
55 void *pTimer::qt_metacast(const char *_clname)
56 {
57 if (!_clname) return 0;
58 if (!strcmp(_clname, qt_meta_stringdata_pTimer))
59 return static_cast<void*>(const_cast< pTimer*>(this));
60 if (!strcmp(_clname, "pObject"))
61 return static_cast< pObject*>(const_cast< pTimer*>(this));
62 return QObject::qt_metacast(_clname);
63 }
64
65 int pTimer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
66 {
67 _id = QObject::qt_metacall(_c, _id, _a);
68 if (_id < 0)
69 return _id;
70 if (_c == QMetaObject::InvokeMetaMethod) {
71 switch (_id) {
72 case 0: onTimeout(); break;
73 default: ;
74 }
75 _id -= 1;
76 }
77 return _id;
78 }
1879 static const uint qt_meta_data_pWindow[] = {
1980
2081 // content:
544605 }
545606 return _id;
546607 }
608 static const uint qt_meta_data_pHorizontalScrollBar[] = {
609
610 // content:
611 5, // revision
612 0, // classname
613 0, 0, // classinfo
614 1, 14, // methods
615 0, 0, // properties
616 0, 0, // enums/sets
617 0, 0, // constructors
618 0, // flags
619 0, // signalCount
620
621 // slots: signature, parameters, type, tag, flags
622 22, 21, 21, 21, 0x0a,
623
624 0 // eod
625 };
626
627 static const char qt_meta_stringdata_pHorizontalScrollBar[] = {
628 "pHorizontalScrollBar\0\0onChange()\0"
629 };
630
631 const QMetaObject pHorizontalScrollBar::staticMetaObject = {
632 { &QObject::staticMetaObject, qt_meta_stringdata_pHorizontalScrollBar,
633 qt_meta_data_pHorizontalScrollBar, 0 }
634 };
635
636 #ifdef Q_NO_DATA_RELOCATION
637 const QMetaObject &pHorizontalScrollBar::getStaticMetaObject() { return staticMetaObject; }
638 #endif //Q_NO_DATA_RELOCATION
639
640 const QMetaObject *pHorizontalScrollBar::metaObject() const
641 {
642 return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
643 }
644
645 void *pHorizontalScrollBar::qt_metacast(const char *_clname)
646 {
647 if (!_clname) return 0;
648 if (!strcmp(_clname, qt_meta_stringdata_pHorizontalScrollBar))
649 return static_cast<void*>(const_cast< pHorizontalScrollBar*>(this));
650 if (!strcmp(_clname, "pWidget"))
651 return static_cast< pWidget*>(const_cast< pHorizontalScrollBar*>(this));
652 return QObject::qt_metacast(_clname);
653 }
654
655 int pHorizontalScrollBar::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
656 {
657 _id = QObject::qt_metacall(_c, _id, _a);
658 if (_id < 0)
659 return _id;
660 if (_c == QMetaObject::InvokeMetaMethod) {
661 switch (_id) {
662 case 0: onChange(); break;
663 default: ;
664 }
665 _id -= 1;
666 }
667 return _id;
668 }
547669 static const uint qt_meta_data_pHorizontalSlider[] = {
548670
549671 // content:
683805
684806 // slots: signature, parameters, type, tag, flags
685807 11, 10, 10, 10, 0x0a,
686 24, 10, 10, 10, 0x0a,
687 40, 35, 10, 10, 0x0a,
808 29, 24, 10, 10, 0x0a,
809 56, 24, 10, 10, 0x0a,
688810
689811 0 // eod
690812 };
691813
692814 static const char qt_meta_stringdata_pListView[] = {
693 "pListView\0\0onActivate()\0onChange()\0"
694 "item\0onTick(QTreeWidgetItem*)\0"
815 "pListView\0\0onActivate()\0item\0"
816 "onChange(QTreeWidgetItem*)\0"
817 "onTick(QTreeWidgetItem*)\0"
695818 };
696819
697820 const QMetaObject pListView::staticMetaObject = {
726849 if (_c == QMetaObject::InvokeMetaMethod) {
727850 switch (_id) {
728851 case 0: onActivate(); break;
729 case 1: onChange(); break;
852 case 1: onChange((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
730853 case 2: onTick((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
731854 default: ;
732855 }
856979 }
857980 return _id;
858981 }
982 static const uint qt_meta_data_pVerticalScrollBar[] = {
983
984 // content:
985 5, // revision
986 0, // classname
987 0, 0, // classinfo
988 1, 14, // methods
989 0, 0, // properties
990 0, 0, // enums/sets
991 0, 0, // constructors
992 0, // flags
993 0, // signalCount
994
995 // slots: signature, parameters, type, tag, flags
996 20, 19, 19, 19, 0x0a,
997
998 0 // eod
999 };
1000
1001 static const char qt_meta_stringdata_pVerticalScrollBar[] = {
1002 "pVerticalScrollBar\0\0onChange()\0"
1003 };
1004
1005 const QMetaObject pVerticalScrollBar::staticMetaObject = {
1006 { &QObject::staticMetaObject, qt_meta_stringdata_pVerticalScrollBar,
1007 qt_meta_data_pVerticalScrollBar, 0 }
1008 };
1009
1010 #ifdef Q_NO_DATA_RELOCATION
1011 const QMetaObject &pVerticalScrollBar::getStaticMetaObject() { return staticMetaObject; }
1012 #endif //Q_NO_DATA_RELOCATION
1013
1014 const QMetaObject *pVerticalScrollBar::metaObject() const
1015 {
1016 return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
1017 }
1018
1019 void *pVerticalScrollBar::qt_metacast(const char *_clname)
1020 {
1021 if (!_clname) return 0;
1022 if (!strcmp(_clname, qt_meta_stringdata_pVerticalScrollBar))
1023 return static_cast<void*>(const_cast< pVerticalScrollBar*>(this));
1024 if (!strcmp(_clname, "pWidget"))
1025 return static_cast< pWidget*>(const_cast< pVerticalScrollBar*>(this));
1026 return QObject::qt_metacast(_clname);
1027 }
1028
1029 int pVerticalScrollBar::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
1030 {
1031 _id = QObject::qt_metacall(_c, _id, _a);
1032 if (_id < 0)
1033 return _id;
1034 if (_c == QMetaObject::InvokeMetaMethod) {
1035 switch (_id) {
1036 case 0: onChange(); break;
1037 default: ;
1038 }
1039 _id -= 1;
1040 }
1041 return _id;
1042 }
8591043 static const uint qt_meta_data_pVerticalSlider[] = {
8601044
8611045 // content:
5353 pFont(Font &font) : font(font) {}
5454 void constructor();
5555 void update();
56 };
57
58 struct pTimer : public QObject, public pObject {
59 Q_OBJECT
60
61 public:
62 Timer &timer;
63 QTimer *qtTimer;
64
65 void setEnabled(bool enabled);
66 void setInterval(unsigned milliseconds);
67
68 pTimer(Timer &timer) : timer(timer) {}
69 void constructor();
70
71 public slots:
72 void onTimeout();
5673 };
5774
5875 struct pMessageWindow : public pObject {
83100 void append(Layout &layout);
84101 void append(Menu &menu);
85102 void append(Widget &widget);
103 Color backgroundColor();
86104 Geometry frameMargin();
87105 bool focused();
88106 Geometry geometry();
89 void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
107 void setBackgroundColor(const Color &color);
90108 void setFocused();
91109 void setFullScreen(bool fullScreen);
92110 void setGeometry(const Geometry &geometry);
310328
311329 public slots:
312330 void onScroll();
331 };
332
333 struct pHorizontalScrollBar : public QObject, public pWidget {
334 Q_OBJECT
335
336 public:
337 HorizontalScrollBar &horizontalScrollBar;
338 QScrollBar *qtScrollBar;
339
340 Geometry minimumGeometry();
341 unsigned position();
342 void setLength(unsigned length);
343 void setPosition(unsigned position);
344
345 pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {}
346 void constructor();
347
348 public slots:
349 void onChange();
313350 };
314351
315352 struct pHorizontalSlider : public QObject, public pWidget {
388425
389426 public slots:
390427 void onActivate();
391 void onChange();
428 void onChange(QTreeWidgetItem *item);
392429 void onTick(QTreeWidgetItem *item);
393430 };
394431
444481 void onChange();
445482 };
446483
447 struct pVerticalSlider : public QObject, public pWidget {
448 Q_OBJECT
449
450 public:
451 VerticalSlider &verticalSlider;
452 QSlider *qtSlider;
484 struct pVerticalScrollBar : public QObject, public pWidget {
485 Q_OBJECT
486
487 public:
488 VerticalScrollBar &verticalScrollBar;
489 QScrollBar *qtScrollBar;
453490
454491 Geometry minimumGeometry();
455492 unsigned position();
456493 void setLength(unsigned length);
457494 void setPosition(unsigned position);
458495
496 pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {}
497 void constructor();
498
499 public slots:
500 void onChange();
501 };
502
503 struct pVerticalSlider : public QObject, public pWidget {
504 Q_OBJECT
505
506 public:
507 VerticalSlider &verticalSlider;
508 QSlider *qtSlider;
509
510 Geometry minimumGeometry();
511 unsigned position();
512 void setLength(unsigned length);
513 void setPosition(unsigned position);
514
459515 pVerticalSlider(VerticalSlider &verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {}
460516 void constructor();
461517
0 void pTimer::setEnabled(bool enabled) {
1 if(enabled) {
2 qtTimer->start();
3 } else {
4 qtTimer->stop();
5 }
6 }
7
8 void pTimer::setInterval(unsigned milliseconds) {
9 qtTimer->setInterval(milliseconds);
10 }
11
12 void pTimer::constructor() {
13 qtTimer = new QTimer;
14 qtTimer->setInterval(0);
15 connect(qtTimer, SIGNAL(timeout()), SLOT(onTimeout()));
16 }
17
18 void pTimer::onTimeout() {
19 if(timer.onTimeout) timer.onTimeout();
20 }
0 Geometry pHorizontalScrollBar::minimumGeometry() {
1 return { 0, 0, 0, 15 };
2 }
3
4 unsigned pHorizontalScrollBar::position() {
5 return qtScrollBar->value();
6 }
7
8 void pHorizontalScrollBar::setLength(unsigned length) {
9 length += length == 0;
10 qtScrollBar->setRange(0, length - 1);
11 qtScrollBar->setPageStep(length >> 3);
12 }
13
14 void pHorizontalScrollBar::setPosition(unsigned position) {
15 qtScrollBar->setValue(position);
16 }
17
18 void pHorizontalScrollBar::constructor() {
19 qtWidget = qtScrollBar = new QScrollBar(Qt::Horizontal);
20 qtScrollBar->setRange(0, 100);
21 qtScrollBar->setPageStep(101 >> 3);
22 connect(qtScrollBar, SIGNAL(valueChanged(int)), SLOT(onChange()));
23 }
24
25 void pHorizontalScrollBar::onChange() {
26 horizontalScrollBar.state.position = position();
27 if(horizontalScrollBar.onChange) horizontalScrollBar.onChange();
28 }
8181 locked = true;
8282 QTreeWidgetItem *item = qtListView->currentItem();
8383 if(item) item->setSelected(false);
84 qtListView->setCurrentItem(0);
8485 auto items = qtListView->findItems("", Qt::MatchContains);
8586 for(unsigned n = 0; n < items.size(); n++) {
8687 if(items[n]->data(0, Qt::UserRole).toUInt() == row) {
99100 qtListView->setRootIsDecorated(false);
100101
101102 connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
102 connect(qtListView, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
103 connect(qtListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(onChange(QTreeWidgetItem*)));
103104 connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
104105 }
105106
107108 if(locked == false && listView.onActivate) listView.onActivate();
108109 }
109110
110 void pListView::onChange() {
111 void pListView::onChange(QTreeWidgetItem *item) {
112 //Qt bug workaround: clicking items with mouse does not mark items as selected
113 if(item) item->setSelected(true);
111114 listView.state.selected = selected();
112115 if(listView.state.selected) listView.state.selection = selection();
113116 if(locked == false && listView.onChange) listView.onChange();
0 Geometry pVerticalScrollBar::minimumGeometry() {
1 return { 0, 0, 15, 0 };
2 }
3
4 unsigned pVerticalScrollBar::position() {
5 return qtScrollBar->value();
6 }
7
8 void pVerticalScrollBar::setLength(unsigned length) {
9 length += length == 0;
10 qtScrollBar->setRange(0, length - 1);
11 qtScrollBar->setPageStep(length >> 3);
12 }
13
14 void pVerticalScrollBar::setPosition(unsigned position) {
15 qtScrollBar->setValue(position);
16 }
17
18 void pVerticalScrollBar::constructor() {
19 qtWidget = qtScrollBar = new QScrollBar(Qt::Vertical);
20 qtScrollBar->setRange(0, 100);
21 qtScrollBar->setPageStep(101 >> 3);
22 connect(qtScrollBar, SIGNAL(valueChanged(int)), SLOT(onChange()));
23 }
24
25 void pVerticalScrollBar::onChange() {
26 verticalScrollBar.state.position = position();
27 if(verticalScrollBar.onChange) verticalScrollBar.onChange();
28 }
1515 }
1616 widget.p.qtWidget->setParent(qtContainer);
1717 widget.setVisible(widget.state.visible);
18 }
19
20 Color pWindow::backgroundColor() {
21 if(window.state.backgroundColorOverride) return window.state.backgroundColor;
22 QColor color = qtWindow->palette().color(QPalette::ColorRole::Window);
23 return { (uint8_t)color.red(), (uint8_t)color.green(), (uint8_t)color.blue(), (uint8_t)color.alpha() };
1824 }
1925
2026 Geometry pWindow::frameMargin() {
4248 return window.state.geometry;
4349 }
4450
45 void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
51 void pWindow::setBackgroundColor(const Color &color) {
4652 QPalette palette;
47 palette.setColor(QPalette::Window, QColor(red, green, blue));
53 palette.setColor(QPalette::Window, QColor(color.red, color.green, color.blue));
4854 qtContainer->setPalette(palette);
4955 qtContainer->setAutoFillBackground(true);
5056 }
0 Geometry pFont::geometry(const string &text) {
1 return { 0, 0, 0, 0 };
2 }
3
04 void pFont::setBold(bool bold) {
15 }
26
00 #include "reference.hpp"
11
22 #include "font.cpp"
3 #include "timer.cpp"
34 #include "message-window.cpp"
45 #include "window.cpp"
56
1213
1314 #include "widget/widget.cpp"
1415 #include "widget/button.cpp"
16 #include "widget/canvas.cpp"
1517 #include "widget/check-box.cpp"
1618 #include "widget/combo-box.cpp"
1719 #include "widget/hex-edit.cpp"
20 #include "widget/horizontal-scroll-bar.cpp"
1821 #include "widget/horizontal-slider.cpp"
1922 #include "widget/label.cpp"
2023 #include "widget/line-edit.cpp"
2225 #include "widget/progress-bar.cpp"
2326 #include "widget/radio-box.cpp"
2427 #include "widget/text-edit.cpp"
28 #include "widget/vertical-scroll-bar.cpp"
2529 #include "widget/vertical-slider.cpp"
2630 #include "widget/viewport.cpp"
2731
2828 struct pFont : public pObject {
2929 Font &font;
3030
31 Geometry geometry(const string &text);
3132 void setBold(bool bold);
3233 void setFamily(const string &family);
3334 void setItalic(bool italic);
3839 void constructor();
3940 };
4041
42 struct pTimer : public pObject {
43 Timer &timer;
44
45 void setEnabled(bool enabled);
46 void setInterval(unsigned milliseconds);
47
48 pTimer(Timer &timer) : timer(timer) {}
49 void constructor();
50 };
51
4152 struct pMessageWindow : public pObject {
4253 static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
4354 static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
5162 void append(Layout &layout);
5263 void append(Menu &menu);
5364 void append(Widget &widget);
65 Color backgroundColor();
5466 bool focused();
5567 Geometry frameMargin();
5668 Geometry geometry();
57 void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
69 void setBackgroundColor(const Color &color);
5870 void setFocused();
5971 void setFullScreen(bool fullScreen);
6072 void setGeometry(const Geometry &geometry);
135147 Widget &widget;
136148
137149 bool enabled();
150 Font& font();
151 Geometry minimumGeometry();
138152 void setEnabled(bool enabled);
139153 void setFocused();
140154 void setFont(Font &font);
154168 void constructor();
155169 };
156170
171 struct pCanvas : public pWidget {
172 Canvas &canvas;
173
174 uint32_t* buffer();
175 void update();
176
177 pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
178 void constructor();
179 };
180
157181 struct pCheckBox : public pWidget {
158182 CheckBox &checkBox;
159183
187211 void update();
188212
189213 pHexEdit(HexEdit &hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {}
214 void constructor();
215 };
216
217 struct pHorizontalScrollBar : public pWidget {
218 HorizontalScrollBar &horizontalScrollBar;
219
220 unsigned position();
221 void setLength(unsigned length);
222 void setPosition(unsigned position);
223
224 pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {}
190225 void constructor();
191226 };
192227
276311 void constructor();
277312 };
278313
314 struct pVerticalScrollBar : public pWidget {
315 VerticalScrollBar &verticalScrollBar;
316
317 unsigned position();
318 void setLength(unsigned length);
319 void setPosition(unsigned position);
320
321 pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {}
322 void constructor();
323 };
324
279325 struct pVerticalSlider : public pWidget {
280326 VerticalSlider &verticalSlider;
281327
0 void pTimer::setEnabled(bool enabled) {
1 }
2
3 void pTimer::setInterval(unsigned milliseconds) {
4 }
5
6 void pTimer::constructor() {
7 }
0 uint32_t* pCanvas::buffer() {
1 return 0;
2 }
3
4 void pCanvas::update() {
5 }
6
7 void pCanvas::constructor() {
8 }
0 unsigned pHorizontalScrollBar::position() {
1 return 0;
2 }
3
4 void pHorizontalScrollBar::setLength(unsigned length) {
5 }
6
7 void pHorizontalScrollBar::setPosition(unsigned position) {
8 }
9
10 void pHorizontalScrollBar::constructor() {
11 }
0 unsigned pVerticalScrollBar::position() {
1 return 0;
2 }
3
4 void pVerticalScrollBar::setLength(unsigned length) {
5 }
6
7 void pVerticalScrollBar::setPosition(unsigned position) {
8 }
9
10 void pVerticalScrollBar::constructor() {
11 }
00 bool pWidget::enabled() {
11 return false;
2 }
3
4 Font& pWidget::font() {
5 throw;
6 }
7
8 Geometry pWidget::minimumGeometry() {
9 return { 0, 0, 0, 0 };
210 }
311
412 void pWidget::setEnabled(bool enabled) {
44 }
55
66 void pWindow::append(Widget &widget) {
7 }
8
9 Color pWindow::backgroundColor() {
10 return { 0, 0, 0, 255 };
711 }
812
913 bool pWindow::focused() {
1822 return { 0, 0, 0, 0 };
1923 }
2024
21 void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
25 void pWindow::setBackgroundColor(const Color &color) {
2226 }
2327
2428 void pWindow::setFocused() {
55 }
66
77 synchronize "nall"
8 rm -r nall/test
4545
4646 void pFont::constructor() {
4747 hfont = Font_createFont("Tahoma", 8, false, false, false);
48 font.setFamily("Tahoma");
49 font.setSize(8);
4850 }
0 static linear_vector<pTimer*> timers;
1
2 static void CALLBACK Timer_timeoutProc(HWND hwnd, UINT msg, UINT_PTR timerID, DWORD time) {
3 foreach(timer, timers) {
4 if(timer->htimer == timerID) {
5 if(timer->timer.onTimeout) timer->timer.onTimeout();
6 return;
7 }
8 }
9 }
10
11 void pTimer::setEnabled(bool enabled) {
12 if(htimer) {
13 KillTimer(NULL, htimer);
14 htimer = 0;
15 }
16
17 if(enabled == true) {
18 htimer = SetTimer(NULL, 0U, timer.state.milliseconds, Timer_timeoutProc);
19 }
20 }
21
22 void pTimer::setInterval(unsigned milliseconds) {
23 //destroy and recreate timer if interval changed
24 setEnabled(timer.state.enabled);
25 }
26
27 void pTimer::constructor() {
28 timers.append(this);
29 htimer = 0;
30 }
0 Geometry pHorizontalScrollBar::minimumGeometry() {
1 return { 0, 0, 0, 18 };
2 }
3
4 unsigned pHorizontalScrollBar::position() {
5 return GetScrollPos(hwnd, SB_CTL);
6 }
7
8 void pHorizontalScrollBar::setLength(unsigned length) {
9 length += (length == 0);
10 SetScrollRange(hwnd, SB_CTL, 0, length - 1, TRUE);
11 horizontalScrollBar.setPosition(0);
12 }
13
14 void pHorizontalScrollBar::setPosition(unsigned position) { return;
15 SetScrollPos(hwnd, SB_CTL, position, TRUE);
16 }
17
18 void pHorizontalScrollBar::constructor() {
19 setParent(Window::None);
20 }
21
22 void pHorizontalScrollBar::setParent(Window &parent) {
23 if(hwnd) DestroyWindow(hwnd);
24 hwnd = CreateWindow(
25 L"SCROLLBAR", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_HORZ,
26 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0
27 );
28 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&horizontalScrollBar);
29 unsigned position = horizontalScrollBar.state.position;
30 setLength(horizontalScrollBar.state.length);
31 setPosition(position);
32 }
2727 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0
2828 );
2929 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&horizontalSlider);
30 unsigned position = horizontalSlider.state.position;
3031 setLength(horizontalSlider.state.length);
31 setPosition(horizontalSlider.state.position);
32 setPosition(position);
3233 }
1212 utf16_t wtext(text);
1313 ListView_SetItemText(hwnd, row, n, wtext);
1414 }
15 //workaround: when there is only one column, the horizontal scrollbar will always appear without this
16 if(listView.state.headerText.size() <= 1) ListView_SetColumnWidth(hwnd, 0, LVSCW_AUTOSIZE_USEHEADER);
1715 }
1816
1917 void pListView::autoSizeColumns() {
3129 utf16_t wtext(text);
3230 ListView_SetItemText(hwnd, row, n, wtext);
3331 }
34 if(listView.state.headerText.size() <= 1) ListView_SetColumnWidth(hwnd, 0, LVSCW_AUTOSIZE_USEHEADER);
3532 }
3633
3734 void pListView::reset() {
109106 void pListView::constructor() {
110107 lostFocus = false;
111108 setParent(Window::None);
109 listView.setHeaderText("");
112110 }
113111
114112 void pListView::setGeometry(const Geometry &geometry) {
0 Geometry pVerticalScrollBar::minimumGeometry() {
1 return { 0, 0, 18, 0 };
2 }
3
4 unsigned pVerticalScrollBar::position() {
5 return GetScrollPos(hwnd, SB_CTL);
6 }
7
8 void pVerticalScrollBar::setLength(unsigned length) {
9 length += (length == 0);
10 SetScrollRange(hwnd, SB_CTL, 0, length - 1, TRUE);
11 verticalScrollBar.setPosition(0);
12 }
13
14 void pVerticalScrollBar::setPosition(unsigned position) {
15 SetScrollPos(hwnd, SB_CTL, position, TRUE);
16 }
17
18 void pVerticalScrollBar::constructor() {
19 setParent(Window::None);
20 }
21
22 void pVerticalScrollBar::setParent(Window &parent) {
23 if(hwnd) DestroyWindow(hwnd);
24 hwnd = CreateWindow(
25 L"SCROLLBAR", L"", WS_CHILD | WS_VISIBLE | SBS_VERT,
26 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0
27 );
28 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&verticalScrollBar);
29 unsigned position = verticalScrollBar.state.position;
30 setLength(verticalScrollBar.state.length);
31 setPosition(position);
32 }
00 Geometry pVerticalSlider::minimumGeometry() {
1 return { 0, 0, 25, 0 };
1 return { 0, 0, 0, 25 };
22 }
33
44 unsigned pVerticalSlider::position() {
2727 0, 0, 0, 0, parent.p.hwnd, (HMENU)id, GetModuleHandle(0), 0
2828 );
2929 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&verticalSlider);
30 unsigned position = verticalSlider.state.position;
3031 setLength(verticalSlider.state.length);
31 setPosition(verticalSlider.state.position);
32 setPosition(position);
3233 }
1313
1414 void pWindow::append(Widget &widget) {
1515 widget.p.setParent(window);
16 }
17
18 Color pWindow::backgroundColor() {
19 if(window.state.backgroundColorOverride) return window.state.backgroundColor;
20 DWORD color = GetSysColor(COLOR_3DFACE);
21 return { (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color >> 0), 255 };
1622 }
1723
1824 bool pWindow::focused() {
3541
3642 Geometry pWindow::geometry() {
3743 Geometry margin = frameMargin();
44
3845 RECT rc;
39 GetWindowRect(hwnd, &rc);
46 if(IsIconic(hwnd)) {
47 //GetWindowRect returns -32000(x),-32000(y) when window is minimized
48 WINDOWPLACEMENT wp;
49 GetWindowPlacement(hwnd, &wp);
50 rc = wp.rcNormalPosition;
51 } else {
52 GetWindowRect(hwnd, &rc);
53 }
4054
4155 signed x = rc.left + margin.x;
4256 signed y = rc.top + margin.y;
4660 return { x, y, width, height };
4761 }
4862
49 void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
63 void pWindow::setBackgroundColor(const Color &color) {
5064 if(brush) DeleteObject(brush);
51 brushColor = RGB(red, green, blue);
65 brushColor = RGB(color.red, color.green, color.blue);
5266 brush = CreateSolidBrush(brushColor);
5367 }
5468
11
22 #include "object.cpp"
33 #include "font.cpp"
4 #include "timer.cpp"
45 #include "message-window.cpp"
56 #include "window.cpp"
67
1718 #include "widget/check-box.cpp"
1819 #include "widget/combo-box.cpp"
1920 #include "widget/hex-edit.cpp"
21 #include "widget/horizontal-scroll-bar.cpp"
2022 #include "widget/horizontal-slider.cpp"
2123 #include "widget/label.cpp"
2224 #include "widget/line-edit.cpp"
2426 #include "widget/progress-bar.cpp"
2527 #include "widget/radio-box.cpp"
2628 #include "widget/text-edit.cpp"
29 #include "widget/vertical-scroll-bar.cpp"
2730 #include "widget/vertical-slider.cpp"
2831 #include "widget/viewport.cpp"
2932
173176 WNDCLASS wc;
174177 wc.cbClsExtra = 0;
175178 wc.cbWndExtra = 0;
176 wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
179 wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
177180 wc.hCursor = LoadCursor(0, IDC_ARROW);
178181 wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
179182 wc.hInstance = GetModuleHandle(0);
197200
198201 wc.cbClsExtra = 0;
199202 wc.cbWndExtra = 0;
200 wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
203 wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
201204 wc.hCursor = LoadCursor(0, IDC_ARROW);
202205 wc.hIcon = LoadIcon(0, IDI_APPLICATION);
203206 wc.hInstance = GetModuleHandle(0);
406409
407410 case WM_HSCROLL:
408411 case WM_VSCROLL: {
409 unsigned id = LOWORD(wparam);
410 HWND control = GetDlgItem(window.p.hwnd, id);
411 if(control == 0) break;
412 Object *object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
412 Object *object = 0;
413 if(lparam) {
414 object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
415 } else {
416 unsigned id = LOWORD(wparam);
417 HWND control = GetDlgItem(window.p.hwnd, id);
418 if(control == 0) break;
419 object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
420 }
413421 if(object == 0) break;
422
423 if(dynamic_cast<HorizontalScrollBar*>(object)
424 || dynamic_cast<VerticalScrollBar*>(object)) {
425 SCROLLINFO info;
426 memset(&info, 0, sizeof(SCROLLINFO));
427 info.cbSize = sizeof(SCROLLINFO);
428 info.fMask = SIF_ALL;
429 GetScrollInfo((HWND)lparam, SB_CTL, &info);
430
431 switch(LOWORD(wparam)) {
432 case SB_LEFT: info.nPos = info.nMin; break;
433 case SB_RIGHT: info.nPos = info.nMax; break;
434 case SB_LINELEFT: info.nPos--; break;
435 case SB_LINERIGHT: info.nPos++; break;
436 case SB_PAGELEFT: info.nPos -= info.nMax >> 3; break;
437 case SB_PAGERIGHT: info.nPos += info.nMax >> 3; break;
438 case SB_THUMBTRACK: info.nPos = info.nTrackPos; break;
439 }
440
441 info.fMask = SIF_POS;
442 SetScrollInfo((HWND)lparam, SB_CTL, &info, TRUE);
443
444 //Windows may clamp position to scrollbar range
445 GetScrollInfo((HWND)lparam, SB_CTL, &info);
446
447 if(dynamic_cast<HorizontalScrollBar*>(object)) {
448 HorizontalScrollBar &horizontalScrollBar = (HorizontalScrollBar&)*object;
449 if(horizontalScrollBar.state.position != info.nPos) {
450 horizontalScrollBar.state.position = info.nPos;
451 horizontalScrollBar.onChange();
452 }
453 } else {
454 VerticalScrollBar &verticalScrollBar = (VerticalScrollBar&)*object;
455 if(verticalScrollBar.state.position != info.nPos) {
456 verticalScrollBar.state.position = info.nPos;
457 verticalScrollBar.onChange();
458 }
459 }
460
461 return TRUE;
462 }
463
414464 if(dynamic_cast<HorizontalSlider*>(object)) {
415465 HorizontalSlider &horizontalSlider = (HorizontalSlider&)*object;
416466 if(horizontalSlider.state.position != horizontalSlider.position()) {
4848 void constructor();
4949 };
5050
51 struct pTimer : public pObject {
52 Timer &timer;
53 UINT_PTR htimer;
54
55 void setEnabled(bool enabled);
56 void setInterval(unsigned milliseconds);
57
58 pTimer(Timer &timer) : timer(timer) {}
59 void constructor();
60 };
61
5162 struct pMessageWindow : public pObject {
5263 static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
5364 static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
6677 void append(Layout &layout);
6778 void append(Menu &menu);
6879 void append(Widget &widget);
80 Color backgroundColor();
6981 bool focused();
7082 Geometry frameMargin();
7183 Geometry geometry();
72 void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
84 void setBackgroundColor(const Color &color);
7385 void setFocused();
7486 void setFullScreen(bool fullScreen);
7587 void setGeometry(const Geometry &geometry);
235247 pHexEdit(HexEdit &hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {}
236248 void constructor();
237249 bool keyPress(unsigned key);
250 void setParent(Window &parent);
251 };
252
253 struct pHorizontalScrollBar : public pWidget {
254 HorizontalScrollBar &horizontalScrollBar;
255
256 Geometry minimumGeometry();
257 unsigned position();
258 void setLength(unsigned length);
259 void setPosition(unsigned position);
260
261 pHorizontalScrollBar(HorizontalScrollBar &horizontalScrollBar) : pWidget(horizontalScrollBar), horizontalScrollBar(horizontalScrollBar) {}
262 void constructor();
238263 void setParent(Window &parent);
239264 };
240265
338363 void setParent(Window &parent);
339364 };
340365
341 struct pVerticalSlider : public pWidget {
342 VerticalSlider &verticalSlider;
366 struct pVerticalScrollBar : public pWidget {
367 VerticalScrollBar &verticalScrollBar;
343368
344369 Geometry minimumGeometry();
345370 unsigned position();
346371 void setLength(unsigned length);
347372 void setPosition(unsigned position);
348373
374 pVerticalScrollBar(VerticalScrollBar &verticalScrollBar) : pWidget(verticalScrollBar), verticalScrollBar(verticalScrollBar) {}
375 void constructor();
376 void setParent(Window &parent);
377 };
378
379 struct pVerticalSlider : public pWidget {
380 VerticalSlider &verticalSlider;
381
382 Geometry minimumGeometry();
383 unsigned position();
384 void setLength(unsigned length);
385 void setPosition(unsigned position);
386
349387 pVerticalSlider(VerticalSlider &verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {}
350388 void constructor();
351389 void setParent(Window &parent);
0 #include <nall/directory.hpp>
1 #include <nall/file.hpp>
2 #include <nall/filemap.hpp>
3 #include <nall/foreach.hpp>
4 #include <nall/platform.hpp>
5 #include <nall/string.hpp>
6 #include <nall/vector.hpp>
7 #include <nall/snes/cartridge.hpp>
8 using namespace nall;
9
10 #include <phoenix/phoenix.hpp>
11 using namespace phoenix;
12
13 static const char applicationTitle[] = "snespurify v10";
14
15 struct Application : Window {
16 Font font;
17 VerticalLayout layout;
18 HorizontalLayout pathLayout;
19 Label pathLabel;
20 LineEdit pathBox;
21 Button pathScan;
22 Button pathBrowse;
23 ListView fileList;
24 HorizontalLayout controlLayout;
25 Button selectAll;
26 Button unselectAll;
27 Widget spacer;
28 Button fixSelected;
29
30 struct FileInfo {
31 string filename;
32 string problem;
33 string solution;
0 #include "snespurify.hpp"
1
2 MainWindow mainWindow;
3
4 void MainWindow::create() {
5 font.setSize(8);
6 setWidgetFont(font);
7 setTitle("SNES Purify v11");
8
9 navigationLabel.setText("Path to scan:");
10 navigationScan.setEnabled(false);
11 navigationScan.setText("Scan");
12 navigationBrowse.setText("Browse ...");
13
14 listView.setHeaderText("Filename", "Problem");
15 listView.setHeaderVisible();
16 listView.setCheckable();
17
18 controlSelectAll.setText("Select All");
19 controlClearAll.setText("Clear All");
20 controlDeleteFiles.setText("Delete ZIP, IPS, UPS files after conversion");
21 controlCorrect.setEnabled(false);
22 controlCorrect.setText("Correct");
23
24 layout.setMargin(5);
25 navigationLayout.append(navigationLabel, 0, 0, 5);
26 navigationLayout.append(navigationPath, ~0, 0, 5);
27 navigationLayout.append(navigationScan, 80, 0, 5);
28 navigationLayout.append(navigationBrowse, 80, 0);
29 layout.append(navigationLayout, 5);
30 layout.append(listView, ~0, ~0, 5);
31 controlLayout.append(controlSelectAll, 80, 0, 5);
32 controlLayout.append(controlClearAll, 80, 0, 5);
33 controlLayout.append(controlDeleteFiles, 0, 0, 5);
34 controlLayout.append(spacer, ~0, 0);
35 controlLayout.append(controlCorrect, 80, 0);
36 layout.append(controlLayout);
37 append(layout);
38
39 onClose = &OS::quit;
40
41 navigationPath.onChange = [this] {
42 navigationScan.setEnabled(navigationPath.text() != "");
3443 };
35 linear_vector<FileInfo> fileInfo;
36 lstring errors;
37
38 void main();
39 void enable(bool);
40 void scan();
41 void scan(const string &pathname);
42 void analyze(const string &filename);
43 void repair();
44 } application;
45
46 void Application::main() {
47 #if defined(PLATFORM_WIN)
48 font.setFamily("Tahoma");
49 font.setSize(8);
50 #else
51 font.setFamily("Sans");
52 font.setSize(8);
53 #endif
54 setTitle(applicationTitle);
55 setGeometry({ 128, 128, 600, 360 });
56 setWidgetFont(font);
57
58 pathLabel.setText("Path to scan:");
59 pathScan.setText("Scan");
60 pathBrowse.setText("Browse ...");
61 fileList.setHeaderText("Filename", "Problem", "Solution");
62 fileList.setHeaderVisible();
63 fileList.setCheckable();
64 selectAll.setText("Select All");
65 unselectAll.setText("Clear All");
66 fixSelected.setText("Correct");
67
68 layout.setMargin(5);
69 pathLayout.append(pathLabel, 0, 0, 5);
70 pathLayout.append(pathBox, ~0, 0, 5);
71 pathLayout.append(pathScan, 80, 0, 5);
72 pathLayout.append(pathBrowse, 80, 0 );
73 layout.append(pathLayout, 5);
74 layout.append(fileList, ~0, ~0, 5);
75 controlLayout.append(selectAll, 80, 0, 5);
76 controlLayout.append(unselectAll, 80, 0, 5);
77 controlLayout.append(spacer, ~0, 0, 5);
78 controlLayout.append(fixSelected, 80, 0 );
79 layout.append(controlLayout );
80 append(layout);
81
82 onClose = &OS::quit;
83
84 pathBox.onActivate = pathScan.onTick = { &Application::scan, this };
85
86 pathBrowse.onTick = []() {
87 string pathname = OS::folderSelect(application, "");
88 if(pathname != "") application.pathBox.setText(pathname);
44
45 navigationPath.onActivate = navigationScan.onTick = { &MainWindow::onScan, this };
46
47 navigationBrowse.onTick = [this] {
48 string path = OS::folderSelect(*this, "");
49 if(path != "") {
50 navigationPath.setText(path);
51 navigationScan.setEnabled(true);
52 navigationScan.onTick();
53 }
8954 };
9055
91 selectAll.onTick = []() {
92 unsigned count = application.fileInfo.size();
93 for(unsigned i = 0; i < count; i++) application.fileList.setChecked(i, true);
56 controlSelectAll.onTick = [this] {
57 for(unsigned n = 0; n < fileList.size(); n++) listView.setChecked(n, true);
9458 };
9559
96 unselectAll.onTick = []() {
97 unsigned count = application.fileInfo.size();
98 for(unsigned i = 0; i < count; i++) application.fileList.setChecked(i, false);
60 controlClearAll.onTick = [this] {
61 for(unsigned n = 0; n < fileList.size(); n++) listView.setChecked(n, false);
9962 };
10063
101 fixSelected.onTick = { &Application::repair, this };
102
64 controlCorrect.onTick = { &MainWindow::onCorrect, this };
65
66 setGeometry({ 128, 128, 640, 360 });
10367 setVisible();
10468 }
10569
106 //don't allow actions to be taken while files are being scanned or fixed
107 void Application::enable(bool state) {
108 if(state == false) {
109 setTitle({ applicationTitle, " - working ..." });
70 void MainWindow::onScan() {
71 string path = navigationPath.text();
72 path.transform("\\", "/");
73 if(path.endswith("/") == false) path.append("/");
74
75 listView.reset();
76 fileList.reset();
77 onScanFolder(path);
78 foreach(file, fileList) {
79 listView.append(notdir(file.name), file.problem);
80 }
81 controlSelectAll.onTick();
82 listView.autoSizeColumns();
83 controlCorrect.setEnabled(fileList.size() > 0);
84 }
85
86 void MainWindow::onScanFolder(const string &path) {
87 lstring contents = directory::contents(path);
88 foreach(filename, contents) {
89 if(filename.endswith("/")) onScanFolder({ path, filename });
90 else analyzeFile({ path, filename });
91 }
92 }
93
94 void MainWindow::analyzeFile(const string &filename) {
95 File file;
96 file.name = filename;
97
98 if(filename.iendswith(".zip")) {
99 //verify there is exactly one SNES image inside the archive
100 zip archive;
101 if(archive.open(filename)) {
102 unsigned fileCount = 0, archiveFileSize = 0;
103 string archiveFileName;
104 foreach(archiveFile, archive.file) if(isImageName(archiveFile.name)) {
105 //make sure file isn't already decompressed
106 string basename = { nall::basename(filename), correctExtension(archiveFile.name) };
107 if(file::exists(basename)) { fileCount = 0; break; } //zero fileCount to prevent multi-archive repeated extractions
108
109 fileCount++;
110 archiveFileName = archiveFile.name;
111 archiveFileSize = archiveFile.size;
112 }
113 archive.close();
114 if(fileCount == 1) {
115 file.problem.append("Compressed with ZIP; ");
116 if(isSnesImageName(archiveFileName) && (archiveFileSize & 0x7fff) == 512) {
117 file.problem.append("Contains copier header; ");
118 }
119 }
120 }
121 }
122
123 if(isBadImageName(filename)) {
124 file.problem.append("Incorrect extension; ");
125 }
126
127 if(isSnesImageName(filename) && (file::size(filename) & 0x7fff) == 512) {
128 file.problem.append("Contains copier header; ");
129 }
130
131 if((isImageName(filename) || filename.iendswith(".zip")) && !file::exists({ nall::basename(filename), ".bps" })) {
132 if(file::exists({ nall::basename(filename), ".ups" })) {
133 file.problem.append("Deprecated UPS patch; ");
134 } else if(file::exists({ nall::basename(filename), ".ips" })) {
135 file.problem.append("Deprecated IPS patch; ");
136 }
137 }
138
139 file.problem.rtrim<1>("; ");
140 if(file.problem != "") fileList.append(file);
141 }
142
143 bool MainWindow::isSnesCartImageName(const string &filename) {
144 if(filename.iendswith(".sfc")) return true;
145 if(filename.iendswith(".048")) return true;
146 if(filename.iendswith(".058")) return true;
147 if(filename.iendswith(".068")) return true;
148 if(filename.iendswith(".078")) return true;
149 if(filename.iendswith(".aus")) return true;
150 if(filename.iendswith(".dx2")) return true;
151 if(filename.iendswith(".eur")) return true;
152 if(filename.iendswith(".fig")) return true;
153 if(filename.iendswith(".gd3")) return true;
154 if(filename.iendswith(".gd7")) return true;
155 if(filename.iendswith(".jap")) return true;
156 if(filename.iendswith(".mgd")) return true;
157 if(filename.iendswith(".mgh")) return true;
158 if(filename.iendswith(".smc")) return true;
159 if(filename.iendswith(".swc")) return true;
160 if(filename.iendswith(".ufo")) return true;
161 if(filename.iendswith(".usa")) return true;
162 return false;
163 }
164
165 bool MainWindow::isSnesBsImageName(const string &filename) {
166 if(filename.iendswith(".bs")) return true;
167 if(filename.iendswith(".bsx")) return true;
168 return false;
169 }
170
171 bool MainWindow::isSnesStImageName(const string &filename) {
172 if(filename.iendswith(".st")) return true;
173 return false;
174 }
175
176 bool MainWindow::isSnesImageName(const string &filename) {
177 if(isSnesCartImageName(filename)) return true;
178 if(isSnesBsImageName(filename)) return true;
179 if(isSnesStImageName(filename)) return true;
180 return false;
181 }
182
183 bool MainWindow::isGameBoyClassicImageName(const string &filename) {
184 if(filename.iendswith(".gb")) return true;
185 if(filename.iendswith(".sgb")) return true;
186 return false;
187 }
188
189 bool MainWindow::isGameBoyColorImageName(const string &filename) {
190 if(filename.iendswith(".gbc")) return true;
191 return false;
192 }
193
194 bool MainWindow::isGameBoyImageName(const string &filename) {
195 if(isGameBoyClassicImageName(filename)) return true;
196 if(isGameBoyColorImageName(filename)) return true;
197 return false;
198 }
199
200 bool MainWindow::isImageName(const string &filename) {
201 if(isSnesImageName(filename)) return true;
202 if(isGameBoyImageName(filename)) return true;
203 return false;
204 }
205
206 bool MainWindow::isGoodImageName(const string &filename) {
207 if(filename.endswith(".sfc")) return true;
208 if(filename.endswith(".bs")) return true;
209 if(filename.endswith(".st")) return true;
210 if(filename.endswith(".gb")) return true;
211 if(filename.endswith(".gbc")) return true;
212 return false;
213 }
214
215 bool MainWindow::isBadImageName(const string &filename) {
216 return (isGoodImageName(filename) == false && isImageName(filename) == true);
217 }
218
219 string MainWindow::correctExtension(const string &filename) {
220 if(isSnesCartImageName(filename)) return ".sfc";
221 if(isSnesBsImageName(filename)) return ".bs";
222 if(isSnesStImageName(filename)) return ".st";
223 if(isGameBoyClassicImageName(filename)) return ".gb";
224 if(isGameBoyColorImageName(filename)) return ".gbc";
225 return { ".", extension(filename) }; //should never occur
226 }
227
228 void MainWindow::onCorrect() {
229 navigationPath.setEnabled(false);
230 navigationScan.setEnabled(false);
231 navigationBrowse.setEnabled(false);
232 listView.setEnabled(false);
233 controlSelectAll.setEnabled(false);
234 controlClearAll.setEnabled(false);
235 controlDeleteFiles.setEnabled(false);
236 controlCorrect.setEnabled(false);
237 OS::processEvents();
238
239 MessageWindow::information(*this,
240 "Corrections may take a long time to complete.\n"
241 "The GUI will be unresponsive during this time, so please be patient.\n"
242 "You will be notified when all corrections have been completed."
243 );
244 OS::processEvents();
245
246 errors.reset();
247 foreach(file, fileList, n) {
248 if(listView.checked(n) == false) continue;
249 if(file.problem.position("Compressed with ZIP")) problemDecompressZip(file);
250 if(file.problem.position("Incorrect extension")) problemCorrectExtension(file);
251 if(file.problem.position("Deprecated UPS patch")) problemCreatePatchFromUPS(file);
252 if(file.problem.position("Deprecated IPS patch")) problemCreatePatchFromIPS(file);
253 if(file.problem.position("Contains copier header")) problemRemoveCopierHeader(file);
254 }
255
256 if(errors.size() == 0) {
257 MessageWindow::information(*this, "Corrections completed!");
110258 } else {
111 setTitle(applicationTitle);
112 }
113
114 pathBox.setEnabled(state);
115 pathScan.setEnabled(state);
116 pathBrowse.setEnabled(state);
117 fileList.setEnabled(state);
118 selectAll.setEnabled(state);
119 unselectAll.setEnabled(state);
120 fixSelected.setEnabled(state);
121 }
122
123 void Application::scan() {
124 fileInfo.reset();
259 file fp;
260 if(fp.open({ navigationPath.text(), "errors.txt" }, file::mode::write)) {
261 foreach(error, errors) fp.print(error, "\n");
262 fp.close();
263 }
264 MessageWindow::information(*this, {
265 "Corrections completed, but there were errors.\n"
266 "Please see ", navigationPath.text(), "errors.txt for more details.\n"
267 });
268 }
269 listView.reset();
270 listView.autoSizeColumns();
125271 fileList.reset();
126272
127 string pathname = pathBox.text();
128 if(pathname == "") {
129 MessageWindow::information(application, "Please specify a directory to scan");
130 return;
131 }
132 pathname.transform("\\", "/");
133 if(pathname.endswith("/") == false) pathname.append("/");
134 if(directory::exists(pathname) == false) {
135 MessageWindow::warning(application, "Specified directory does not exist");
136 return;
137 }
138
139 enable(false);
140 scan(pathname);
141 enable(true);
142
143 if(fileInfo.size() == 0) {
144 MessageWindow::information(application, "All files are correct");
145 return;
146 }
147
148 unsigned counter = 0;
149 foreach(info, fileInfo) {
150 fileList.append(notdir(info.filename), info.problem, info.solution);
151 fileList.setChecked(counter++, true);
152 }
153 fileList.autoSizeColumns();
154 }
155
156 void Application::scan(const string &pathname) {
157 lstring files = directory::files(pathname);
158 foreach(file, files) {
159 OS::processEvents();
160 analyze({ pathname, file });
161 }
162
163 //recursion
164 lstring folders = directory::folders(pathname);
165 foreach(folder, folders) scan({ pathname, folder });
166 }
167
168 void Application::analyze(const string &filename) {
169 if(file::exists(filename) == false) return;
170
171 if(filename.iendswith(".sfc") || filename.iendswith(".bs") || filename.iendswith(".st")
172 || filename.iendswith(".gb") || filename.iendswith(".gbc") || filename.iendswith(".sgb")
173 || filename.iendswith(".smc") || filename.iendswith(".swc") || filename.iendswith(".fig") || filename.iendswith(".ufo")
174 || filename.iendswith(".gd3") || filename.iendswith(".gd7") || filename.iendswith(".dx2") || filename.iendswith(".mgd")
175 || filename.iendswith(".mgh") || filename.iendswith(".048") || filename.iendswith(".058") || filename.iendswith(".068")
176 || filename.iendswith(".078") || filename.iendswith(".usa") || filename.iendswith(".eur") || filename.iendswith(".jap")
177 || filename.iendswith(".aus") || filename.iendswith(".bsx")
178 ) {
179 filemap map(filename, filemap::mode::read);
180 unsigned filesize = map.size();
181 SNESCartridge information(map.data(), filesize);
182
183 //note: the ordering of rules is very important
184 switch(information.type) {
185 case SNESCartridge::TypeNormal:
186 case SNESCartridge::TypeBsxSlotted:
187 case SNESCartridge::TypeBsxBios:
188 case SNESCartridge::TypeSufamiTurboBios:
189 case SNESCartridge::TypeSuperGameBoy1Bios:
190 case SNESCartridge::TypeSuperGameBoy2Bios: {
191 if((filesize & 0x7fff) == 512) {
192 FileInfo info;
193 info.filename = filename;
194 info.problem = "Copier header present";
195 info.solution = "Remove copier header";
196 fileInfo.append(info);
273 navigationPath.setEnabled(true);
274 navigationScan.setEnabled(true);
275 navigationBrowse.setEnabled(true);
276 listView.setEnabled(true);
277 controlSelectAll.setEnabled(true);
278 controlClearAll.setEnabled(true);
279 controlDeleteFiles.setEnabled(true);
280 }
281
282 void MainWindow::problemDecompressZip(File &item) {
283 zip archive;
284 if(archive.open(item.name)) {
285 foreach(archiveFile, archive.file) {
286 if(isImageName(archiveFile.name)) {
287 uint8_t *data;
288 unsigned size;
289 if(archive.extract(archiveFile, data, size)) {
290 string targetFileName = { nall::basename(item.name), correctExtension(archiveFile.name) };
291 if(file::write(targetFileName, data, size) == false) {
292 errors.append({ "Failed to write file: ", item.name });
293 } else {
294 if(controlDeleteFiles.checked()) unlink(item.name);
295 item.name = targetFileName;
296 }
297 } else {
298 errors.append({ "Failed to decompress file: ", item.name });
197299 }
198
199 if(filename.endswith(".sfc") == false) {
200 FileInfo info;
201 info.filename = filename;
202 info.problem = "Wrong file extension";
203 info.solution = "Rename to .sfc";
204 fileInfo.append(info);
205 }
206
207300 break;
208301 }
209
210 case SNESCartridge::TypeBsx: {
211 if((filesize & 0x7fff) == 512) {
212 FileInfo info;
213 info.filename = filename;
214 info.problem = "Copier header present";
215 info.solution = "Remove copier header";
216 fileInfo.append(info);
217 }
218
219 if(filename.endswith(".bs") == false) {
220 FileInfo info;
221 info.filename = filename;
222 info.problem = "Wrong file extension";
223 info.solution = "Rename to .bs";
224 fileInfo.append(info);
225 }
226
227 break;
302 }
303 }
304 }
305
306 void MainWindow::problemCorrectExtension(File &item) {
307 string filename = { nall::basename(item.name), correctExtension(item.name) };
308 if(rename(item.name, filename) == -1) {
309 errors.append({ "Failed to rename file: ", item.name });
310 } else {
311 item.name = filename;
312 }
313 }
314
315 void MainWindow::problemCreatePatchFromUPS(File &item) {
316 string upsPatchName = { nall::basename(item.name), ".ups" };
317 string bpsPatchName = { nall::basename(item.name), ".bps" };
318 ups oldPatch;
319 filemap patchFile, sourceFile;
320 patchFile.open(upsPatchName, filemap::mode::read);
321 sourceFile.open(item.name, filemap::mode::read);
322 uint8_t *targetData = 0;
323 unsigned targetSize = 0;
324 oldPatch.apply(patchFile.data(), patchFile.size(), sourceFile.data(), sourceFile.size(), targetData, targetSize);
325 targetData = new uint8_t[targetSize];
326 if(oldPatch.apply(patchFile.data(), patchFile.size(), sourceFile.data(), sourceFile.size(), targetData, targetSize)
327 == ups::result::success) {
328 bpslinear newPatch;
329 newPatch.source(item.name);
330 newPatch.target(targetData, targetSize);
331 if(newPatch.create(bpsPatchName)) {
332 patchFile.close();
333 if(controlDeleteFiles.checked()) unlink(upsPatchName);
334 } else {
335 errors.append({ "Failed to create BPS patch: ", bpsPatchName });
336 }
337 } else {
338 errors.append({ "Invalid UPS patch: ", upsPatchName });
339 }
340 }
341
342 void MainWindow::problemCreatePatchFromIPS(File &item) {
343 string ipsPatchName = { nall::basename(item.name), ".ips" };
344 string bpsPatchName = { nall::basename(item.name), ".bps" };
345 ips oldPatch;
346 oldPatch.source(item.name);
347 oldPatch.modify(ipsPatchName);
348 if(oldPatch.apply()) {
349 bpslinear newPatch;
350 newPatch.source(item.name);
351 newPatch.target(oldPatch.data, oldPatch.size);
352 if(newPatch.create(bpsPatchName)) {
353 if(controlDeleteFiles.checked()) unlink(ipsPatchName);
354 } else {
355 errors.append({ "Failed to create BPS patch: ", bpsPatchName });
356 }
357 } else {
358 errors.append({ "Invalid IPS patch: ", ipsPatchName });
359 }
360 }
361
362 /*
363 void MainWindow::problemCreateUpsPatch(File &item) {
364 string ipsPatchName = { nall::basename(item.name), ".ips" };
365 ips oldPatch;
366 oldPatch.source(item.name);
367 oldPatch.modify(ipsPatchName);
368 if(oldPatch.apply()) {
369 ups newPatch;
370 if(newPatch.create(
371 oldPatch.sourceData, oldPatch.sourceSize,
372 oldPatch.data, oldPatch.size,
373 string(nall::basename(item.name), ".ups")
374 ) != ups::result::success) {
375 errors.append({ "Failed to convert IPS patch: ", ipsPatchName });
376 } else {
377 if(controlDeleteFiles.checked()) unlink(ipsPatchName);
378 }
379 }
380 }
381 */
382
383 void MainWindow::problemRemoveCopierHeader(File &item) {
384 uint8_t *data;
385 unsigned size;
386 if(file::read(item.name, data, size)) {
387 if((size & 0x7fff) == 512) {
388 if(file::write(item.name, data + 512, size - 512) == false) {
389 errors.append({ "Failed to write file: ", item.name });
228390 }
229
230 case SNESCartridge::TypeSufamiTurbo: {
231 if((filesize & 0x7fff) == 512) {
232 FileInfo info;
233 info.filename = filename;
234 info.problem = "Copier header present";
235 info.solution = "Remove copier header";
236 fileInfo.append(info);
237 }
238
239 if(filename.endswith(".st") == false) {
240 FileInfo info;
241 info.filename = filename;
242 info.problem = "Wrong file extension";
243 info.solution = "Rename to .st";
244 fileInfo.append(info);
245 }
246
247 break;
248 }
249
250 case SNESCartridge::TypeGameBoy: {
251 if(filename.endswith(".gb") == false && filename.endswith(".gbc") == false && filename.endswith(".sgb") == false) {
252 FileInfo info;
253 info.filename = filename;
254 info.problem = "Wrong file extension";
255 info.solution = "Rename to .gb";
256 fileInfo.append(info);
257 }
258
259 break;
260 }
261 }
262 }
263 }
264
265 void Application::repair() {
266 enable(false);
267 errors.reset();
268
269 for(unsigned n = 0; n < fileInfo.size(); n++) {
270 if(fileList.checked(n) == false) continue;
271 OS::processEvents();
272
273 FileInfo &info = fileInfo[n];
274 if(info.solution == "Remove copier header") {
275 file fp;
276 if(fp.open(info.filename, file::mode::read)) {
277 unsigned size = fp.size();
278 uint8_t *data = new uint8_t[size];
279 fp.read(data, size);
280 fp.close();
281 if(fp.open(info.filename, file::mode::write)) {
282 fp.write(data + 512, size - 512);
283 fp.close();
284 }
285 }
286 } else if(info.solution == "Rename to .sfc") {
287 rename(info.filename, string(nall::basename(info.filename), ".sfc"));
288 } else if(info.solution == "Rename to .bs") {
289 rename(info.filename, string(nall::basename(info.filename), ".bs"));
290 } else if(info.solution == "Rename to .st") {
291 rename(info.filename, string(nall::basename(info.filename), ".st"));
292 } else if(info.solution == "Rename to .gb") {
293 rename(info.filename, string(nall::basename(info.filename), ".gb"));
294 }
295 }
296
297 if(errors.size() == 0) {
298 MessageWindow::information(application, "Selected problems have been corrected");
299 } else {
300 string output;
301 for(unsigned i = 0; i < 3 && i < errors.size(); i++) output.append(string(errors[i], "\n"));
302 if(errors.size() > 3) output.append("\n(too many errors to show ...)");
303 MessageWindow::information(application, {
304 "Selected problems have been corrected, but there were errors:\n\n",
305 output
306 });
307 }
308
309 fileInfo.reset();
310 fileList.reset();
311 enable(true);
391 }
392 }
312393 }
313394
314395 int main() {
315 application.main();
396 mainWindow.create();
316397 OS::main();
317398 return 0;
318399 }
0 #include <nall/directory.hpp>
1 #include <nall/file.hpp>
2 #include <nall/ips.hpp>
3 #include <nall/ups.hpp>
4 #include <nall/vector.hpp>
5 #include <nall/zip.hpp>
6 #include <nall/bps/linear.hpp>
7 #include <phoenix/phoenix.hpp>
8 using namespace nall;
9 using namespace phoenix;
10
11 struct MainWindow : public Window {
12 Font font;
13 VerticalLayout layout;
14 HorizontalLayout navigationLayout;
15 Label navigationLabel;
16 LineEdit navigationPath;
17 Button navigationScan;
18 Button navigationBrowse;
19 ListView listView;
20 HorizontalLayout controlLayout;
21 Button controlSelectAll;
22 Button controlClearAll;
23 CheckBox controlDeleteFiles;
24 Widget spacer;
25 Button controlCorrect;
26
27 void create();
28 void onScan();
29 void onScanFolder(const string &path);
30 void analyzeFile(const string &filename);
31
32 bool isSnesCartImageName(const string &filename);
33 bool isSnesBsImageName(const string &filename);
34 bool isSnesStImageName(const string &filename);
35 bool isSnesImageName(const string &filename);
36 bool isGameBoyClassicImageName(const string &filename);
37 bool isGameBoyColorImageName(const string &filename);
38 bool isGameBoyImageName(const string &filename);
39 bool isImageName(const string &filename);
40 bool isGoodImageName(const string &filename);
41 bool isBadImageName(const string &filename);
42 string correctExtension(const string &filename);
43
44 struct File {
45 string name;
46 string problem;
47 };
48 linear_vector<File> fileList;
49 lstring errors;
50
51 void onCorrect();
52 void problemDecompressZip(File &file);
53 void problemCorrectExtension(File &file);
54 void problemCreatePatchFromUPS(File &file);
55 void problemCreatePatchFromIPS(File &file);
56 void problemRemoveCopierHeader(File &file);
57 };
66
77 synchronize "nall"
88 synchronize "phoenix"
9 rm -r nall/test
10 rm -r phoenix/test*
9
10 test -d nall/test && rm -r nall/test
11 test -d phoenix/nall && rm -r phoenix/nall
12 test -d phoenix/test && rm -r phoenix/test