Compare commits
196 Commits
armCpu
...
musashiUpg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df927c1e45 | ||
|
|
a06d013f33 | ||
|
|
c08bdd573a | ||
|
|
4712e77413 | ||
|
|
57d19df30d | ||
|
|
dd09261b53 | ||
|
|
c72edbfa1b | ||
|
|
20348abf85 | ||
|
|
6b1e293c44 | ||
|
|
d0292b312f | ||
|
|
2b982cee22 | ||
|
|
2c072ded8a | ||
|
|
309f91312f | ||
|
|
4450ac9402 | ||
|
|
01bebf5418 | ||
|
|
4c7d34facf | ||
|
|
16924bb811 | ||
|
|
e9d6d21625 | ||
|
|
6b351c67fd | ||
|
|
7be8825f96 | ||
|
|
02778eeb08 | ||
|
|
f76abf87a1 | ||
|
|
0bb3287d6d | ||
|
|
64950ac431 | ||
|
|
85e9a03796 | ||
|
|
14e0d66101 | ||
|
|
eea4c328d2 | ||
|
|
9143759c29 | ||
|
|
9289232dd0 | ||
|
|
a2dbb98d88 | ||
|
|
fd572858e2 | ||
|
|
d5b6664c73 | ||
|
|
ff46e40ded | ||
|
|
f00cfd057b | ||
|
|
12ed98e68b | ||
|
|
e277ae8a3b | ||
|
|
80850117e6 | ||
|
|
09ae1544e4 | ||
|
|
c4e9edf702 | ||
|
|
dbf1341597 | ||
|
|
5af248eaef | ||
|
|
afa5b13d14 | ||
|
|
68c9e28c08 | ||
|
|
7962bee8bf | ||
|
|
e6535b546c | ||
|
|
696874b42a | ||
|
|
ab608e1d78 | ||
|
|
7ccef9020c | ||
|
|
65e12a2b7b | ||
|
|
7ab964efcb | ||
|
|
4129e74af0 | ||
|
|
8dcf19d2e1 | ||
|
|
aa196cb87f | ||
|
|
136cdca5d7 | ||
|
|
d4b9997d43 | ||
|
|
8de283a87d | ||
|
|
c860faa9e7 | ||
|
|
0d87bf2610 | ||
|
|
99da94a143 | ||
|
|
ca89c58c1a | ||
|
|
771856944b | ||
|
|
814d180642 | ||
|
|
ad53041077 | ||
|
|
6bfae8fcb2 | ||
|
|
9eb415c4ac | ||
|
|
632a57a38f | ||
|
|
430ebc01a0 | ||
|
|
cc882d2141 | ||
|
|
5ad9760c52 | ||
|
|
d67233cc8e | ||
|
|
07d8ee95f1 | ||
|
|
a6f3ec5c1f | ||
|
|
631111ce25 | ||
|
|
4237ae0eb8 | ||
|
|
07b4aa53a8 | ||
|
|
81bbcd20f0 | ||
|
|
58d59a9964 | ||
|
|
e601bf1e15 | ||
|
|
369b2ebaf4 | ||
|
|
bc47eee5c0 | ||
|
|
943dfb3b09 | ||
|
|
a23df8f79a | ||
|
|
e0c1cb9d6b | ||
|
|
7b6fcdb0e1 | ||
|
|
e70d84fac4 | ||
|
|
d67b44130a | ||
|
|
1567cbce67 | ||
|
|
3059dfda06 | ||
|
|
94f4c09d54 | ||
|
|
452d5030a1 | ||
|
|
1bb71d8aec | ||
|
|
0337882c4f | ||
|
|
33f7cb8948 | ||
|
|
51e405fc84 | ||
|
|
d0ccc7115f | ||
|
|
61602de392 | ||
|
|
29ca09302f | ||
|
|
4c8649da4e | ||
|
|
9723c83381 | ||
|
|
37f4b859aa | ||
|
|
7ba0cb5dca | ||
|
|
c95792b146 | ||
|
|
c111be3f64 | ||
|
|
b145a329c0 | ||
|
|
0ca5627ee3 | ||
|
|
a1fd0799be | ||
|
|
4fb3bed984 | ||
|
|
9ed1d0c21d | ||
|
|
1405e2a681 | ||
|
|
55013870ca | ||
|
|
912210695d | ||
|
|
5c89783ea0 | ||
|
|
c68fac77cc | ||
|
|
d0ca2655bb | ||
|
|
5c1547467b | ||
|
|
8e9ef22f42 | ||
|
|
892359f226 | ||
|
|
d46e146ae7 | ||
|
|
fc6b32d065 | ||
|
|
66f32cdb94 | ||
|
|
3601c471cf | ||
|
|
9384fc37a8 | ||
|
|
02fe7809ff | ||
|
|
5f3ace9b6b | ||
|
|
967c2f3ec1 | ||
|
|
99dfc62823 | ||
|
|
f0b9d524a6 | ||
|
|
80026cb33e | ||
|
|
5f1e8a53c1 | ||
|
|
b068d6ed53 | ||
|
|
b222b23bd0 | ||
|
|
7e0399ad17 | ||
|
|
f355c82d0b | ||
|
|
535c9254f6 | ||
|
|
4476697b4b | ||
|
|
92d6a857a8 | ||
|
|
6e8005cf56 | ||
|
|
eb4a241ef4 | ||
|
|
ec66577b53 | ||
|
|
41a305f0bd | ||
|
|
e9f7a40c53 | ||
|
|
b1914d9586 | ||
|
|
a63000884f | ||
|
|
5a38b67708 | ||
|
|
97e00aaef2 | ||
|
|
82c767a7a0 | ||
|
|
ab4788c921 | ||
|
|
c4eec6864b | ||
|
|
9b09d19e19 | ||
|
|
3de2c67cae | ||
|
|
1d693ae10d | ||
|
|
1b3336c9af | ||
|
|
4d88e893e0 | ||
|
|
2238274f51 | ||
|
|
5b93a54b2b | ||
|
|
c89da48739 | ||
|
|
b6093dc8ca | ||
|
|
48ba518086 | ||
|
|
372d23e534 | ||
|
|
125e85d73b | ||
|
|
d70e2b02b9 | ||
|
|
a2058e2d73 | ||
|
|
c7f8816541 | ||
|
|
6c53ade08b | ||
|
|
d8abf3643d | ||
|
|
a80b783c71 | ||
|
|
06acab1345 | ||
|
|
8482c98010 | ||
|
|
3c645bd0bd | ||
|
|
368757023c | ||
|
|
4d803c6fc0 | ||
|
|
cb9093c5f4 | ||
|
|
fa5f85e77c | ||
|
|
1b5f4d215f | ||
|
|
55a2e97bc5 | ||
|
|
0a58122f4b | ||
|
|
5a7191cd47 | ||
|
|
cee653b1a0 | ||
|
|
0bf5f9f981 | ||
|
|
23f943ce8b | ||
|
|
9e98f29215 | ||
|
|
ee7fd8e676 | ||
|
|
34e4b9ce7c | ||
|
|
4e7a08e6df | ||
|
|
ae6efb6b7b | ||
|
|
f1d1c3f051 | ||
|
|
03101a5214 | ||
|
|
f4a6d6c1b0 | ||
|
|
bb2698b498 | ||
|
|
48ff83d3af | ||
|
|
48d3983b72 | ||
|
|
f7f7b9d2d9 | ||
|
|
2244a1edd8 | ||
|
|
f7c1dacba4 | ||
|
|
47ba41fdc5 | ||
|
|
6df973a77c |
15
.circleci/config.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
# Use the latest 2.1 version of CircleCI pipeline processing engine, see https://circleci.com/docs/2.0/configuration-reference/
|
||||
version: 2.1
|
||||
|
||||
# Use a package of configuration called an orb, see https://circleci.com/docs/2.0/orb-intro/
|
||||
orbs:
|
||||
# Declare a dependency on the welcome-orb
|
||||
welcome: circleci/welcome-orb@0.3.1
|
||||
|
||||
# Orchestrate or schedule a set of jobs, see https://circleci.com/docs/2.0/workflows/
|
||||
workflows:
|
||||
# Name the workflow "Welcome"
|
||||
Welcome:
|
||||
# Run the welcome/run job in its own container
|
||||
jobs:
|
||||
- welcome/run
|
||||
10
.gitignore
vendored
@@ -3,7 +3,7 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.pro.user
|
||||
*.pro.user*
|
||||
*_emscripten.bc
|
||||
/libretroBuildSystem/obj
|
||||
/libretroBuildSystem/libs
|
||||
@@ -11,16 +11,10 @@
|
||||
/tools/palm/hwTestSuite/*.bin
|
||||
/tools/palm/hwTestSuite/*.grc
|
||||
/tools/palm/hwTestSuite/*.prc
|
||||
/tools/palm/hwTestSuite/armCode
|
||||
/tools/palm/hwTestSuite/TstSuite
|
||||
/tools/palm/hwTestSuite/TstSuite-sections.s
|
||||
/tools/palm/hwTestSuite/TstSuite-sections.ld
|
||||
/tools/palm/muExpansionDriver/devStuff/*
|
||||
/tools/palm/muExpansionDriver/*.bin
|
||||
/tools/palm/muExpansionDriver/*.grc
|
||||
/tools/palm/muExpansionDriver/*.prc
|
||||
/tools/palm/muExpansionDriver/muExpDriver
|
||||
/tools/palm/muExpansionDriver/blobs/*.S68
|
||||
/tools/palm/muExpansionDriver/blobs/*.L68
|
||||
/tools/desktop/build-BufferGraphViewer-*
|
||||
/tools/desktop/build-MakePalmBitmap-*
|
||||
/tools/desktop/export16BitImageProperly/convert
|
||||
@@ -1,453 +0,0 @@
|
||||
Cant draw screen, LCD on:false, PLL on:true, power save on:false, forced blank on:false(printed 4 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
Cant draw screen, LCD on:false, PLL on:true, power save on:false, forced blank on:false(printed 2 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:OS booting! (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM size:255232 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM free:224284, RAM biggest block:224074 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage size:16514802 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage free:15796336 bytes, Storage biggest block:15769916 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:New trap table created at:0x0003A39C (printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEA94.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEABA.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEAD2.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000800 to register 0x906, PC:0x100AEAE6.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AEAEE.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x000000C0 to register 0x908, PC:0x100AEB1E.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE118.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE14C.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE150.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000000 to register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2F4.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE286.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE296.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2D2.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
SD command blocked by idle state: isAcmd:0, cmd:5, arg:0x00000000, CRC:0x00(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Attempting to load GUI. (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Attempting reboot! (printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEA94.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEABA.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEAD2.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000800 to register 0x906, PC:0x100AEAE6.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AEAEE.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x000000C0 to register 0x908, PC:0x100AEB1E.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE118.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE14C.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE150.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000000 to register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2F4.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE286.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE296.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2D2.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
SD command blocked by idle state: isAcmd:0, cmd:5, arg:0x00000000, CRC:0x00(printed 1 times)
|
||||
Sandbox: Command 1 started(printed 1 times)
|
||||
m68k jumped 0xEFF7B2D6 bytes to invalid address, from 0x10084D0A to 0xFFFFFFE0(printed 1 times)
|
||||
m68k jumped 0x00000000 bytes to invalid address, from 0xFFFFFFE4 to 0xFFFFFFE4(printed 1 times)
|
||||
m68k jumped 0x0000000E bytes to invalid address, from 0xFFFFFFEE to 0xFFFFFFE0(printed 1 times)
|
||||
m68k jumped 0x00000000 bytes to invalid address, from 0xFFFFFFE4 to 0xFFFFFFE4(printed 1 times)
|
||||
m68k jumped 0x0000000E bytes to invalid address, from 0xFFFFFFEE to 0xFFFFFFE0(printed 1 times)
|
||||
m68k jumped 0x00000000 bytes to invalid address, from 0xFFFFFFE4 to 0xFFFFFFE4(printed 1 times)
|
||||
Sandbox: Command 1 finished(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:No config file, setting default config. (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Attempting to load GUI. (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Attempting reboot! (printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:OS booting! (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM size:255232 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM free:224284, RAM biggest block:224074 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage size:16514802 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage free:15796364 bytes, Storage biggest block:15769940 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:New trap table created at:0x0003A39C (printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEA94.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEABA.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEAD2.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000800 to register 0x906, PC:0x100AEAE6.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AEAEE.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x000000C0 to register 0x908, PC:0x100AEB1E.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE118.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE14C.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE150.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000000 to register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2F4.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE286.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE296.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2D2.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
SD command blocked by idle state: isAcmd:0, cmd:5, arg:0x00000000, CRC:0x00(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Called ARM function:0x000D4CA2 (printed 1 times)
|
||||
Bus error timeout at:0xAA22CD58, PC:0x000EC522(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:OS booting! (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM size:255232 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM free:224284, RAM biggest block:224074 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage size:16514802 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage free:15796364 bytes, Storage biggest block:15769940 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:New trap table created at:0x0003A39C (printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEA94.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEABA.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEAD2.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000800 to register 0x906, PC:0x100AEAE6.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AEAEE.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x000000C0 to register 0x908, PC:0x100AEB1E.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE118.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE14C.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE150.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000000 to register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2F4.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE286.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE296.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2D2.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
SD command blocked by idle state: isAcmd:0, cmd:5, arg:0x00000000, CRC:0x00(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Called ARM function:0x000D4CA2 (printed 1 times)
|
||||
Bus error timeout at:0xAA22CD58, PC:0x000EC522(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:OS booting! (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM size:255232 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM free:224284, RAM biggest block:224074 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage size:16514802 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage free:15796364 bytes, Storage biggest block:15769940 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:New trap table created at:0x0003A39C (printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEA94.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEABA.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEAD2.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000800 to register 0x906, PC:0x100AEAE6.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AEAEE.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x000000C0 to register 0x908, PC:0x100AEB1E.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE118.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE14C.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE150.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000000 to register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2F4.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE286.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE296.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2D2.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
SD command blocked by idle state: isAcmd:0, cmd:5, arg:0x00000000, CRC:0x00(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Called ARM function:0x000D4CA2 (printed 1 times)
|
||||
Bus error timeout at:0xAA22CD58, PC:0x000EC522(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0xFB(printed 1 times)
|
||||
USB command 0xFB, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x00(printed 1 times)
|
||||
USB command 0x00, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x02(printed 1 times)
|
||||
USB command 0x02, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0x04(printed 1 times)
|
||||
USB command 0x04, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0xF2(printed 1 times)
|
||||
USB unknown command, value:0xF3(printed 1 times)
|
||||
USB command 0xF3, write not handeled(printed 2 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x40(printed 1 times)
|
||||
USB command 0x40, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x41(printed 1 times)
|
||||
USB command 0x41, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x42(printed 1 times)
|
||||
USB command 0x42, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x43(printed 1 times)
|
||||
USB command 0x43, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x44(printed 1 times)
|
||||
USB command 0x44, read not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, write not handeled(printed 1 times)
|
||||
USB unknown command, value:0x45(printed 1 times)
|
||||
USB command 0x45, read not handeled(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:OS booting! (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM size:255232 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:RAM free:224284, RAM biggest block:224074 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage size:16514802 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Storage free:15810968 bytes, Storage biggest block:15785686 bytes (printed 1 times)
|
||||
CMD_PRINT: muExpDriver:New trap table created at:0x0003A39C (printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEA94.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEABA.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AEAD2.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000800 to register 0x906, PC:0x100AEAE6.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AEAEE.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x000000C0 to register 0x908, PC:0x100AEB1E.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE118.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE12A.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE14C.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE150.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000000 to register 0x908, PC:0x100AE2E8.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2F4.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE286.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE296.(printed 1 times)
|
||||
CPU read 16 bits from register 0x900, PC:0x100AE2D2.(printed 1 times)
|
||||
CPU read 16 bits from register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
CPU wrote 16 bits of 0x00000020 to register 0x908, PC:0x100AE2D6.(printed 1 times)
|
||||
SD command blocked by idle state: isAcmd:0, cmd:5, arg:0x00000000, CRC:0x00(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:Called ARM function:0x000D1484 (printed 1 times)
|
||||
50 ARM opcodes have been ran(printed 16 times)
|
||||
36 ARM opcodes have been ran(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:ARM calling 68k function:0x00000013, stackBlob:0x0003A330, stackBlobSize:0x00000004, wantA0:1 (printed 1 times)
|
||||
50 ARM opcodes have been ran(printed 1 times)
|
||||
20 ARM opcodes have been ran(printed 1 times)
|
||||
CMD_PRINT: muExpDriver:ARM calling 68k function:0x00000013, stackBlob:0x0003A328, stackBlobSize:0x00000004, wantA0:1 (printed 1 times)
|
||||
m68k jumped 0x1AAF6E8C bytes to invalid address, from 0x000EA178 to 0x1ABE1004(printed 1 times)
|
||||
Bus error timeout at:0x1ABE1004, PC:0x1ABE1004(printed 1 times)
|
||||
@@ -1 +0,0 @@
|
||||
ARM executes mostly normal up until 68k functions are called when 32 bit aligned but acts weird when 16 bit aligned, there may be part of the CPU core I haven't patched yet.
|
||||
1
bugs/currentBug.txt
Normal file
@@ -0,0 +1 @@
|
||||
T3 locks up endlessly checking TSC2101 interrupts
|
||||
@@ -1,87 +0,0 @@
|
||||
The datasheet states:
|
||||
When external interrupts INT[3:0], IRQ1, IRQ2, IRQ3, and IRQ6 are programmed as edge-triggered interrupts, they can be cleared by writing a 1 to the corresponding status bit in the interrupt status register in the interrupt controller. When programmed as level-triggered interrupts, these interrupts are cleared at the requesting sources.
|
||||
|
||||
But all attempts to use the INT* pins as edge triggered have failed and they continue as level triggered
|
||||
|
||||
PDIUSBD12 uses CSA1 and CPU A1 as USB A0
|
||||
|
||||
All of the interrupt signals in the table can be used as system wake-up interrupts, except for the edge interrupt on INT[3:0]. Edge interrupts on INT[3:0] can only interrupt the CPU when the system is awake. The INT[3:0] signals are all level 4 interrupts, but IRQx has its own level. Any combination of Port D signals and OR (negative logic) can be selected to generate keyboard (KB) interrupts to the CPU. The KBx signal is an active low, level-sensitive interrupt of the selected pins. Like the other ports, each pin can be configured as an input or output on a bit-by-bit basis. When they are configured as inputs, each pin can generate a CPU interrupt.
|
||||
|
||||
CS(A/B/C/D)1 seem to not be connected, only CS*0 is used
|
||||
|
||||
PFPUEN has both pull up and pull down on it, the 4 address lines are the pull downs
|
||||
|
||||
cmp.* seems like it can only set the Carry flag if the result or one of the parameters is negative
|
||||
|
||||
The first argument to a function is the last pushed on the stack(proof below, the 16 bit int is the last argument and its pushed first)
|
||||
|
||||
ROM:1003026C move.w d0,-(sp) ; Move Data from Source to Destination
|
||||
ROM:1003026E move.l a4,-(sp) ; Move Data from Source to Destination
|
||||
ROM:10030270 move.l d7,-(sp) ; Move Data from Source to Destination
|
||||
ROM:10030272 trap #$F ; Trap sysTrapStrNCopy
|
||||
ROM:10030272 dc.w $A2CE
|
||||
Char * StrNCopy(Char *dst, const Char *src, Int16 n)SYS_TRAP(sysTrapStrNCopy);
|
||||
|
||||
|
||||
HwrIRQ4Handler Interrupt Level 4 Priority(top of the list is checked first):
|
||||
UART 1 and 2(they have the same priority)
|
||||
RTC
|
||||
All Buttons
|
||||
|
||||
IVR = 0x18
|
||||
interrupt vector start = 0x60
|
||||
|
||||
vectors starting at level 0(no interrupt) to level 7
|
||||
0x00000060:0x00000000 (no interrupt, never called)
|
||||
0x00000064:0x101904BE
|
||||
0x00000068:0x101904EC
|
||||
0x0000006C:0x1019051A
|
||||
0x00000070:0x10190548 (level 4, hardware buttons)
|
||||
0x00000074:0x10190576 (level 5, seems to be touchscreen)
|
||||
0x00000078:0x101905A4
|
||||
0x0000007C:0x10015F34 (level 7, debugging IRQ, not used)
|
||||
|
||||
SPI Routine Location:
|
||||
PrvSetBB7846ChanRef or PrvReadnBB7846PwrDn
|
||||
0x10081518
|
||||
|
||||
SPI Start Chunk(sent once on boot):
|
||||
12 4 bit delay, 8 bit check battery command, 0x0AE0
|
||||
5 5 bit receive, continued from last command, 0x0014
|
||||
|
||||
Palm OS reads from the touchscreen SPI in 5 accesses:
|
||||
SPI2 transfer, ENABLE:true, XCH:true, IRQ:false, IRQEN:false, BITCOUNT:16(printed 1 times)
|
||||
SPI2 transfer, before:0xE01B, after:0x00FF(printed 1 times)
|
||||
|
||||
SPI2 transfer, ENABLE:true, XCH:true, IRQ:false, IRQEN:false, BITCOUNT:3(printed 1 times)
|
||||
SPI2 transfer, before:0x0004, after:0x0026(printed 1 times)
|
||||
|
||||
SPI2 transfer, ENABLE:true, XCH:true, IRQ:false, IRQEN:false, BITCOUNT:5(printed 1 times)
|
||||
SPI2 transfer, before:0x001D, after:0x03BF(printed 1 times)
|
||||
|
||||
SPI2 transfer, ENABLE:true, XCH:true, IRQ:false, IRQEN:false, BITCOUNT:12(printed 1 times)
|
||||
SPI2 transfer, before:0x0E1C, after:0xCE00(printed 1 times)
|
||||
|
||||
SPI2 transfer, ENABLE:true, XCH:true, IRQ:false, IRQEN:false, BITCOUNT:16(printed 1 times)
|
||||
SPI2 transfer, before:0xE01C, after:0xFEFF(printed 1 times)
|
||||
|
||||
|
||||
resync event?{
|
||||
16 0xE01B
|
||||
3 only sends 0s, delay or receive, 0x0004
|
||||
5 only sends 0s, delay or receive, 0x001D
|
||||
}
|
||||
12 4 bit delay, 8 bit send command, 0x0E1C
|
||||
16 0xE01C
|
||||
|
||||
TouchScreen Read Order:
|
||||
|
||||
//check x
|
||||
Accessed ADS7846 Ch:5, Normal Mode, Power Save:0, PC:0x1008119E.(printed 1 times)
|
||||
//don't know why
|
||||
Accessed ADS7846 Ch:0, Normal Mode, Power Save:3, PC:0x10081208.(printed 1 times)
|
||||
//don't know why
|
||||
Accessed ADS7846 Ch:6, Normal Mode, Power Save:3, PC:0x10081208.(printed 1 times)
|
||||
//...repeat until released
|
||||
//check battery before returning
|
||||
Accessed ADS7846 Ch:2, Normal Mode, Power Save:3, PC:0x10081208.(printed 1 times)
|
||||
6
bugs/fixed/T3Crash.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
10:32:11: Debugging starts
|
||||
mincore\com\oleaut32\dispatch\ups.cpp(2125)\OLEAUT32.dll!00007FFE26F51D23: (caller: 00007FFE26F51E9A) ReturnHr(1) tid(1870) 8002801D Library not registered.
|
||||
QObject::~QObject: Timers cannot be stopped from another thread
|
||||
10:32:24: Debugging has finished
|
||||
|
||||
Just a crash from killing the program due to a buffer overflow.
|
||||
@@ -1,4 +1,4 @@
|
||||
Cinco De Mayo(May 5th), 17:00 GMT, hopefully with some good ARM stuff
|
||||
Cinco De Mayo(May 5th), 17:00 GMT, hopefully with some good ARM stuff(delayed again)
|
||||
Easter release, 17:00 GMT, hopefully with some good ARM stuff(delayed)
|
||||
|
||||
Done:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
This is like unimplementedHardware.txt but only lists things that have functionality issues not accuracy issues.
|
||||
|
||||
UGUI file picker for RetroArch
|
||||
State manager goes bezerk and crashes when saving on android, also can't close the window or it won't open again(also only on Android)
|
||||
If there is no userdata-en-m515.ram on Android the emu won't create it(this is likely because theres no graceful exit being done on Android only goto home menu and kill process)
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Fixed:
|
||||
Endian compatibility is broken(the CPU state needs to be standardized)
|
||||
RetroArch port crashes on exit(needed to check if environ_cb returned true, switched to libretro-common filestreams too)
|
||||
BIN
bugs/shadowTheifBug/Screenshot_20190426-220702.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
4
bugs/shadowTheifBug/text.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Whenever I register ShadowThief, this happens:
|
||||
|
||||
It happens on any version of Mu
|
||||
PHEM/ST is fine
|
||||
@@ -1,9 +1,5 @@
|
||||
CPU:
|
||||
sysTrapPceNativeCall, ARM Emulator
|
||||
VFP(floating point) coprocessor for ARM
|
||||
Test what bits of IMR are writable
|
||||
sandbox isnt notified about switches to Thumb mode
|
||||
function name finders for ARMv5 and Thumb are unimplemented
|
||||
hardware registers don't have there names printed in sandbox
|
||||
|
||||
CPU I/O:
|
||||
@@ -21,13 +17,13 @@ RxOverflow on SPI1, don't know if back or front of FIFO is overwritten on overfl
|
||||
ICR POL(1,2,3,6) may flip the pin value as well as the interrupt, POL5 does not flip the INT5 pin though, this was confirmed with a hardware test(it doesnt seem to but there is instability on the pin when the SD card is plugged in, this may have to do with card detect also being a data line on the SD pinout)
|
||||
PWM2 is not implemented
|
||||
while it is stated that the PLL is turned off "30 clocks" after the DISPLL bit is set, it doesnt state where the clocks come from, CLK32 or SYSCLK
|
||||
UART1 USTCNT1
|
||||
PLLFSR has a hack that makes busy wait loops finish faster by toggling the CLK32 bit on read, for power button issue
|
||||
should also not transfer data to SD card when MOSI, MISO or SPICLK1 are disabled
|
||||
port d data register INT* bits seem to have there data bits cleared when an edge triggered interrupt is cleared(according to MC68VZ328UM.pdf Page 10-15)
|
||||
sound plays too long when the category's menu is selected on the home screen and the pen is pressed and held in the middle of the screen(only happens there, other views of the same type don't have this issue)(effected by CPU speed, turning it up reduces the duration of the excess squeal)
|
||||
ARM CPU state isn't saved
|
||||
trying to beam anything will lock up the OS
|
||||
sound plays too long when the category's menu is selected on the home screen and the pen is pressed and held in the middle of the screen(only happens there, other views of the same type don't have this issue)(effected by CPU speed, turning it up reduces the duration of the excess squeal)(the home menu may be changing the clock speed when this menu is released since it refreshes a bunch of icons which is CPU intensive, if it is it would distort the audio since sysclks are only calculated at the begining of a frame the new value would not take effect until a new frame began, and since it works properly sometimes that is probably when the change occurs just at the end of the last frame and the sysclk duration refresh happens at the intended time due to the new frame starting)
|
||||
UART1 OLD DATA interrupt uses timing, may just have this be the same a DATA READY
|
||||
SPI1 rxOverflow is may not be emulated exactly as its supposed to be, the overflow data is written to the newest FIFO byte when it should probably be written to the oldest
|
||||
UART CTS pin is not emulated
|
||||
since actual UART hardware is not being used should be safe to ignore the parity bit and timing
|
||||
|
||||
Memory:
|
||||
unknown if DRAM bit expanded address space is used for CSC when its not an extension of CSD
|
||||
@@ -43,21 +39,44 @@ electrical noise on lines(conversions probably should have +-20 added to values)
|
||||
in the edge case that SPICLK2 is disabled while using ADS7846 and a 1 was the last bit shifted out 0s will still be shifted in
|
||||
need to to verify behavior of differential mode bit
|
||||
|
||||
TSC2101:
|
||||
values of AUX1 and AUX2 are unknown an need to be tested, emulation has issues with the USB port shortly after and it would make sense that since the T3 has the same connector as the m515 AUX1 is the device type resistor in the bottom connector
|
||||
|
||||
SD Card:
|
||||
block specific write protect bits don't work
|
||||
IRQ2 may actually be attached to the SD Card data out pin, triggering an interrupt when a 0 is received to process the return data
|
||||
need to test if Port J Pin 3(SD card chip select) is attached to Port D Pin 5(SD Card Status(IRQ2))(pinouts.ru says chip select and card detect are the same line)
|
||||
This thing: case SEND_STATUS://HACK, need to add real write protection, this command is also how the host reads the value of the little switch on the side
|
||||
|
||||
Debug tools:
|
||||
ADS7846 channels can't be read in single reference mode in hwTestSuite
|
||||
Mu sandbox dosent have memory and opcode hooks setup when in ARMv5 mode
|
||||
|
||||
MakePalmBitmap:
|
||||
|
||||
Other:
|
||||
Support for Silkyboard 2 silkscreen:https://archive.org/details/tucows_228076_SILKYBOARD_II
|
||||
Qt port dosent support Windows touchscreen input
|
||||
memory dumping dosent work for OS 5 yet
|
||||
T3 I2C currently has no ACK bits(should work without them its just inaccurate)(I2C works fine though)
|
||||
T3 emulation attempts to set GPIO1(reset button) as an output
|
||||
GPIO lines from misc chips to CPU are not implemented
|
||||
PXA260 idle mode is unimplemented
|
||||
|
||||
|
||||
Fixed:
|
||||
Endian compatibility is broken(the CPU state needs to be standardized)
|
||||
RetroArch port crashes on exit(needed to check if environ_cb returned true, switched to libretro-common filestreams too)
|
||||
make the headers belong to the main file of the target chip being emulated for specs
|
||||
remove specs folder
|
||||
UART1 USTCNT1
|
||||
trying to beam anything will lock up the OS
|
||||
Qt dosent have a hybrid file/folder selector so apps will always have to be launched from folders for now
|
||||
File Installer isnt working yet
|
||||
Qt GUI dosent resize properly with 320x320 framebuffer
|
||||
PLLFSR has a hack that makes busy wait loops finish faster by toggling the CLK32 bit on read, for power button issue(removed, power button works as expected if you wait at least 2 seconds before pushing it again(makes sence that it cnat read the new press while its turning off the CPU))
|
||||
(CPU)VFP(floating point) coprocessor for ARM(dont think the ARM Palms even used VFP)
|
||||
(Other)need to get rid of buffer_t, its not used much anyway
|
||||
ARM dynarec SIGSEGVs on exit(pushing play in the debugger still lets it continue, dont think this is a bug)
|
||||
(Feature)need to add FEATURE_DURABLE which will ignore CPU errors, increasing stability at the cost of bugginess
|
||||
(RetroArch port)set the alarm LED using retro_set_led_state_t on RetroArch
|
||||
(CPU I/O)SPI1 SPISPC register(this is just a clock divider used to slow transfers to allow the voltages to settle, since the emu has no voltages all transfers are just instant)
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -35,6 +35,8 @@ else ifeq ($(platform),windows_msvc2003_x86)
|
||||
include $(BUILD_DIR)/Makefile.windows_msvc2003_x86
|
||||
else ifeq ($(platform),windows_msvc2005_x86)
|
||||
include $(BUILD_DIR)/Makefile.windows_msvc2005_x86
|
||||
else ifeq ($(platform),windows_msvc2008_x86)
|
||||
include $(BUILD_DIR)/Makefile.windows_msvc2008_x86
|
||||
else ifeq ($(platform),windows_msvc2010_x86)
|
||||
include $(BUILD_DIR)/Makefile.windows_msvc2010_x86
|
||||
else ifeq ($(platform),windows_msvc2010_x64)
|
||||
@@ -159,6 +161,17 @@ CC += -miphoneos-version-min=5.0
|
||||
CFLAGS += -miphoneos-version-min=5.0
|
||||
endif
|
||||
|
||||
# tvOS
|
||||
else ifeq ($(platform), tvos-arm64)
|
||||
TARGET := $(TARGET_NAME)_libretro_tvos.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
CFLAGS := -DIOS
|
||||
|
||||
ifeq ($(IOSSDK),)
|
||||
IOSSDK := $(shell xcodebuild -version -sdk appletvos Path)
|
||||
endif
|
||||
|
||||
# Theos iOS
|
||||
else ifeq ($(platform), theos_ios)
|
||||
DEPLOYMENT_IOSVERSION = 5.0
|
||||
@@ -442,7 +455,7 @@ else ifeq ($(platform), xbox1_msvc2003)
|
||||
else
|
||||
EXT ?= dll
|
||||
TARGET := $(TARGET_NAME)_libretro.$(EXT)
|
||||
CC = gcc
|
||||
CC ?= gcc
|
||||
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=$(BUILD_DIR)/link.T
|
||||
CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__
|
||||
endif
|
||||
@@ -463,9 +476,9 @@ endif
|
||||
|
||||
include $(BUILD_DIR)/Makefile.common
|
||||
|
||||
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_ASM:.S=.o)
|
||||
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_CXX:.cpp=.o) $(SOURCES_ASM:.S=.o)
|
||||
|
||||
DEFINES = $(COREDEFINES)
|
||||
DEFINES += $(COREDEFINES)
|
||||
|
||||
ifeq ($(STATIC_LINKING), 1)
|
||||
DEFINES += -DSTATIC_LINKING
|
||||
@@ -488,6 +501,7 @@ endif
|
||||
COMMON_DEFINES += $(CODE_DEFINES) $(WARNINGS_DEFINES) $(fpic)
|
||||
|
||||
CFLAGS += $(DEFINES) $(COMMON_DEFINES)
|
||||
CXXFLAGS += $(DEFINES) $(COMMON_DEFINES)
|
||||
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
OBJOUT = -Fo
|
||||
@@ -507,7 +521,7 @@ endif
|
||||
ifeq ($(platform), theos_ios)
|
||||
COMMON_FLAGS := -DIOS -DARM $(COMMON_DEFINES) $(INCFLAGS) -I$(THEOS_INCLUDE_PATH) -Wno-error
|
||||
$(LIBRARY_NAME)_CFLAGS += $(COMMON_FLAGS)
|
||||
${LIBRARY_NAME}_FILES = $(SOURCES_C) $(SOURCES_ASM)
|
||||
${LIBRARY_NAME}_FILES = $(SOURCES_C) $(SOURCES_CXX) $(SOURCES_ASM)
|
||||
include $(THEOS_MAKE_PATH)/library.mk
|
||||
else
|
||||
all: $(TARGET)
|
||||
@@ -526,8 +540,6 @@ else
|
||||
$(CC) $(fpic) $(SHARED) $(INCFLAGS) $(LDFLAGS) $(OBJOUT)$@ $(OBJECTS) $(LIBM)
|
||||
endif
|
||||
|
||||
@echo "** BUILD SUCCESSFUL! GG NO RE **"
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(INCFLAGS) $(CFLAGS) -c $(OBJOUT)$@ $<
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ EMU_PATH := $(CORE_DIR)/../src
|
||||
LIBRETRO_COMM_DIR := $(CORE_DIR)/libretro-common
|
||||
COREDEFINES :=
|
||||
|
||||
# my first make function!!!
|
||||
CHECK_ALL = $(strip $(foreach v,$(2),$(if $(findstring $(v),$(1)),$(v),)))
|
||||
|
||||
INCFLAGS := -I$(LIBRETRO_COMM_DIR)/include
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
@@ -10,24 +13,96 @@ else
|
||||
COREDEFINES += -DEMU_NO_SAFETY
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring msvc200,$(platform)))
|
||||
# "unix" or "win" is not specific enough, need to know the CPU arch too
|
||||
this_system := $(platform)
|
||||
ifneq (,$(filter unix win,$(this_system)))
|
||||
this_system := $(shell $(CC) -dumpmachine)
|
||||
endif
|
||||
|
||||
|
||||
ifneq (,$(findstring msvc200,$(this_system)))
|
||||
INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring msvc20,$(platform)))
|
||||
ifneq (,$(findstring msvc20,$(this_system)))
|
||||
# Mu is dependent on stdbool.h and the standard inline directive existing
|
||||
INCFLAGS += -I$(CORE_DIR)/fixIncludes/stdbool
|
||||
COREDEFINES += -Dinline=_inline -DINLINE=_inline
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ps3 sncps3 psl1ght ngc wii wiiu,$(platform)))
|
||||
ifneq (,$(call CHECK_ALL,$(this_system),windows mingw))
|
||||
# Windows
|
||||
ifeq (,$(findstring msvc,$(this_system)))
|
||||
EMU_SUPPORT_PALM_OS5 := 1
|
||||
EMU_OS := windows
|
||||
ifneq (,$(call CHECK_ALL,$(this_system),x86_64 x64))
|
||||
EMU_ARCH := x86_64
|
||||
else
|
||||
EMU_ARCH := x86_32
|
||||
endif
|
||||
else
|
||||
# MSVC uses its own(incompatible) ASM syntax
|
||||
EMU_SUPPORT_PALM_OS5 := 0
|
||||
endif
|
||||
else ifneq (,$(call CHECK_ALL,$(this_system),armv8 aarch64))
|
||||
# ARM Linux 64
|
||||
EMU_SUPPORT_PALM_OS5 := 1
|
||||
EMU_ARCH := armv8
|
||||
EMU_OS := linux
|
||||
else ifneq (,$(call CHECK_ALL,$(this_system),armv rpi2 rpi3))
|
||||
# ARM Linux(rpi3 is aarch64 but its almost always used in 32bit mode)
|
||||
EMU_SUPPORT_PALM_OS5 := 1
|
||||
EMU_ARCH := armv7
|
||||
EMU_OS := linux
|
||||
else ifneq (,$(findstring armhf,$(this_system)))
|
||||
# ARM Linux ARMv5
|
||||
# this needs to be before "linux" because it will trigger the linux case
|
||||
EMU_SUPPORT_PALM_OS5 := 0
|
||||
else ifneq (,$(call CHECK_ALL,$(this_system),osx linux))
|
||||
# x86_* Linux
|
||||
EMU_SUPPORT_PALM_OS5 := 1
|
||||
ifneq (,$(call CHECK_ALL,$(this_system),osx x86_64 x64))
|
||||
EMU_ARCH := x86_64
|
||||
else
|
||||
EMU_ARCH := x86_32
|
||||
endif
|
||||
EMU_OS := linux
|
||||
endif
|
||||
|
||||
# OS 5 isnt even booting yet, just turn the dynarec off to make it compile easier
|
||||
EMU_ARCH := unknown
|
||||
|
||||
ifneq (,$(filter ps3 sncps3 psl1ght ngc wii wiiu,$(this_system)))
|
||||
COREDEFINES += -DEMU_BIG_ENDIAN
|
||||
else ifeq ($(platform), osx)
|
||||
else ifeq ($(this_system), osx)
|
||||
ifeq ($(arch), ppc)
|
||||
COREDEFINES += -DEMU_BIG_ENDIAN
|
||||
endif
|
||||
endif
|
||||
|
||||
# use all CPUs and optimize for the most likely outcome, Android is handled separately
|
||||
# Apple broke OpenMP in there port of Clang so no Mac OS or iOS
|
||||
# ifneq (,$(call CHECK_ALL,$(this_system),windows mingw linux))
|
||||
# # none of libretros MSVC compilers work with these optimizations for multiple different reasons
|
||||
# # they dont have the library "VCOMP.lib"
|
||||
# # they are too old for the extension to exist
|
||||
# # MSVC never has or will support __builtin_expect
|
||||
# ifeq (,$(findstring msvc,$(this_system)))
|
||||
# COREDEFINES += -fopenmp -DEMU_MULTITHREADED -DEMU_MANAGE_HOST_CPU_PIPELINE
|
||||
# LDFLAGS += -fopenmp
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# use C++11
|
||||
ifeq ($(EMU_SUPPORT_PALM_OS5), 1)
|
||||
ifneq ($(this_system), android_jni)
|
||||
CXXFLAGS += -std=c++11
|
||||
endif
|
||||
endif
|
||||
|
||||
# RetroArch needs to be able to launch files directly
|
||||
EMU_HAVE_FILE_LAUNCHER := 1
|
||||
|
||||
include $(EMU_PATH)/makefile.all
|
||||
|
||||
COREDEFINES += $(EMU_DEFINES)
|
||||
@@ -35,8 +110,8 @@ COREDEFINES += $(EMU_DEFINES)
|
||||
SOURCES_C := $(CORE_DIR)/libretro.c \
|
||||
$(CORE_DIR)/cursors.c \
|
||||
$(EMU_SOURCES_C)
|
||||
|
||||
SOURCES_ASM :=
|
||||
SOURCES_CXX := $(EMU_SOURCES_CXX)
|
||||
SOURCES_ASM := $(EMU_SOURCES_ASM)
|
||||
|
||||
ifneq ($(STATIC_LINKING), 1)
|
||||
SOURCES_C += $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
101
libretroBuildSystem/build/Makefile.windows_msvc2008_x86
Normal file
@@ -0,0 +1,101 @@
|
||||
##############
|
||||
# Works on hosts Linux
|
||||
# apt-get install mingw-w64
|
||||
|
||||
##########################
|
||||
# Checks the host platform
|
||||
|
||||
HOST_PLATFORM = linux
|
||||
ifeq ($(shell uname -a),)
|
||||
HOST_PLATFORM = windows
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
HOST_PLATFORM = windows
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
HOST_PLATFORM = darwin
|
||||
else ifneq ($(findstring win,$(shell uname -a)),)
|
||||
HOST_PLATFORM = windows
|
||||
endif
|
||||
|
||||
|
||||
####################################
|
||||
# Variable setup for Makefile.common
|
||||
|
||||
CORE_DIR ?= ..
|
||||
BUILD_DIR ?= .
|
||||
INCLUDES =
|
||||
|
||||
include $(BUILD_DIR)/Makefile.common
|
||||
|
||||
#################
|
||||
# Toolchain setup
|
||||
|
||||
CC = cl.exe
|
||||
CXX = cl.exe
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/bin"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS90COMNTOOLS)../../VC/include")
|
||||
LIB := $(shell IFS=$$'\n'; cygpath -w "$(VS90COMNTOOLS)../../VC/lib")
|
||||
|
||||
WindowsSdkDir := $(INETSDK)
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(WindowsSdkDir)/Include
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
|
||||
############
|
||||
# Extensions
|
||||
|
||||
OBJEXT = .obj
|
||||
SOEXT = .dll
|
||||
|
||||
################
|
||||
# Platform setup
|
||||
|
||||
STATIC_LINKING = 0
|
||||
platform = win
|
||||
PLATDEFS =
|
||||
PLATCFLAGS = -DWINVER=0x0400 -D_WIN32_WINNT=0x0400 -DWIN32 -DCORRECT_VRAM_READS -D_WINDOWS -D_USRDLL -D_CRT_SECURE_NO_WARNINGS -DMSVC2010_EXPORTS -DFRONTEND_SUPPORTS_RGB565 -DGIT_VERSION=\"$(GIT_VERSION)\"
|
||||
PLATCXXFLAGS = $(PLATCFLAGS)
|
||||
#PLATLDFLAGS = -shared -lm
|
||||
#PLATLDXFLAGS = -shared -lm
|
||||
|
||||
################
|
||||
# libretro setup
|
||||
|
||||
RETRODEFS = -D__LIBRETRO__ -wd4710 -wd4711 -wd4127 -wd4204 -wd4242 -wd4244 -wd4820 -wd4214 -wd4100 -wd4738 -wd4706 -wd4668 -wd4245 -wd4255 -wd4389 -wd4305 -wd4113
|
||||
RETROCFLAGS =
|
||||
RETROCXXFLAGS =
|
||||
RETROLDFLAGS =
|
||||
RETROLDXFLAGS =
|
||||
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
LDXFLAGS = $(PLATLDXFLAGS) $(RETROLDXFLAGS)
|
||||
|
||||
########
|
||||
# Tuning
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS += -Od -Zi -D_DEBUG
|
||||
CXXFLAGS += -Od -Zi -D_DEBUG
|
||||
LDFLAGS += -DEBUG -DLL
|
||||
else
|
||||
CFLAGS += -O2 -DNDEBUG
|
||||
CXXFLAGS += -O2 -DNDEBUG
|
||||
LDFLAGS += -DLL
|
||||
endif
|
||||
|
||||
ifneq ($(LOG_PERFORMANCE),)
|
||||
CFLAGS += -DLOG_PERFORMANCE
|
||||
CXXFLAGS += -DLOG_PERFORMANCE
|
||||
endif
|
||||
|
||||
###############
|
||||
# Include rules
|
||||
|
||||
include $(BUILD_DIR)/Makefile.rules
|
||||
@@ -44,8 +44,8 @@ platform = win
|
||||
PLATDEFS =
|
||||
PLATCFLAGS = -fstrict-aliasing
|
||||
PLATCXXFLAGS = -fstrict-aliasing
|
||||
PLATLDFLAGS = -shared -lm
|
||||
PLATLDXFLAGS = -shared -lm
|
||||
PLATLDFLAGS = -shared -lm -static-libgcc -static-libstdc++
|
||||
PLATLDXFLAGS = -shared -lm -static-libgcc -static-libstdc++
|
||||
|
||||
################
|
||||
# libretro setup
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -44,8 +44,8 @@ platform = win
|
||||
PLATDEFS =
|
||||
PLATCFLAGS = -fpic -fstrict-aliasing
|
||||
PLATCXXFLAGS = -fpic -fstrict-aliasing
|
||||
PLATLDFLAGS = -shared -lm
|
||||
PLATLDXFLAGS = -shared -lm
|
||||
PLATLDFLAGS = -shared -lm -static-libgcc -static-libstdc++
|
||||
PLATLDXFLAGS = -shared -lm -static-libgcc -static-libstdc++
|
||||
|
||||
################
|
||||
# libretro setup
|
||||
@@ -59,7 +59,7 @@ RETROLDXFLAGS =
|
||||
#################
|
||||
# Final variables
|
||||
|
||||
DEFINES = $(PLATDEFS) $(RETRODEFS)
|
||||
DEFINES = $(PLATDEFS) $(COREDEFINES) $(RETRODEFS)
|
||||
CFLAGS = $(PLATCFLAGS) $(RETROCFLAGS) $(DEFINES) $(INCLUDES)
|
||||
CXXFLAGS = $(PLATCXXFLAGS) $(RETROCXXFLAGS) $(DEFINES) $(INCLUDES)
|
||||
LDFLAGS = $(PLATLDFLAGS) $(RETROLDFLAGS)
|
||||
|
||||
@@ -4,6 +4,23 @@ CORE_DIR := $(LOCAL_PATH)/..
|
||||
|
||||
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
|
||||
|
||||
platform = android_jni
|
||||
|
||||
# Palm OS 5 support
|
||||
EMU_SUPPORT_PALM_OS5 := 1
|
||||
EMU_OS := linux
|
||||
ifeq ($(TARGET_ARCH_ABI), x86)
|
||||
EMU_ARCH := x86_32
|
||||
else ifeq ($(TARGET_ARCH_ABI), x86_64)
|
||||
EMU_ARCH := x86_64
|
||||
else ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
|
||||
EMU_ARCH := armv7
|
||||
else ifeq ($(TARGET_ARCH_ABI), arm64-v8a)
|
||||
EMU_ARCH := armv8
|
||||
else
|
||||
EMU_ARCH := unknown
|
||||
endif
|
||||
|
||||
include $(CORE_DIR)/build/Makefile.common
|
||||
|
||||
COREFLAGS := -ffast-math -funroll-loops -D__LIBRETRO__ -DINLINE=inline -DFRONTEND_SUPPORTS_RGB565 $(INCFLAGS) $(COREDEFINES)
|
||||
@@ -14,7 +31,9 @@ endif
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := retro
|
||||
LOCAL_SRC_FILES := $(SOURCES_C) $(SOURCES_ASM)
|
||||
LOCAL_SRC_FILES := $(SOURCES_C) $(SOURCES_CXX) $(SOURCES_ASM)
|
||||
# LOCAL_CFLAGS := $(COREFLAGS) -fopenmp -DEMU_MULTITHREADED -DEMU_MANAGE_HOST_CPU_PIPELINE
|
||||
# LOCAL_LDFLAGS := -Wl,-version-script=$(CORE_DIR)/build/link.T -fopenmp
|
||||
LOCAL_CFLAGS := $(COREFLAGS)
|
||||
LOCAL_LDFLAGS := -Wl,-version-script=$(CORE_DIR)/build/link.T
|
||||
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
APP_ABI := all
|
||||
# only compile the CPUs that Android actually used at some point
|
||||
APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64
|
||||
APP_PLATFORM := android-18
|
||||
APP_STL := c++_static
|
||||
APP_CPPFLAGS += -std=c++11
|
||||
|
||||
@@ -11,15 +11,18 @@
|
||||
#include <compat/strl.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include "../src/emulator.h"
|
||||
#include "../src/portability.h"
|
||||
#include "../src/silkscreen.h"
|
||||
#include "../src/fileLauncher/launcher.h"
|
||||
#include "cursors.h"
|
||||
|
||||
|
||||
#define JOYSTICK_DEADZONE 4000
|
||||
#define JOYSTICK_MULTIPLIER 0.0001
|
||||
#define SCREEN_HIRES (!(palmFramebufferWidth == 160 && palmFramebufferHeight == 220))
|
||||
#define SCREEN_HIRES (!(palmFramebufferWidth == 160))
|
||||
|
||||
|
||||
static retro_log_printf_t log_cb = NULL;
|
||||
@@ -30,12 +33,35 @@ static retro_environment_t environ_cb = NULL;
|
||||
static retro_input_poll_t input_poll_cb = NULL;
|
||||
static retro_input_state_t input_state_cb = NULL;
|
||||
|
||||
static uint32_t emuFeatures;
|
||||
static double cpuSpeed;
|
||||
static bool syncRtc;
|
||||
static bool allowInvalidBehavior;
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
static bool useOs5;
|
||||
#endif
|
||||
static bool firstRetroRunCall;
|
||||
static bool dontRenderGraffiti;
|
||||
static bool useJoystickAsMouse;
|
||||
static float touchCursorX;
|
||||
static float touchCursorY;
|
||||
static char contentPath[PATH_MAX_LENGTH];
|
||||
static uint16_t mouseCursorOldArea[32 * 32];
|
||||
static bool runningImgFile;
|
||||
static uint16_t screenYEnd;
|
||||
|
||||
|
||||
static void frontendGetCurrentTime(uint8_t* writeBack){
|
||||
time_t rawTime;
|
||||
struct tm* timeInfo;
|
||||
|
||||
time(&rawTime);
|
||||
timeInfo = localtime(&rawTime);
|
||||
|
||||
writeBack[0] = timeInfo->tm_hour;
|
||||
writeBack[1] = timeInfo->tm_min;
|
||||
writeBack[2] = timeInfo->tm_sec;
|
||||
}
|
||||
|
||||
static void renderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
if(SCREEN_HIRES){
|
||||
int8_t x;
|
||||
@@ -44,11 +70,15 @@ static void renderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
//align cursor to side of image
|
||||
screenX -= 6;
|
||||
|
||||
for(y = 0; y < 32; y++)
|
||||
for(x = 6; x < 26; x++)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
|
||||
for(y = 0; y < 32; y++){
|
||||
for(x = 6; x < 26; x++){
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight){
|
||||
mouseCursorOldArea[y * 32 + x] = palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x];
|
||||
if(cursor32x32[y * 32 + x] != 0xFFFF)
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor32x32[y * 32 + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
int8_t x;
|
||||
@@ -57,11 +87,42 @@ static void renderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
//align cursor to side of image
|
||||
screenX -= 3;
|
||||
|
||||
for(y = 0; y < 16; y++){
|
||||
for(x = 3; x < 13; x++){
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight){
|
||||
mouseCursorOldArea[y * 16 + x] = palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x];
|
||||
if(cursor16x16[y * 16 + x] != 0xFFFF)
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor16x16[y * 16 + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void unrenderMouseCursor(int16_t screenX, int16_t screenY){
|
||||
if(SCREEN_HIRES){
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
|
||||
//align cursors missing rectangle to side of image
|
||||
screenX -= 6;
|
||||
|
||||
for(y = 0; y < 32; y++)
|
||||
for(x = 6; x < 26; x++)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = mouseCursorOldArea[y * 32 + x];
|
||||
}
|
||||
else{
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
|
||||
//align cursors missing rectangle to side of image
|
||||
screenX -= 3;
|
||||
|
||||
for(y = 0; y < 16; y++)
|
||||
for(x = 3; x < 13; x++)
|
||||
if(screenX + x >= 0 && screenY + y >= 0 && screenX + x < palmFramebufferWidth && screenY + y < palmFramebufferHeight)
|
||||
if(cursor16x16[y * 16 + x] != 0xFFFF)
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = cursor16x16[y * 16 + x];
|
||||
palmFramebuffer[(screenY + y) * palmFramebufferWidth + screenX + x] = mouseCursorOldArea[y * 16 + x];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,66 +140,32 @@ static void check_variables(bool booting){
|
||||
struct retro_variable var = {0};
|
||||
|
||||
if(booting){
|
||||
emuFeatures = FEATURE_ACCURATE;
|
||||
|
||||
var.key = "palm_emu_feature_ram_huge";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_RAM_HUGE;
|
||||
|
||||
var.key = "palm_emu_feature_fast_cpu";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_FAST_CPU;
|
||||
|
||||
var.key = "palm_emu_feature_hybrid_cpu";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_HYBRID_CPU;
|
||||
|
||||
var.key = "palm_emu_feature_custom_fb";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_CUSTOM_FB;
|
||||
var.key = "palm_emu_cpu_speed";
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
cpuSpeed = atoi(var.value);
|
||||
|
||||
var.key = "palm_emu_feature_synced_rtc";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_SYNCED_RTC;
|
||||
|
||||
var.key = "palm_emu_feature_hle_apis";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_HLE_APIS;
|
||||
|
||||
var.key = "palm_emu_feature_emu_honest";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_EMU_HONEST;
|
||||
|
||||
var.key = "palm_emu_feature_ext_keys";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_EXT_KEYS;
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
syncRtc = !strcmp(var.value, "enabled");
|
||||
|
||||
var.key = "palm_emu_feature_durable";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_DURABLE;
|
||||
|
||||
var.key = "palm_emu_feature_snd_strms";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
emuFeatures |= FEATURE_SND_STRMS;
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
allowInvalidBehavior = !strcmp(var.value, "enabled");
|
||||
}
|
||||
|
||||
var.key = "palm_emu_use_joystick_as_mouse";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value){
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
useJoystickAsMouse = true;
|
||||
else
|
||||
useJoystickAsMouse = false;
|
||||
}
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
useJoystickAsMouse = !strcmp(var.value, "enabled");
|
||||
|
||||
var.key = "palm_emu_disable_graffiti";
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
dontRenderGraffiti = !strcmp(var.value, "enabled");
|
||||
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
var.key = "palm_emu_use_os5";
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
useOs5 = !strcmp(var.value, "enabled");
|
||||
#endif
|
||||
}
|
||||
|
||||
void retro_init(void){
|
||||
@@ -167,9 +194,9 @@ void retro_get_system_info(struct retro_system_info *info){
|
||||
#ifndef GIT_VERSION
|
||||
#define GIT_VERSION ""
|
||||
#endif
|
||||
info->library_version = "v1.0.0" GIT_VERSION;
|
||||
info->need_fullpath = false;
|
||||
info->valid_extensions = "rom";
|
||||
info->library_version = "v1.1.0" GIT_VERSION;
|
||||
info->need_fullpath = true;
|
||||
info->valid_extensions = "prc|pqa|img";
|
||||
}
|
||||
|
||||
void retro_get_system_av_info(struct retro_system_av_info *info){
|
||||
@@ -178,8 +205,13 @@ void retro_get_system_av_info(struct retro_system_av_info *info){
|
||||
|
||||
info->geometry.base_width = 160;
|
||||
info->geometry.base_height = 220;
|
||||
info->geometry.max_width = 480;
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
info->geometry.max_width = 320;
|
||||
info->geometry.max_height = 480;
|
||||
#else
|
||||
info->geometry.max_width = 160;
|
||||
info->geometry.max_height = 220;
|
||||
#endif
|
||||
info->geometry.aspect_ratio = 160.0 / 220.0;
|
||||
}
|
||||
|
||||
@@ -188,37 +220,39 @@ void retro_set_environment(retro_environment_t cb){
|
||||
struct retro_vfs_interface_info vfs_getter = { 1, NULL };
|
||||
struct retro_led_interface led_getter;
|
||||
struct retro_variable vars[] = {
|
||||
{ "palm_emu_feature_ram_huge", "128mb RAM; disabled|enabled" },
|
||||
{ "palm_emu_feature_fast_cpu", "Custom CPU Speeds; disabled|enabled" },
|
||||
{ "palm_emu_feature_hybrid_cpu", "ARM Instruction Set; disabled|enabled" },
|
||||
{ "palm_emu_feature_custom_fb", "Custom Resolution; disabled|enabled" },
|
||||
{ "palm_emu_cpu_speed", "CPU Speed; 1.0|1.5|2.0|2.5|3.0|0.5" },
|
||||
{ "palm_emu_feature_synced_rtc", "Force Match System Clock; disabled|enabled" },
|
||||
{ "palm_emu_feature_hle_apis", "HLE API Implementations; disabled|enabled" },
|
||||
{ "palm_emu_feature_emu_honest", "Is Emulator(for test programs); disabled|enabled" },
|
||||
{ "palm_emu_feature_ext_keys", "Left, Right, Center Keys; disabled|enabled" },
|
||||
{ "palm_emu_feature_durable", "Ignore Invalid Behavior; disabled|enabled" },
|
||||
{ "palm_emu_feature_snd_strms", "Palm OS 5 PWM Streams; disabled|enabled" },
|
||||
{ "palm_emu_use_joystick_as_mouse", "Use Left Joystick As Mouse; disabled|enabled" },
|
||||
{ "palm_emu_disable_graffiti", "Disable Graffiti Area; disabled|enabled" },
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
{ "palm_emu_use_os5", "Boot Apps In OS 5(DEV ONLY); disabled|enabled" },
|
||||
#endif
|
||||
{ 0 }
|
||||
};
|
||||
struct retro_input_descriptor input_desc[] = {
|
||||
{ 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Touchscreen Mouse X" },
|
||||
{ 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Touchscreen Mouse Y" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "Touchscreen Mouse Click" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Dpad Left" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Touchscreen Mouse Click" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Dpad Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Dpad Down" },
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Dpad Left" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Dpad Right" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Dpad Middle" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Dpad Center" },
|
||||
#endif
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Power" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Calender" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Address Book" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Todo" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Notes" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Date Book" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Address Book" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "To Do List" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Note Pad" },
|
||||
{ 0 }
|
||||
};
|
||||
bool no_rom = true;
|
||||
|
||||
environ_cb = cb;
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom);
|
||||
|
||||
if(environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging) && logging.log)
|
||||
log_cb = logging.log;
|
||||
@@ -264,6 +298,40 @@ void retro_reset(void){
|
||||
void retro_run(void){
|
||||
input_poll_cb();
|
||||
|
||||
//some RetroArch functions can only be called from this function so call those if needed
|
||||
if(unlikely(firstRetroRunCall)){
|
||||
struct retro_game_geometry geometry;
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5){
|
||||
if(dontRenderGraffiti){
|
||||
geometry.base_width = 320;
|
||||
geometry.base_height = 320;
|
||||
geometry.max_width = 320;
|
||||
geometry.max_height = 480;
|
||||
}
|
||||
else{
|
||||
geometry.base_width = 320;
|
||||
geometry.base_height = 480;
|
||||
}
|
||||
}
|
||||
else{
|
||||
#endif
|
||||
if(dontRenderGraffiti){
|
||||
geometry.base_width = 160;
|
||||
geometry.base_height = 160;
|
||||
}
|
||||
else{
|
||||
geometry.base_width = 160;
|
||||
geometry.base_height = 220;
|
||||
}
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
}
|
||||
#endif
|
||||
geometry.aspect_ratio = (float)geometry.base_width / (float)geometry.base_height;
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &geometry);
|
||||
firstRetroRunCall = false;
|
||||
}
|
||||
|
||||
//touchscreen
|
||||
if(useJoystickAsMouse){
|
||||
int16_t x = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
|
||||
@@ -287,27 +355,31 @@ void retro_run(void){
|
||||
|
||||
palmInput.touchscreenX = touchCursorX / (palmFramebufferWidth - 1);
|
||||
palmInput.touchscreenY = touchCursorY / (palmFramebufferHeight - 1);
|
||||
palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
|
||||
palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R);
|
||||
}
|
||||
else{
|
||||
//use RetroArch internal pointer
|
||||
palmInput.touchscreenX = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) / 0x7FFF + 1.0) / 2.0;
|
||||
palmInput.touchscreenY = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) / 0x7FFF + 1.0) / 2.0;
|
||||
palmInput.touchscreenY = ((float)input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) / 0x7FFF + 1.0) / 2.0 * ((float)screenYEnd / palmFramebufferHeight);
|
||||
palmInput.touchscreenTouched = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
|
||||
}
|
||||
|
||||
//dpad
|
||||
palmInput.buttonUp = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP);
|
||||
palmInput.buttonRight = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT);
|
||||
palmInput.buttonDown = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN);
|
||||
palmInput.buttonLeft = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT);
|
||||
palmInput.buttonCenter = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5){
|
||||
palmInput.buttonLeft = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT);
|
||||
palmInput.buttonRight = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT);
|
||||
palmInput.buttonCenter = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT);
|
||||
}
|
||||
#endif
|
||||
|
||||
//app buttons
|
||||
palmInput.buttonCalendar = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
|
||||
palmInput.buttonAddress = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
|
||||
palmInput.buttonTodo = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y);
|
||||
palmInput.buttonNotes = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X);
|
||||
palmInput.buttonCalendar = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y);
|
||||
palmInput.buttonAddress = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X);
|
||||
palmInput.buttonTodo = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B);
|
||||
palmInput.buttonNotes = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A);
|
||||
|
||||
//special buttons
|
||||
palmInput.buttonPower = input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START);
|
||||
@@ -319,70 +391,119 @@ void retro_run(void){
|
||||
if(useJoystickAsMouse)
|
||||
renderMouseCursor(touchCursorX, touchCursorY);
|
||||
|
||||
video_cb(palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t));
|
||||
video_cb(palmFramebuffer, palmFramebufferWidth, screenYEnd, palmFramebufferWidth * sizeof(uint16_t));
|
||||
audio_cb(palmAudio, AUDIO_SAMPLES_PER_FRAME);
|
||||
if(led_cb)
|
||||
led_cb(0, palmMisc.powerButtonLed);
|
||||
if(led_cb){
|
||||
led_cb(0, palmMisc.greenLed);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
led_cb(1, palmMisc.redLed);
|
||||
#endif
|
||||
}
|
||||
|
||||
//repair damage done to the framebuffer by the mouse cursor
|
||||
if(useJoystickAsMouse)
|
||||
unrenderMouseCursor(touchCursorX, touchCursorY);
|
||||
}
|
||||
|
||||
bool retro_load_game(const struct retro_game_info *info){
|
||||
buffer_t rom;
|
||||
buffer_t bootloader;
|
||||
uint8_t* romData;
|
||||
uint32_t romSize;
|
||||
uint8_t* bootloaderData;
|
||||
uint32_t bootloaderSize;
|
||||
char romPath[PATH_MAX_LENGTH];
|
||||
char bootloaderPath[PATH_MAX_LENGTH];
|
||||
char saveRamPath[PATH_MAX_LENGTH];
|
||||
char sdImgPath[PATH_MAX_LENGTH];
|
||||
struct RFILE* romFile;
|
||||
struct RFILE* bootloaderFile;
|
||||
struct RFILE* saveRamFile;
|
||||
struct RFILE* sdImgFile;
|
||||
const char* systemDir;
|
||||
const char* saveDir;
|
||||
time_t rawTime;
|
||||
struct tm* timeInfo;
|
||||
bool hasSram = false;
|
||||
uint32_t error;
|
||||
|
||||
if(info == NULL)
|
||||
return false;
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemDir);
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &saveDir);
|
||||
|
||||
rom.data = info->data;
|
||||
rom.size = info->size;
|
||||
|
||||
//bootloader
|
||||
strlcpy(bootloaderPath, systemDir, PATH_MAX_LENGTH);
|
||||
strlcat(bootloaderPath, "/bootloader-en-m515.rom", PATH_MAX_LENGTH);
|
||||
bootloaderFile = filestream_open(bootloaderPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(bootloaderFile){
|
||||
bootloader.size = filestream_get_size(bootloaderFile);
|
||||
bootloader.data = malloc(bootloader.size);
|
||||
|
||||
if(bootloader.data)
|
||||
filestream_read(bootloaderFile, bootloader.data, bootloader.size);
|
||||
else
|
||||
bootloader.size = 0;
|
||||
filestream_close(bootloaderFile);
|
||||
}
|
||||
else{
|
||||
bootloader.data = NULL;
|
||||
bootloader.size = 0;
|
||||
}
|
||||
|
||||
//updates the emulator configuration
|
||||
check_variables(true);
|
||||
|
||||
error = emulatorInit(rom, bootloader, emuFeatures);
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemDir);
|
||||
|
||||
if(info && !string_is_empty(info->path)){
|
||||
//boot application
|
||||
strlcpy(contentPath, info->path, PATH_MAX_LENGTH);
|
||||
runningImgFile = string_is_equal_case_insensitive(contentPath + strlen(contentPath) - 4, ".img");
|
||||
}
|
||||
else{
|
||||
//boot standard device image, "os5" or "os4" gets appended below
|
||||
strlcpy(contentPath, systemDir, PATH_MAX_LENGTH);
|
||||
strlcat(contentPath, "/default", PATH_MAX_LENGTH);
|
||||
runningImgFile = false;
|
||||
}
|
||||
|
||||
//ROM
|
||||
strlcpy(romPath, systemDir, PATH_MAX_LENGTH);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5)
|
||||
strlcat(romPath, "/palmos52-en-t3.rom", PATH_MAX_LENGTH);
|
||||
else
|
||||
#endif
|
||||
strlcat(romPath, "/palmos41-en-m515.rom", PATH_MAX_LENGTH);
|
||||
romFile = filestream_open(romPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(romFile){
|
||||
romSize = filestream_get_size(romFile);
|
||||
romData = malloc(romSize);
|
||||
|
||||
if(romData)
|
||||
filestream_read(romFile, romData, romSize);
|
||||
else
|
||||
romSize = 0;
|
||||
filestream_close(romFile);
|
||||
}
|
||||
else{
|
||||
//cant load without ROM
|
||||
return false;
|
||||
}
|
||||
|
||||
//bootloader, will simple be ignored for Tungsten T3
|
||||
strlcpy(bootloaderPath, systemDir, PATH_MAX_LENGTH);
|
||||
strlcat(bootloaderPath, "/bootloader-en-m515.rom", PATH_MAX_LENGTH);
|
||||
bootloaderFile = filestream_open(bootloaderPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(bootloaderFile){
|
||||
bootloaderSize = filestream_get_size(bootloaderFile);
|
||||
bootloaderData = malloc(bootloaderSize);
|
||||
|
||||
if(bootloaderData)
|
||||
filestream_read(bootloaderFile, bootloaderData, bootloaderSize);
|
||||
else
|
||||
bootloaderSize = 0;
|
||||
filestream_close(bootloaderFile);
|
||||
}
|
||||
else{
|
||||
bootloaderData = NULL;
|
||||
bootloaderSize = 0;
|
||||
}
|
||||
|
||||
error = emulatorInit(romData, romSize, bootloaderData, bootloaderSize, syncRtc, allowInvalidBehavior);
|
||||
free(romData);
|
||||
if(bootloaderData)
|
||||
free(bootloaderData);
|
||||
|
||||
if(error != EMU_ERROR_NONE)
|
||||
return false;
|
||||
|
||||
if(bootloader.data)
|
||||
free(bootloader.data);
|
||||
|
||||
//save RAM
|
||||
strlcpy(saveRamPath, saveDir, PATH_MAX_LENGTH);
|
||||
strlcat(saveRamPath, "/userdata-en-m515.ram", PATH_MAX_LENGTH);
|
||||
strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5)
|
||||
strlcat(saveRamPath, ".os5", PATH_MAX_LENGTH);
|
||||
else
|
||||
#endif
|
||||
strlcat(saveRamPath, ".os4", PATH_MAX_LENGTH);
|
||||
strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH);
|
||||
saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(saveRamFile){
|
||||
hasSram = true;
|
||||
if(filestream_get_size(saveRamFile) == emulatorGetRamSize()){
|
||||
filestream_read(saveRamFile, palmRam, emulatorGetRamSize());
|
||||
swap16BufferIfLittle(palmRam, emulatorGetRamSize() / sizeof(uint16_t));
|
||||
@@ -390,25 +511,28 @@ bool retro_load_game(const struct retro_game_info *info){
|
||||
filestream_close(saveRamFile);
|
||||
}
|
||||
|
||||
//SD card
|
||||
strlcpy(sdImgPath, saveDir, PATH_MAX_LENGTH);
|
||||
strlcat(sdImgPath, "/sd-en-m515.img", PATH_MAX_LENGTH);
|
||||
sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(sdImgFile){
|
||||
buffer_t sdCard;
|
||||
uint32_t sdImgSize = filestream_get_size(sdImgFile);
|
||||
|
||||
//use the NULL, size method because it takes less RAM
|
||||
sdCard.data = NULL;
|
||||
sdCard.size = sdImgSize;
|
||||
|
||||
error = emulatorInsertSdCard(sdCard, false);
|
||||
if(error == EMU_ERROR_NONE){
|
||||
sdCard = emulatorGetSdCardBuffer();
|
||||
filestream_read(sdImgFile, sdCard.data, sdImgSize);
|
||||
if(!runningImgFile){
|
||||
//SD card
|
||||
strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5)
|
||||
strlcat(sdImgPath, ".os5", PATH_MAX_LENGTH);
|
||||
else
|
||||
#endif
|
||||
strlcat(sdImgPath, ".os4", PATH_MAX_LENGTH);
|
||||
strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH);
|
||||
sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(sdImgFile){
|
||||
uint32_t sdImgSize = filestream_get_size(sdImgFile);
|
||||
|
||||
//use the NULL, size, NULL method because it takes less RAM
|
||||
|
||||
error = emulatorInsertSdCard(NULL, sdImgSize, NULL);
|
||||
if(error == EMU_ERROR_NONE)
|
||||
filestream_read(sdImgFile, palmSdCard.flashChipData, sdImgSize);
|
||||
|
||||
filestream_close(sdImgFile);
|
||||
}
|
||||
|
||||
filestream_close(sdImgFile);
|
||||
}
|
||||
|
||||
//set RTC
|
||||
@@ -416,26 +540,115 @@ bool retro_load_game(const struct retro_game_info *info){
|
||||
timeInfo = localtime(&rawTime);
|
||||
emulatorSetRtc(timeInfo->tm_yday, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
|
||||
|
||||
//see if RetroArch wants something launched
|
||||
if(info && !string_is_empty(info->path)){
|
||||
struct RFILE* contentFile;
|
||||
uint8_t* contentData;
|
||||
uint32_t contentSize;
|
||||
|
||||
contentFile = filestream_open(contentPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(contentFile){
|
||||
contentSize = filestream_get_size(contentFile);
|
||||
contentData = malloc(contentSize);
|
||||
|
||||
if(contentData)
|
||||
filestream_read(contentFile, contentData, contentSize);
|
||||
else
|
||||
return false;
|
||||
filestream_close(contentFile);
|
||||
}
|
||||
else{
|
||||
//no content at path, fail time
|
||||
return false;
|
||||
}
|
||||
|
||||
launcherBootInstantly(hasSram);
|
||||
|
||||
if(runningImgFile){
|
||||
char infoPath[PATH_MAX_LENGTH];
|
||||
struct RFILE* infoFile;
|
||||
uint8_t* infoData = NULL;
|
||||
uint32_t infoSize;
|
||||
sd_card_info_t sdInfo;
|
||||
|
||||
memset(&sdInfo, 0x00, sizeof(sdInfo));
|
||||
|
||||
strlcpy(infoPath, contentPath, PATH_MAX_LENGTH);
|
||||
infoPath[strlen(infoPath) - 4] = '\0';//chop off ".img"
|
||||
strlcat(infoPath, ".info", PATH_MAX_LENGTH);
|
||||
infoFile = filestream_open(infoPath, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(infoFile){
|
||||
infoSize = filestream_get_size(infoFile);
|
||||
infoData = malloc(infoSize);
|
||||
|
||||
if(infoData)
|
||||
filestream_read(infoFile, infoData, infoSize);
|
||||
|
||||
filestream_close(infoFile);
|
||||
}
|
||||
|
||||
if(infoData)
|
||||
launcherGetSdCardInfoFromInfoFile(infoData, infoSize, &sdInfo);
|
||||
error = emulatorInsertSdCard(contentData, contentSize, infoData ? &sdInfo : NULL);
|
||||
if(infoData)
|
||||
free(infoData);
|
||||
}
|
||||
else{
|
||||
if(!hasSram)
|
||||
error = launcherInstallFile(contentData, contentSize);
|
||||
if(error == EMU_ERROR_NONE)
|
||||
error = launcherExecute(launcherGetAppId(contentData, contentSize));
|
||||
}
|
||||
|
||||
free(contentData);
|
||||
if(error != EMU_ERROR_NONE)
|
||||
return false;
|
||||
}
|
||||
|
||||
//set the time callback
|
||||
palmGetRtcFromHost = frontendGetCurrentTime;
|
||||
|
||||
//set mouse position
|
||||
touchCursorX = palmFramebufferWidth / 2;
|
||||
touchCursorY = palmFramebufferHeight / 2;
|
||||
|
||||
//make touches land on the correct spot and screen render the correct size when the graffiti area is off
|
||||
if(dontRenderGraffiti){
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5)
|
||||
screenYEnd = 320;
|
||||
else
|
||||
#endif
|
||||
screenYEnd = 160;
|
||||
}
|
||||
else{
|
||||
screenYEnd = palmFramebufferHeight;
|
||||
}
|
||||
|
||||
//used to resize things properly
|
||||
firstRetroRunCall = true;
|
||||
|
||||
//set default CPU speed
|
||||
emulatorSetCpuSpeed(cpuSpeed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void retro_unload_game(void){
|
||||
const char* saveDir;
|
||||
char saveRamPath[PATH_MAX_LENGTH];
|
||||
char sdImgPath[PATH_MAX_LENGTH];
|
||||
struct RFILE* saveRamFile;
|
||||
struct RFILE* sdImgFile;
|
||||
buffer_t sdCard = emulatorGetSdCardBuffer();
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &saveDir);
|
||||
|
||||
//save RAM
|
||||
strlcpy(saveRamPath, saveDir, PATH_MAX_LENGTH);
|
||||
strlcat(saveRamPath, "/userdata-en-m515.ram", PATH_MAX_LENGTH);
|
||||
strlcpy(saveRamPath, contentPath, PATH_MAX_LENGTH);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5)
|
||||
strlcat(saveRamPath, ".os5", PATH_MAX_LENGTH);
|
||||
else
|
||||
#endif
|
||||
strlcat(saveRamPath, ".os4", PATH_MAX_LENGTH);
|
||||
strlcat(saveRamPath, ".ram", PATH_MAX_LENGTH);
|
||||
saveRamFile = filestream_open(saveRamPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(saveRamFile){
|
||||
swap16BufferIfLittle(palmRam, emulatorGetRamSize() / sizeof(uint16_t));//this will no longer be used, so its ok to destroy it when swapping
|
||||
@@ -443,18 +656,26 @@ void retro_unload_game(void){
|
||||
filestream_close(saveRamFile);
|
||||
}
|
||||
|
||||
//SD card
|
||||
if(sdCard.data){
|
||||
strlcpy(sdImgPath, saveDir, PATH_MAX_LENGTH);
|
||||
strlcat(sdImgPath, "/sd-en-m515.img", PATH_MAX_LENGTH);
|
||||
sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(sdImgFile){
|
||||
filestream_write(sdImgFile, sdCard.data, sdCard.size);
|
||||
filestream_close(sdImgFile);
|
||||
if(!runningImgFile){
|
||||
//SD card
|
||||
if(palmSdCard.flashChipData){
|
||||
strlcpy(sdImgPath, contentPath, PATH_MAX_LENGTH);
|
||||
#if defined(EMU_SUPPORT_PALM_OS5)
|
||||
if(useOs5)
|
||||
strlcat(sdImgPath, ".os5", PATH_MAX_LENGTH);
|
||||
else
|
||||
#endif
|
||||
strlcat(sdImgPath, ".os4", PATH_MAX_LENGTH);
|
||||
strlcat(sdImgPath, ".sd.img", PATH_MAX_LENGTH);
|
||||
sdImgFile = filestream_open(sdImgPath, RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);
|
||||
if(sdImgFile){
|
||||
filestream_write(sdImgFile, palmSdCard.flashChipData, palmSdCard.flashChipSize);
|
||||
filestream_close(sdImgFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emulatorExit();
|
||||
emulatorDeinit();
|
||||
}
|
||||
|
||||
unsigned retro_get_region(void){
|
||||
@@ -473,21 +694,11 @@ size_t retro_serialize_size(void){
|
||||
}
|
||||
|
||||
bool retro_serialize(void *data, size_t size){
|
||||
buffer_t saveBuffer;
|
||||
|
||||
saveBuffer.data = (uint8_t*)data;
|
||||
saveBuffer.size = size;
|
||||
|
||||
return emulatorSaveState(saveBuffer);
|
||||
return emulatorSaveState(data, size);
|
||||
}
|
||||
|
||||
bool retro_unserialize(const void *data, size_t size){
|
||||
buffer_t saveBuffer;
|
||||
|
||||
saveBuffer.data = (uint8_t*)data;
|
||||
saveBuffer.size = size;
|
||||
|
||||
return emulatorLoadState(saveBuffer);
|
||||
return emulatorLoadState(data, size);
|
||||
}
|
||||
|
||||
void* retro_get_memory_data(unsigned id){
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
display_name = "Palm OS (Mu)"
|
||||
authors = "guicrith / meepingsnesroms"
|
||||
supported_extensions = "rom"
|
||||
supported_extensions = "prc|pqa|img"
|
||||
corename = "Mu"
|
||||
manufacturer = "Palm"
|
||||
categories = "Emulator"
|
||||
systemname = "Palm OS"
|
||||
license = "Non-commercial"
|
||||
permissions = ""
|
||||
display_version = "v1.0.0"
|
||||
supports_no_game = "false"
|
||||
firmware_count = 1
|
||||
firmware0_desc = "bootloader-en-m515.rom (MC68VZ328 UART Bootloader)"
|
||||
firmware0_path = "bootloader-en-m515.rom"
|
||||
display_version = "v1.1.0"
|
||||
supports_no_game = "true"
|
||||
firmware_count = 3
|
||||
firmware0_desc = "palmos41-en-m515.rom (Palm OS 4.1)"
|
||||
firmware0_path = "palmos41-en-m515.rom"
|
||||
firmware0_opt = "true"
|
||||
firmware1_desc = "palmos52-en-t3.rom (Palm OS 5.2.1)"
|
||||
firmware1_path = "palmos52-en-t3.rom"
|
||||
firmware1_opt = "true"
|
||||
firmware2_desc = "bootloader-en-m515.rom (MC68VZ328 UART Bootloader)"
|
||||
firmware2_path = "bootloader-en-m515.rom"
|
||||
firmware2_opt = "true"
|
||||
|
||||
@@ -11,14 +11,14 @@ overlay0_desc2 = "up,0.504283,0.802938,radial,0.06852,0.04479"
|
||||
overlay0_desc2_overlay = "X1_wswan.png"
|
||||
overlay0_desc3 = "down,0.504283,0.964221,radial,0.06852,0.04479"
|
||||
overlay0_desc3_overlay = "X3_wswan.png"
|
||||
overlay0_desc4 = "a,0.0821626,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc4_overlay = "A.png"
|
||||
overlay0_desc5 = "b,0.234211,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc5_overlay = "B.png"
|
||||
overlay0_desc6 = "x,0.918421,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc6_overlay = "X.png"
|
||||
overlay0_desc7 = "y,0.770469,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc7_overlay = "Y.png"
|
||||
overlay0_desc4 = "y,0.0821626,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc4_overlay = "Y.png"
|
||||
overlay0_desc5 = "x,0.234211,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc5_overlay = "X.png"
|
||||
overlay0_desc6 = "a,0.918421,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc6_overlay = "A.png"
|
||||
overlay0_desc7 = "b,0.770469,0.960563,radial,0.07407,0.04167"
|
||||
overlay0_desc7_overlay = "B.png"
|
||||
overlay0_desc8 = "start,0.860359,0.810741,rect,0.07037,0.03958"
|
||||
overlay0_desc8_overlay = "start.png"
|
||||
overlay0_desc9 = "menu_toggle,0.0552632,0.801573,radial,0.046296,0.02604"
|
||||
|
||||
@@ -22,40 +22,46 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
CONFIG += support_palm_os5
|
||||
|
||||
windows{
|
||||
RC_ICONS = windows/Mu.ico
|
||||
*msvc*{
|
||||
QMAKE_CFLAGS += -openmp
|
||||
QMAKE_CXXFLAGS += -openmp
|
||||
DEFINES += "_Pragma=__pragma"
|
||||
DEFINES += "_Pragma=__pragma" EMU_MULTITHREADED
|
||||
}
|
||||
*-g++{
|
||||
QMAKE_CFLAGS += -fopenmp
|
||||
QMAKE_CXXFLAGS += -fopenmp
|
||||
QMAKE_LFLAGS += -fopenmp
|
||||
DEFINES += EMU_MULTITHREADED EMU_MANAGE_HOST_CPU_PIPELINE
|
||||
}
|
||||
DEFINES += EMU_MULTITHREADED
|
||||
CONFIG += cpu_x86_32 # this should be auto detected in the future
|
||||
}
|
||||
|
||||
macx{
|
||||
QMAKE_CFLAGS += -std=c89 -D__STDBOOL_H -Dinline= -Dbool=char -Dtrue=1 -Dfalse=0 # tests C89 mode
|
||||
# QMAKE_CFLAGS += -std=c89 -D__STDBOOL_H -Dinline= -Dbool=char -Dtrue=1 -Dfalse=0 # tests C89 mode
|
||||
ICON = macos/Mu.icns
|
||||
QMAKE_INFO_PLIST = macos/Info.plist
|
||||
DEFINES += EMU_MULTITHREADED
|
||||
DEFINES += EMU_MULTITHREADED EMU_MANAGE_HOST_CPU_PIPELINE
|
||||
CONFIG += cpu_x86_64 # Mac OS is only x86_64
|
||||
}
|
||||
|
||||
linux-g++{
|
||||
QMAKE_CFLAGS += -fopenmp
|
||||
QMAKE_CXXFLAGS += -fopenmp
|
||||
QMAKE_LFLAGS += -fopenmp
|
||||
DEFINES += EMU_MULTITHREADED
|
||||
DEFINES += EMU_MULTITHREADED EMU_MANAGE_HOST_CPU_PIPELINE
|
||||
CONFIG += cpu_x86_64 # this should be auto detected in the future
|
||||
}
|
||||
|
||||
android{
|
||||
QMAKE_CFLAGS += -fopenmp
|
||||
QMAKE_CXXFLAGS += -fopenmp
|
||||
QMAKE_LFLAGS += -fopenmp
|
||||
DEFINES += EMU_MULTITHREADED
|
||||
DEFINES += EMU_MULTITHREADED EMU_MANAGE_HOST_CPU_PIPELINE
|
||||
CONFIG += cpu_armv7 # this should be auto detected in the future
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +69,10 @@ CONFIG(debug, debug|release){
|
||||
# debug build, be accurate, fail hard, and add logging
|
||||
DEFINES += EMU_DEBUG EMU_CUSTOM_DEBUG_LOG_HANDLER EMU_SANDBOX
|
||||
# DEFINES += EMU_SANDBOX_LOG_MEMORY_ACCESSES # checks all reads and writes to memory and logs certain events
|
||||
DEFINES += EMU_SANDBOX_OPCODE_LEVEL_DEBUG # for breakpoints
|
||||
DEFINES += EMU_SANDBOX_LOG_JUMPS # log large jumps
|
||||
DEFINES += EMU_SANDBOX_LOG_APIS # for printing sysTrap* calls, EMU_SANDBOX_OPCODE_LEVEL_DEBUG must be on too
|
||||
# DEFINES += EMU_SANDBOX_OPCODE_LEVEL_DEBUG # for breakpoints
|
||||
# DEFINES += EMU_SANDBOX_LOG_JUMPS # log large jumps
|
||||
# DEFINES += EMU_SANDBOX_LOG_APIS # for printing sysTrap* calls, EMU_SANDBOX_OPCODE_LEVEL_DEBUG must be on too
|
||||
CONFIG += no_dynarec # easier to debug with
|
||||
macx|linux-g++{
|
||||
# also check for any buffer overflows and memory leaks
|
||||
# -fsanitize=undefined,leak
|
||||
@@ -78,83 +85,193 @@ CONFIG(debug, debug|release){
|
||||
DEFINES += EMU_NO_SAFETY
|
||||
}
|
||||
|
||||
support_palm_os5{
|
||||
DEFINES += EMU_SUPPORT_PALM_OS5 # the Qt build will not be supporting anything too slow to run OS 5
|
||||
DEFINES += SUPPORT_LINUX # forces the dynarec to use accurate mode and disable Nspire OS hacks
|
||||
|
||||
!no_dynarec{
|
||||
# Windows is only supported in 32 bit mode right now(this is a limitation of the dynarec)
|
||||
# iOS needs IS_IOS_BUILD set, but the Qt port does not support iOS currently
|
||||
|
||||
cpu_x86_32{
|
||||
SOURCES += \
|
||||
../../src/armv5te/translate_x86.c \
|
||||
../../src/armv5te/asmcode_x86.S
|
||||
}
|
||||
else{
|
||||
# x86 has this implemented in asmcode_x86.S
|
||||
SOURCES += \
|
||||
../../src/armv5te/asmcode.c
|
||||
}
|
||||
|
||||
cpu_x86_64{
|
||||
SOURCES += \
|
||||
../../src/armv5te/translate_x86_64.c \
|
||||
../../src/armv5te/asmcode_x86_64.S
|
||||
}
|
||||
|
||||
cpu_armv7{
|
||||
SOURCES += \
|
||||
../../src/armv5te/translate_arm.cpp \
|
||||
../../src/armv5te/asmcode_arm.S
|
||||
}
|
||||
|
||||
cpu_armv8{
|
||||
SOURCES += \
|
||||
../../src/armv5te/translate_aarch64.cpp \
|
||||
../../src/armv5te/asmcode_aarch64.S
|
||||
}
|
||||
}
|
||||
else{
|
||||
# use platform independant C with no dynarec
|
||||
SOURCES += \
|
||||
../../src/armv5te/asmcode.c
|
||||
DEFINES += NO_TRANSLATION
|
||||
}
|
||||
|
||||
windows{
|
||||
SOURCES += \
|
||||
../../src/armv5te/os/os-win32.c
|
||||
}
|
||||
|
||||
macx|linux-g++|android{
|
||||
SOURCES += \
|
||||
../../src/armv5te/os/os-linux.c
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
../../src/pxa260/pxa260_DMA.c \
|
||||
../../src/pxa260/pxa260_DSP.c \
|
||||
../../src/pxa260/pxa260_GPIO.c \
|
||||
../../src/pxa260/pxa260_IC.c \
|
||||
../../src/pxa260/pxa260_LCD.c \
|
||||
../../src/pxa260/pxa260_PwrClk.c \
|
||||
../../src/pxa260/pxa260_RTC.c \
|
||||
../../src/pxa260/pxa260_TIMR.c \
|
||||
../../src/pxa260/pxa260_UART.c \
|
||||
../../src/pxa260/pxa260I2c.c \
|
||||
../../src/pxa260/pxa260Memctrl.c \
|
||||
../../src/pxa260/pxa260Timing.c \
|
||||
../../src/pxa260/pxa260Ssp.c \
|
||||
../../src/pxa260/pxa260Udc.c \
|
||||
../../src/pxa260/pxa260.c \
|
||||
../../src/armv5te/arm_interpreter.cpp \
|
||||
../../src/armv5te/cpu.cpp \
|
||||
../../src/armv5te/coproc.cpp \
|
||||
../../src/armv5te/emuVarPool.c \
|
||||
../../src/armv5te/thumb_interpreter.cpp \
|
||||
../../src/armv5te/mem.c \
|
||||
../../src/armv5te/mmu.c \
|
||||
../../src/tps65010.c \
|
||||
../../src/tsc2101.c \
|
||||
../../src/w86l488.c
|
||||
|
||||
HEADERS += \
|
||||
../../src/pxa260/pxa260_CPU.h \
|
||||
../../src/pxa260/pxa260_DMA.h \
|
||||
../../src/pxa260/pxa260_DSP.h \
|
||||
../../src/pxa260/pxa260_GPIO.h \
|
||||
../../src/pxa260/pxa260_IC.h \
|
||||
../../src/pxa260/pxa260_LCD.h \
|
||||
../../src/pxa260/pxa260_PwrClk.h \
|
||||
../../src/pxa260/pxa260_RTC.h \
|
||||
../../src/pxa260/pxa260_TIMR.h \
|
||||
../../src/pxa260/pxa260_UART.h \
|
||||
../../src/pxa260/pxa260I2c.h \
|
||||
../../src/pxa260/pxa260Memctrl.h \
|
||||
../../src/pxa260/pxa260Timing.h \
|
||||
../../src/pxa260/pxa260Ssp.h \
|
||||
../../src/pxa260/pxa260Udc.h \
|
||||
../../src/pxa260/pxa260_types.h \
|
||||
../../src/pxa260/pxa260_math64.h \
|
||||
../../src/pxa260/pxa260Accessors.c.h \
|
||||
../../src/pxa260/pxa260.h \
|
||||
../../src/armv5te/os/os.h \
|
||||
../../src/armv5te/asmcode.h \
|
||||
../../src/armv5te/bitfield.h \
|
||||
../../src/armv5te/cpu.h \
|
||||
../../src/armv5te/emu.h \
|
||||
../../src/armv5te/mem.h \
|
||||
../../src/armv5te/translate.h \
|
||||
../../src/armv5te/cpudefs.h \
|
||||
../../src/armv5te/debug.h \
|
||||
../../src/armv5te/mmu.h \
|
||||
../../src/armv5te/armsnippets.h \
|
||||
../../src/armv5te/literalpool.h \
|
||||
../../src/tungstenT3Bus.h \
|
||||
../../src/tps65010.h \
|
||||
../../src/tsc2101.h \
|
||||
../../src/w86l488.h
|
||||
}
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
INCLUDEPATH += $$PWD/qt-common/include
|
||||
|
||||
SOURCES += \
|
||||
../../src/ads7846.c \
|
||||
../../src/armv5te/disasm.c \
|
||||
../../src/audio/blip_buf.c \
|
||||
../../src/dbvz.c \
|
||||
../../src/debug/sandbox.c \
|
||||
../../src/emulator.c \
|
||||
../../src/fileLauncher/launcher.c \
|
||||
../../src/flx68000.c \
|
||||
../../src/m515Bus.c \
|
||||
../../src/m68k/m68kcpu.c \
|
||||
../../src/m68k/m68kdasm.c \
|
||||
../../src/m68k/m68kops.c \
|
||||
../../src/pdiUsbD12.c \
|
||||
../../src/sdCard.c \
|
||||
../../src/sed1376.c \
|
||||
../../src/silkscreen.c \
|
||||
debugviewer.cpp \
|
||||
emuwrapper.cpp \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
statemanager.cpp \
|
||||
touchscreen.cpp \
|
||||
../../src/audio/blip_buf.c \
|
||||
../../src/debug/sandbox.c \
|
||||
../../src/ads7846.c \
|
||||
../../src/emulator.c \
|
||||
../../src/flx68000.c \
|
||||
../../src/hardwareRegisters.c \
|
||||
../../src/memoryAccess.c \
|
||||
../../src/pdiUsbD12.c \
|
||||
../../src/sdCard.c \
|
||||
../../src/sed1376.c \
|
||||
../../src/silkscreen.c \
|
||||
../../src/m68k/m68kcpu.c \
|
||||
../../src/m68k/m68kdasm.c \
|
||||
../../src/m68k/m68kopac.c \
|
||||
../../src/m68k/m68kopdm.c \
|
||||
../../src/m68k/m68kopnz.c \
|
||||
../../src/m68k/m68kops.c \
|
||||
../../src/armv5/CPU.c \
|
||||
../../src/armv5/icache.c \
|
||||
../../src/armv5.c \
|
||||
../../src/expansionHardware.c \
|
||||
settingsmanager.cpp
|
||||
|
||||
HEADERS += \
|
||||
debugviewer.h \
|
||||
emuwrapper.h \
|
||||
mainwindow.h \
|
||||
statemanager.h \
|
||||
touchscreen.h \
|
||||
../../src/ads7846.h \
|
||||
../../src/armv5te/disasm.h \
|
||||
../../src/audio/blip_buf.h \
|
||||
../../src/dbvz.h \
|
||||
../../src/dbvzRegisterAccessors.c.h \
|
||||
../../src/dbvzRegisterNames.c.h \
|
||||
../../src/dbvzTiming.c.h \
|
||||
../../src/debug/sandbox.h \
|
||||
../../src/debug/sandboxTrapNumToName.c.h \
|
||||
../../src/debug/trapNames.h \
|
||||
../../src/emulator.h \
|
||||
../../src/fileLauncher/launcher.h \
|
||||
../../src/flx68000.h \
|
||||
../../src/m515Bus.h \
|
||||
../../src/m68k/m68k.h \
|
||||
../../src/m68k/m68kconf.h \
|
||||
../../src/m68k/m68kcpu.h \
|
||||
../../src/m68k/m68kexternal.h \
|
||||
../../src/m68k/m68kops.h \
|
||||
../../src/specs/dragonballVzRegisterSpec.h \
|
||||
../../src/ads7846.h \
|
||||
../../src/emulator.h \
|
||||
../../src/flx68000.h \
|
||||
../../src/hardwareRegisters.h \
|
||||
../../src/hardwareRegistersAccessors.c.h \
|
||||
../../src/hardwareRegistersTiming.c.h \
|
||||
../../src/memoryAccess.h \
|
||||
../../src/pdiUsbD12.h \
|
||||
../../src/pdiUsbD12CommandNames.c.h \
|
||||
../../src/portability.h \
|
||||
../../src/sdCard.h \
|
||||
../../src/sdCardAccessors.c.h \
|
||||
../../src/sdCardCommandNames.c.h \
|
||||
../../src/sdCardCrcTables.c.h \
|
||||
../../src/sed1376.h \
|
||||
../../src/sed1376Accessors.c.h \
|
||||
../../src/sed1376RegisterNames.c.h \
|
||||
../../src/silkscreen.h \
|
||||
../../src/specs/sed1376RegisterSpec.h \
|
||||
../../src/specs/pdiUsbD12CommandSpec.h \
|
||||
../../src/specs/emuFeatureRegisterSpec.h \
|
||||
../../src/specs/sdCardCommandSpec.h \
|
||||
../../src/armv5/CPU.h \
|
||||
../../src/armv5/math64.h \
|
||||
../../src/armv5/types.h \
|
||||
../../src/armv5/icache.h \
|
||||
../../src/armv5.h \
|
||||
../../src/expansionHardware.h \
|
||||
../../src/sdCardAccessors.c.h \
|
||||
../../src/sdCardCrcTables.c.h \
|
||||
debugviewer.h \
|
||||
emuwrapper.h \
|
||||
mainwindow.h \
|
||||
statemanager.h \
|
||||
touchscreen.h \
|
||||
settingsmanager.h
|
||||
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
debugviewer.ui \
|
||||
@@ -165,6 +282,7 @@ CONFIG += mobility
|
||||
MOBILITY =
|
||||
|
||||
DISTFILES += \
|
||||
../../src/fileLauncher/readme.md \
|
||||
android/AndroidManifest.xml \
|
||||
android/gradle/wrapper/gradle-wrapper.jar \
|
||||
android/gradlew \
|
||||
@@ -175,18 +293,22 @@ DISTFILES += \
|
||||
android/res/drawable-hdpi/icon.png \
|
||||
android/res/drawable-ldpi/icon.png \
|
||||
android/res/drawable-mdpi/icon.png \
|
||||
images/boot.svg \
|
||||
images/addressBook.svg \
|
||||
images/calendar.svg \
|
||||
images/center.svg \
|
||||
images/center.svg \
|
||||
images/debugger.svg \
|
||||
images/down.svg \
|
||||
images/install.svg \
|
||||
images/left.svg \
|
||||
images/left.svg \
|
||||
images/notes.svg \
|
||||
images/pause.svg \
|
||||
images/play.svg \
|
||||
images/power.svg \
|
||||
images/right.svg \
|
||||
images/right.svg \
|
||||
images/screenshot.svg \
|
||||
images/settingsManager.svg \
|
||||
images/stateManager.svg \
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "debugviewer.h"
|
||||
#include "ui_debugviewer.h"
|
||||
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "emuwrapper.h"
|
||||
@@ -44,24 +45,6 @@ int64_t DebugViewer::numberFromString(QString str, bool negativeAllowed){
|
||||
return value;
|
||||
}
|
||||
|
||||
QString DebugViewer::stringFromNumber(int64_t number, bool hex, uint32_t forcedZeros){
|
||||
QString numString;
|
||||
|
||||
if(hex){
|
||||
numString += QString::number(number, 16).toUpper();
|
||||
while(numString.length() < (int)forcedZeros)numString.push_front("0");
|
||||
numString.push_front("0x");
|
||||
}
|
||||
else{
|
||||
numString += QString::number(qAbs(number), 10);
|
||||
while(numString.length() < (int)forcedZeros)numString.push_front("0");
|
||||
if(number < 0)
|
||||
numString.push_front("-");
|
||||
}
|
||||
|
||||
return numString;
|
||||
}
|
||||
|
||||
void DebugViewer::debugRadioButtonHandler(){
|
||||
switch(bitsPerEntry){
|
||||
case 8:
|
||||
@@ -94,12 +77,12 @@ void DebugViewer::on_debugGetHexValues_clicked(){
|
||||
|
||||
if(address != INT64_MIN && length != INT64_MIN && length != 0 && address + bits / 8 * length - 1 <= 0xFFFFFFFF){
|
||||
for(int64_t count = 0; count < length; count++){
|
||||
uint64_t data = emu.getEmulatorMemory(address, bits);
|
||||
uint64_t data = emu.debugGetEmulatorMemory(address, bits);
|
||||
QString value;
|
||||
value += stringFromNumber(address, true, 8);
|
||||
value += QString::asprintf("0x%08X", (uint32_t)address);
|
||||
value += ":";
|
||||
if(data != UINT64_MAX)
|
||||
value += stringFromNumber(data, true, bits / 8 * 2);
|
||||
value += QString::asprintf("0x%0*X", bits / 8 * 2, (uint32_t)data);
|
||||
else
|
||||
value += "Unsafe Access";
|
||||
ui->debugValueList->addItem(value);
|
||||
@@ -126,7 +109,7 @@ void DebugViewer::on_debug32Bit_clicked(){
|
||||
debugRadioButtonHandler();
|
||||
}
|
||||
|
||||
void DebugViewer::on_debugDump_clicked(){
|
||||
void DebugViewer::on_debugDumpToFile_clicked(){
|
||||
QString fileBuffer;
|
||||
QFile fileOut(((MainWindow*)parentWidget())->settings->value("resourceDirectory", "").toString() + "/debugDumps/" + ui->debugFilePath->text());
|
||||
|
||||
@@ -142,23 +125,23 @@ void DebugViewer::on_debugDump_clicked(){
|
||||
}
|
||||
}
|
||||
|
||||
void DebugViewer::on_debugDumpToTerminal_clicked(){
|
||||
for(int index = 0; index < ui->debugValueList->count(); index++)
|
||||
printf("%s\n", ui->debugValueList->item(index)->text().toStdString().c_str());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void DebugViewer::on_debugShowRegisters_clicked(){
|
||||
std::vector<uint32_t> registers = ((MainWindow*)parentWidget())->emu.getCpuRegisters();
|
||||
EmuWrapper& emu = ((MainWindow*)parentWidget())->emu;
|
||||
|
||||
ui->debugValueList->clear();
|
||||
for(uint8_t dRegs = 0; dRegs < 8; dRegs++)
|
||||
ui->debugValueList->addItem("D" + stringFromNumber(dRegs, false, 0) + ":" + stringFromNumber(registers[dRegs], true, 8));
|
||||
for(uint8_t aRegs = 0; aRegs < 8; aRegs++)
|
||||
ui->debugValueList->addItem("A" + stringFromNumber(aRegs, false, 0) + ":" + stringFromNumber(registers[8 + aRegs], true, 8));
|
||||
ui->debugValueList->addItem("SP:" + stringFromNumber(registers[15], true, 8));
|
||||
ui->debugValueList->addItem("PC:" + stringFromNumber(registers[16], true, 8));
|
||||
ui->debugValueList->addItem("SR:" + stringFromNumber(registers[17], true, 4));
|
||||
ui->debugValueList->addItems(emu.debugGetCpuRegisterString().split('\n'));
|
||||
}
|
||||
|
||||
void DebugViewer::on_debugShowDebugLogs_clicked(){
|
||||
EmuWrapper& emu = ((MainWindow*)parentWidget())->emu;
|
||||
std::vector<QString>& debugStrings = emu.getDebugStrings();
|
||||
std::vector<uint64_t>& duplicateCallCount = emu.getDuplicateCallCount();
|
||||
QVector<QString>& debugStrings = emu.debugGetLogEntrys();
|
||||
QVector<uint64_t>& duplicateCallCount = emu.debugGetDuplicateLogEntryCount();
|
||||
int64_t length = numberFromString(ui->debugLength->text(), true/*negative allowed*/);
|
||||
|
||||
ui->debugValueList->clear();
|
||||
@@ -181,6 +164,6 @@ void DebugViewer::on_debugShowDebugLogs_clicked(){
|
||||
void DebugViewer::on_debugEraseDebugLogs_clicked(){
|
||||
EmuWrapper& emu = ((MainWindow*)parentWidget())->emu;
|
||||
|
||||
emu.getDebugStrings().clear();
|
||||
emu.getDuplicateCallCount().clear();
|
||||
emu.debugGetLogEntrys().clear();
|
||||
emu.debugGetDuplicateLogEntryCount().clear();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
|
||||
private:
|
||||
int64_t numberFromString(QString str, bool negativeAllowed);
|
||||
QString stringFromNumber(int64_t number, bool hex, uint32_t forcedZeros = 0);
|
||||
|
||||
private slots:
|
||||
void debugRadioButtonHandler();
|
||||
@@ -29,7 +28,8 @@ private slots:
|
||||
void on_debug16Bit_clicked();
|
||||
void on_debug32Bit_clicked();
|
||||
|
||||
void on_debugDump_clicked();
|
||||
void on_debugDumpToFile_clicked();
|
||||
void on_debugDumpToTerminal_clicked();
|
||||
void on_debugShowRegisters_clicked();
|
||||
void on_debugShowDebugLogs_clicked();
|
||||
void on_debugEraseDebugLogs_clicked();
|
||||
|
||||
@@ -45,6 +45,16 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="1">
|
||||
<widget class="QRadioButton" name="debug8Bit">
|
||||
<property name="text">
|
||||
<string>8bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="11">
|
||||
<widget class="QListWidget" name="debugValueList"/>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QRadioButton" name="debug16Bit">
|
||||
<property name="text">
|
||||
@@ -52,6 +62,34 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="debugFilePath">
|
||||
<property name="placeholderText">
|
||||
<string>File Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="debugAddress">
|
||||
<property name="placeholderText">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="debugLength">
|
||||
<property name="placeholderText">
|
||||
<string>Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QRadioButton" name="debug32Bit">
|
||||
<property name="text">
|
||||
<string>32bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugGetHexValues">
|
||||
<property name="text">
|
||||
@@ -62,26 +100,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="10">
|
||||
<widget class="QListWidget" name="debugValueList"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QRadioButton" name="debug32Bit">
|
||||
<property name="text">
|
||||
<string>32bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugDump">
|
||||
<property name="text">
|
||||
<string>Dump To File</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugShowRegisters">
|
||||
<property name="text">
|
||||
@@ -89,37 +107,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="debugLength">
|
||||
<property name="placeholderText">
|
||||
<string>Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QRadioButton" name="debug8Bit">
|
||||
<property name="text">
|
||||
<string>8bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugEraseDebugLogs">
|
||||
<property name="text">
|
||||
<string>Erase Debug Logs</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="debugFilePath">
|
||||
<property name="placeholderText">
|
||||
<string>File Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugShowDebugLogs">
|
||||
<property name="text">
|
||||
@@ -130,10 +117,33 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="debugAddress">
|
||||
<property name="placeholderText">
|
||||
<string>Address</string>
|
||||
<item row="9" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugDumpToFile">
|
||||
<property name="text">
|
||||
<string>Dump To File</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugEraseDebugLogs">
|
||||
<property name="text">
|
||||
<string>Erase Debug Logs</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1" colspan="3">
|
||||
<widget class="QPushButton" name="debugDumpToTerminal">
|
||||
<property name="text">
|
||||
<string>Dump To Terminal</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <QString>
|
||||
#include <QPixmap>
|
||||
#include <QImage>
|
||||
#include <QVector>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QDate>
|
||||
@@ -10,25 +11,33 @@
|
||||
#include <new>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "emuwrapper.h"
|
||||
#include "../../src/emulator.h"
|
||||
#include "../../src/fileLauncher/launcher.h"
|
||||
|
||||
extern "C"{
|
||||
#include "../../src/flx68000.h"
|
||||
#include "../../src/m68k/m68k.h"
|
||||
#include "../../src/pxa260/pxa260.h"
|
||||
#include "../../src/armv5te/disasm.h"
|
||||
#include "../../src/debug/sandbox.h"
|
||||
}
|
||||
|
||||
|
||||
#define MAX_LOG_ENTRY_LENGTH 200
|
||||
|
||||
|
||||
static bool alreadyExists = false;//there can only be one of this class since it wrappers C code
|
||||
|
||||
static std::vector<QString> debugStrings;
|
||||
static std::vector<uint64_t> duplicateCallCount;
|
||||
uint32_t frontendDebugStringSize;
|
||||
char* frontendDebugString;
|
||||
static QVector<QString> debugStrings;
|
||||
static QVector<uint64_t> duplicateCallCount;
|
||||
uint32_t frontendDebugStringSize;
|
||||
char* frontendDebugString;
|
||||
|
||||
|
||||
void frontendHandleDebugPrint(){
|
||||
@@ -50,6 +59,18 @@ void frontendHandleDebugPrint(){
|
||||
}
|
||||
}
|
||||
|
||||
static void frontendGetCurrentTime(uint8_t* writeBack){
|
||||
time_t rawTime;
|
||||
struct tm* timeInfo;
|
||||
|
||||
time(&rawTime);
|
||||
timeInfo = localtime(&rawTime);
|
||||
|
||||
writeBack[0] = timeInfo->tm_hour;
|
||||
writeBack[1] = timeInfo->tm_min;
|
||||
writeBack[2] = timeInfo->tm_sec;
|
||||
}
|
||||
|
||||
|
||||
EmuWrapper::EmuWrapper(){
|
||||
if(alreadyExists == true)
|
||||
@@ -62,8 +83,8 @@ EmuWrapper::EmuWrapper(){
|
||||
emuPaused = false;
|
||||
emuNewFrameReady = false;
|
||||
|
||||
frontendDebugString = new char[200];
|
||||
frontendDebugStringSize = 200;
|
||||
frontendDebugString = new char[MAX_LOG_ENTRY_LENGTH];
|
||||
frontendDebugStringSize = MAX_LOG_ENTRY_LENGTH;
|
||||
}
|
||||
|
||||
EmuWrapper::~EmuWrapper(){
|
||||
@@ -74,6 +95,9 @@ EmuWrapper::~EmuWrapper(){
|
||||
frontendDebugStringSize = 0;
|
||||
debugStrings.clear();
|
||||
duplicateCallCount.clear();
|
||||
|
||||
//allow creating a new emu class after the old one is closed
|
||||
alreadyExists = false;
|
||||
}
|
||||
|
||||
void EmuWrapper::emuThreadRun(){
|
||||
@@ -90,100 +114,93 @@ void EmuWrapper::emuThreadRun(){
|
||||
emuPaused = true;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(3));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::init(const QString& romPath, const QString& bootloaderPath, const QString& ramPath, const QString& sdCardPath, uint32_t features){
|
||||
void EmuWrapper::writeOutSaves(){
|
||||
if(emuRamFilePath != ""){
|
||||
QFile ramFile(emuRamFilePath);
|
||||
uint32_t emuRamSize = emulatorGetRamSize();
|
||||
uint8_t* emuRamData = new uint8_t[emuRamSize];
|
||||
|
||||
emulatorSaveRam(emuRamData, emuRamSize);
|
||||
|
||||
//save out RAM before exit
|
||||
if(ramFile.open(QFile::WriteOnly | QFile::Truncate)){
|
||||
ramFile.write((const char*)emuRamData, emuRamSize);
|
||||
ramFile.close();
|
||||
}
|
||||
|
||||
delete[] emuRamData;
|
||||
}
|
||||
if(emuSdCardFilePath != ""){
|
||||
uint32_t emuSdCardSize = emulatorGetSdCardSize();
|
||||
uint8_t* emuSdCardData = new uint8_t[emuSdCardSize];
|
||||
|
||||
if(emulatorGetSdCardData(emuSdCardData, emuSdCardSize) == EMU_ERROR_NONE){
|
||||
QFile sdCardFile(emuSdCardFilePath);
|
||||
|
||||
//save out SD card before exit
|
||||
if(sdCardFile.open(QFile::WriteOnly | QFile::Truncate)){
|
||||
sdCardFile.write((const char*)emuSdCardData, emuSdCardSize);
|
||||
sdCardFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::init(const QString& assetPath, uint8_t osVersion, bool syncRtc, bool allowInvalidBehavior, bool fastBoot){
|
||||
if(!emuRunning && !emuInited){
|
||||
//start emu
|
||||
uint32_t error;
|
||||
QFile romFile(romPath);
|
||||
QFile bootloaderFile(bootloaderPath);
|
||||
QByteArray romData;
|
||||
QByteArray bootloaderData;
|
||||
buffer_t romBuff;
|
||||
buffer_t bootloaderBuff;
|
||||
QString osVersionId = osVersion == 4 ? "41" : osVersion == 5 ? "52" : QString::number((int)osVersion) + "0";
|
||||
QString model = osVersion > 4 ? "en-t3" : "en-m515";
|
||||
QFile romFile(assetPath + "/palmos" + osVersionId + "-" + model + ".rom");
|
||||
QFile bootloaderFile(assetPath + "/bootloader-" + model + ".rom");
|
||||
QFile ramFile(assetPath + "/userdata-" + model + ".ram");
|
||||
QFile sdCardFile(assetPath + "/sd-" + model + ".img");
|
||||
bool hasBootloader = true;
|
||||
|
||||
if(romFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
romData = romFile.readAll();
|
||||
romFile.close();
|
||||
//used to mark saves with there OS version and prevent corruption
|
||||
emuOsName = "os" + QString::number((int)osVersion);
|
||||
|
||||
romBuff.data = (uint8_t*)romData.data();
|
||||
romBuff.size = romData.size();
|
||||
}
|
||||
else{
|
||||
if(!romFile.open(QFile::ReadOnly | QFile::ExistingOnly))
|
||||
return EMU_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if(bootloaderPath != ""){
|
||||
if(bootloaderFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
bootloaderData = bootloaderFile.readAll();
|
||||
bootloaderFile.close();
|
||||
if(!bootloaderFile.open(QFile::ReadOnly | QFile::ExistingOnly))
|
||||
hasBootloader = false;
|
||||
|
||||
bootloaderBuff.data = (uint8_t*)bootloaderData.data();
|
||||
bootloaderBuff.size = bootloaderData.size();
|
||||
}
|
||||
else{
|
||||
return EMU_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
else{
|
||||
bootloaderBuff.data = NULL;
|
||||
bootloaderBuff.size = 0;
|
||||
}
|
||||
|
||||
error = emulatorInit(romBuff, bootloaderBuff, features);
|
||||
error = emulatorInit((uint8_t*)romFile.readAll().data(), romFile.size(), hasBootloader ? (uint8_t*)bootloaderFile.readAll().data() : NULL, hasBootloader ? bootloaderFile.size() : 0, syncRtc, allowInvalidBehavior);
|
||||
if(error == EMU_ERROR_NONE){
|
||||
QTime now = QTime::currentTime();
|
||||
|
||||
palmGetRtcFromHost = frontendGetCurrentTime;
|
||||
emulatorSetRtc(QDate::currentDate().day(), now.hour(), now.minute(), now.second());
|
||||
|
||||
if(ramPath != ""){
|
||||
QFile ramFile(ramPath);
|
||||
|
||||
if(ramFile.exists()){
|
||||
if(ramFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
QByteArray ramData;
|
||||
buffer_t emuRam;
|
||||
|
||||
ramData = ramFile.readAll();
|
||||
ramFile.close();
|
||||
|
||||
emuRam.data = (uint8_t*)ramData.data();
|
||||
emuRam.size = ramData.size();
|
||||
|
||||
//only copy in data if its the correct size, the file will be overwritten on exit with the devices RAM either way
|
||||
//(changing RAM size requires a factory reset for now and always will when going from 128mb back to 16mb)
|
||||
if(emuRam.size == emulatorGetRamSize())
|
||||
emulatorLoadRam(emuRam);
|
||||
}
|
||||
}
|
||||
if(ramFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
emulatorLoadRam((uint8_t*)ramFile.readAll().data(), ramFile.size());
|
||||
ramFile.close();
|
||||
}
|
||||
|
||||
if(sdCardPath != ""){
|
||||
QFile sdCardFile(sdCardPath);
|
||||
|
||||
if(sdCardFile.exists()){
|
||||
if(sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
QByteArray sdCardData;
|
||||
buffer_t newSdCard;
|
||||
|
||||
sdCardData = sdCardFile.readAll();
|
||||
sdCardFile.close();
|
||||
|
||||
newSdCard.data = (uint8_t*)sdCardData.data();
|
||||
newSdCard.size = sdCardData.size();
|
||||
|
||||
emulatorInsertSdCard(newSdCard, false);
|
||||
}
|
||||
}
|
||||
if(sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
emulatorInsertSdCard((uint8_t*)sdCardFile.readAll().data(), sdCardFile.size(), NULL);
|
||||
sdCardFile.close();
|
||||
}
|
||||
|
||||
emuInput = palmInput;
|
||||
emuRamFilePath = ramPath;
|
||||
emuSdCardFilePath = sdCardPath;
|
||||
emuRamFilePath = assetPath + "/userdata-" + model + ".ram";
|
||||
emuSdCardFilePath = assetPath + "/sd-" + model + ".img";
|
||||
emuSaveStatePath = assetPath + "/states-" + model + ".states";
|
||||
|
||||
//make the place to store the saves
|
||||
QDir(emuSaveStatePath).mkdir(".");
|
||||
|
||||
//skip the boot screen
|
||||
if(fastBoot)
|
||||
launcherBootInstantly(ramFile.exists());
|
||||
|
||||
//start the thread
|
||||
emuThreadJoin = false;
|
||||
emuInited = true;
|
||||
emuRunning = true;
|
||||
@@ -194,6 +211,9 @@ uint32_t EmuWrapper::init(const QString& romPath, const QString& bootloaderPath,
|
||||
else{
|
||||
return error;
|
||||
}
|
||||
|
||||
romFile.close();
|
||||
bootloaderFile.close();
|
||||
}
|
||||
|
||||
return EMU_ERROR_NONE;
|
||||
@@ -205,36 +225,8 @@ void EmuWrapper::exit(){
|
||||
if(emuThread.joinable())
|
||||
emuThread.join();
|
||||
if(emuInited){
|
||||
if(emuRamFilePath != ""){
|
||||
QFile ramFile(emuRamFilePath);
|
||||
buffer_t emuRam;
|
||||
emuRam.size = emulatorGetRamSize();
|
||||
emuRam.data = new uint8_t[emuRam.size];
|
||||
|
||||
emulatorSaveRam(emuRam);
|
||||
|
||||
//save out RAM before exit
|
||||
if(ramFile.open(QFile::WriteOnly | QFile::Truncate)){
|
||||
ramFile.write((const char*)emuRam.data, emuRam.size);
|
||||
ramFile.close();
|
||||
}
|
||||
|
||||
delete[] emuRam.data;
|
||||
}
|
||||
if(emuSdCardFilePath != ""){
|
||||
buffer_t emuSdCard = emulatorGetSdCardBuffer();
|
||||
|
||||
if(emuSdCard.data){
|
||||
QFile sdCardFile(emuSdCardFilePath);
|
||||
|
||||
//save out SD card before exit
|
||||
if(sdCardFile.open(QFile::WriteOnly | QFile::Truncate)){
|
||||
sdCardFile.write((const char*)emuSdCard.data, emuSdCard.size);
|
||||
sdCardFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
emulatorExit();
|
||||
writeOutSaves();
|
||||
emulatorDeinit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,23 +263,146 @@ void EmuWrapper::reset(bool hard){
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::saveState(const QString& path){
|
||||
void EmuWrapper::setCpuSpeed(double speed){
|
||||
if(emuInited){
|
||||
bool wasPaused = isPaused();
|
||||
|
||||
if(!wasPaused)
|
||||
pause();
|
||||
|
||||
emulatorSetCpuSpeed(speed);
|
||||
|
||||
if(!wasPaused)
|
||||
resume();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::bootFromFile(const QString& mainPath){
|
||||
bool wasPaused = isPaused();
|
||||
uint32_t error = EMU_ERROR_NONE;
|
||||
QFileInfo pathInfo(mainPath);
|
||||
QFile appFile(mainPath);
|
||||
QFile ramFile(mainPath + "." + emuOsName + ".ram");
|
||||
QFile sdCardFile(mainPath + "." + emuOsName + ".sd.img");
|
||||
QString suffix = QFileInfo(mainPath).suffix().toLower();
|
||||
bool hasSaveRam;
|
||||
bool hasSaveSdCard;
|
||||
|
||||
if(!wasPaused)
|
||||
pause();
|
||||
|
||||
//save the current data for the last program launched, or the standard device image if none where launched
|
||||
writeOutSaves();
|
||||
|
||||
//its OK if these fail, the buffer will just be NULL, 0 if they do
|
||||
hasSaveRam = ramFile.open(QFile::ReadOnly | QFile::ExistingOnly);
|
||||
hasSaveSdCard = suffix != "img" ? sdCardFile.open(QFile::ReadOnly | QFile::ExistingOnly) : false;
|
||||
|
||||
//fully clear the emu
|
||||
emulatorEjectSdCard();
|
||||
emulatorHardReset();
|
||||
|
||||
if(hasSaveRam)
|
||||
emulatorLoadRam((uint8_t*)ramFile.readAll().data(), ramFile.size());
|
||||
if(hasSaveSdCard)
|
||||
emulatorInsertSdCard((uint8_t*)sdCardFile.readAll().data(), sdCardFile.size(), NULL);
|
||||
|
||||
//its OK if these fail
|
||||
if(hasSaveRam)
|
||||
ramFile.close();
|
||||
if(hasSaveSdCard)
|
||||
sdCardFile.close();
|
||||
|
||||
launcherBootInstantly(hasSaveRam);
|
||||
|
||||
if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
QByteArray fileBuffer = appFile.readAll();
|
||||
|
||||
appFile.close();
|
||||
|
||||
if(suffix == "img"){
|
||||
QFile infoFile(mainPath.mid(0, mainPath.length() - 3) + "info");//swap "img" for "info"
|
||||
sd_card_info_t sdInfo;
|
||||
|
||||
memset(&sdInfo, 0x00, sizeof(sdInfo));
|
||||
|
||||
if(infoFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
launcherGetSdCardInfoFromInfoFile((uint8_t*)infoFile.readAll().data(), infoFile.size(), &sdInfo);
|
||||
infoFile.close();
|
||||
}
|
||||
|
||||
error = emulatorInsertSdCard((uint8_t*)fileBuffer.data(), fileBuffer.size(), &sdInfo);
|
||||
if(error != EMU_ERROR_NONE)
|
||||
goto errorOccurred;
|
||||
}
|
||||
else{
|
||||
if(!hasSaveRam){
|
||||
error = launcherInstallFile((uint8_t*)fileBuffer.data(), fileBuffer.size());
|
||||
if(error != EMU_ERROR_NONE)
|
||||
goto errorOccurred;
|
||||
}
|
||||
error = launcherExecute(launcherGetAppId((uint8_t*)fileBuffer.data(), fileBuffer.size()));
|
||||
if(error != EMU_ERROR_NONE)
|
||||
goto errorOccurred;
|
||||
}
|
||||
}
|
||||
|
||||
//everything worked, set output save files
|
||||
emuRamFilePath = mainPath + "." + emuOsName + ".ram";
|
||||
emuSdCardFilePath = suffix != "img" ? mainPath + "." + emuOsName + ".sd.img" : "";//dont duplicate booted SD card images
|
||||
emuSaveStatePath = mainPath + "." + emuOsName + ".states";
|
||||
|
||||
//make the place to store the saves
|
||||
QDir(emuSaveStatePath).mkdir(".");
|
||||
|
||||
//need this goto because the emulator must be released before returning
|
||||
errorOccurred:
|
||||
if(error != EMU_ERROR_NONE){
|
||||
//try and recover from error
|
||||
emulatorEjectSdCard();
|
||||
emulatorHardReset();
|
||||
}
|
||||
|
||||
if(!wasPaused)
|
||||
resume();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::installApplication(const QString& path){
|
||||
bool wasPaused = isPaused();
|
||||
uint32_t error = EMU_ERROR_INVALID_PARAMETER;
|
||||
QFile stateFile(path);
|
||||
QFile appFile(path);
|
||||
|
||||
if(!wasPaused)
|
||||
pause();
|
||||
|
||||
if(appFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
error = launcherInstallFile((uint8_t*)appFile.readAll().data(), appFile.size());
|
||||
appFile.close();
|
||||
}
|
||||
|
||||
if(!wasPaused)
|
||||
resume();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::saveState(const QString& name){
|
||||
bool wasPaused = isPaused();
|
||||
uint32_t error = EMU_ERROR_INVALID_PARAMETER;
|
||||
QFile stateFile(emuSaveStatePath + "/" + name + ".state");
|
||||
|
||||
if(!wasPaused)
|
||||
pause();
|
||||
|
||||
//save here
|
||||
if(stateFile.open(QFile::WriteOnly)){
|
||||
buffer_t stateData;
|
||||
uint32_t stateSize = emulatorGetStateSize();
|
||||
uint8_t* stateData = new uint8_t[stateSize];
|
||||
|
||||
stateData.size = emulatorGetStateSize();
|
||||
stateData.data = new uint8_t[stateData.size];
|
||||
|
||||
emulatorSaveState(stateData);//no need to check for errors since the buffer is always the right size
|
||||
stateFile.write((const char*)stateData.data, stateData.size);
|
||||
emulatorSaveState(stateData, stateSize);//no need to check for errors since the buffer is always the right size
|
||||
stateFile.write((const char*)stateData, stateSize);
|
||||
stateFile.close();
|
||||
|
||||
error = EMU_ERROR_NONE;
|
||||
@@ -299,25 +414,19 @@ uint32_t EmuWrapper::saveState(const QString& path){
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::loadState(const QString& path){
|
||||
uint32_t EmuWrapper::loadState(const QString& name){
|
||||
bool wasPaused = isPaused();
|
||||
uint32_t error = EMU_ERROR_INVALID_PARAMETER;
|
||||
QFile stateFile(path);
|
||||
QFile stateFile(emuSaveStatePath + "/" + name + ".state");
|
||||
|
||||
if(!wasPaused)
|
||||
pause();
|
||||
|
||||
if(stateFile.open(QFile::ReadOnly)){
|
||||
QByteArray stateDataBuffer;
|
||||
buffer_t stateData;
|
||||
|
||||
stateDataBuffer = stateFile.readAll();
|
||||
stateFile.close();
|
||||
stateData.data = (uint8_t*)stateDataBuffer.data();
|
||||
stateData.size = stateDataBuffer.size();
|
||||
|
||||
if(emulatorLoadState(stateData))
|
||||
if(stateFile.open(QFile::ReadOnly | QFile::ExistingOnly)){
|
||||
if(emulatorLoadState((uint8_t*)stateFile.readAll().data(), stateFile.size()))
|
||||
error = EMU_ERROR_NONE;
|
||||
stateFile.close();
|
||||
|
||||
}
|
||||
|
||||
if(!wasPaused)
|
||||
@@ -370,6 +479,10 @@ void EmuWrapper::setKeyValue(uint8_t key, bool pressed){
|
||||
emuInput.buttonNotes = pressed;
|
||||
break;
|
||||
|
||||
case BUTTON_VOICE_MEMO:
|
||||
emuInput.buttonVoiceMemo = pressed;
|
||||
break;
|
||||
|
||||
case BUTTON_POWER:
|
||||
emuInput.buttonPower = pressed;
|
||||
break;
|
||||
@@ -379,47 +492,56 @@ void EmuWrapper::setKeyValue(uint8_t key, bool pressed){
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuWrapper::installApplication(const QString& path){
|
||||
bool wasPaused = isPaused();
|
||||
uint32_t error = EMU_ERROR_INVALID_PARAMETER;
|
||||
QFile appFile(path);
|
||||
|
||||
if(!wasPaused)
|
||||
pause();
|
||||
|
||||
if(appFile.open(QFile::ReadOnly)){
|
||||
QByteArray appDataBuffer;
|
||||
buffer_t appData;
|
||||
|
||||
appDataBuffer = appFile.readAll();
|
||||
appFile.close();
|
||||
appData.data = (uint8_t*)appDataBuffer.data();
|
||||
appData.size = appDataBuffer.size();
|
||||
error = sandboxCommand(SANDBOX_CMD_DEBUG_INSTALL_APP, &appData);
|
||||
}
|
||||
|
||||
if(!wasPaused)
|
||||
resume();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
std::vector<QString>& EmuWrapper::getDebugStrings(){
|
||||
QVector<QString>& EmuWrapper::debugGetLogEntrys(){
|
||||
return debugStrings;
|
||||
}
|
||||
|
||||
std::vector<uint64_t>& EmuWrapper::getDuplicateCallCount(){
|
||||
QVector<uint64_t>& EmuWrapper::debugGetDuplicateLogEntryCount(){
|
||||
return duplicateCallCount;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> EmuWrapper::getCpuRegisters(){
|
||||
std::vector<uint32_t> registers;
|
||||
QString EmuWrapper::debugGetCpuRegisterString(){
|
||||
QString regString = "";
|
||||
|
||||
for(uint8_t reg = 0; reg < 18; reg++)
|
||||
registers.push_back(flx68000GetRegister(reg));
|
||||
return registers;
|
||||
if(palmEmulatingTungstenT3){
|
||||
for(uint8_t regs = 0; regs < 16; regs++)
|
||||
regString += QString::asprintf("R%d:0x%08X\n", regs, pxa260GetRegister(regs));
|
||||
regString += QString::asprintf("SP:0x%08X\n", pxa260GetRegister(13));
|
||||
regString += QString::asprintf("LR:0x%08X\n", pxa260GetRegister(14));
|
||||
regString += QString::asprintf("PC:0x%08X\n", pxa260GetPc());
|
||||
regString += QString::asprintf("CPSR:0x%08X\n", pxa260GetCpsr());
|
||||
regString += QString::asprintf("SPSR:0x%08X", pxa260GetSpsr());
|
||||
}
|
||||
else{
|
||||
for(uint8_t dRegs = 0; dRegs < 8; dRegs++)
|
||||
regString += QString::asprintf("D%d:0x%08X\n", dRegs, flx68000GetRegister(dRegs));
|
||||
for(uint8_t aRegs = 0; aRegs < 8; aRegs++)
|
||||
regString += QString::asprintf("A%d:0x%08X\n", aRegs, flx68000GetRegister(8 + aRegs));
|
||||
regString += QString::asprintf("SP:0x%08X\n", flx68000GetRegister(15));
|
||||
regString += QString::asprintf("PC:0x%08X\n", flx68000GetPc());
|
||||
regString += QString::asprintf("SR:0x%04X", flx68000GetStatusRegister());
|
||||
}
|
||||
|
||||
return regString;
|
||||
}
|
||||
|
||||
uint64_t EmuWrapper::getEmulatorMemory(uint32_t address, uint8_t size){
|
||||
uint64_t EmuWrapper::debugGetEmulatorMemory(uint32_t address, uint8_t size){
|
||||
if(palmEmulatingTungstenT3)
|
||||
return pxa260ReadArbitraryMemory(address, size);
|
||||
return flx68000ReadArbitraryMemory(address, size);
|
||||
}
|
||||
|
||||
QString EmuWrapper::debugGetEmulatorDisassemble(uint32_t address, uint32_t opcodes){
|
||||
QString output = "";
|
||||
|
||||
if(palmEmulatingTungstenT3){
|
||||
|
||||
}
|
||||
else{
|
||||
for(uint32_t index = 0; index < opcodes; index++){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QImage>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../src/emulator.h"
|
||||
@@ -22,11 +22,14 @@ private:
|
||||
std::atomic<bool> emuRunning;
|
||||
std::atomic<bool> emuPaused;
|
||||
std::atomic<bool> emuNewFrameReady;
|
||||
QString emuOsName;
|
||||
QString emuRamFilePath;
|
||||
QString emuSdCardFilePath;
|
||||
QString emuSaveStatePath;
|
||||
input_t emuInput;
|
||||
|
||||
void emuThreadRun();
|
||||
void writeOutSaves();
|
||||
|
||||
public:
|
||||
enum{
|
||||
@@ -39,6 +42,7 @@ public:
|
||||
BUTTON_ADDRESS,
|
||||
BUTTON_TODO,
|
||||
BUTTON_NOTES,
|
||||
BUTTON_VOICE_MEMO,
|
||||
BUTTON_POWER,
|
||||
BUTTON_TOTAL_COUNT
|
||||
};
|
||||
@@ -46,34 +50,36 @@ public:
|
||||
EmuWrapper();
|
||||
~EmuWrapper();
|
||||
|
||||
uint32_t init(const QString& romPath, const QString& bootloaderPath = "", const QString& ramPath = "", const QString& sdCardPath = "", uint32_t features = FEATURE_ACCURATE);
|
||||
uint32_t init(const QString& assetPath, uint8_t osVersion, bool syncRtc = false, bool allowInvalidBehavior = false, bool fastBoot = false);
|
||||
void exit();
|
||||
void pause();
|
||||
void resume();
|
||||
void reset(bool hard);
|
||||
uint32_t saveState(const QString& path);
|
||||
uint32_t loadState(const QString& path);
|
||||
void setCpuSpeed(double speed);
|
||||
uint32_t bootFromFile(const QString& mainPath);
|
||||
uint32_t installApplication(const QString& path);
|
||||
const QString& getStatePath() const{return emuSaveStatePath;}//needed for looking up state pictures in the GUI
|
||||
uint32_t saveState(const QString& name);
|
||||
uint32_t loadState(const QString& name);
|
||||
bool isInited() const{return emuInited;}
|
||||
bool isRunning() const{return emuRunning;}
|
||||
bool isPaused() const{return emuPaused;}
|
||||
void setPenValue(float x, float y, bool touched);
|
||||
void setKeyValue(uint8_t key, bool pressed);
|
||||
|
||||
uint32_t installApplication(const QString& path);
|
||||
|
||||
std::vector<QString>& getDebugStrings();
|
||||
std::vector<uint64_t>& getDuplicateCallCount();
|
||||
std::vector<uint32_t> getCpuRegisters();
|
||||
|
||||
uint16_t screenWidth() const{return palmFramebufferWidth;}
|
||||
uint16_t screenHeight() const{return palmFramebufferHeight;}
|
||||
bool newFrameReady() const{return emuNewFrameReady;}
|
||||
void frameHandled(){emuNewFrameReady = false;}
|
||||
|
||||
//calling these while newFrameReady() == false is undefined behavior, the other thread may be writing to them
|
||||
const QPixmap getFramebuffer(){return QPixmap::fromImage(QImage((uchar*)palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t), QImage::Format_RGB16));}
|
||||
const QImage getFramebufferImage(){return QImage((uchar*)palmFramebuffer, palmFramebufferWidth, palmFramebufferHeight, palmFramebufferWidth * sizeof(uint16_t), QImage::Format_RGB16);}
|
||||
const int16_t* getAudioSamples() const{return palmAudio;}
|
||||
bool getPowerButtonLed() const{return palmMisc.powerButtonLed;}
|
||||
bool getPowerButtonLed() const{return palmMisc.greenLed;}
|
||||
|
||||
uint64_t getEmulatorMemory(uint32_t address, uint8_t size);
|
||||
QVector<QString>& debugGetLogEntrys();
|
||||
QVector<uint64_t>& debugGetDuplicateLogEntryCount();
|
||||
QString debugGetCpuRegisterString();
|
||||
uint64_t debugGetEmulatorMemory(uint32_t address, uint8_t size);
|
||||
QString debugGetEmulatorDisassemble(uint32_t address, uint32_t opcodes);
|
||||
};
|
||||
|
||||
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.6 KiB |
1
qtBuildSystem/Mu/images/boot.svg
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.4 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="24.837" cy="36.421" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.645"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="21.929" cy="-3.218" gradientTransform="matrix(3.658819 0 0 2.080782 -62.4164 12.76204)" gradientUnits="userSpaceOnUse" r="13"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="c" cx="22.5" cy="28.116" gradientTransform="matrix(2.365562 0 0 2.202845 -30.72517 -34.23996)" gradientUnits="userSpaceOnUse" r="14.538"><stop offset="0" stop-color="#ef2929"/><stop offset="1" stop-color="#c00"/></radialGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="21.702" x2="21.816" y1="8.912" y2="35.546"><stop offset="0"/><stop offset="1" stop-color="#fff" stop-opacity=".784"/></linearGradient><g fill-rule="evenodd"><path d="m36.5 22a14 13 0 1 1 -28 0 14 13 0 1 1 28 0z" style="opacity:.15;stroke-width:3.136616;stroke-linecap:square;stroke-linejoin:round;stroke:url(#d);fill:url(#c)" transform="matrix(.920697 0 0 .99358 3.679484 1.641236)"/><path d="m40.481863 36.421127a15.644737 8.3968935 0 1 1 -31.2894745 0 15.644737 8.3968935 0 1 1 31.2894745 0z" fill="url(#a)" opacity=".04" transform="matrix(1.150533 0 0 .565685 -4.5765 16.55285)"/><path d="m36.5 22a14 13 0 1 1 -28 0 14 13 0 1 1 28 0z" fill="url(#c)" stroke="#c00" stroke-linecap="square" stroke-linejoin="round" stroke-width="1.076" transform="matrix(.894862 0 0 .9657 3.855776 2.660348)"/></g><path d="m38 24a14 14 0 1 1 -28 0 14 14 0 1 1 28 0z" fill="none" stroke="#f77d7d" stroke-linecap="square" stroke-linejoin="round" stroke-width="1.217" transform="matrix(.821429 0 0 .821429 4.285117 4.191455)"/><path d="m23.84315 11.90574c-6.279532.079595-11.404423 4.992059-11.8125 11.1875 6.117823 2.51678 13.87042-1.451223 23.142005-3.381886-.68841-2.748569-4.55472-7.805614-11.173255-7.805614-.051707 0-.104697-.000653-.15625 0z" fill="url(#b)" fill-rule="evenodd" opacity=".6"/></svg>
|
||||
<svg height="32.880508" width="35.999573" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="22.5" cy="28.115999" gradientTransform="matrix(2.365562 0 0 2.202845 -30.72517 -34.23996)" gradientUnits="userSpaceOnUse" r="14.538"><stop offset="0" stop-color="#ef2929"/><stop offset="1" stop-color="#c00"/></radialGradient><radialGradient id="b" cx="24.837" cy="36.421001" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.645"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="c" cx="21.929001" cy="-3.218" gradientTransform="matrix(3.658819 0 0 2.080782 -68.416046 3.736818)" gradientUnits="userSpaceOnUse" r="13"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="21.702" x2="21.816" y1="8.912" y2="35.546001"><stop offset="0"/><stop offset="1" stop-color="#fff" stop-opacity=".784"/></linearGradient><g fill-rule="evenodd" transform="translate(-5.999646 -9.025222)"><path d="m36.5 22a14 13 0 1 1 -28 0 14 13 0 1 1 28 0z" style="opacity:.15;stroke-width:3.136616;stroke-linecap:square;stroke-linejoin:round;fill:url(#a);stroke:url(#d)" transform="matrix(.920697 0 0 .99358 3.679484 1.641236)"/><path d="m40.481863 36.421127a15.644737 8.3968937 0 1 1 -31.2894745 0 15.644737 8.3968937 0 1 1 31.2894745 0z" fill="url(#b)" opacity=".04" transform="matrix(1.150533 0 0 .565685 -4.5765 16.55285)"/><path d="m36.5 22a14 13 0 1 1 -28 0 14 13 0 1 1 28 0z" fill="url(#a)" stroke="#c00" stroke-linecap="square" stroke-linejoin="round" stroke-width="1.076" transform="matrix(.894862 0 0 .9657 3.855776 2.660348)"/></g><path d="m29.499773 14.880529a11.500006 11.500006 0 1 1 -23.0000123 0 11.500006 11.500006 0 1 1 23.0000123 0z" fill="none" stroke="#f77d7d" stroke-linecap="square" stroke-linejoin="round" stroke-width=".999679"/><path d="m17.843504 2.8805179c-6.279532.07959-11.4044233 4.992059-11.8125003 11.1875001 6.1178233 2.51678 13.8704203-1.451223 23.1420053-3.381886-.68841-2.7485691-4.55472-7.8056141-11.173255-7.8056141-.05171 0-.104697-.000653-.15625 0z" fill="url(#c)" fill-rule="evenodd" opacity=".6"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.3 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="35.292667" cy="20.494493" gradientTransform="matrix(0 -.843022 1.020168 0 .606436 42.58614)" gradientUnits="userSpaceOnUse" r="16.956199"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><radialGradient id="c" cx="15.987216" cy="1.535031" gradientTransform="matrix(0 -2.046729 -1.55761 0 44.11559 66.93275)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><path d="m40.481863 36.421127a15.644737 8.3968935 0 1 1 -31.2894745 0 15.644737 8.3968935 0 1 1 31.2894745 0z" fill="url(#a)" fill-rule="evenodd" opacity=".204545" transform="matrix(1.214466 0 0 .595458 -6.163846 16.31275)"/><g transform="matrix(-1 0 0 -1 47.02856 43.99921)"><path d="m14.519136 38.5 18.005029-.003906v-12.991626l7.995366-.007812-17.144722-19.9974425-16.8462505 19.9980705 7.9958815.00379-.005304 12.998926z" style="fill-rule:evenodd;stroke:#3a7304;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill:url(#b)"/><path d="m39.429889 24.993467-7.406391.011719.002681 12.992837-15.378556-.009153c.769922-18.34099 10.722649-10.993073 15.381659-21.646879z" fill="url(#c)" fill-rule="evenodd" opacity=".508021"/><path d="m15.520704 37.496094 16.001405.003906v-12.99295l6.816811-.015625-14.954276-17.4525854-14.7065267 17.4569424 6.8399007.005247z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></g></svg>
|
||||
<svg height="38.00079" width="38.000004" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="24.837126" cy="36.421127" gradientTransform="matrix(1.214466 0 0 .319596 -11.163843 21.360739)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="35.292667" cy="20.494493" gradientTransform="matrix(0 -.843022 1.020168 0 .606436 42.58614)" gradientUnits="userSpaceOnUse" r="16.9562"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><radialGradient id="c" cx="15.987216" cy="1.535031" gradientTransform="matrix(0 -2.046729 -1.55761 0 44.11559 66.93275)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><path d="m38.000003 33.000791a19.000001 4.9999976 0 1 1 -38.000003 0 19.000001 4.9999976 0 1 1 38.000003 0z" fill="url(#a)" fill-rule="evenodd" opacity=".204545" stroke-width=".85039"/><g transform="matrix(-1 0 0 -1 42.028562 39)"><path d="m14.519136 38.5 18.005029-.0039v-12.991632l7.995366-.0078-17.144722-19.9974545-16.8462505 19.9980705 7.9958815.0038z" style="fill-rule:evenodd;stroke:#3a7304;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;fill:url(#b)"/><path d="m39.429889 24.993467-7.406391.01172.0027 12.992837-15.378556-.0092c.769903-18.340944 10.72263-10.993027 15.38164-21.646833z" fill="url(#c)" fill-rule="evenodd" opacity=".508021"/><path d="m15.520704 37.496094 16.001405.003906v-12.99295l6.816811-.015625-14.954276-17.4525854-14.7065267 17.4569424 6.8399007.0052z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="25.075571" cy="5.78598" gradientTransform="matrix(-2.046729 0 0 1.55761 67.59375 3.275309)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="c" cx="22.291636" cy="32.797512" gradientTransform="matrix(-.843022 0 0 1.020168 43.57646 1.205215)" gradientUnits="userSpaceOnUse" r="16.956199"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><g fill-rule="evenodd"><path d="m40.481863 36.421127a15.644737 8.3968935 0 1 1 -31.2894745 0 15.644737 8.3968935 0 1 1 31.2894745 0z" fill="url(#b)" opacity=".299465" transform="matrix(-1.271186 0 0 1.271186 56.19514 -15.27857)"/><path d="m39.490316 15.496821v16.99442h-12.952563v8.482538l-19.959836-17.000191 19.953646-17.2439979v8.7725349z" fill="url(#c)" stroke="#3a7304" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="m25.988368 7.9779766v8.0564744h12.94217v8.884463c-16.75-6.25-16.133537 5.294712-31.383538-.955288z" fill="url(#a)" opacity=".508021"/></g><path d="m38.475551 16.541365v14.92194h-12.985367v7.301416l-17.321765-14.795691 17.337726-14.9054001v7.4826321z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></svg>
|
||||
<svg height="35.463821" width="39.774742" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="25.075571" cy="5.78598" gradientTransform="matrix(-2.046729 0 0 1.55761 67.59375 3.275309)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="c" cx="22.291636" cy="32.797512" gradientTransform="matrix(-.843022 0 0 1.020168 43.57646 1.205215)" gradientUnits="userSpaceOnUse" r="16.9562"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><g fill-rule="evenodd" transform="translate(-4.735163 -6.229649)"><path d="m40.481863 36.421127a15.644737 8.3968937 0 1 1 -31.2894745 0 15.644737 8.3968937 0 1 1 31.2894745 0z" fill="url(#b)" opacity=".299465" transform="matrix(-1.271186 0 0 1.271186 56.19514 -15.27857)"/><path d="m39.490316 15.496821v16.99442h-12.952563v8.482538l-19.959836-17.000191 19.953646-17.2439979v8.7725349z" fill="url(#c)" stroke="#3a7304" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="m25.988368 7.9779766v8.0564744h12.94217v8.884463c-16.75-6.25-16.133537 5.294712-31.383538-.955288z" fill="url(#a)" opacity=".508021"/></g><path d="m33.740388 10.311716v14.92194h-12.985367v7.301416l-17.3217645-14.795691 17.3377255-14.9054005v7.4826325z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.9 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="15.089121" x2="13.9996" y1="15.197734" y2="52.416314"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b" gradientTransform="matrix(1 0 0 1.004384 -145.0004 -71.4625)" gradientUnits="userSpaceOnUse" x1="169" x2="169" y1="110.33805" y2="93.204849"><stop offset="0" stop-color="#babdb6"/><stop offset="1" stop-color="#555753"/></linearGradient><radialGradient id="c" cx="169.77171" cy="100.20107" gradientTransform="matrix(.00000356 -1.07205 1.992104 -.00000125 -175.6121 212.6949)" gradientUnits="userSpaceOnUse" r="11"><stop offset="0" stop-color="#f7f7f7"/><stop offset="1" stop-color="#ccd0c7"/></radialGradient><linearGradient id="d" gradientTransform="matrix(1.103262 0 0 1.054917 -163.1228 -76.31138)" gradientUnits="userSpaceOnUse" x1="174.83363" x2="174.74524" y1="84.263489" y2="105.49083"><stop offset="0"/><stop offset="1" stop-color="#fff" stop-opacity=".484536"/></linearGradient><path d="m26.086565 12.829103v22.153256h8.826093v-22.153256z" style="opacity:.15;fill:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke:url(#d)"/><path d="m26.4996 13.40575v21h8v-21z" fill="url(#c)" fill-rule="evenodd"/><path d="m26.4996 13.407946v21.092064h8v-21.092064z" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round"/><path d="m27.4996 14.40575v19h6v-19z" fill="none" stroke="url(#a)" stroke-linecap="square"/><path d="m28.019106 14.942758v8.385631l4.993942-.618719v-7.8553z" display="block" fill="#f7f7f7" opacity=".5"/><g transform="translate(-12.97229)"><path d="m26.086565 12.829103v22.153256h8.826093v-22.153256z" style="opacity:.15;fill:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke:url(#d)"/><path d="m26.4996 13.40575v21h8v-21z" fill="url(#c)" fill-rule="evenodd"/><path d="m26.4996 13.407946v21.092064h8v-21.092064z" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round"/><path d="m27.4996 14.40575v19h6v-19z" fill="none" stroke="url(#a)" stroke-linecap="square"/><path d="m28.019106 14.942758v10.06501l4.993942-.618719v-9.534679z" display="block" fill="#f7f7f7" opacity=".5"/></g></svg>
|
||||
<svg height="24.153255" width="23.798384" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(1.103262 0 0 1.054917 -175.23707 -88.140483)" gradientUnits="userSpaceOnUse" x1="174.83363" x2="174.74524" xlink:href="#l" y1="84.263489" y2="105.49083"/><radialGradient id="b" cx="169.77171" cy="100.20107" gradientTransform="matrix(.00000356 -1.07205 1.992104 -.00000125 -187.72637 200.8658)" gradientUnits="userSpaceOnUse" r="11" xlink:href="#k"/><linearGradient id="c" gradientTransform="matrix(1 0 0 1.004384 -157.11467 -83.291603)" gradientUnits="userSpaceOnUse" x1="169" x2="169" xlink:href="#j" y1="110.33805" y2="93.204849"/><linearGradient id="d" gradientUnits="userSpaceOnUse" x1="2.974846" x2="1.885325" xlink:href="#i" y1="3.368631" y2="40.58721"/><linearGradient id="e" gradientTransform="matrix(1.103262 0 0 1.054917 -163.1228 -76.31138)" gradientUnits="userSpaceOnUse" x1="174.83363" x2="174.74524" xlink:href="#l" y1="84.263489" y2="105.49083"/><radialGradient id="f" cx="169.77171" cy="100.20107" gradientTransform="matrix(.00000356 -1.07205 1.992104 -.00000125 -175.6121 212.6949)" gradientUnits="userSpaceOnUse" r="11" xlink:href="#k"/><linearGradient id="g" gradientTransform="matrix(1 0 0 1.004384 -145.0004 -71.4625)" gradientUnits="userSpaceOnUse" x1="169" x2="169" xlink:href="#j" y1="110.33805" y2="93.204849"/><linearGradient id="h" gradientUnits="userSpaceOnUse" x1="15.089121" x2="13.9996" xlink:href="#i" y1="15.197734" y2="52.416313"/><linearGradient id="i" gradientUnits="userSpaceOnUse" x1="15.089121" x2="13.9996" y1="15.197734" y2="52.416313"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="j" gradientTransform="matrix(1 0 0 1.004384 -145.0004 -71.4625)" gradientUnits="userSpaceOnUse" x1="169" x2="169" y1="110.33805" y2="93.204849"><stop offset="0" stop-color="#babdb6"/><stop offset="1" stop-color="#555753"/></linearGradient><radialGradient id="k" cx="169.77171" cy="100.20107" gradientTransform="matrix(.00000356 -1.07205 1.992104 -.00000125 -175.6121 212.6949)" gradientUnits="userSpaceOnUse" r="11"><stop offset="0" stop-color="#f7f7f7"/><stop offset="1" stop-color="#ccd0c7"/></radialGradient><linearGradient id="l" gradientTransform="matrix(1.103262 0 0 1.054917 -163.1228 -76.31138)" gradientUnits="userSpaceOnUse" x1="174.83363" x2="174.74524" y1="84.263489" y2="105.49083"><stop offset="0"/><stop offset="1" stop-color="#fff" stop-opacity=".484536"/></linearGradient><path d="m13.97229 1v22.153256h8.826093v-22.153256z" style="opacity:.15;fill:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke:url(#a)"/><path d="m14.385325 1.576647v21h8v-21z" fill="url(#b)" fill-rule="evenodd"/><path d="m14.385325 1.578843v21.092064h8v-21.092064z" fill="none" stroke="url(#c)" stroke-linecap="square" stroke-linejoin="round"/><path d="m15.385325 2.576647v19h6v-19z" fill="none" stroke="url(#d)" stroke-linecap="square"/><path d="m15.904831 3.113655v8.385631l4.993942-.618719v-7.8553z" display="block" fill="#f7f7f7" opacity=".5"/><g transform="translate(-25.086565 -11.829103)"><path d="m26.086565 12.829103v22.153256h8.826093v-22.153256z" style="opacity:.15;fill:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke:url(#e)"/><path d="m26.4996 13.40575v21h8v-21z" fill="url(#f)" fill-rule="evenodd"/><path d="m26.4996 13.407946v21.092064h8v-21.092064z" fill="none" stroke="url(#g)" stroke-linecap="square" stroke-linejoin="round"/><path d="m27.4996 14.40575v19h6v-19z" fill="none" stroke="url(#h)" stroke-linecap="square"/><path d="m28.019106 14.942758v10.06501l4.993942-.618719v-9.534679z" display="block" fill="#f7f7f7" opacity=".5"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 3.7 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="26.288536" x2="25.826522" y1="53.02227" y2="23.90575"><stop offset="0" stop-color="#adb0a8"/><stop offset="1" stop-color="#464744"/></linearGradient><radialGradient id="b" cx="107.5884" cy="83.990814" gradientTransform="matrix(.05324342 -.836238 2.019473 .128568 -151.9195 108.0768)" gradientUnits="userSpaceOnUse" r="12.551644"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d3d7cf"/></radialGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="26.010638" x2="26.053493" y1="31.42276" y2="16.961972"><stop offset="0" stop-color="#fff"/><stop offset="1"/></linearGradient><path d="m12 39.5v-30.5l26.06998 14.817079z" style="fill:none;stroke-width:1.999998;stroke-linecap:square;stroke-linejoin:round;opacity:.15;stroke:url(#c)"/><path d="m12.49946 37.81149v-27.811485l24.103287 13.905743z" fill="url(#b)" fill-rule="evenodd"/><path d="m12.49946 37.81149v-27.811485l24.103287 13.905743z" fill="none" stroke="url(#a)" stroke-linecap="square" stroke-linejoin="round"/><g fill="#fff"><path d="m12.99946 10.87449v26.0625l22.59375-13.03125zm1 1.75 19.5625 11.28125-19.5625 11.28125z" fill-rule="evenodd"/><path d="m13.9375 12.5625v11.6875c4.269198-.044785 9.164156-.345564 17.0625-1.875z" display="block" opacity=".5"/></g></svg>
|
||||
<svg height="32.499847" width="28.06988" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="15.288535" x2="14.826522" y1="45.022197" y2="15.905677"><stop offset="0" stop-color="#adb0a8"/><stop offset="1" stop-color="#464744"/></linearGradient><radialGradient id="b" cx="107.5884" cy="83.990814" gradientTransform="matrix(.05324342 -.836238 2.019473 .128568 -162.9195 100.07673)" gradientUnits="userSpaceOnUse" r="12.551644"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d3d7cf"/></radialGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="15.010636" x2="15.053492" y1="23.422687" y2="8.961898"><stop offset="0" stop-color="#fff"/><stop offset="1"/></linearGradient><path d="m.99999899 31.499927v-30.49999985l26.06998001 14.81707885z" style="opacity:.15;fill:none;stroke-width:1.999998;stroke-linecap:square;stroke-linejoin:round;stroke:url(#c)"/><path d="m1.499459 29.811417v-27.8114848l24.103287 13.9057428z" fill="url(#b)" fill-rule="evenodd"/><path d="m1.499459 29.811417v-27.8114848l24.103287 13.9057428z" fill="none" stroke="url(#a)" stroke-linecap="square" stroke-linejoin="round"/><g fill="#fff" transform="translate(-11.000001 -8.000073)"><path d="m12.99946 10.87449v26.0625l22.59375-13.03125zm1 1.75 19.5625 11.28125-19.5625 11.28125z" fill-rule="evenodd"/><path d="m13.9375 12.5625v11.6875c4.269198-.044785 9.164156-.345564 17.0625-1.875z" display="block" opacity=".5"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="605.714" cy="486.648" gradientTransform="matrix(-2.774389 0 0 1.969706 112.7623 -872.8854)" gradientUnits="userSpaceOnUse" r="117.143" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><radialGradient id="c" cx="605.714" cy="486.648" gradientTransform="matrix(2.774389 0 0 1.969706 -1891.633 -872.8854)" gradientUnits="userSpaceOnUse" r="117.143" xlink:href="#b"/><linearGradient id="d" gradientTransform="matrix(2.774389 0 0 1.969706 -1892.179 -872.8854)" gradientUnits="userSpaceOnUse" x1="302.857" x2="302.857" y1="366.648" y2="609.505"><stop offset="0" stop-opacity="0"/><stop offset=".5"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d1d1d1"/></linearGradient><linearGradient id="f"><stop offset="0" stop-color="#fbfbfb"/><stop offset="1" stop-color="#dcdcdc"/></linearGradient><radialGradient id="g" cx="24.446" cy="35.878" gradientTransform="matrix(1.995058 0 0 1.855412 -24.37145 -30.2043)" gradientUnits="userSpaceOnUse" r="20.531" xlink:href="#f"/><linearGradient id="h" gradientTransform="matrix(1.045319 0 0 .957884 -1.154429 1.415543)" gradientUnits="userSpaceOnUse" x1="20.092" x2="31.799" xlink:href="#e" y1="8.947" y2="38.947"/><linearGradient id="i" gradientTransform="matrix(.984324 0 0 .957884 .336637 1.415543)" gradientUnits="userSpaceOnUse" x1="24.446" x2="24.446" xlink:href="#f" y1=".498" y2="39.447"/><linearGradient id="j" gradientTransform="matrix(.476329 0 0 .627721 12.7549 9.156933)" gradientUnits="userSpaceOnUse" x1="31.597" x2="24.446" xlink:href="#e" y1="33.448" y2="21.067"/><radialGradient id="k" cx="24.399" cy="29.1" gradientTransform="matrix(2.407878 0 0 1.86105 -34.35094 -20.55775)" gradientUnits="userSpaceOnUse" r="6.027"><stop offset="0" stop-color="#525252"/><stop offset="1"/></radialGradient><linearGradient id="l" gradientTransform="matrix(1.059222 0 0 .808101 -1.234132 4.001391)" gradientUnits="userSpaceOnUse" x1="22.586" x2="22.586" y1="34.15" y2="11.043"><stop offset="0" stop-color="#fff"/><stop offset=".46" stop-color="#e3e3e3"/><stop offset=".62" stop-color="#dadada" stop-opacity=".671"/><stop offset="1" stop-color="#d1d1d1" stop-opacity=".343"/></linearGradient><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="25.279" x2="28.284" xlink:href="#b" y1="28.555" y2="38.454"/><radialGradient id="n" cx="24.484" cy="29.61" gradientTransform="matrix(2.777122 -.08126449 .06891211 2.223012 -45.28558 -33.24798)" gradientUnits="userSpaceOnUse" r="4.477"><stop offset="0" stop-color="#fff"/><stop offset=".216" stop-color="#fff"/><stop offset=".5" stop-color="#838383"/><stop offset="1" stop-color="#838383" stop-opacity="0"/></radialGradient><path d="m-1559.2523-150.69685h1339.6335v478.35718h-1339.6335z" fill="url(#d)" opacity=".402" transform="matrix(.02312904 0 0 .01818338 45.14375 40.29231)"/><path d="m-219.61876-150.68038v478.33079c142.874166.90045 345.40022-107.16966 345.40014-239.196175 0-132.026537-159.436816-239.134595-345.40014-239.134615z" fill="url(#c)" opacity=".402" transform="matrix(.02312904 0 0 .01818338 45.14375 40.29231)"/><path d="m-1559.2523-150.68038v478.33079c-142.8742.90045-345.4002-107.16966-345.4002-239.196175 0-132.026537 159.4368-239.134595 345.4002-239.134615z" fill="url(#a)" opacity=".402" transform="matrix(.02312904 0 0 .01818338 45.14375 40.29231)"/><rect fill="url(#g)" fill-rule="evenodd" height="39.915" rx="5.455" stroke="#9b9b9b" stroke-linejoin="bevel" stroke-miterlimit="10" width="40.062" x="4.368" y="3.617"/><rect fill="none" height="37.782" rx="4.243" stroke="#fff" stroke-linejoin="bevel" stroke-miterlimit="10" width="37.697" x="5.551" y="4.651"/><g fill-rule="evenodd"><rect fill="url(#i)" height="32.706" rx="2.298" stroke="url(#h)" stroke-linejoin="bevel" stroke-miterlimit="10" width="24.258" x="12.27" y="7.522"/><rect fill="url(#k)" height="20.903" rx="1.591" stroke="url(#j)" stroke-linejoin="bevel" stroke-miterlimit="10" width="12.115" x="18.519" y="13.866"/><path d="m19.975767 34.034641 2.65165 2.651651 11.136932-.176776s-2.828427-9.369166-2.828427-9.369166-.707107-9.369166-.707107-9.369166l-.707107 15.909904z" fill="url(#m)" opacity=".316"/><g stroke-linejoin="bevel" stroke-miterlimit="10"><rect fill="#8a8a8a" height="4.315" rx="1.061" stroke="#595959" width="8.971" x="20.02" y="29.218"/><rect fill="url(#l)" height="15.812" rx=".884" stroke="url(#n)" width="8.912" x="20.05" y="15.231"/></g></g></svg>
|
||||
<svg height="43.133282" width="46.961987" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="605.71399" cy="486.64801" gradientTransform="matrix(-.06416895 0 0 .03581591 46.660868 21.303303)" gradientUnits="userSpaceOnUse" r="117.143" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><radialGradient id="c" cx="605.71399" cy="486.64801" gradientTransform="matrix(.06416895 0 0 .03581591 .301129 21.303303)" gradientUnits="userSpaceOnUse" r="117.143" xlink:href="#b"/><linearGradient id="d" gradientTransform="matrix(.06416895 0 0 .03581591 .2885 21.303303)" gradientUnits="userSpaceOnUse" x1="302.85699" x2="302.85699" y1="366.64801" y2="609.505"><stop offset="0" stop-opacity="0"/><stop offset=".5"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#d1d1d1"/></linearGradient><linearGradient id="f"><stop offset="0" stop-color="#fbfbfb"/><stop offset="1" stop-color="#dcdcdc"/></linearGradient><radialGradient id="g" cx="24.445999" cy="35.877998" gradientTransform="matrix(1.995058 0 0 1.855412 -25.462416 -33.3213)" gradientUnits="userSpaceOnUse" r="20.531" xlink:href="#f"/><linearGradient id="h" gradientTransform="matrix(1.045319 0 0 .957884 -1.154429 1.415543)" gradientUnits="userSpaceOnUse" x1="20.091999" x2="31.799" xlink:href="#e" y1="8.947" y2="38.946999"/><linearGradient id="i" gradientTransform="matrix(.984324 0 0 .957884 .336637 1.415543)" gradientUnits="userSpaceOnUse" x1="24.445999" x2="24.445999" xlink:href="#f" y1=".498" y2="39.446999"/><linearGradient id="j" gradientTransform="matrix(.476329 0 0 .627721 12.7549 9.156933)" gradientUnits="userSpaceOnUse" x1="31.597" x2="24.445999" xlink:href="#e" y1="33.448002" y2="21.066999"/><radialGradient id="k" cx="24.399" cy="29.1" gradientTransform="matrix(2.407878 0 0 1.86105 -34.35094 -20.55775)" gradientUnits="userSpaceOnUse" r="6.027"><stop offset="0" stop-color="#525252"/><stop offset="1"/></radialGradient><linearGradient id="l" gradientTransform="matrix(1.059222 0 0 .808101 -1.234132 4.001391)" gradientUnits="userSpaceOnUse" x1="22.586" x2="22.586" y1="34.150002" y2="11.043"><stop offset="0" stop-color="#fff"/><stop offset=".46" stop-color="#e3e3e3"/><stop offset=".62" stop-color="#dadada" stop-opacity=".671"/><stop offset="1" stop-color="#d1d1d1" stop-opacity=".343"/></linearGradient><linearGradient id="m" gradientUnits="userSpaceOnUse" x1="25.278999" x2="28.284" xlink:href="#b" y1="28.555" y2="38.453999"/><radialGradient id="n" cx="24.483999" cy="29.610001" gradientTransform="matrix(2.777122 -.08126449 .06891211 2.223012 -45.28558 -33.24798)" gradientUnits="userSpaceOnUse" r="4.477"><stop offset="0" stop-color="#fff"/><stop offset=".216" stop-color="#fff"/><stop offset=".5" stop-color="#838383"/><stop offset="1" stop-color="#838383" stop-opacity="0"/></radialGradient><g stroke-width=".020508"><path d="m7.988775 34.435132h30.984437v8.69815h-30.984437z" fill="url(#d)" opacity=".402"/><path d="m38.973213 34.435431v8.697671c3.304542.01637 7.988775-1.948707 7.988773-4.349395 0-2.400689-3.68762-4.348275-7.988773-4.348276z" fill="url(#c)" opacity=".402"/><path d="m7.988775 34.435431v8.697671c-3.304543.016373-7.988775-1.948707-7.988775-4.349395 0-2.400689 3.6876201-4.348275 7.988775-4.348276z" fill="url(#a)" opacity=".402"/></g><rect fill="url(#g)" fill-rule="evenodd" height="39.915001" rx="5.455" stroke="#9b9b9b" stroke-linejoin="bevel" stroke-miterlimit="10" width="40.062" x="3.277034" y=".5"/><rect fill="none" height="37.782001" rx="4.243" stroke="#fff" stroke-linejoin="bevel" stroke-miterlimit="10" width="37.696999" x="4.460034" y="1.534"/><g fill-rule="evenodd" transform="translate(-1.090966 -3.117)"><rect fill="url(#i)" height="32.706001" rx="2.298" stroke="url(#h)" stroke-linejoin="bevel" stroke-miterlimit="10" width="24.257999" x="12.27" y="7.522"/><rect fill="url(#k)" height="20.903" rx="1.591" stroke="url(#j)" stroke-linejoin="bevel" stroke-miterlimit="10" width="12.115" x="18.518999" y="13.866"/><path d="m19.975767 34.034641 2.65165 2.651651 11.136932-.176776s-2.828427-9.369166-2.828427-9.369166-.707107-9.369166-.707107-9.369166l-.707107 15.909904z" fill="url(#m)" opacity=".316"/><g stroke-linejoin="bevel" stroke-miterlimit="10"><rect fill="#8a8a8a" height="4.315" rx="1.061" stroke="#595959" width="8.971" x="20.02" y="29.218"/><rect fill="url(#l)" height="15.812" rx=".884" stroke="url(#n)" width="8.912" x="20.049999" y="15.231"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.2 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="19.701141" cy="2.896938" gradientTransform="matrix(2.046729 0 0 1.55761 -19.51799 3.452086)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="c" cx="22.291636" cy="32.797512" gradientTransform="matrix(.843022 0 0 1.020168 4.499298 1.381992)" gradientUnits="userSpaceOnUse" r="16.9562"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><g fill-rule="evenodd"><path d="m40.481863 36.421127a15.644737 8.3968935 0 1 1 -31.2894745 0 15.644737 8.3968935 0 1 1 31.2894745 0z" fill="url(#b)" opacity=".299465" transform="matrix(1.271186 0 0 1.271186 -8.119376 -15.10179)"/><path d="m8.5541875 15.517348v16.99442h12.9838125v8.545038l19.959835-16.906441-20.078645-17.0252482v8.3975352z" fill="url(#c)" stroke="#3a7304" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="m21.962385 8.2485033v7.8064747h-12.8171699v9.040713c17.7499999 2 16.6335369-7.455288 31.3835369-.955288z" fill="url(#a)" opacity=".508021"/></g><path d="m9.537702 16.561892v14.98444h12.985367v7.395166l17.478014-14.795691-17.493975-14.7804004v7.2013824z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></svg>
|
||||
<svg height="35.245075" width="39.774742" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="19.701141" cy="2.896938" gradientTransform="matrix(2.046729 0 0 1.55761 -19.51799 3.452086)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><radialGradient id="c" cx="22.291636" cy="32.797512" gradientTransform="matrix(.843022 0 0 1.020168 4.499298 1.381992)" gradientUnits="userSpaceOnUse" r="16.9562"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><g fill-rule="evenodd" transform="translate(-3.56586 -6.625175)"><path d="m40.481863 36.421127a15.644737 8.3968937 0 1 1 -31.2894745 0 15.644737 8.3968937 0 1 1 31.2894745 0z" fill="url(#b)" opacity=".299465" transform="matrix(1.271186 0 0 1.271186 -8.119376 -15.10179)"/><path d="m8.5541875 15.517348v16.99442h12.9838125v8.545038l19.959835-16.906441-20.078645-17.0252482v8.3975352z" fill="url(#c)" stroke="#3a7304" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="m21.962385 8.2485033v7.8064747h-12.8171699v9.040713c17.7499999 2 16.6335369-7.455288 31.3835369-.955288z" fill="url(#a)" opacity=".508021"/></g><path d="m5.9718424 9.9367173v14.9844397h12.9853666v7.395166l17.478014-14.795691-17.493975-14.7804001v7.2013824z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="25.456" cy="39.161" gradientTransform="matrix(1 0 0 .315315 0 26.81305)" gradientUnits="userSpaceOnUse" r="19.622"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="12.934" x2="37.862" y1="8.048" y2="42.077"><stop offset="0" stop-color="#c9c9c9"/><stop offset=".25" stop-color="#f8f8f8"/><stop offset=".5" stop-color="#e2e2e2"/><stop offset=".75" stop-color="#b0b0b0"/><stop offset="1" stop-color="#c9c9c9"/></linearGradient><path d="m45.078058 39.161163a19.622213 6.1871843 0 1 1 -39.2444265 0 19.622213 6.1871843 0 1 1 39.2444265 0z" fill="url(#a)" opacity=".409" transform="translate(-.883885 2.474874)"/><path d="m23.25.46875c-.465439.03184628-.917834.10393469-1.375.15625h-.03125l-1.09375 5.96875c-1.782725.4059899-3.459909 1.0949915-4.96875 2.03125l-4.90625-3.53125c-1.3262882 1.0296906-2.5331984 2.2305953-3.59375 3.53125l3.40625 4.96875c-1.0342329 1.580515-1.8119683 3.385224-2.25 5.28125-.000075.008963-.0000609.029688 0 .03125l-5.9375.9375c-.1085533.886633-.15625 1.802939-.15625 2.71875.0000001.7493.0206894 1.488589.09375 2.21875l5.9375 1.0625c.422279 2.061892 1.2244587 3.987512 2.34375 5.6875l-3.53125 4.84375c1.0113261 1.255518 2.1788917 2.398616 3.4375 3.40625l5-3.4375c1.747433 1.114717 3.698083 1.896374 5.8125 2.28125l.9375 5.90625c.666183.060639 1.349349.0625 2.03125.0625.962685-.000001 1.882237-.036483 2.8125-.15625l1.125-6.03125c2.007561-.499601 3.893469-1.36629 5.53125-2.53125l4.8125 3.5c1.248028-1.061797 2.389277-2.282256 3.375-3.59375l-3.5-5.0625c.947853-1.63699 1.604629-3.443141 1.9375-5.375l5.90625-.9375c.051794-.616346.0625-1.214087.0625-1.84375 0-1.094214-.127182-2.167084-.28125-3.21875l-6-1.09375c-.470194-1.736224-1.241676-3.356102-2.21875-4.8125l3.53125-4.84375c-1.094573-1.3386071-2.343178-2.5751812-3.71875-3.625l-5.09375 3.5c-1.463996-.8658374-3.039463-1.5301821-4.75-1.90625l-.9375-5.9375c-.853299-.10037539-1.713621-.15625-2.59375-.15625-.237872.00000001-.482684-.0074846-.71875 0-.115083.00364881-.228966-.0066949-.34375 0-.031088.0018132-.062721-.00212309-.09375 0zm.8125 15.1875c.114166-.005793.228152 0 .34375 0 3.699127 0 6.71875 3.019624 6.71875 6.71875.000001 3.699126-3.019624 6.6875-6.71875 6.6875-3.699125.000001-6.6875-2.988374-6.6875-6.6875.000001-3.583527 2.8046-6.539158 6.34375-6.71875z" fill="url(#b)" stroke="gray"/><g fill="none" stroke="#fff"><path d="m36.239223 23.781593a12.727922 12.727922 0 1 1 -25.455844 0 12.727922 12.727922 0 1 1 25.455844 0z" opacity=".648" stroke-width="1.649" transform="matrix(.606518 0 0 .606518 10.15021 7.936835)"/><path d="m22.557788 1.6501132-.878189 5.7790101c-1.670998.3805456-4.744725 1.5444111-6.159004 2.4219929l-4.672033-3.4871869c-1.2431682.965158-1.3284229 1.0306101-2.3225076 2.2497511l3.3780526 5.0099536c-.969415 1.481461-2.1338039 4.121495-2.5518734 6.008088 0 0-5.9194088.997841-5.9194088.997841-.1017499.831066-.0528497 2.609798.0156321 3.294198l5.6542436 1.018588c.395814 1.932669 1.8770305 5.043588 2.9261735 6.637034l-3.5755759 4.724044c.9479445 1.176832 1.1376642 1.284521 2.3173929 2.229005l4.781168-3.50282c1.637918 1.044855 4.889033 2.315886 6.870935 2.676641l.784687 5.706254c.624432.056839 2.349481.216281 3.221443.10402l.878188-5.940154c1.881743-.468289 5.13316-1.80296 6.668298-2.89491l4.776055 3.450808c1.169811-.995251 1.180292-1.145216 2.104238-2.374516l-3.539198-5.030701c.888449-1.534398 2.037228-4.535223 2.349237-6.346009l5.794642-.961463c.048547-.577719.05091-2.188789-.093502-3.174545l-5.903777-1.018588c-.440727-1.627411-1.953211-4.559982-2.869049-5.925104l3.752352-4.7240431c-1.025972-1.2547143-1.407444-1.4268709-2.696806-2.4108954l-4.942313 3.5391967c-1.372246-.8115728-4.108614-2.0487474-5.711948-2.4012464l-.873075-5.6542436c-.799821-.0940847-3.107395-.0523057-3.564478 0z" opacity=".347"/></g></svg>
|
||||
<svg height="47.857918" width="45.125" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="25.455999" cy="39.160999" gradientTransform="matrix(1 0 0 .315315 -2.727635 29.322619)" gradientUnits="userSpaceOnUse" r="19.622"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="11.09025" x2="36.01825" y1="8.082695" y2="42.111695"><stop offset="0" stop-color="#c9c9c9"/><stop offset=".25" stop-color="#f8f8f8"/><stop offset=".5" stop-color="#e2e2e2"/><stop offset=".75" stop-color="#b0b0b0"/><stop offset="1" stop-color="#c9c9c9"/></linearGradient><path d="m42.350423 41.670732a19.622213 6.1871845 0 1 1 -39.2444265 0 19.622213 6.1871845 0 1 1 39.2444265 0z" fill="url(#a)" opacity=".409"/><path d="m21.40625.50344454c-.465439.0318463-.917834.10393469-1.375.15625h-.03125l-1.09375 5.96874996c-1.782725.4059899-3.459909 1.0949915-4.96875 2.03125l-4.90625-3.53125c-1.3262882 1.0296906-2.5331984 2.2305953-3.59375 3.53125l3.40625 4.9687505c-1.0342329 1.580515-1.8119683 3.385224-2.25 5.28125-.000075.009-.0000609.02969 0 .03125l-5.9375.9375c-.1085533.886633-.15625 1.802939-.15625 2.71875.0000001.7493.020689 1.488589.09375 2.21875l5.9375 1.0625c.422279 2.061892 1.2244587 3.987512 2.34375 5.6875l-3.53125 4.84375c1.0113261 1.255518 2.1788917 2.398616 3.4375 3.40625l5-3.4375c1.747433 1.114717 3.698083 1.896374 5.8125 2.28125l.9375 5.90625c.666183.06064 1.349349.0625 2.03125.0625.962685-.000001 1.882237-.03648 2.8125-.15625l1.125-6.03125c2.007561-.499601 3.893469-1.36629 5.53125-2.53125l4.8125 3.5c1.248028-1.061797 2.389277-2.282256 3.375-3.59375l-3.5-5.0625c.947853-1.63699 1.604629-3.443141 1.9375-5.375l5.90625-.9375c.05179-.616346.0625-1.214087.0625-1.84375 0-1.094214-.127182-2.167084-.28125-3.21875l-6-1.09375c-.470194-1.736224-1.241676-3.356102-2.21875-4.8125l3.53125-4.8437505c-1.094573-1.3386071-2.343178-2.5751812-3.71875-3.625l-5.09375 3.5c-1.463996-.8658374-3.039463-1.5301821-4.75-1.90625l-.9375-5.93749996c-.853299-.10037539-1.713621-.15625-2.59375-.15625-.237872.00000001-.482684-.007485-.71875 0-.115083.003649-.228966-.006695-.34375 0-.03109.001813-.06272-.002123-.09375 0zm.8125 15.18750046c.114166-.0058.228152 0 .34375 0 3.699127 0 6.71875 3.019624 6.71875 6.71875.000001 3.699126-3.019624 6.6875-6.71875 6.6875-3.699125.000001-6.6875-2.988374-6.6875-6.6875.000001-3.583527 2.8046-6.539158 6.34375-6.71875z" fill="url(#b)" stroke="#808080"/><g fill="none" stroke="#fff" transform="translate(-1.84375 .034695)"><path d="m36.239223 23.781593a12.727922 12.727922 0 1 1 -25.455844 0 12.727922 12.727922 0 1 1 25.455844 0z" opacity=".648" stroke-width="1.649" transform="matrix(.606518 0 0 .606518 10.15021 7.936835)"/><path d="m22.557788 1.6501132-.878189 5.7790101c-1.670998.3805456-4.744725 1.5444111-6.159004 2.4219929l-4.672033-3.4871869c-1.2431682.965158-1.3284229 1.0306101-2.3225076 2.2497511l3.3780526 5.0099536c-.969415 1.481461-2.1338039 4.121495-2.5518734 6.008088 0 0-5.9194088.997841-5.9194088.997841-.1017499.831066-.05285 2.609798.015632 3.294198l5.6542436 1.018588c.395814 1.932669 1.8770306 5.043588 2.9261736 6.637034l-3.575576 4.724044c.9479445 1.176832 1.1376642 1.284521 2.317393 2.229005l4.781168-3.50282c1.637918 1.044855 4.889033 2.315886 6.870935 2.676641l.784687 5.706254c.624432.05684 2.349481.216281 3.221443.10402l.878188-5.940154c1.881743-.468289 5.13316-1.80296 6.668298-2.89491l4.776055 3.450808c1.169811-.995251 1.180292-1.145216 2.104238-2.374516l-3.539198-5.030701c.888449-1.534398 2.037228-4.535223 2.349237-6.346009l5.794642-.961463c.04855-.577719.05091-2.188789-.0935-3.174545l-5.903779-1.018588c-.440727-1.627411-1.953211-4.559982-2.869049-5.925104l3.752352-4.7240431c-1.025972-1.2547143-1.407444-1.4268709-2.696806-2.4108954l-4.942313 3.5391967c-1.372246-.8115728-4.108614-2.0487474-5.711948-2.4012464l-.873075-5.6542436c-.799821-.094085-3.107395-.052306-3.564478 0z" opacity=".347"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="605.71429" cy="486.64789" gradientTransform="matrix(-2.774389 0 0 1.969706 112.7623 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><radialGradient id="c" cx="605.71429" cy="486.64789" gradientTransform="matrix(2.774389 0 0 1.969706 -1891.633 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="d" gradientTransform="matrix(2.774389 0 0 1.969706 -1892.179 -872.8854)" gradientUnits="userSpaceOnUse" x1="302.85715" x2="302.85715" y1="366.64789" y2="609.50507"><stop offset="0" stop-opacity="0"/><stop offset=".5"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e" gradientTransform="matrix(.976612 0 0 1.139789 .564215 -3.271158)" gradientUnits="userSpaceOnUse" x1="40.884724" x2="16.879831" y1="71.869133" y2="-.389314"><stop offset="0" stop-color="#1e2d69"/><stop offset="1" stop-color="#78a7e0"/></linearGradient><linearGradient id="f" gradientTransform="matrix(.985432 0 0 1.148179 .64107 -2.933883)" gradientUnits="userSpaceOnUse" x1="13.783585" x2="33.074715" y1="-.996729" y2="55.701546"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="g" gradientTransform="matrix(1.067698 0 0 1.121532 -1.368937 -5.57446)" gradientUnits="userSpaceOnUse" x1="20.125" x2="28.5625" y1="21.84375" y2="42.46875"><stop offset="0" stop-color="#858585"/><stop offset=".5" stop-color="#cbcbcb"/><stop offset="1" stop-color="#6b6b6b"/></linearGradient><g transform="matrix(.02415802 0 0 .02086758 45.237 41.6536)"><path d="m-1559.2523-150.69685h1339.6335v478.35718h-1339.6335z" fill="url(#d)" opacity=".402062"/><path d="m-219.61876-150.68038v478.33079c142.874166.90045 345.40022-107.16966 345.40014-239.196175 0-132.026537-159.436816-239.134595-345.40014-239.134615z" fill="url(#c)" opacity=".402062"/><path d="m-1559.2523-150.68038v478.33079c-142.8742.90045-345.4002-107.16966-345.4002-239.196175 0-132.026537 159.4368-239.134595 345.4002-239.134615z" fill="url(#a)" opacity=".402062"/></g><path d="m4.5577604 3.5675797h38.8903026c.589294 0 1.063708.4744141 1.063708 1.0637086v37.7652107c0 .589294-.474414 1.063708-1.063708 1.063708h-36.8903026s-3.0637085-3.063708-3.0637085-3.063708v-35.7652107c0-.5892945.474414-1.0637086 1.0637085-1.0637086z" fill="url(#e)" stroke="#25375f" stroke-linecap="round" stroke-linejoin="round"/><path d="m9 4h30v23h-30z" fill="#fff"/><rect fill="#d31c00" height="4" rx=".126208" width="30" x="9" y="4"/><rect height="2" opacity=".738636" rx=".126208" width="2" x="6" y="6"/><g stroke="#000"><path d="m11 12.5h26" opacity=".130682"/><path d="m11 17.5h26" opacity=".130682"/><path d="m11 22.5h26" opacity=".130682"/></g><path d="m4.6189226 4.5276647h38.7684814c.069919 0 .126208.0562886.126208.1262077v37.6482386c0 .069919-.056289.126208-.126208.126208h-36.4591222s-2.4355669-2.391373-2.4355669-2.391373v-35.3830736c0-.0699191.0562886-.1262077.1262077-.1262077z" fill="none" opacity=".596591" stroke="url(#f)" stroke-linecap="round"/><g stroke="#525252"><path d="m14.113967 28.562183h19.749824c.887971 0 1.602836.75091 1.602836 1.683653v13.201551h-22.955496v-13.201551c0-.932743.714865-1.683653 1.602836-1.683653z" fill="url(#g)" stroke-width=".999999"/><rect fill="#4967a2" height="10.06597" rx=".751207" ry=".751208" width="5.029753" x="16.464279" y="30.4566"/></g></svg>
|
||||
<svg height="45.4235" width="49.051262" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="605.71429" cy="486.64789" gradientTransform="matrix(-2.774389 0 0 1.969706 112.7623 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><radialGradient id="c" cx="605.71429" cy="486.64789" gradientTransform="matrix(2.774389 0 0 1.969706 -1891.633 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="d" gradientTransform="matrix(2.774389 0 0 1.969706 -1892.179 -872.8854)" gradientUnits="userSpaceOnUse" x1="302.85715" x2="302.85715" y1="366.64789" y2="609.50507"><stop offset="0" stop-opacity="0"/><stop offset=".5"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e" gradientTransform="matrix(.976612 0 0 1.139789 1.339848 -6.338738)" gradientUnits="userSpaceOnUse" x1="40.884724" x2="16.879831" y1="71.869133" y2="-.389314"><stop offset="0" stop-color="#1e2d69"/><stop offset="1" stop-color="#78a7e0"/></linearGradient><linearGradient id="f" gradientTransform="matrix(.985432 0 0 1.148179 1.416703 -6.001463)" gradientUnits="userSpaceOnUse" x1="13.783585" x2="33.074715" y1="-.996729" y2="55.701546"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="g" gradientTransform="matrix(1.067698 0 0 1.121532 -1.368937 -5.57446)" gradientUnits="userSpaceOnUse" x1="20.125" x2="28.5625" y1="21.84375" y2="42.46875"><stop offset="0" stop-color="#858585"/><stop offset=".5" stop-color="#cbcbcb"/><stop offset="1" stop-color="#6b6b6b"/></linearGradient><g transform="matrix(.02415802 0 0 .02086758 46.012633 38.58602)"><path d="m-1559.2523-150.69685h1339.6335v478.35718h-1339.6335z" fill="url(#d)" opacity=".402062"/><path d="m-219.61876-150.68038v478.33079c142.874166.90045 345.40022-107.16966 345.40014-239.196175 0-132.026537-159.436816-239.134595-345.40014-239.134615z" fill="url(#c)" opacity=".402062"/><path d="m-1559.2523-150.68038v478.33079c-142.8742.90045-345.4002-107.16966-345.4002-239.196175 0-132.026537 159.4368-239.134595 345.4002-239.134615z" fill="url(#a)" opacity=".402062"/></g><path d="m5.3333936.5h38.8903024c.589294 0 1.063708.4744141 1.063708 1.0637086v37.7652104c0 .589294-.474414 1.063708-1.063708 1.063708h-36.8903024s-3.0637085-3.063708-3.0637085-3.063708v-35.7652104c0-.5892945.474414-1.0637086 1.0637085-1.0637086z" fill="url(#e)" stroke="#25375f" stroke-linecap="round" stroke-linejoin="round"/><path d="m9.7756332.9324203h29.9999998v22.9999997h-29.9999998z" fill="#fff"/><rect fill="#d31c00" height="4" rx=".126208" width="30" x="9.775633" y=".93242"/><rect height="2" opacity=".738636" rx=".126208" width="2" x="6.775633" y="2.93242"/><g stroke="#000" transform="translate(.775633 -3.06758)"><path d="m11 12.5h26" opacity=".130682"/><path d="m11 17.5h26" opacity=".130682"/><path d="m11 22.5h26" opacity=".130682"/></g><path d="m5.3945558 1.460085h38.7684812c.06992 0 .126208.056289.126208.1262077v37.6482383c0 .06992-.05629.126208-.126208.126208h-36.459122s-2.4355669-2.391373-2.4355669-2.391373v-35.3830733c0-.069919.056289-.1262077.1262077-.1262077z" fill="none" opacity=".596591" stroke="url(#f)" stroke-linecap="round"/><g stroke="#525252" transform="translate(.775633 -3.06758)"><path d="m14.113967 28.562183h19.749824c.887971 0 1.602836.75091 1.602836 1.683653v13.201551h-22.955496v-13.201551c0-.932743.714865-1.683653 1.602836-1.683653z" fill="url(#g)" stroke-width=".999999"/><rect fill="#4967a2" height="10.06597" rx=".751207" ry=".751208" width="5.029753" x="16.464279" y="30.4566"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(3.000198 0 0 1 -67.006 -.09426)" gradientUnits="userSpaceOnUse" x1="15.089521" x2="14" y1="15.291994" y2="52.510574"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b" gradientTransform="matrix(2.498884 0 0 1.004384 -414.0618 -71.4625)" gradientUnits="userSpaceOnUse" x1="169" x2="169" y1="110.33805" y2="93.204849"><stop offset="0" stop-color="#babdb6"/><stop offset="1" stop-color="#555753"/></linearGradient><radialGradient id="c" cx="169.77171" cy="100.20107" gradientTransform="matrix(.00000891 -1.07205 4.98026 -.00000125 -490.7792 212.6949)" gradientUnits="userSpaceOnUse" r="11"><stop offset="0" stop-color="#f7f7f7"/><stop offset="1" stop-color="#ccd0c7"/></radialGradient><linearGradient id="d" gradientTransform="matrix(2.624525 0 0 1.054917 -436.1019 -76.31138)" gradientUnits="userSpaceOnUse" x1="174.83363" x2="174.74524" y1="84.263489" y2="105.49083"><stop offset="0"/><stop offset="1" stop-color="#fff" stop-opacity=".484536"/></linearGradient><path d="m14.00382 12.829103v22.153256h20.996184v-22.153256z" style="opacity:.15;fill:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke:url(#d)"/><path d="m14.5 13.40575v21h20v-21z" fill="url(#c)" fill-rule="evenodd"/><path d="m14.496737 13.407946v21.092064h19.991071v-21.092064z" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round"/><path d="m15.499412 14.40575v19h18.001183v-19z" fill="none" stroke="url(#a)" stroke-linecap="square"/><path d="m16 14.942758v10.557242l17-2.79033v-7.8553z" display="block" fill="#f7f7f7" opacity=".5"/></svg>
|
||||
<svg height="24.153255" width="22.996183" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(3.000198 0 0 1 -80.00982 -11.923363)" gradientUnits="userSpaceOnUse" x1="15.089521" x2="14" y1="15.291994" y2="52.510574"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="b" gradientTransform="matrix(2.498884 0 0 1.004384 -427.06562 -83.291603)" gradientUnits="userSpaceOnUse" x1="169" x2="169" y1="110.33805" y2="93.204849"><stop offset="0" stop-color="#babdb6"/><stop offset="1" stop-color="#555753"/></linearGradient><radialGradient id="c" cx="169.77171" cy="100.20107" gradientTransform="matrix(.00000891 -1.07205 4.98026 -.00000125 -503.78302 200.8658)" gradientUnits="userSpaceOnUse" r="11"><stop offset="0" stop-color="#f7f7f7"/><stop offset="1" stop-color="#ccd0c7"/></radialGradient><linearGradient id="d" gradientTransform="matrix(2.624525 0 0 1.054917 -449.10572 -88.140483)" gradientUnits="userSpaceOnUse" x1="174.83363" x2="174.74524" y1="84.263489" y2="105.49083"><stop offset="0"/><stop offset="1" stop-color="#fff" stop-opacity=".484536"/></linearGradient><path d="m1 1v22.153256h20.996184v-22.153256z" style="opacity:.15;fill:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke:url(#d)"/><path d="m1.49618 1.576647v21h20v-21z" fill="url(#c)" fill-rule="evenodd"/><path d="m1.492917 1.578843v21.092064h19.991071v-21.092064z" fill="none" stroke="url(#b)" stroke-linecap="square" stroke-linejoin="round"/><path d="m2.495592 2.576647v19h18.001183v-19z" fill="none" stroke="url(#a)" stroke-linecap="square"/><path d="m2.99618 3.113655v10.557242l17-2.79033v-7.8553z" display="block" fill="#f7f7f7" opacity=".5"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="605.71429" cy="486.64789" gradientTransform="matrix(-2.774389 0 0 1.969706 112.7623 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><radialGradient id="c" cx="605.71429" cy="486.64789" gradientTransform="matrix(2.774389 0 0 1.969706 -1891.633 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="d" gradientTransform="matrix(2.774389 0 0 1.969706 -1892.179 -872.8854)" gradientUnits="userSpaceOnUse" x1="302.85715" x2="302.85715" y1="366.64789" y2="609.50507"><stop offset="0" stop-opacity="0"/><stop offset=".5"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e" gradientTransform="matrix(1.342704 0 0 1.235378 -8.219611 -6.577189)" gradientUnits="userSpaceOnUse" x1="20.794008" x2="35.596001" y1="18.378813" y2="39.60046"><stop offset="0" stop-color="#f8f8f7"/><stop offset=".59928656" stop-color="#e8e8e8"/><stop offset="1" stop-color="#e2e2de"/></linearGradient><g transform="matrix(.02330573 0 0 .01227058 44.47891 44.41691)"><path d="m-1559.2523-150.69685h1339.6335v478.35718h-1339.6335z" fill="url(#d)" opacity=".402062"/><path d="m-219.61876-150.68038v478.33079c142.874166.90045 345.40022-107.16966 345.40014-239.196175 0-132.026537-159.436816-239.134595-345.40014-239.134615z" fill="url(#c)" opacity=".402062"/><path d="m-1559.2523-150.68038v478.33079c-142.8742.90045-345.4002-107.16966-345.4002-239.196175 0-132.026537 159.4368-239.134595 345.4002-239.134615z" fill="url(#a)" opacity=".402062"/></g><g fill-rule="evenodd"><rect fill="url(#e)" height="45.003101" rx=".566508" stroke="#888a85" width="38.996792" x="4.501602" y="1.496899"/><g fill="#999"><path d="m9 10h27v2h-27z"/><path d="m9 16h25v2h-25z"/><path d="m9 22h22.971531v2h-22.971531z"/><path d="m9 28h27v2h-27z"/><path d="m9 34h17v2h-17z"/></g></g><path d="m5.499713 2.499718h37.025566v43.022316h-37.025566z" fill="none" stroke="#fff"/></svg>
|
||||
<svg height="47.440594" width="47.320744" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="605.71429" cy="486.64789" gradientTransform="matrix(-2.774389 0 0 1.969706 112.7623 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="b"><stop offset="0"/><stop offset="1" stop-opacity="0"/></linearGradient><radialGradient id="c" cx="605.71429" cy="486.64789" gradientTransform="matrix(2.774389 0 0 1.969706 -1891.633 -872.8854)" gradientUnits="userSpaceOnUse" r="117.14286" xlink:href="#b"/><linearGradient id="d" gradientTransform="matrix(2.774389 0 0 1.969706 -1892.179 -872.8854)" gradientUnits="userSpaceOnUse" x1="302.85715" x2="302.85715" y1="366.64789" y2="609.50507"><stop offset="0" stop-opacity="0"/><stop offset=".5"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="e" gradientTransform="matrix(1.342704 0 0 1.235378 -8.219611 -6.577189)" gradientUnits="userSpaceOnUse" x1="20.794008" x2="35.596001" y1="18.378813" y2="39.60046"><stop offset="0" stop-color="#f8f8f7"/><stop offset=".59928656" stop-color="#e8e8e8"/><stop offset="1" stop-color="#e2e2de"/></linearGradient><g transform="matrix(.02330573 0 0 .01227058 44.389317 43.420011)"><path d="m-1559.2523-150.69685h1339.6335v478.35718h-1339.6335z" fill="url(#d)" opacity=".402062"/><path d="m-219.61876-150.68038v478.33079c142.874166.90045 345.40022-107.16966 345.40014-239.196175 0-132.026537-159.436816-239.134595-345.40014-239.134615z" fill="url(#c)" opacity=".402062"/><path d="m-1559.2523-150.68038v478.33079c-142.8742.90045-345.4002-107.16966-345.4002-239.196175 0-132.026537 159.4368-239.134595 345.4002-239.134615z" fill="url(#a)" opacity=".402062"/></g><g fill-rule="evenodd" transform="translate(-.089593 -.996899)"><rect fill="url(#e)" height="45.003101" rx=".566508" stroke="#888a85" width="38.996792" x="4.501602" y="1.496899"/><g fill="#999"><path d="m9 10h27v2h-27z"/><path d="m9 16h25v2h-25z"/><path d="m9 22h22.971531v2h-22.971531z"/><path d="m9 28h27v2h-27z"/><path d="m9 34h17v2h-17z"/></g></g><path d="m5.4101199 1.502819h37.0255661v43.022316h-37.0255661z" fill="none" stroke="#fff"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -1 +1 @@
|
||||
<svg height="48" width="48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="24.53788" cy=".400108" gradientTransform="matrix(0 -2.046729 1.55761 0 2.767009 66.93275)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="11.319205" cy="22.454971" gradientTransform="matrix(0 -.843022 1.020168 0 .606436 42.58614)" gradientUnits="userSpaceOnUse" r="16.956199"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><radialGradient id="c" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><g fill-rule="evenodd"><path d="m40.481863 36.421127a15.644737 8.3968935 0 1 1 -31.2894745 0 15.644737 8.3968935 0 1 1 31.2894745 0z" fill="url(#c)" opacity=".299465" transform="matrix(1.214466 0 0 .595458 -6.163846 16.31275)"/><path d="m14.491792 38.5h17.977685v-12.952563h8.030523l-17.125191-20.0482235-16.8462505 19.9902575 7.9685375.066291z" fill="url(#b)" stroke="#3a7304" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="m7.5855237 25.03253h7.4102973l.066601 6.561809c5.655612-11.000461 15.993095-8.844411 16.594346-15.627665 0 0-8.28983-9.5447048-8.28983-9.5447048z" fill="url(#a)" opacity=".508021"/></g><path d="m15.602735 37.5h15.899843v-12.99295h6.808998l-14.95037-17.4369604-14.7065262 17.4803804 6.8203692-.022097z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></svg>
|
||||
<svg height="38.000759" width="38.000004" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="a" cx="24.53788" cy=".400108" gradientTransform="matrix(0 -2.046729 1.55761 0 2.767009 66.93275)" gradientUnits="userSpaceOnUse" r="17.171415"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="11.319205" cy="22.454971" gradientTransform="matrix(0 -.843022 1.020168 0 .606436 42.58614)" gradientUnits="userSpaceOnUse" r="16.9562"><stop offset="0" stop-color="#73d216"/><stop offset="1" stop-color="#4e9a06"/></radialGradient><radialGradient id="c" cx="24.837126" cy="36.421127" gradientTransform="matrix(1 0 0 .536723 0 16.87306)" gradientUnits="userSpaceOnUse" r="15.644737"><stop offset="0"/><stop offset="1" stop-opacity="0"/></radialGradient><g fill-rule="evenodd" transform="translate(-4.999997 -4.999241)"><path d="m40.481863 36.421127a15.644737 8.3968937 0 1 1 -31.2894745 0 15.644737 8.3968937 0 1 1 31.2894745 0z" fill="url(#c)" opacity=".299465" transform="matrix(1.214466 0 0 .595458 -6.163846 16.31275)"/><path d="m14.491792 38.5h17.977685v-12.952563h8.030523l-17.125191-20.0482235-16.8462505 19.9902575 7.9685375.06629z" fill="url(#b)" stroke="#3a7304" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"/><path d="m7.5855237 25.03253h7.4102973l.0666 6.561809c5.655612-11.000461 15.993095-8.844411 16.594346-15.627665 0 0-8.28983-9.5447048-8.28983-9.5447048z" fill="url(#a)" opacity=".508021"/></g><path d="m10.602738 32.500759h15.899843v-12.99295h6.808998l-14.95037-17.4369602-14.7065265 17.4803802 6.8203695-.0221z" fill="none" opacity=".481283" stroke="#fff" stroke-miterlimit="10"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
501
qtBuildSystem/Mu/images/voiceMemo.svg
Normal file
|
After Width: | Height: | Size: 42 KiB |
@@ -14,7 +14,6 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QGraphicsScene>
|
||||
#include <QCoreApplication>
|
||||
#include <QPixmap>
|
||||
#include <QAudioOutput>
|
||||
#include <QAudioFormat>
|
||||
|
||||
@@ -29,8 +28,6 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow){
|
||||
QAudioFormat format;
|
||||
QString resourceDirPath;
|
||||
bool hideOnscreenKeys;
|
||||
|
||||
//audio output
|
||||
format.setSampleRate(AUDIO_SAMPLE_RATE);
|
||||
@@ -53,23 +50,34 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
audioDevice = new QAudioOutput(format, this);
|
||||
audioOut = audioDevice->start();
|
||||
|
||||
//resource directory
|
||||
resourceDirPath = settings->value("resourceDirectory", "").toString();
|
||||
|
||||
//get default path if path not set
|
||||
if(resourceDirPath == ""){
|
||||
//set variables to there default if its the first boot
|
||||
if(settings->value("firstBootCompleted", "").toString() == ""){
|
||||
//resource dir
|
||||
#if defined(Q_OS_ANDROID)
|
||||
resourceDirPath = "/sdcard/Mu";
|
||||
settings->setValue("resourceDirectory", "/sdcard/Mu");
|
||||
#elif defined(Q_OS_IOS)
|
||||
resourceDirPath = "/var/mobile/Media/Mu";
|
||||
settings->setValue("resourceDirectory", "/var/mobile/Media/Mu");
|
||||
#else
|
||||
resourceDirPath = QDir::homePath() + "/Mu";
|
||||
settings->setValue("resourceDirectory", QDir::homePath() + "/Mu");
|
||||
#endif
|
||||
settings->setValue("resourceDirectory", resourceDirPath);
|
||||
}
|
||||
createHomeDirectoryTree(settings->value("resourceDirectory", "").toString());
|
||||
|
||||
//create directory tree, in case someone deleted it since the emu was last run or it was never created
|
||||
createHomeDirectoryTree(resourceDirPath);
|
||||
//onscreen keys
|
||||
#if defined(Q_OS_ANDROID) && defined(Q_OS_IOS)
|
||||
settings->setValue("hideOnscreenKeys", false);
|
||||
#else
|
||||
//not a mobile device disable the on screen buttons
|
||||
settings->setValue("hideOnscreenKeys", true);
|
||||
#endif
|
||||
|
||||
//skip boot screen, most users dont want to wait 5 seconds on boot
|
||||
settings->setValue("fastBoot", true);
|
||||
|
||||
settings->setValue("palmOsVersion", 4);
|
||||
|
||||
//dont run this function again unless the config is deleted
|
||||
settings->setValue("firstBootCompleted", true);
|
||||
}
|
||||
|
||||
//keyboard
|
||||
for(uint8_t index = 0; index < EmuWrapper::BUTTON_TOTAL_COUNT; index++)
|
||||
@@ -78,17 +86,6 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
//GUI
|
||||
ui->setupUi(this);
|
||||
|
||||
//check if onscreen keys should be hidden
|
||||
if(settings->value("hideOnscreenKeys", "").toString() == ""){
|
||||
#if defined(Q_OS_ANDROID) && defined(Q_OS_IOS)
|
||||
settings->setValue("hideOnscreenKeys", false);
|
||||
#else
|
||||
//not a mobile device disable the on screen buttons
|
||||
settings->setValue("hideOnscreenKeys", true);
|
||||
#endif
|
||||
}
|
||||
hideOnscreenKeys = settings->value("hideOnscreenKeys", false).toBool();
|
||||
|
||||
//this makes the display window and button icons resize properly
|
||||
ui->centralWidget->installEventFilter(this);
|
||||
ui->centralWidget->setObjectName("centralWidget");
|
||||
@@ -103,6 +100,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
ui->addressBook->installEventFilter(this);
|
||||
ui->todo->installEventFilter(this);
|
||||
ui->notes->installEventFilter(this);
|
||||
ui->voiceMemo->installEventFilter(this);
|
||||
|
||||
ui->power->installEventFilter(this);
|
||||
|
||||
@@ -113,20 +111,9 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
ui->settings->installEventFilter(this);
|
||||
ui->install->installEventFilter(this);
|
||||
ui->debugger->installEventFilter(this);
|
||||
ui->bootApp->installEventFilter(this);
|
||||
|
||||
//hide onscreen keys if needed
|
||||
ui->up->setHidden(hideOnscreenKeys);
|
||||
ui->down->setHidden(hideOnscreenKeys);
|
||||
ui->left->setHidden(hideOnscreenKeys);
|
||||
ui->right->setHidden(hideOnscreenKeys);
|
||||
ui->center->setHidden(hideOnscreenKeys);
|
||||
|
||||
ui->calendar->setHidden(hideOnscreenKeys);
|
||||
ui->addressBook->setHidden(hideOnscreenKeys);
|
||||
ui->todo->setHidden(hideOnscreenKeys);
|
||||
ui->notes->setHidden(hideOnscreenKeys);
|
||||
|
||||
ui->power->setHidden(hideOnscreenKeys);
|
||||
redraw();
|
||||
|
||||
#if !defined(EMU_DEBUG) || defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
|
||||
//doesnt support debug tools
|
||||
@@ -167,33 +154,10 @@ void MainWindow::createHomeDirectoryTree(const QString& path){
|
||||
|
||||
//creates directorys if not present, does nothing if they exist already
|
||||
homeDir.mkpath(".");
|
||||
homeDir.mkpath("./saveStates");
|
||||
homeDir.mkpath("./screenshots");
|
||||
homeDir.mkpath("./debugDumps");
|
||||
}
|
||||
|
||||
uint32_t MainWindow::getEmuFeatureList(){
|
||||
uint32_t features = FEATURE_ACCURATE;
|
||||
|
||||
features |= settings->value("feature128mbRam", false).toBool() ? FEATURE_RAM_HUGE : 0;
|
||||
features |= settings->value("featureFastCpu", false).toBool() ? FEATURE_FAST_CPU : 0;
|
||||
features |= settings->value("featureHybridCpu", false).toBool() ? FEATURE_HYBRID_CPU : 0;
|
||||
features |= settings->value("featureCustomFb", false).toBool() ? FEATURE_CUSTOM_FB : 0;
|
||||
features |= settings->value("featureSyncedRtc", false).toBool() ? FEATURE_SYNCED_RTC : 0;
|
||||
features |= settings->value("featureHleApis", false).toBool() ? FEATURE_HLE_APIS : 0;
|
||||
features |= settings->value("featureEmuHonest", false).toBool() ? FEATURE_EMU_HONEST : 0;
|
||||
features |= settings->value("featureExtraKeys", false).toBool() ? FEATURE_EXT_KEYS : 0;
|
||||
features |= settings->value("featureDurable", false).toBool() ? FEATURE_DURABLE : 0;
|
||||
features |= settings->value("featureSoundStreams", false).toBool() ? FEATURE_SND_STRMS : 0;
|
||||
|
||||
//lazy debug overrides
|
||||
//features = FEATURE_EXT_KEYS | FEATURE_EMU_HONEST | FEATURE_FAST_CPU | FEATURE_HYBRID_CPU | FEATURE_CUSTOM_FB | FEATURE_DEBUG | FEATURE_SND_STRMS;
|
||||
//features = FEATURE_FAST_CPU | FEATURE_HYBRID_CPU | FEATURE_CUSTOM_FB | FEATURE_DEBUG;
|
||||
//features = FEATURE_FAST_CPU | FEATURE_HYBRID_CPU | FEATURE_DEBUG;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
void MainWindow::popupErrorDialog(const QString& error){
|
||||
QMessageBox::critical(this, "Mu", error, QMessageBox::Ok);
|
||||
}
|
||||
@@ -217,6 +181,7 @@ void MainWindow::redraw(){
|
||||
ui->addressBook->setHidden(hideOnscreenKeys);
|
||||
ui->todo->setHidden(hideOnscreenKeys);
|
||||
ui->notes->setHidden(hideOnscreenKeys);
|
||||
ui->voiceMemo->setHidden(hideOnscreenKeys);
|
||||
|
||||
ui->power->setHidden(hideOnscreenKeys);
|
||||
|
||||
@@ -240,16 +205,14 @@ bool MainWindow::eventFilter(QObject* object, QEvent* event){
|
||||
ui->displayContainer->setFixedHeight(ui->centralWidget->height() * (hideOnscreenKeys ? 0.80 : 0.60));
|
||||
|
||||
smallestRatio = qMin(ui->displayContainer->size().width() * 0.98 / 3.0 , ui->displayContainer->size().height() * 0.98 / 4.0);
|
||||
//the 0.98 above allows the display to shrink, without it the displayContainer couldent shrink because of the fixed size of the display
|
||||
//the 0.98 above allows the display to shrink, without it the displayContainer couldnt shrink because of the fixed size of the display
|
||||
|
||||
//set new size
|
||||
ui->display->setFixedSize(smallestRatio * 3.0, smallestRatio * 4.0);
|
||||
|
||||
//scale framebuffer to new size and refresh
|
||||
if(emu.isInited()){
|
||||
ui->display->setPixmap(emu.getFramebuffer().scaled(QSize(ui->display->size().width(), ui->display->size().height()), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
ui->display->update();
|
||||
}
|
||||
if(emu.isInited())
|
||||
ui->display->repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,8 +222,8 @@ bool MainWindow::eventFilter(QObject* object, QEvent* event){
|
||||
//display
|
||||
void MainWindow::updateDisplay(){
|
||||
if(emu.newFrameReady()){
|
||||
//video, this is doing bilinear filitering in software, this is why the Qt port is broken on Android, move this to a new thread if possible
|
||||
ui->display->setPixmap(emu.getFramebuffer().scaled(ui->display->size().width(), ui->display->size().height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
//video
|
||||
ui->display->repaint();
|
||||
|
||||
//audio
|
||||
audioOut->write((const char*)emu.getAudioSamples(), AUDIO_SAMPLES_PER_FRAME * 2/*channels*/ * sizeof(int16_t));
|
||||
@@ -270,10 +233,6 @@ void MainWindow::updateDisplay(){
|
||||
|
||||
//allow next frame to start
|
||||
emu.frameHandled();
|
||||
|
||||
//update GUI
|
||||
ui->display->repaint();
|
||||
ui->powerButtonLed->repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,6 +269,14 @@ void MainWindow::on_todo_released(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_TODO, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_voiceMemo_pressed(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_VOICE_MEMO, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_voiceMemo_released(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_VOICE_MEMO, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_notes_pressed(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_NOTES, true);
|
||||
}
|
||||
@@ -350,35 +317,48 @@ void MainWindow::on_right_released(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_RIGHT, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_center_pressed(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_CENTER, true);
|
||||
}
|
||||
|
||||
void MainWindow::on_center_released(){
|
||||
emu.setKeyValue(EmuWrapper::BUTTON_CENTER, false);
|
||||
}
|
||||
|
||||
//emu control
|
||||
void MainWindow::on_ctrlBtn_clicked(){
|
||||
if(!emu.isInited()){
|
||||
uint32_t enabledFeatures = getEmuFeatureList();
|
||||
QString sysDir = settings->value("resourceDirectory", "").toString();
|
||||
uint32_t error = emu.init(sysDir + "/palmos41-en-m515.rom", QFile(sysDir + "/bootloader-en-m515.rom").exists() ? sysDir + "/bootloader-en-m515.rom" : "", sysDir + "/userdata-en-m515.ram", sysDir + "/sd-en-m515.img", enabledFeatures);
|
||||
uint32_t error = emu.init(sysDir, settings->value("palmOsVersion", false).toInt(), settings->value("featureSyncedRtc", false).toBool(), settings->value("featureDurable", false).toBool(), settings->value("fastBoot", false).toBool());
|
||||
|
||||
if(error == EMU_ERROR_NONE){
|
||||
emu.setCpuSpeed(settings->value("cpuSpeed", 1.00).toDouble());
|
||||
|
||||
ui->up->setEnabled(true);
|
||||
ui->down->setEnabled(true);
|
||||
|
||||
if(settings->value("palmOsVersion", false).toInt() > 4){
|
||||
ui->left->setEnabled(true);
|
||||
ui->right->setEnabled(true);
|
||||
ui->center->setEnabled(true);
|
||||
}
|
||||
|
||||
ui->calendar->setEnabled(true);
|
||||
ui->addressBook->setEnabled(true);
|
||||
ui->todo->setEnabled(true);
|
||||
ui->notes->setEnabled(true);
|
||||
|
||||
ui->power->setEnabled(true);
|
||||
if(settings->value("palmOsVersion", false).toInt() > 4)
|
||||
ui->voiceMemo->setEnabled(true);
|
||||
|
||||
if(enabledFeatures & FEATURE_EXT_KEYS){
|
||||
ui->left->setEnabled(true);
|
||||
ui->right->setEnabled(true);
|
||||
ui->center->setEnabled(true);
|
||||
}
|
||||
ui->power->setEnabled(true);
|
||||
|
||||
ui->screenshot->setEnabled(true);
|
||||
ui->install->setEnabled(true);
|
||||
ui->stateManager->setEnabled(true);
|
||||
ui->debugger->setEnabled(true);
|
||||
ui->reset->setEnabled(true);
|
||||
ui->bootApp->setEnabled(true);
|
||||
|
||||
ui->ctrlBtn->setIcon(QIcon(":/buttons/images/pause.svg"));
|
||||
}
|
||||
@@ -394,20 +374,29 @@ void MainWindow::on_ctrlBtn_clicked(){
|
||||
emu.resume();
|
||||
ui->ctrlBtn->setIcon(QIcon(":/buttons/images/pause.svg"));
|
||||
}
|
||||
|
||||
ui->ctrlBtn->repaint();
|
||||
}
|
||||
|
||||
void MainWindow::on_install_clicked(){
|
||||
if(emu.isInited()){
|
||||
QString app = QFileDialog::getOpenFileName(this, "Select Application", QDir::root().path(), "Palm OS App (*.prc *.pdb *.pqa)");
|
||||
QString app;
|
||||
bool loadedNewApp = false;
|
||||
bool wasPaused = emu.isPaused();
|
||||
|
||||
if(!wasPaused)
|
||||
emu.pause();
|
||||
|
||||
app = QFileDialog::getOpenFileName(this, "Select File", QDir::root().path(), "Palm OS File (*.prc *.pdb *.pqa)");
|
||||
if(app != ""){
|
||||
uint32_t error = emu.installApplication(app);
|
||||
|
||||
if(error != EMU_ERROR_NONE)
|
||||
if(error == EMU_ERROR_NONE)
|
||||
loadedNewApp = true;
|
||||
else
|
||||
popupErrorDialog("Could not install app, Error:" + QString::number(error));
|
||||
}
|
||||
|
||||
if(!wasPaused || loadedNewApp)
|
||||
emu.resume();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +404,6 @@ void MainWindow::on_debugger_clicked(){
|
||||
if(emu.isInited()){
|
||||
emu.pause();
|
||||
ui->ctrlBtn->setIcon(QIcon(":/buttons/images/play.svg"));
|
||||
ui->ctrlBtn->repaint();
|
||||
emuDebugger->exec();
|
||||
}
|
||||
}
|
||||
@@ -425,7 +413,7 @@ void MainWindow::on_screenshot_clicked(){
|
||||
qlonglong screenshotNumber = settings->value("screenshotNum", 0).toLongLong();
|
||||
QString screenshotPath = settings->value("resourceDirectory", "").toString() + "/screenshots/screenshot" + QString::number(screenshotNumber, 10) + ".png";
|
||||
|
||||
emu.getFramebuffer().save(screenshotPath, "PNG", 100);
|
||||
emu.getFramebufferImage().save(screenshotPath, "PNG", 100);
|
||||
screenshotNumber++;
|
||||
settings->setValue("screenshotNum", screenshotNumber);
|
||||
}
|
||||
@@ -468,3 +456,27 @@ void MainWindow::on_settings_clicked(){
|
||||
if(wasInited && !wasPaused)
|
||||
emu.resume();
|
||||
}
|
||||
|
||||
void MainWindow::on_bootApp_clicked(){
|
||||
if(emu.isInited()){
|
||||
QString app;
|
||||
bool loadedNewApp = false;
|
||||
bool wasPaused = emu.isPaused();
|
||||
|
||||
if(!wasPaused)
|
||||
emu.pause();
|
||||
|
||||
app = QFileDialog::getOpenFileName(this, "Select File", QDir::root().path(), "Palm OS File (*.prc *.pqa *.img)");
|
||||
if(app != ""){
|
||||
uint32_t error = emu.bootFromFile(app);
|
||||
|
||||
if(error == EMU_ERROR_NONE)
|
||||
loadedNewApp = true;
|
||||
else
|
||||
popupErrorDialog("Could not boot app, Error:" + QString::number(error));
|
||||
}
|
||||
|
||||
if(!wasPaused || loadedNewApp)
|
||||
emu.resume();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ public:
|
||||
void createHomeDirectoryTree(const QString& path);
|
||||
|
||||
private:
|
||||
uint32_t getEmuFeatureList();
|
||||
void popupErrorDialog(const QString& error);
|
||||
void popupInformationDialog(const QString& info);
|
||||
void redraw();
|
||||
@@ -60,6 +59,8 @@ private slots:
|
||||
void on_todo_released();
|
||||
void on_notes_pressed();
|
||||
void on_notes_released();
|
||||
void on_voiceMemo_pressed();
|
||||
void on_voiceMemo_released();
|
||||
void on_up_pressed();
|
||||
void on_up_released();
|
||||
void on_down_pressed();
|
||||
@@ -68,6 +69,8 @@ private slots:
|
||||
void on_left_released();
|
||||
void on_right_pressed();
|
||||
void on_right_released();
|
||||
void on_center_pressed();
|
||||
void on_center_released();
|
||||
|
||||
//frontend buttons
|
||||
void on_ctrlBtn_clicked();
|
||||
@@ -77,6 +80,7 @@ private slots:
|
||||
void on_stateManager_clicked();
|
||||
void on_reset_clicked();
|
||||
void on_settings_clicked();
|
||||
void on_bootApp_clicked();
|
||||
|
||||
private:
|
||||
SettingsManager* settingsManager;
|
||||
|
||||
@@ -2,16 +2,13 @@
|
||||
<qresource prefix="/buttons">
|
||||
<file>images/addressBook.svg</file>
|
||||
<file>images/calendar.svg</file>
|
||||
<file>images/center.svg</file>
|
||||
<file>images/debugger.svg</file>
|
||||
<file>images/down.svg</file>
|
||||
<file>images/install.svg</file>
|
||||
<file>images/left.svg</file>
|
||||
<file>images/notes.svg</file>
|
||||
<file>images/pause.svg</file>
|
||||
<file>images/play.svg</file>
|
||||
<file>images/power.svg</file>
|
||||
<file>images/right.svg</file>
|
||||
<file>images/screenshot.svg</file>
|
||||
<file>images/stateManager.svg</file>
|
||||
<file>images/stop.svg</file>
|
||||
@@ -19,5 +16,10 @@
|
||||
<file>images/up.svg</file>
|
||||
<file>images/reset.svg</file>
|
||||
<file>images/settingsManager.svg</file>
|
||||
<file>images/center.svg</file>
|
||||
<file>images/left.svg</file>
|
||||
<file>images/right.svg</file>
|
||||
<file>images/boot.svg</file>
|
||||
<file>images/voiceMemo.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="TouchScreen" name="display">
|
||||
<widget class="TouchScreen" name="display" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -56,12 +56,6 @@
|
||||
<height>220</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -94,8 +88,8 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="7" column="1">
|
||||
<widget class="QPushButton" name="addressBook">
|
||||
<item row="6" column="0">
|
||||
<widget class="QPushButton" name="calendar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -105,43 +99,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/addressBook.svg</normaloff>:/buttons/images/addressBook.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QPushButton" name="screenshot">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/screenshot.svg</normaloff>:/buttons/images/screenshot.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="5">
|
||||
<widget class="QPushButton" name="right">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/right.svg</normaloff>:/buttons/images/right.svg</iconset>
|
||||
<normaloff>:/buttons/images/calendar.svg</normaloff>:/buttons/images/calendar.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -153,6 +116,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Run/Pause</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@@ -162,7 +131,310 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="5">
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="reset">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/reset.svg</normaloff>:/buttons/images/reset.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QPushButton" name="stateManager">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save/Load State</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/stateManager.svg</normaloff>:/buttons/images/stateManager.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="settings">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/settingsManager.svg</normaloff>:/buttons/images/settingsManager.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="power">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/power.svg</normaloff>:/buttons/images/power.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="bootApp">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Boot App</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/boot.svg</normaloff>:/buttons/images/boot.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="install">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Install App</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/install.svg</normaloff>:/buttons/images/install.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="screenshot">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Snapshot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/screenshot.svg</normaloff>:/buttons/images/screenshot.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLabel" name="powerButtonLed">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>This is an LED not a button.😜</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPushButton" name="addressBook">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/addressBook.svg</normaloff>:/buttons/images/addressBook.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="left">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/left.svg</normaloff>:/buttons/images/left.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="up">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/up.svg</normaloff>:/buttons/images/up.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="center">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/center.svg</normaloff>:/buttons/images/center.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QPushButton" name="down">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/down.svg</normaloff>:/buttons/images/down.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QPushButton" name="right">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/right.svg</normaloff>:/buttons/images/right.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="5">
|
||||
<widget class="QPushButton" name="todo">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@@ -185,26 +457,16 @@
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/todo.svg</normaloff>:/buttons/images/todo.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<widget class="QLabel" name="powerButtonLed">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>LED</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="7">
|
||||
<item row="6" column="6">
|
||||
<widget class="QPushButton" name="notes">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@@ -215,180 +477,16 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/notes.svg</normaloff>:/buttons/images/notes.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="left">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/left.svg</normaloff>:/buttons/images/left.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="stateManager">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/stateManager.svg</normaloff>:/buttons/images/stateManager.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="up">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/up.svg</normaloff>:/buttons/images/up.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QPushButton" name="center">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/center.svg</normaloff>:/buttons/images/center.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="4">
|
||||
<widget class="QPushButton" name="down">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/down.svg</normaloff>:/buttons/images/down.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QPushButton" name="calendar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/calendar.svg</normaloff>:/buttons/images/calendar.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="power">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/power.svg</normaloff>:/buttons/images/power.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="reset">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/reset.svg</normaloff>:/buttons/images/reset.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="settings">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/settingsManager.svg</normaloff>:/buttons/images/settingsManager.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="install">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/install.svg</normaloff>:/buttons/images/install.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<item row="1" column="5">
|
||||
<widget class="QPushButton" name="debugger">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@@ -399,12 +497,35 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Debugger</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/debugger.svg</normaloff>:/buttons/images/debugger.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="voiceMemo">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/voiceMemo.svg</normaloff>:/buttons/images/voiceMemo.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -415,8 +536,9 @@
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TouchScreen</class>
|
||||
<extends>QLabel</extends>
|
||||
<extends>QWidget</extends>
|
||||
<header>touchscreen.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "emuwrapper.h"
|
||||
|
||||
|
||||
SettingsManager::SettingsManager(QWidget* parent) :
|
||||
@@ -23,16 +24,11 @@ SettingsManager::SettingsManager(QWidget* parent) :
|
||||
ui->homeDirectory->setText(settings->value("resourceDirectory", "").toString());
|
||||
ui->showOnscreenKeys->setChecked(!settings->value("hideOnscreenKeys", false).toBool());
|
||||
|
||||
ui->feature128mbRam->setChecked(settings->value("feature128mbRam", false).toBool());
|
||||
ui->featureFastCpu->setChecked(settings->value("featureFastCpu", false).toBool());
|
||||
ui->featureHybridCpu->setChecked(settings->value("featureHybridCpu", false).toBool());
|
||||
ui->featureCustomFb->setChecked(settings->value("featureCustomFb", false).toBool());
|
||||
ui->fastBoot->setChecked(settings->value("fastBoot", false).toBool());
|
||||
ui->palmOsVersion->setValue(settings->value("palmOsVersion", false).toInt());
|
||||
|
||||
ui->featureSyncedRtc->setChecked(settings->value("featureSyncedRtc", false).toBool());
|
||||
ui->featureHleApis->setChecked(settings->value("featureHleApis", false).toBool());
|
||||
ui->featureEmuHonest->setChecked(settings->value("featureEmuHonest", false).toBool());
|
||||
ui->featureExtraKeys->setChecked(settings->value("featureExtraKeys", false).toBool());
|
||||
ui->featureDurable->setChecked(settings->value("featureDurable", false).toBool());
|
||||
ui->featureSoundStreams->setChecked(settings->value("featureSoundStreams", false).toBool());
|
||||
|
||||
setKeySelectorState(-1);
|
||||
updateButtonKeys();
|
||||
@@ -73,6 +69,7 @@ void SettingsManager::updateButtonKeys(){
|
||||
ui->selectAddressBookKey->setText(QKeySequence(settings->value("palmButton" + QString::number(EmuWrapper::BUTTON_ADDRESS) + "Key", '\0').toInt()).toString());
|
||||
ui->selectTodoKey->setText(QKeySequence(settings->value("palmButton" + QString::number(EmuWrapper::BUTTON_TODO) + "Key", '\0').toInt()).toString());
|
||||
ui->selectNotesKey->setText(QKeySequence(settings->value("palmButton" + QString::number(EmuWrapper::BUTTON_NOTES) + "Key", '\0').toInt()).toString());
|
||||
ui->selectVoiceMemoKey->setText(QKeySequence(settings->value("palmButton" + QString::number(EmuWrapper::BUTTON_VOICE_MEMO) + "Key", '\0').toInt()).toString());
|
||||
ui->selectPowerKey->setText(QKeySequence(settings->value("palmButton" + QString::number(EmuWrapper::BUTTON_POWER) + "Key", '\0').toInt()).toString());
|
||||
}
|
||||
|
||||
@@ -127,6 +124,10 @@ void SettingsManager::on_selectNotesKey_clicked(){
|
||||
setKeySelectorState(EmuWrapper::BUTTON_NOTES);
|
||||
}
|
||||
|
||||
void SettingsManager::on_selectVoiceMemoKey_clicked(){
|
||||
setKeySelectorState(EmuWrapper::BUTTON_VOICE_MEMO);
|
||||
}
|
||||
|
||||
void SettingsManager::on_selectPowerKey_clicked(){
|
||||
setKeySelectorState(EmuWrapper::BUTTON_POWER);
|
||||
}
|
||||
@@ -140,42 +141,26 @@ void SettingsManager::on_clearKeyBind_clicked(){
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsManager::on_feature128mbRam_toggled(bool checked){
|
||||
settings->setValue("feature128mbRam", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureFastCpu_toggled(bool checked){
|
||||
settings->setValue("featureFastCpu", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureHybridCpu_toggled(bool checked){
|
||||
settings->setValue("featureHybridCpu", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureCustomFb_toggled(bool checked){
|
||||
settings->setValue("featureCustomFb", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureSyncedRtc_toggled(bool checked){
|
||||
settings->setValue("featureSyncedRtc", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureHleApis_toggled(bool checked){
|
||||
settings->setValue("featureHleApis", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureEmuHonest_toggled(bool checked){
|
||||
settings->setValue("featureEmuHonest", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureExtraKeys_toggled(bool checked){
|
||||
settings->setValue("featureExtraKeys", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureSoundStreams_toggled(bool checked){
|
||||
settings->setValue("featureSoundStreams", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_featureDurable_toggled(bool checked){
|
||||
settings->setValue("featureDurable", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_fastBoot_toggled(bool checked){
|
||||
settings->setValue("fastBoot", checked);
|
||||
}
|
||||
|
||||
void SettingsManager::on_cpuSpeed_valueChanged(double arg1){
|
||||
EmuWrapper& emu = ((MainWindow*)parentWidget())->emu;
|
||||
|
||||
settings->setValue("cpuSpeed", arg1);
|
||||
if(emu.isInited())
|
||||
emu.setCpuSpeed(arg1);
|
||||
}
|
||||
|
||||
void SettingsManager::on_palmOsVersion_valueChanged(int arg1){
|
||||
settings->setValue("palmOsVersion", arg1);
|
||||
}
|
||||
|
||||
@@ -40,20 +40,17 @@ private slots:
|
||||
void on_selectAddressBookKey_clicked();
|
||||
void on_selectTodoKey_clicked();
|
||||
void on_selectNotesKey_clicked();
|
||||
void on_selectVoiceMemoKey_clicked();
|
||||
void on_selectPowerKey_clicked();
|
||||
void on_clearKeyBind_clicked();
|
||||
|
||||
void on_feature128mbRam_toggled(bool checked);
|
||||
void on_featureFastCpu_toggled(bool checked);
|
||||
void on_featureHybridCpu_toggled(bool checked);
|
||||
void on_featureCustomFb_toggled(bool checked);
|
||||
void on_featureSyncedRtc_toggled(bool checked);
|
||||
void on_featureHleApis_toggled(bool checked);
|
||||
void on_featureEmuHonest_toggled(bool checked);
|
||||
void on_featureExtraKeys_toggled(bool checked);
|
||||
void on_featureSoundStreams_toggled(bool checked);
|
||||
void on_featureDurable_toggled(bool checked);
|
||||
|
||||
void on_fastBoot_toggled(bool checked);
|
||||
void on_cpuSpeed_valueChanged(double arg1);
|
||||
void on_palmOsVersion_valueChanged(int arg1);
|
||||
|
||||
private:
|
||||
Ui::SettingsManager* ui;
|
||||
QSettings* settings;
|
||||
|
||||
@@ -30,13 +30,16 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>630</width>
|
||||
<height>417</height>
|
||||
<width>613</width>
|
||||
<height>444</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="homeDirectory">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -44,13 +47,22 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pickHomeDirectory">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pick Home Directory</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="showOnscreenKeys">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Onscreen Keys</string>
|
||||
</property>
|
||||
@@ -58,8 +70,11 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Set Keyboard Keys:</string>
|
||||
<string>Set Palm Button Map:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -72,42 +87,26 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="selectAddressBookKey">
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="selectNotesKey">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/addressBook.svg</normaloff>:/buttons/images/addressBook.svg</iconset>
|
||||
<normaloff>:/buttons/images/notes.svg</normaloff>:/buttons/images/notes.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="selectUpKey">
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/up.svg</normaloff>:/buttons/images/up.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="selectDownKey">
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/down.svg</normaloff>:/buttons/images/down.svg</iconset>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -119,6 +118,9 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
@@ -126,6 +128,26 @@
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/calendar.svg</normaloff>:/buttons/images/calendar.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="selectDownKey">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/down.svg</normaloff>:/buttons/images/down.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
@@ -136,6 +158,9 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
@@ -143,22 +168,8 @@
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/todo.svg</normaloff>:/buttons/images/todo.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="selectNotesKey">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/notes.svg</normaloff>:/buttons/images/notes.svg</iconset>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -170,6 +181,9 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
@@ -177,10 +191,73 @@
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/power.svg</normaloff>:/buttons/images/power.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="selectUpKey">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/up.svg</normaloff>:/buttons/images/up.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="selectAddressBookKey">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/addressBook.svg</normaloff>:/buttons/images/addressBook.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="selectCenterKey">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/center.svg</normaloff>:/buttons/images/center.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="selectLeftKey">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
@@ -188,10 +265,16 @@
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/left.svg</normaloff>:/buttons/images/left.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="selectRightKey">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
@@ -199,16 +282,28 @@
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/right.svg</normaloff>:/buttons/images/right.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="selectCenterKey">
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="selectVoiceMemoKey">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MAXSIZE</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="mainwindow.qrc">
|
||||
<normaloff>:/buttons/images/center.svg</normaloff>:/buttons/images/center.svg</iconset>
|
||||
<normaloff>:/buttons/images/voiceMemo.svg</normaloff>:/buttons/images/voiceMemo.svg</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -224,13 +319,72 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearKeyBind">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear Key Bind</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="palmOsVersionLabel">
|
||||
<property name="text">
|
||||
<string>Palm OS Version:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="palmOsVersion">
|
||||
<property name="minimum">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>CPU Speed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="cpuSpeed">
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="fastBoot">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fast Boot(Fastforwards Through The Boot Screen)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Set Emulator Features(Restart Required):</string>
|
||||
</property>
|
||||
@@ -239,73 +393,20 @@
|
||||
<item>
|
||||
<widget class="QWidget" name="gridWidget_2" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="featureSyncedRtc">
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="featureDurable">
|
||||
<property name="text">
|
||||
<string>Sync Real Time Clock</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="featureHybridCpu">
|
||||
<property name="text">
|
||||
<string>ARM Instruction Set(OS 5)</string>
|
||||
<string>Ignore Invalid Behavior</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="featureEmuHonest">
|
||||
<property name="text">
|
||||
<string>Tell Programs Their Emulated</string>
|
||||
<widget class="QCheckBox" name="featureSyncedRtc">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="feature128mbRam">
|
||||
<property name="text">
|
||||
<string>128MB RAM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="featureFastCpu">
|
||||
<property name="text">
|
||||
<string>Overclocking</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QCheckBox" name="featureSoundStreams">
|
||||
<property name="text">
|
||||
<string>PWM Audio Streams(OS 5)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="featureHleApis">
|
||||
<property name="text">
|
||||
<string>HLE APIs(Speed Hack)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="featureExtraKeys">
|
||||
<property name="text">
|
||||
<string>Extra Dpad Keys(OS 5)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="featureCustomFb">
|
||||
<property name="text">
|
||||
<string>Resizeable Display(HiRes Mode)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="featureDurable">
|
||||
<property name="text">
|
||||
<string>Ignore Invalid Behavior</string>
|
||||
<string>Sync Real Time Clock</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QListWidgetItem>
|
||||
#include <QRegExp>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
@@ -15,23 +17,30 @@
|
||||
StateManager::StateManager(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::StateManager){
|
||||
settings = ((MainWindow*)parent)->settings;
|
||||
emu = &((MainWindow*)parent)->emu;
|
||||
|
||||
//init GUI
|
||||
ui->setupUi(this);
|
||||
|
||||
//this allows resizing the screenshot of the savestate
|
||||
this->installEventFilter(this);
|
||||
ui->statePreview->installEventFilter(this);
|
||||
ui->statePreview->setObjectName("statePreview");
|
||||
|
||||
updateStateList();
|
||||
noBadPaths = new QRegExpValidator(QRegExp("[a-z0-9_()-\\s]*"));
|
||||
ui->newStateName->setValidator(noBadPaths);
|
||||
}
|
||||
|
||||
StateManager::~StateManager(){
|
||||
delete noBadPaths;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool StateManager::eventFilter(QObject* object, QEvent* event){
|
||||
if(object->objectName() == "StateManager" && event->type() == QEvent::WindowActivate){
|
||||
updateStateList();
|
||||
ui->states->setCurrentRow(0);
|
||||
}
|
||||
if(object->objectName() == "statePreview" && event->type() == QEvent::Resize)
|
||||
updateStatePreview();
|
||||
|
||||
@@ -39,8 +48,7 @@ bool StateManager::eventFilter(QObject* object, QEvent* event){
|
||||
}
|
||||
|
||||
void StateManager::updateStateList(){
|
||||
QString saveDirPath = settings->value("resourceDirectory", "").toString() + "/saveStates";
|
||||
QDir saveDir(saveDirPath);
|
||||
QDir saveDir(emu->getStatePath());
|
||||
QStringList saveStateNames;
|
||||
QStringList filter;
|
||||
|
||||
@@ -60,7 +68,7 @@ void StateManager::updateStateList(){
|
||||
|
||||
void StateManager::updateStatePreview(){
|
||||
if(ui->states->currentItem()){
|
||||
QString statePath = settings->value("resourceDirectory", "").toString() + "/saveStates/" + ui->states->currentItem()->text();
|
||||
QString statePath = emu->getStatePath() + "/" + ui->states->currentItem()->text();
|
||||
|
||||
ui->statePreview->setPixmap(QPixmap(statePath + ".png").scaled(ui->statePreview->width() * 0.98, ui->statePreview->height() * 0.98, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
@@ -68,8 +76,6 @@ void StateManager::updateStatePreview(){
|
||||
//remove outdated image
|
||||
ui->statePreview->clear();
|
||||
}
|
||||
|
||||
ui->statePreview->update();
|
||||
}
|
||||
|
||||
int StateManager::getStateIndexRowByName(const QString& name){
|
||||
@@ -83,10 +89,10 @@ int StateManager::getStateIndexRowByName(const QString& name){
|
||||
void StateManager::on_saveState_clicked(){
|
||||
if(ui->newStateName->text() != ""){
|
||||
MainWindow* parent = (MainWindow*)parentWidget();
|
||||
QString statePath = settings->value("resourceDirectory", "").toString() + "/saveStates/" + ui->newStateName->text();
|
||||
QString statePath = emu->getStatePath() + "/" + ui->newStateName->text();
|
||||
|
||||
parent->emu.saveState(statePath + ".state");
|
||||
parent->emu.getFramebuffer().save(statePath + ".png");
|
||||
parent->emu.saveState(ui->newStateName->text());
|
||||
parent->emu.getFramebufferImage().save(statePath + ".png");
|
||||
updateStateList();
|
||||
|
||||
ui->states->setCurrentRow(getStateIndexRowByName(ui->newStateName->text()));//this also updates the preview image
|
||||
@@ -96,15 +102,15 @@ void StateManager::on_saveState_clicked(){
|
||||
void StateManager::on_loadState_clicked(){
|
||||
if(ui->states->currentItem()){
|
||||
MainWindow* parent = (MainWindow*)parentWidget();
|
||||
QString statePath = settings->value("resourceDirectory", "").toString() + "/saveStates/" + ui->states->currentItem()->text();
|
||||
QString statePath = emu->getStatePath() + "/" + ui->states->currentItem()->text();
|
||||
|
||||
parent->emu.loadState(statePath + ".state");
|
||||
parent->emu.loadState(ui->states->currentItem()->text());
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager::on_deleteState_clicked(){
|
||||
if(ui->states->currentItem()){
|
||||
QString statePath = settings->value("resourceDirectory", "").toString() + "/saveStates/" + ui->states->currentItem()->text();
|
||||
QString statePath = emu->getStatePath() + "/" + ui->states->currentItem()->text();
|
||||
|
||||
QFile(statePath + ".state").remove();
|
||||
QFile(statePath + ".png").remove();
|
||||
@@ -116,6 +122,4 @@ void StateManager::on_deleteState_clicked(){
|
||||
|
||||
void StateManager::on_states_currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous){
|
||||
updateStatePreview();
|
||||
ui->states->repaint();
|
||||
ui->statePreview->repaint();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
#include <QObject>
|
||||
#include <QEvent>
|
||||
#include <QListWidgetItem>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
#include "emuwrapper.h"
|
||||
|
||||
namespace Ui{
|
||||
class StateManager;
|
||||
@@ -32,5 +35,6 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::StateManager* ui;
|
||||
QSettings* settings;
|
||||
EmuWrapper* emu;
|
||||
QRegExpValidator* noBadPaths;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "touchscreen.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -10,7 +11,7 @@
|
||||
|
||||
|
||||
TouchScreen::TouchScreen(QWidget* parent)
|
||||
: QLabel(parent){
|
||||
: QWidget(parent){
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +23,17 @@ float TouchScreen::rangeSwap(float newRange, float oldRange, float value){
|
||||
return value / oldRange * newRange;
|
||||
}
|
||||
|
||||
void TouchScreen::paintEvent(QPaintEvent* ev){
|
||||
EmuWrapper& emu = ((MainWindow*)(parentWidget()->parentWidget()->parentWidget()))->emu;
|
||||
|
||||
if(emu.isInited()){
|
||||
QPainter painter(this);
|
||||
QImage image = emu.getFramebufferImage().scaled(painter.window().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
painter.drawImage((painter.window().width() - image.width()) / 2, (painter.window().height() - image.height()) / 2, image);
|
||||
}
|
||||
}
|
||||
|
||||
void TouchScreen::mousePressEvent(QMouseEvent* ev){
|
||||
if(ev->x() >= 0 && ev->x() < this->width() && ev->y() >= 0 && ev->y() < this->height()){
|
||||
EmuWrapper& emu = ((MainWindow*)(parentWidget()->parentWidget()->parentWidget()))->emu;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
#include <QPaintEvent>
|
||||
#include <QMouseEvent>
|
||||
|
||||
class TouchScreen : public QLabel{
|
||||
class TouchScreen : public QWidget{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
@@ -14,6 +15,7 @@ public:
|
||||
~TouchScreen();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* ev);
|
||||
void mousePressEvent(QMouseEvent* ev);
|
||||
void mouseMoveEvent(QMouseEvent* ev);
|
||||
void mouseReleaseEvent(QMouseEvent* ev);
|
||||
|
||||
51
readme.md
@@ -1,4 +1,4 @@
|
||||
# Palm m515/OS 4.1 emulator(Mu)
|
||||
# Palm OS emulator(Mu)
|
||||
|
||||
This is a complete restart of my Palm OS emulator, with the last one the code got too messy and the goal too ambitious(to emulate every palm API in software and for compatibility with all Palm OS versions and devices).
|
||||
|
||||
@@ -17,41 +17,17 @@ It is the best Palm brand OS 4 device that has no special hardware builtin(cellp
|
||||
|
||||
The Palm keyboard attachment will likely be emulated later on so the PC keyboard can be used on text fields.
|
||||
|
||||
## OS improvements
|
||||
## What about OS 5?
|
||||
|
||||
If there is something the OS does not support(like an OS 5 API) I may add it manually, this will be in the form of a custom firmware as a ROM image or a .bps patch, not a patch to the emulator with only 1 exception "PceNativeCall" which would require an ARM interpreter, it would also be an option to not apply this patch leaving you with an accurately emulated stock Palm m515.
|
||||
|
||||
These patches will not be worked on until the emulator is actually running.
|
||||
|
||||
## But you shouldnt waste your time on OS 4, OS 5 can do more.
|
||||
|
||||
I have made a video of OS 5 doing that "more", it is extremely incompatible with OS 4 games which most games are, very few games used the ARM CPU and those that did are available on other platforms, some used the 320x320 display mode.
|
||||
|
||||
On Clie PEG-SL10:
|
||||
ArgonV: Normal
|
||||
Galax: Normal
|
||||
Zap!20XX: Normal
|
||||
Invaders: Normal
|
||||
Platypus: No ARM CPU, Cant Run
|
||||
|
||||
On Palm T|X:
|
||||
ArgonV: Runs At Warpspeed
|
||||
Galax: Audio Cuts Out
|
||||
Zap!20XX: Audio Cuts Out
|
||||
Invaders: Reboots System
|
||||
Platypus: Normal, Used To Prove Speaker Isnt Defective
|
||||
Bonus: Has Adware(Addit)
|
||||
|
||||
[Palm T|X vs OS 4 Games](https://youtu.be/ithVLI_M6i0)
|
||||
|
||||
The lack of ARM CPU will be fixed in my emulator see "OS improvements".
|
||||
I am planning on adding Tungsten T3 support as soon as possible.
|
||||
|
||||
## Credits
|
||||
uARM (ARMv5 Core)
|
||||
Musashi v3.4 (last version that builds outside of MAME)(68k Core)
|
||||
blip_buf 1.1.0 (Audio Resampler)
|
||||
http://www.iconarchive.com/show/crystal-clear-icons-by-everaldo/App-palm-icon.html (Desktop Icon)
|
||||
http://tango.freedesktop.org/Tango_Icon_Library (Palm Action Buttons, All UI buttons)
|
||||
[Firebird Emu](https://github.com/nspire-emus/firebird) (ARMv5TE Core)
|
||||
[uARM](https://dmitry.gr/?r=05.Projects&proj=07.%20Linux%20on%208bit) (PXA260 CPU Peripherals)
|
||||
[Musashi v3.4](https://github.com/kstenerud/Musashi) (last version that builds outside of MAME)(68k Core)
|
||||
[blip_buf 1.1.0](https://github.com/TASVideos/BizHawk/tree/master/blip_buf) (Audio Resampler)
|
||||
https://www.iconarchive.com/show/crystal-clear-icons-by-everaldo/App-palm-icon.html (Desktop Icon)
|
||||
https://tango.freedesktop.org/Tango_Icon_Library (Palm Action Buttons, All UI buttons)
|
||||
https://www.iconfinder.com/icons/2317746/chip_computer_cpu_device_frequency_microchip_processor_icon (hwTestSuite Icon)
|
||||
https://www.flaticon.com/free-icon/cow_235371#term=cow&page=1&position=13 (muExpDriver Icon)
|
||||
https://findicons.com/icon/164302/cursor (Libretro Port Joystick Cursor)
|
||||
@@ -89,6 +65,7 @@ Install prc-tools from the below link(self compiled or prepackaged VM)
|
||||
#### Files
|
||||
palmos41-en-m515.rom(all euro languages, from Palm dev program): 412557a221933a8be12622de7a21320a (MD5)
|
||||
palmos41-en-m515.rom(English only, verified authentic from device): 83cb1d1c76e568b916dc2e7c0bf669f6 (MD5)
|
||||
palmos52-en-t3.rom: de46ec84d9aabf655eabdf9b00a3845d (MD5)
|
||||
bootloader-en-m515.rom(v1): 9da101cd2317830649a31f8fa46debec (MD5)
|
||||
bootloader-en-m515.rom(v2): e64c755205bc3e79d1bc5b70128f688d (MD5)
|
||||
|
||||
@@ -97,14 +74,16 @@ I understand not everyone speaks English so I list both ROMs, I do all my testin
|
||||
|
||||
#### For Qt
|
||||
1. Run once to create the directory tree
|
||||
2. Copy "palmos41-en-m515.rom" to "~/Mu"
|
||||
3. Copy "bootloader-en-m515.rom" to "~/Mu"
|
||||
2. Copy "palmos41-en-m515.rom" and "palmos52-en-t3.rom" to "~/Mu"
|
||||
3. (Optional)Copy "bootloader-en-m515.rom" to "~/Mu"
|
||||
4. Run emu and press start button
|
||||
|
||||
#### For RetroArch
|
||||
1. Download "Palm OS(Mu)" from "Online Updater->Core Updater"
|
||||
2. Go back, select "Load Core", select "Palm OS(Mu)"
|
||||
3. Run "palmos41-en-m515.rom"
|
||||
3. Copy "palmos41-en-m515.rom" and "palmos52-en-t3.rom" to the RetroArch system directory
|
||||
4. (Optional)Copy "bootloader-en-m515.rom" to the RetroArch system directory
|
||||
5. Run a .prc or .img file
|
||||
|
||||
## Tools
|
||||
[Prc-tools, Palm OS SDKs, pilrc, pilot-link](https://github.com/meepingsnesroms/prc-tools-remix)
|
||||
|
||||
65
roadmap.txt
@@ -5,40 +5,55 @@ The end???
|
||||
v3.2.0 to v4.0.0(*** ** 2020 - *** ** 2020)
|
||||
|
||||
Core:
|
||||
Add Dragonball OG/EZ/VZ CPU builtin LCD controller support, some Palm OS 1<->3 games write directly to these registers to display their video and they won't work(with the exception of LSSA since the OS monitors that one)
|
||||
add Dragonball OG/EZ/VZ CPU builtin LCD controller support too muExpDriver, some Palm OS 1<->3 games write directly to these registers to display their video and they won't work(with the exception of LSSA since the OS monitors that one)
|
||||
|
||||
------------------------------------------
|
||||
v2.5.0 to v3.2.0(*** ** 2019 - *** ** 2020)
|
||||
v1.1.0 to v3.2.0(*** ** 2020 - *** ** 2020)
|
||||
|
||||
RetroArch GUI:
|
||||
//TODO: allow adding more content after boot
|
||||
//TODO: get EMU_MANAGE_HOST_CPU_PIPELINE working on other platforms then the main 4
|
||||
//TODO: get OpenMP working with RetroArch(already works but breaks the no external libs rule)
|
||||
//TODO: switch to high contrast and top left corner aligned mouse cursors
|
||||
//FIXED: when compiling with "make platform=windows_x86_64" the dll wont load(theres a really good chance its because "libgomp-1.dll"(the OpenMP handler library) is missing from the RetroArch folder)(fixed by disableing OpenMP :( )
|
||||
|
||||
Qt GUI:
|
||||
//TODO: get circleci builds for QT port on Win/Mac/Linux
|
||||
//TODO: allow reiniting the emu without closing the program
|
||||
//FAIL: render with OpenGL widget(should be a major speed boost)(switched to the method from firebird instead and it changed nothing)
|
||||
|
||||
Core:
|
||||
*allow direct 320x320 bitmap rendered over the 160x160 framebuffer expanded 2x in both directions, black pixels will be transparent showing what's on the 160x160 framebuffer
|
||||
|
||||
Emu Hwr Driver:
|
||||
*set fake display framebuffer for 320x320 mode
|
||||
|
||||
------------------------------------------
|
||||
v2.0.0 to v2.5.0(*** ** 2019 - *** ** 2019)
|
||||
|
||||
Core:
|
||||
*add single 16 bit PCM sound stream, mixed with PWM1
|
||||
|
||||
Emu Hwr Driver:
|
||||
*OS 5.1.* sound stream API support(possibly can use PRC file dumped from an OS 5.1.1 device as long as I still add the extra sound stream for it to write to)
|
||||
|
||||
------------------------------------------
|
||||
v1.0.0 to v2.0.0(*** ** 2019 - *** ** 2019)
|
||||
|
||||
Core:
|
||||
*ARM opcode support, most apps that use ARM code work, as long as no OS 5.1.* APIs are used(partialy done, alignment broken)
|
||||
|
||||
Emu Hwr Driver:
|
||||
*ARM CPU is exported to OS 4 with custom PceNativeCall(already done)
|
||||
*can set fake version number to prevent tripping compatibility checks(already done)
|
||||
//TODO: thumb mode supposedly dosent work with ARM dynarec, test this and fix mode switches if it does
|
||||
add Palm Tungsten T3 support
|
||||
|
||||
------------------------------------------
|
||||
v1.0.0 to v1.1.0(Feb 25 2019 - Easter 2019)
|
||||
|
||||
RetroArch GUI:
|
||||
*allow mouse cursor to be rendered with multiple CPUs(removed for now)
|
||||
*now launches content like cartridge based systems
|
||||
*make default button layout match default controller layout better
|
||||
*allow disabling the silkscreen area
|
||||
*booting without game works again
|
||||
*add multithreading and pipeline speedups(disabled for now because of compiling issues)
|
||||
|
||||
Qt GUI:
|
||||
//TODO: allow using host serial ports in Palm OS
|
||||
//TODO: saving states isn't working on Mac OS, it won't create the directory, don't know why(its not the . in the path either already tested), QDir returns false so it is failing?
|
||||
*fixed state manager not loading until a state is saved
|
||||
*boot button uses install button icon now, changed install button to icon a "+"
|
||||
*put back left/right/center keys
|
||||
*added install and boot buttons to both modes, content loaded with the boot button has separate save paths just like cartridge systems
|
||||
*added instant boot option, no longer have to wait for the 5 second boot up if you dont want to(instant boot is always on for loading games)
|
||||
*can now set the feature bits
|
||||
*can now set the resource directory
|
||||
*keyboard mapping support
|
||||
|
||||
Core:
|
||||
*implement UART1/2 to fix crashing when beaming or hotsyncing
|
||||
*PLLFSR timing hack is gone, CLK32 bit now just toggles properly mid CLK32
|
||||
*SD card access routines are now 6<->7X faster
|
||||
*add a launcher to load prc/pdb/pqa files
|
||||
*add frameskip for really low power devices and when video is not needed
|
||||
*added host CPU pipeline control for another speed up
|
||||
*implement FEATURE_SYNCED_RTC to make the Palm clock always match the host system clock
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
#include "emulator.h"
|
||||
#include "portability.h"
|
||||
#include "hardwareRegisters.h"
|
||||
#include "dbvz.h"
|
||||
|
||||
|
||||
bool ads7846PenIrqEnabled;
|
||||
|
||||
static const uint16_t ads7846DockResistorValues[PORT_END] = {0xFFF/*none*/, 0x1EB/*USB cradle*/, 0x000/*serial cradle, unknown*/, 0x000/*USB peripheral, unknown*/, 0x000/*serial peripheral, unknown*/};
|
||||
static const uint16_t ads7846DockResistorValues[EMU_PORT_END] = {0xFFF/*none*/, 0x1EB/*USB cradle*/, 0x000/*serial cradle, unknown*/, 0x000/*USB peripheral, unknown*/, 0x000/*serial peripheral, unknown*/};
|
||||
|
||||
static uint8_t ads7846BitsToNextControl;
|
||||
static uint8_t ads7846ControlByte;
|
||||
@@ -33,7 +33,7 @@ void ads7846Reset(void){
|
||||
ads7846OutputValue = 0x0000;
|
||||
ads7846ChipSelect = true;
|
||||
#if !defined(EMU_NO_SAFETY)
|
||||
refreshTouchState();
|
||||
m515RefreshTouchState();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ void ads7846SetChipSelect(bool value){
|
||||
ads7846PenIrqEnabled = true;
|
||||
ads7846OutputValue = 0x0000;
|
||||
#if !defined(EMU_NO_SAFETY)
|
||||
refreshTouchState();
|
||||
m515RefreshTouchState();
|
||||
#endif
|
||||
}
|
||||
ads7846ChipSelect = value;
|
||||
@@ -116,7 +116,7 @@ bool ads7846ExchangeBit(bool bitIn){
|
||||
//control byte and busy cycle finished, get output value
|
||||
bool bitMode = !!(ads7846ControlByte & 0x08);
|
||||
bool differentialMode = !(ads7846ControlByte & 0x04);
|
||||
uint8_t channel = (ads7846ControlByte & 0x70) >> 4;
|
||||
uint8_t channel = ads7846ControlByte >> 4 & 0x07;
|
||||
uint8_t powerSave = ads7846ControlByte & 0x03;
|
||||
|
||||
//debugLog("Accessed ADS7846 Ch:%d, %d bits, %s Mode, Power Save:%d, PC:0x%08X.\n", channel, bitMode ? 8 : 12, differentialMode ? "Diff" : "Normal", ads7846ControlByte & 0x03, flx68000GetPc());
|
||||
@@ -202,15 +202,15 @@ bool ads7846ExchangeBit(bool bitIn){
|
||||
break;
|
||||
|
||||
case 2:
|
||||
//battery, unknown hasent gotten low enough to test yet
|
||||
//battery
|
||||
//ads7846OutputValue = 0x600;//5%
|
||||
//ads7846OutputValue = 0x61C;//30%
|
||||
//ads7846OutputValue = 0x63C;//40%
|
||||
//ads7846OutputValue = 0x65C;//60%
|
||||
//ads7846OutputValue = 0x67C;//80%
|
||||
//ads7846OutputValue = 0x68C;//100%
|
||||
ads7846OutputValue = 0x69C;//100%
|
||||
//ads7846OutputValue = ads7846RangeMap(0, 100, palmMisc.batteryLevel, 0x000, 0x7F8);
|
||||
//ads7846OutputValue = 0x69C;//100%
|
||||
ads7846OutputValue = ads7846RangeMap(0, 100, palmMisc.batteryLevel, 0x5FD, 0x68C);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@@ -273,7 +273,7 @@ bool ads7846ExchangeBit(bool bitIn){
|
||||
|
||||
ads7846PenIrqEnabled = !(powerSave & 0x01);
|
||||
#if !defined(EMU_NO_SAFETY)
|
||||
refreshTouchState();
|
||||
m515RefreshTouchState();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
297
src/armv5.c
@@ -1,297 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "emulator.h"
|
||||
#include "hardwareRegisters.h"
|
||||
#include "memoryAccess.h"
|
||||
#include "portability.h"
|
||||
#include "armv5/CPU.h"
|
||||
#include "m68k/m68k.h"
|
||||
#include "debug/sandbox.h"
|
||||
|
||||
|
||||
#define ARMV5_CYCLES_PER_OPCODE 2
|
||||
|
||||
|
||||
bool armv5ServiceRequest;
|
||||
|
||||
static ArmCpu armv5Cpu;
|
||||
|
||||
|
||||
static Boolean armv5MemoryAccess(ArmCpu* cpu, void* buf, UInt32 vaddr, UInt8 size, Boolean write, Boolean privileged, UInt8* fsr){
|
||||
//just gonna have ARM and 68k share the same bus for now, ARM may want fonts/bitmaps from ROM
|
||||
|
||||
//Fake ARM 32 bit alignment convention
|
||||
//0x0XXXXXXX<->0x1XXXXXXX Normal memory access
|
||||
//0x20000000<->0x3XXXXXXX Mirrored range, realAddress = address - 0x20000000 + 0x00000002
|
||||
|
||||
//this will still fail if ARM allocates a 16 bit aligned buffer and passes it to the m68k,
|
||||
//but it allows 16 bit aligned data to be executed from the 68k stack and works as a
|
||||
//temporary measure until I get MemChunkNew patched correctly
|
||||
|
||||
//while executing wont support non 32 bit alignment regular accesses can for now
|
||||
/*
|
||||
#if !defined(EMU_NO_SAFETY)
|
||||
//size is not a power of two or address isnt aligned to size
|
||||
if(size & (size - 1) || vaddr & (size - 1)){
|
||||
debugLog("ARM attempted unaligned access: address:0x%08X, size:%d\n", vaddr, size);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
if(vaddr & 0x20000000)
|
||||
vaddr ^= 0x20000002;
|
||||
|
||||
if(write){
|
||||
switch(size){
|
||||
case 1:
|
||||
m68k_write_memory_8(vaddr, *(uint8_t*)buf);
|
||||
return true;
|
||||
|
||||
case 2:
|
||||
m68k_write_memory_16(vaddr, SWAP_16(*(uint16_t*)buf));
|
||||
return true;
|
||||
|
||||
case 4:
|
||||
m68k_write_memory_32(vaddr, SWAP_32(*(uint32_t*)buf));
|
||||
return true;
|
||||
|
||||
default:
|
||||
debugLog("Invalid ARMv5 write: address:0x%08X, size:%d\n", vaddr, size * 8);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
switch(size){
|
||||
case 1:
|
||||
*(uint8_t*)buf = m68k_read_memory_8(vaddr);
|
||||
return true;
|
||||
|
||||
case 2:
|
||||
*(uint16_t*)buf = SWAP_16(m68k_read_memory_16(vaddr));
|
||||
return true;
|
||||
|
||||
case 4:
|
||||
*(uint32_t*)buf = SWAP_32(m68k_read_memory_32(vaddr));
|
||||
return true;
|
||||
|
||||
default:
|
||||
debugLog("Invalid ARMv5 read: address:0x%08X, size:%d\n", vaddr, size * 8);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean armv5Hypercall(ArmCpu* cpu){
|
||||
armv5ServiceRequest = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void armv5EmulErr(ArmCpu* cpu, const char* errStr){
|
||||
debugLog("%s\n", errStr);
|
||||
}
|
||||
|
||||
static void armv5SetFaultAddr(struct ArmCpu* cpu, UInt32 adr, UInt8 faultStatus){
|
||||
//TODO
|
||||
}
|
||||
|
||||
void armv5Reset(void){
|
||||
cpuInit(&armv5Cpu, 0x00000000/*PC, set by 68k while emulating*/, armv5MemoryAccess, armv5EmulErr, armv5Hypercall, armv5SetFaultAddr);
|
||||
armv5ServiceRequest = false;
|
||||
}
|
||||
|
||||
uint32_t armv5StateSize(void){
|
||||
uint32_t size = 0;
|
||||
|
||||
//armv5Cpu
|
||||
size += sizeof(uint32_t) * 16;//armv5Cpu.regs
|
||||
size += sizeof(uint32_t) * 2;//armv5Cpu.CPSR / armv5Cpu.SPSR
|
||||
size += sizeof(uint32_t) * 3 * 6;//armv5Cpu.bank_(usr/svc/abt/und/irq/fiq)
|
||||
size += sizeof(uint32_t) * 5;//armv5Cpu.extra_regs
|
||||
size += sizeof(uint16_t) * 3;//armv5Cpu.waiting(Irqs/Fiqs) / armv5Cpu.CPAR
|
||||
size += sizeof(uint32_t);//armv5Cpu.vectorBase
|
||||
|
||||
//variables
|
||||
size += sizeof(uint8_t);//armv5ServiceRequest
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void armv5SaveState(uint8_t* data){
|
||||
uint32_t offset = 0;
|
||||
uint8_t index;
|
||||
|
||||
//armv5Cpu
|
||||
for(index = 0; index < 16; index++){
|
||||
writeStateValue32(data + offset, armv5Cpu.regs[index]);
|
||||
offset += sizeof(uint32_t);
|
||||
}
|
||||
writeStateValue32(data + offset, armv5Cpu.CPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_usr.R13);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_usr.R14);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_usr.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_svc.R13);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_svc.R14);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_svc.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_abt.R13);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_abt.R14);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_abt.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_und.R13);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_und.R14);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_und.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_irq.R13);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_irq.R14);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_irq.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_fiq.R13);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_fiq.R14);
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.bank_fiq.SPSR);
|
||||
offset += sizeof(uint32_t);
|
||||
for(index = 0; index < 5; index++){
|
||||
writeStateValue32(data + offset, armv5Cpu.extra_regs[index]);
|
||||
offset += sizeof(uint32_t);
|
||||
}
|
||||
writeStateValue16(data + offset, armv5Cpu.waitingIrqs);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValue16(data + offset, armv5Cpu.waitingFiqs);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValue16(data + offset, armv5Cpu.CPAR);
|
||||
offset += sizeof(uint16_t);
|
||||
writeStateValue32(data + offset, armv5Cpu.vectorBase);
|
||||
offset += sizeof(uint32_t);
|
||||
|
||||
//variables
|
||||
writeStateValue8(data + offset, armv5ServiceRequest);
|
||||
offset += sizeof(uint8_t);
|
||||
}
|
||||
|
||||
void armv5LoadState(uint8_t* data){
|
||||
uint32_t offset = 0;
|
||||
uint8_t index;
|
||||
|
||||
//armv5Cpu
|
||||
for(index = 0; index < 16; index++){
|
||||
armv5Cpu.regs[index] = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
}
|
||||
armv5Cpu.CPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_usr.R13 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_usr.R14 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_usr.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_svc.R13 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_svc.R14 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_svc.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_abt.R13 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_abt.R14 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_abt.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_und.R13 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_und.R14 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_und.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_irq.R13 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_irq.R14 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_irq.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_fiq.R13 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_fiq.R14 = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
armv5Cpu.bank_fiq.SPSR = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
for(index = 0; index < 5; index++){
|
||||
armv5Cpu.extra_regs[index] = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
}
|
||||
armv5Cpu.waitingIrqs = readStateValue16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
armv5Cpu.waitingFiqs = readStateValue16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
armv5Cpu.CPAR = readStateValue16(data + offset);
|
||||
offset += sizeof(uint16_t);
|
||||
armv5Cpu.vectorBase = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
|
||||
//variables
|
||||
armv5ServiceRequest = readStateValue8(data + offset);
|
||||
offset += sizeof(uint8_t);
|
||||
}
|
||||
|
||||
uint32_t armv5GetRegister(uint8_t reg){
|
||||
return cpuGetRegExternal(&armv5Cpu, reg);
|
||||
}
|
||||
|
||||
void armv5SetRegister(uint8_t reg, uint32_t value){
|
||||
cpuSetReg(&armv5Cpu, reg, value);
|
||||
}
|
||||
|
||||
int32_t armv5Execute(int32_t cycles){
|
||||
#if defined(EMU_DEBUG)
|
||||
uint32_t ranOpcodes = 0;
|
||||
#endif
|
||||
|
||||
armv5ServiceRequest = false;
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX)
|
||||
sandboxSetCpuArch(SANDBOX_CPU_ARCH_ARMV5);
|
||||
#endif
|
||||
|
||||
//execution aborts on hypercall to request things from the m68k
|
||||
while(cycles > 0 && !armv5ServiceRequest){
|
||||
cpuCycleNoIrqs(&armv5Cpu);
|
||||
cycles -= ARMV5_CYCLES_PER_OPCODE;
|
||||
|
||||
#if defined(EMU_DEBUG)
|
||||
ranOpcodes++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(EMU_DEBUG)
|
||||
debugLog("%d ARM opcodes have been ran\n", ranOpcodes);
|
||||
#endif
|
||||
|
||||
#if defined(EMU_DEBUG) && defined(EMU_SANDBOX)
|
||||
sandboxSetCpuArch(SANDBOX_CPU_ARCH_M68K);
|
||||
#endif
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
uint32_t armv5GetPc(void){
|
||||
return cpuGetRegExternal(&armv5Cpu, 15/*pc*/);
|
||||
}
|
||||
20
src/armv5.h
@@ -1,20 +0,0 @@
|
||||
#ifndef ARMV5_H
|
||||
#define ARMV5_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern bool armv5ServiceRequest;
|
||||
|
||||
void armv5Reset(void);
|
||||
uint32_t armv5StateSize(void);
|
||||
void armv5SaveState(uint8_t* data);
|
||||
void armv5LoadState(uint8_t* data);
|
||||
|
||||
uint32_t armv5GetRegister(uint8_t reg);
|
||||
void armv5SetRegister(uint8_t reg, uint32_t value);
|
||||
int32_t armv5Execute(int32_t cycles);//returns cycles left
|
||||
|
||||
uint32_t armv5GetPc(void);//only for debugging
|
||||
|
||||
#endif
|
||||
2745
src/armv5/CPU.c
173
src/armv5/CPU.h
@@ -1,173 +0,0 @@
|
||||
#ifndef UARM_CPU_H
|
||||
#define UARM_CPU_H
|
||||
|
||||
|
||||
//#define ARM_V6 //define to allow v6 instructions
|
||||
//#define THUMB_2 //define to allow Thumb2
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct ArmCpu;
|
||||
|
||||
#define ARM_SR_N 0x80000000UL
|
||||
#define ARM_SR_Z 0x40000000UL
|
||||
#define ARM_SR_C 0x20000000UL
|
||||
#define ARM_SR_V 0x10000000UL
|
||||
#define ARM_SR_Q 0x08000000UL
|
||||
#ifdef ARM_V6 //V6KT2, but without T2 to be exact (we implement things like MLS, but not Thumb2 or ThumbEE)
|
||||
#define ARM_SR_J 0x01000000UL
|
||||
#define ARM_SR_E 0x00000200UL
|
||||
#define ARM_SR_A 0x00000100UL
|
||||
#define ARM_SR_GE_0 0x00010000UL
|
||||
#define ARM_SR_GE_1 0x00020000UL
|
||||
#define ARM_SR_GE_2 0x00040000UL
|
||||
#define ARM_SR_GE_3 0x00080000UL
|
||||
#define ARM_SR_GE_MASK 0x000F0000UL
|
||||
#define ARM_SR_GE_SHIFT 16
|
||||
#endif
|
||||
#define ARM_SR_I 0x00000080UL
|
||||
#define ARM_SR_F 0x00000040UL
|
||||
#define ARM_SR_T 0x00000020UL
|
||||
#define ARM_SR_M 0x0000001FUL
|
||||
|
||||
#define ARM_SR_MODE_USR 0x00000010UL
|
||||
#define ARM_SR_MODE_FIQ 0x00000011UL
|
||||
#define ARM_SR_MODE_IRQ 0x00000012UL
|
||||
#define ARM_SR_MODE_SVC 0x00000013UL
|
||||
#define ARM_SR_MODE_ABT 0x00000017UL
|
||||
#define ARM_SR_MODE_UND 0x0000001BUL
|
||||
#define ARM_SR_MODE_SYS 0x0000001FUL
|
||||
|
||||
#define ARV_VECTOR_OFFT_RST 0x00000000UL
|
||||
#define ARM_VECTOR_OFFT_UND 0x00000004UL
|
||||
#define ARM_VECTOR_OFFT_SWI 0x00000008UL
|
||||
#define ARM_VECTOR_OFFT_P_ABT 0x0000000CUL
|
||||
#define ARM_VECTOR_OFFT_D_ABT 0x00000010UL
|
||||
#define ARM_VECTOR_OFFT_UNUSED 0x00000014UL
|
||||
#define ARM_VECTOR_OFFT_IRQ 0x00000018UL
|
||||
#define ARM_VECTOR_OFFT_FIQ 0x0000001CUL
|
||||
|
||||
#define HYPERCALL_ARM 0xF7BBBBBBUL
|
||||
#define HYPERCALL_THUMB 0xBBBBUL
|
||||
|
||||
//the following are for cpuGetRegExternal() and are generally used for debugging purposes
|
||||
#define ARM_REG_NUM_CPSR 16
|
||||
#define ARM_REG_NUM_SPSR 17
|
||||
|
||||
struct ArmCpu;
|
||||
|
||||
typedef Boolean (*ArmCoprocRegXferF) (struct ArmCpu* cpu, void* userData, Boolean two/* MCR2/MRC2 ? */, Boolean MRC, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2);
|
||||
typedef Boolean (*ArmCoprocDatProcF) (struct ArmCpu* cpu, void* userData, Boolean two/* CDP2 ? */, UInt8 op1, UInt8 CRd, UInt8 CRn, UInt8 CRm, UInt8 op2);
|
||||
typedef Boolean (*ArmCoprocMemAccsF) (struct ArmCpu* cpu, void* userData, Boolean two /* LDC2/STC2 ? */, Boolean N, Boolean store, UInt8 CRd, UInt32 addr, UInt8* option /* NULL if none */);
|
||||
typedef Boolean (*ArmCoprocTwoRegF) (struct ArmCpu* cpu, void* userData, Boolean MRRC, UInt8 op, UInt8 Rd, UInt8 Rn, UInt8 CRm);
|
||||
|
||||
typedef Boolean (*ArmCpuMemF) (struct ArmCpu* cpu, void* buf, UInt32 vaddr, UInt8 size, Boolean write, Boolean priviledged, UInt8* fsr); //read/write
|
||||
typedef Boolean (*ArmCpuHypercall) (struct ArmCpu* cpu); //return true if handled
|
||||
typedef void (*ArmCpuEmulErr) (struct ArmCpu* cpu, const char* err_str);
|
||||
|
||||
typedef void (*ArmSetFaultAdrF) (struct ArmCpu* cpu, UInt32 adr, UInt8 faultStatus);
|
||||
|
||||
#include "icache.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
coprocessors:
|
||||
|
||||
0 - DSP (pxa only)
|
||||
0, 1 - WMMX (pxa only)
|
||||
11 - VFP (arm standard)
|
||||
15 - system control (arm standard)
|
||||
*/
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
ArmCoprocRegXferF regXfer;
|
||||
ArmCoprocDatProcF dataProcessing;
|
||||
ArmCoprocMemAccsF memAccess;
|
||||
ArmCoprocTwoRegF twoRegF;
|
||||
void* userData;
|
||||
|
||||
}ArmCoprocessor;
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 R13, R14;
|
||||
UInt32 SPSR; //usr mode doesn't have an SPSR
|
||||
}ArmBankedRegs;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct ArmCpu{
|
||||
|
||||
UInt32 regs[16]; //current active regs as per current mode
|
||||
UInt32 CPSR, SPSR;
|
||||
|
||||
ArmBankedRegs bank_usr; //usr regs when in another mode
|
||||
ArmBankedRegs bank_svc; //svc regs when in another mode
|
||||
ArmBankedRegs bank_abt; //abt regs when in another mode
|
||||
ArmBankedRegs bank_und; //und regs when in another mode
|
||||
ArmBankedRegs bank_irq; //irq regs when in another mode
|
||||
ArmBankedRegs bank_fiq; //fiq regs when in another mode
|
||||
UInt32 extra_regs[5]; //fiq regs when not in fiq mode, usr regs when in fiq mode. R8-12
|
||||
|
||||
UInt16 waitingIrqs;
|
||||
UInt16 waitingFiqs;
|
||||
UInt16 CPAR;
|
||||
|
||||
ArmCoprocessor coproc[16]; //coprocessors
|
||||
|
||||
// various other cpu config options
|
||||
UInt32 vectorBase; //address of vector base
|
||||
|
||||
#ifdef ARM_V6
|
||||
|
||||
Boolean EEE; //endianness one exception entry
|
||||
Boolean impreciseAbtWaiting;
|
||||
#endif
|
||||
|
||||
ArmCpuMemF memF;
|
||||
ArmCpuEmulErr emulErrF;
|
||||
ArmCpuHypercall hypercallF;
|
||||
ArmSetFaultAdrF setFaultAdrF;
|
||||
|
||||
//icache ic; //not using icache for now
|
||||
|
||||
void* userData; //shared by all callbacks
|
||||
}ArmCpu;
|
||||
|
||||
|
||||
Err cpuInit(ArmCpu* cpu, UInt32 pc, ArmCpuMemF memF, ArmCpuEmulErr emulErrF, ArmCpuHypercall hypercallF, ArmSetFaultAdrF setFaultAdrF);
|
||||
Err cpuDeinit(ArmCpu* cp);
|
||||
void cpuCycle(ArmCpu* cpu);
|
||||
void cpuCycleNoIrqs(ArmCpu* cpu);
|
||||
void cpuIrq(ArmCpu* cpu, Boolean fiq, Boolean raise); //unraise when acknowledged
|
||||
|
||||
#ifdef ARM_V6
|
||||
|
||||
void cpuSignalImpreciseAbt(ArmCpu* cpu, Boolean raise);
|
||||
|
||||
#endif
|
||||
|
||||
UInt32 cpuGetRegExternal(ArmCpu* cpu, UInt8 reg);
|
||||
void cpuSetReg(ArmCpu* cpu, UInt8 reg, UInt32 val);
|
||||
|
||||
void cpuCoprocessorRegister(ArmCpu* cpu, UInt8 cpNum, ArmCoprocessor* coproc);
|
||||
void cpuCoprocessorUnregister(ArmCpu* cpu, UInt8 cpNum);
|
||||
|
||||
void cpuSetVectorAddr(ArmCpu* cpu, UInt32 adr);
|
||||
|
||||
UInt16 cpuGetCPAR(ArmCpu* cpu);
|
||||
void cpuSetCPAR(ArmCpu* cpu, UInt16 cpar);
|
||||
|
||||
void cpuIcacheInval(ArmCpu* cpu);
|
||||
void cpuIcacheInvalAddr(ArmCpu* cpu, UInt32 addr);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,140 +0,0 @@
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
#include "icache.h"
|
||||
|
||||
//#define ICACHE_DEBUGGING
|
||||
|
||||
|
||||
|
||||
#ifdef ICACHE_DEBUGGING
|
||||
#define _icache_fetch_func icacheFetch_
|
||||
#define _icache_test_func icacheFetch
|
||||
#else
|
||||
#define _icache_fetch_func icacheFetch
|
||||
#define _icache_test_func icacheFetch_test
|
||||
#endif
|
||||
|
||||
void icacheInval(icache* ic){
|
||||
|
||||
UInt8 i, j;
|
||||
|
||||
for(i = 0; i < ICACHE_BUCKET_NUM; i++){
|
||||
for(j = 0; j < ICACHE_BUCKET_SZ; j++) ic->lines[i][j].info = 0;
|
||||
ic->ptr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void icacheInit(icache* ic, ArmCpu* cpu, ArmCpuMemF memF){
|
||||
|
||||
ic->cpu = cpu;
|
||||
ic->memF = memF;
|
||||
|
||||
icacheInval(ic);
|
||||
}
|
||||
|
||||
|
||||
static UInt8 icachePrvHash(UInt32 addr){
|
||||
|
||||
addr >>= ICACHE_L;
|
||||
addr &= (1UL << ICACHE_S) - 1UL;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void icacheInvalAddr(icache* ic, UInt32 va){
|
||||
|
||||
UInt32 off = va % ICACHE_LINE_SZ;
|
||||
Int8 i, j, bucket;
|
||||
icacheLine* lines;
|
||||
|
||||
va -= off;
|
||||
|
||||
bucket = icachePrvHash(va);
|
||||
lines = ic->lines[bucket];
|
||||
|
||||
for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
|
||||
|
||||
if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
|
||||
|
||||
if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){ //found it!
|
||||
|
||||
lines[j].info = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
we cannot have data overlap cachelines since data is self aligned (word on 4-byte boundary, halfwords on2, etc. this is enforced elsewhere
|
||||
*/
|
||||
|
||||
Boolean _icache_fetch_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
UInt32 off = va % ICACHE_LINE_SZ;
|
||||
Int8 i, j, bucket;
|
||||
icacheLine* lines;
|
||||
icacheLine* line;
|
||||
|
||||
va -= off;
|
||||
|
||||
bucket = icachePrvHash(va);
|
||||
lines = ic->lines[bucket];
|
||||
|
||||
for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
|
||||
|
||||
if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
|
||||
|
||||
if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){ //found it!
|
||||
|
||||
if(sz == 4){
|
||||
*(UInt32*)buf = *(UInt32*)(lines[j].data + off);
|
||||
}
|
||||
else if(sz == 2){
|
||||
*(UInt16*)buf = *(UInt16*)(lines[j].data + off);
|
||||
}
|
||||
else __mem_copy(buf, lines[j].data + off, sz);
|
||||
return priviledged || !(lines[j].info & ICACHE_PRIV_MASK);
|
||||
}
|
||||
}
|
||||
//if we're here, we found nothing - time to populate the cache
|
||||
j = ic->ptr[bucket]++;
|
||||
if(ic->ptr[bucket] == ICACHE_BUCKET_SZ) ic->ptr[bucket] = 0;
|
||||
line = lines + j;
|
||||
|
||||
line->info = va | (priviledged ? ICACHE_PRIV_MASK : 0);
|
||||
if(!ic->memF(ic->cpu, line->data, va, ICACHE_LINE_SZ, false, priviledged, fsrP)){
|
||||
|
||||
return false;
|
||||
}
|
||||
line->info |= ICACHE_USED_MASK;
|
||||
|
||||
if(sz == 4){
|
||||
*(UInt32*)buf = *(UInt32*)(line->data + off);
|
||||
}
|
||||
else if(sz == 2){
|
||||
*(UInt16*)buf = *(UInt16*)(line->data + off);
|
||||
}
|
||||
else __mem_copy(buf, line->data + off, sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "stdio.h"
|
||||
Boolean _icache_test_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
|
||||
|
||||
UInt8 fsrO = -1, fsrT = -1;
|
||||
UInt8 dataO[4] = {0}, dataT[4] = {0};
|
||||
Boolean retO, retT;
|
||||
UInt8 i;
|
||||
|
||||
retO = _icache_fetch_func(ic, va, sz, priviledged, &fsrO, dataO);
|
||||
retT = ic->memF(ic->cpu, dataT, va, sz, false, priviledged, &fsrT);
|
||||
|
||||
if((retT != retO) || (fsrT != fsrO) || (dataT[0] != dataO[0]) || (dataT[1] != dataO[1]) || (dataT[2] != dataO[2]) || (dataT[3] != dataO[3])){
|
||||
|
||||
fprintf(stderr, "icache fail!");
|
||||
}
|
||||
|
||||
for(i = 0; i < sz; i++) ((UInt8*)buf)[i] = dataT[i];
|
||||
if(retT) *fsrP = fsrT;
|
||||
return retT;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#ifndef UARM_ICACHE_H
|
||||
#define UARM_ICACHE_H
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "CPU.h"
|
||||
|
||||
|
||||
#define ICACHE_L 5UL //line size is 2^L bytes
|
||||
#define ICACHE_S 6UL //number of sets is 2^S
|
||||
#define ICACHE_A 3UL //set associativity
|
||||
|
||||
|
||||
#define ICACHE_LINE_SZ (1UL << ICACHE_L)
|
||||
#define ICACHE_BUCKET_NUM (1UL << ICACHE_S)
|
||||
#define ICACHE_BUCKET_SZ (ICACHE_A)
|
||||
|
||||
|
||||
#define ICACHE_ADDR_MASK ((UInt32)-ICACHE_LINE_SZ)
|
||||
#define ICACHE_USED_MASK 1UL
|
||||
#define ICACHE_PRIV_MASK 2UL
|
||||
|
||||
typedef struct{
|
||||
|
||||
UInt32 info; //addr, masks
|
||||
UInt8 data[ICACHE_LINE_SZ];
|
||||
|
||||
}icacheLine;
|
||||
|
||||
typedef struct{
|
||||
|
||||
struct ArmCpu* cpu;
|
||||
ArmCpuMemF memF;
|
||||
icacheLine lines[ICACHE_BUCKET_NUM][ICACHE_BUCKET_SZ];
|
||||
UInt8 ptr[ICACHE_BUCKET_NUM];
|
||||
|
||||
}icache;
|
||||
|
||||
|
||||
void icacheInit(icache* ic, struct ArmCpu* cpu, ArmCpuMemF memF);
|
||||
Boolean icacheFetch(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsr, void* buf);
|
||||
void icacheInval(icache* ic);
|
||||
void icacheInvalAddr(icache* ic, UInt32 addr);
|
||||
|
||||
#endif
|
||||
539
src/armv5te/arm_interpreter.cpp
Normal file
@@ -0,0 +1,539 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "asmcode.h"
|
||||
#include "cpu.h"
|
||||
#include "cpudefs.h"
|
||||
#include "debug.h"
|
||||
#include "mmu.h"
|
||||
|
||||
// Detect overflow after an addition or subtraction
|
||||
#define ADD_OVERFLOW(left, right, sum) ((int32_t)(((left) ^ (sum)) & ((right) ^ (sum))) < 0)
|
||||
#define SUB_OVERFLOW(left, right, sum) ((int32_t)(((left) ^ (right)) & ((left) ^ (sum))) < 0)
|
||||
|
||||
static uint32_t add(uint32_t left, uint32_t right, int carry, int setcc) {
|
||||
uint32_t sum = left + right + carry;
|
||||
if (!setcc)
|
||||
return sum;
|
||||
|
||||
if (sum < left) carry = 1;
|
||||
if (sum > left) carry = 0;
|
||||
arm.cpsr_c = carry;
|
||||
arm.cpsr_v = ADD_OVERFLOW(left, right, sum);
|
||||
return sum;
|
||||
}
|
||||
|
||||
// "uint8_t shift_val" is correct here. If it is a shift by register, only the bottom 8 bits are looked at.
|
||||
static uint32_t shift(uint32_t value, uint8_t shift_type, uint8_t shift_val, bool setcc, bool has_rs)
|
||||
{
|
||||
if(shift_val == 0)
|
||||
{
|
||||
if(unlikely(!has_rs))
|
||||
{
|
||||
switch(shift_type)
|
||||
{
|
||||
case SH_ROR:
|
||||
{
|
||||
// RRX
|
||||
bool carry = arm.cpsr_c;
|
||||
if(setcc) arm.cpsr_c = value & 1;
|
||||
return value >> 1 | uint32_t(carry) << 31;
|
||||
}
|
||||
case SH_ASR:
|
||||
case SH_LSR: // #32 is encoded as LSR #0
|
||||
return shift(value, shift_type, 32, setcc, false);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
else if(likely(shift_val < 32))
|
||||
{
|
||||
switch(shift_type)
|
||||
{
|
||||
case SH_LSL:
|
||||
if(setcc) arm.cpsr_c = (value >> (32 - shift_val)) & 1;
|
||||
return value << shift_val;
|
||||
case SH_LSR:
|
||||
if(setcc) arm.cpsr_c = (value >> (shift_val - 1)) & 1;
|
||||
return value >> shift_val;
|
||||
case SH_ASR:
|
||||
if(setcc) arm.cpsr_c = (value >> (shift_val - 1)) & 1;
|
||||
if(value & (1u << 31)) //TODO: Verify!
|
||||
return ~((~value) >> shift_val);
|
||||
else
|
||||
return value >> shift_val;
|
||||
case SH_ROR:
|
||||
if(setcc) arm.cpsr_c = (value >> (shift_val - 1)) & 1;
|
||||
return value >> shift_val | (value << (32 - shift_val));
|
||||
}
|
||||
}
|
||||
else if(shift_val == 32 || shift_type == SH_ASR || shift_type == SH_ROR)
|
||||
{
|
||||
switch(shift_type)
|
||||
{
|
||||
case SH_LSL: if(setcc) arm.cpsr_c = value & 1; return 0;
|
||||
case SH_LSR: if(setcc) arm.cpsr_c = !!(value & (1u << 31)); return 0;
|
||||
case SH_ASR: if(setcc) arm.cpsr_c = !!(value & (1u << 31));
|
||||
if(value & (1u << 31))
|
||||
return 0xFFFFFFFF;
|
||||
else
|
||||
return 0x00000000;
|
||||
case SH_ROR: return shift(value, SH_ROR, shift_val & 0b11111, setcc, false);
|
||||
}
|
||||
}
|
||||
else // shift_val > 32
|
||||
{
|
||||
if(setcc)
|
||||
arm.cpsr_c = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t addr_mode_2(Instruction i)
|
||||
{
|
||||
if(!i.mem_proc.not_imm)
|
||||
return i.mem_proc.immed;
|
||||
|
||||
return shift(reg_pc(i.mem_proc.rm), i.mem_proc.shift, i.mem_proc.shift_imm, false, false);
|
||||
}
|
||||
|
||||
static uint32_t rotated_imm(Instruction i, bool setcc)
|
||||
{
|
||||
uint32_t imm = i.data_proc.immed_8;
|
||||
uint8_t count = i.data_proc.rotate_imm << 1;
|
||||
if(count == 0)
|
||||
return imm;
|
||||
|
||||
imm = (imm >> count) | (imm << (32 - count));
|
||||
if(setcc)
|
||||
arm.cpsr_c = !!(imm & (1u << 31));
|
||||
return imm;
|
||||
}
|
||||
|
||||
static uint32_t addr_mode_1(Instruction i, bool setcc)
|
||||
{
|
||||
if(i.data_proc.imm)
|
||||
return rotated_imm(i, setcc);
|
||||
|
||||
if(i.data_proc.reg_shift)
|
||||
return shift(reg_pc(i.data_proc.rm), i.data_proc.shift, reg(i.data_proc.rs), setcc, true);
|
||||
else
|
||||
return shift(reg_pc(i.data_proc.rm), i.data_proc.shift, i.data_proc.shift_imm, setcc, false);
|
||||
}
|
||||
|
||||
static inline void set_nz_flags(uint32_t value) {
|
||||
arm.cpsr_n = value >> 31;
|
||||
arm.cpsr_z = value == 0;
|
||||
}
|
||||
|
||||
static inline void set_nz_flags_64(uint64_t value) {
|
||||
arm.cpsr_n = value >> 63;
|
||||
arm.cpsr_z = value == 0;
|
||||
}
|
||||
|
||||
void do_arm_instruction(Instruction i)
|
||||
{
|
||||
bool exec = true;
|
||||
|
||||
// Shortcut for unconditional instructions
|
||||
if(likely(i.cond == CC_AL))
|
||||
goto always;
|
||||
|
||||
switch(i.cond)
|
||||
{
|
||||
case CC_EQ: case CC_NE: exec = arm.cpsr_z; break;
|
||||
case CC_CS: case CC_CC: exec = arm.cpsr_c; break;
|
||||
case CC_MI: case CC_PL: exec = arm.cpsr_n; break;
|
||||
case CC_VS: case CC_VC: exec = arm.cpsr_v; break;
|
||||
case CC_HI: case CC_LS: exec = !arm.cpsr_z && arm.cpsr_c; break;
|
||||
case CC_GE: case CC_LT: exec = arm.cpsr_n == arm.cpsr_v; break;
|
||||
case CC_GT: case CC_LE: exec = !arm.cpsr_z && arm.cpsr_n == arm.cpsr_v; break;
|
||||
case CC_NV:
|
||||
if((i.raw & 0xFD70F000) == 0xF550F000)
|
||||
return;
|
||||
else if((i.raw & 0xFE000000) == 0xFA000000)
|
||||
{
|
||||
// BLX
|
||||
arm.reg[14] = arm.reg[15];
|
||||
arm.reg[15] += 4 + ((int32_t) (i.raw << 8) >> 6) + (i.raw >> 23 & 2);
|
||||
arm.cpsr_low28 |= 0x20; // Enter Thumb mode
|
||||
return;
|
||||
}
|
||||
else
|
||||
undefined_instruction();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exec ^= i.cond & 1;
|
||||
|
||||
if(!exec)
|
||||
return;
|
||||
|
||||
always:
|
||||
uint32_t insn = i.raw;
|
||||
|
||||
if((insn & 0xE000090) == 0x0000090)
|
||||
{
|
||||
// MUL, SWP, etc.
|
||||
// LDRH, STRSH, etc.
|
||||
int type = insn >> 5 & 3;
|
||||
if (type == 0) {
|
||||
if ((insn & 0xFC000F0) == 0x0000090) {
|
||||
/* MUL, MLA: 32x32 to 32 multiplications */
|
||||
uint32_t res = reg(insn & 15)
|
||||
* reg(insn >> 8 & 15);
|
||||
if (insn & 0x0200000)
|
||||
res += reg(insn >> 12 & 15);
|
||||
|
||||
set_reg(insn >> 16 & 15, res);
|
||||
if (insn & 0x0100000) set_nz_flags(res);
|
||||
} else if ((insn & 0xF8000F0) == 0x0800090) {
|
||||
/* UMULL, UMLAL, SMULL, SMLAL: 32x32 to 64 multiplications */
|
||||
uint32_t left = reg(insn & 15);
|
||||
uint32_t right = reg(insn >> 8 & 15);
|
||||
uint32_t reg_lo = insn >> 12 & 15;
|
||||
uint32_t reg_hi = insn >> 16 & 15;
|
||||
|
||||
if (reg_lo == reg_hi)
|
||||
error("RdLo and RdHi cannot be same for 64-bit multiply");
|
||||
|
||||
uint64_t res;
|
||||
if (insn & 0x0400000) res = (int64_t)(int32_t)left * (int32_t)right;
|
||||
else res = (uint64_t)left * right;
|
||||
if (insn & 0x0200000) {
|
||||
/* Accumulate */
|
||||
res += (uint64_t)reg(reg_hi) << 32 | reg(reg_lo);
|
||||
}
|
||||
|
||||
set_reg(reg_lo, res);
|
||||
set_reg(reg_hi, res >> 32);
|
||||
if (insn & 0x0100000) set_nz_flags_64(res);
|
||||
} else if ((insn & 0xFB00FF0) == 0x1000090) {
|
||||
/* SWP, SWPB */
|
||||
uint32_t addr = reg(insn >> 16 & 15);
|
||||
uint32_t ld, st = reg(insn & 15);
|
||||
if (insn & 0x0400000) {
|
||||
ld = read_byte(addr); write_byte(addr, st);
|
||||
} else {
|
||||
ld = read_word(addr); write_word(addr, st);
|
||||
}
|
||||
set_reg(insn >> 12 & 15, ld);
|
||||
} else {
|
||||
undefined_instruction();
|
||||
}
|
||||
} else {
|
||||
/* Load/store halfword, signed byte/halfword, or doubleword */
|
||||
int base_reg = insn >> 16 & 15;
|
||||
int data_reg = insn >> 12 & 15;
|
||||
int offset = (insn & (1 << 22))
|
||||
? (insn & 0x0F) | (insn >> 4 & 0xF0)
|
||||
: reg(insn & 15);
|
||||
bool writeback = false;
|
||||
uint32_t addr = reg_pc(base_reg);
|
||||
|
||||
if (!(insn & (1 << 23))) // Subtracted offset
|
||||
offset = -offset;
|
||||
|
||||
if (insn & (1 << 24)) { // Offset or pre-indexed addressing
|
||||
addr += offset;
|
||||
offset = 0;
|
||||
writeback = insn & (1 << 21);
|
||||
} else {
|
||||
if(insn & (1 << 21))
|
||||
mmu_check_priv(addr, !((insn & (1 << 20)) || type == 2));
|
||||
|
||||
writeback = true;
|
||||
}
|
||||
|
||||
if (insn & (1 << 20)) {
|
||||
uint32_t data;
|
||||
if (base_reg == data_reg && writeback)
|
||||
error("Load instruction modifies base register twice");
|
||||
if (type == 1) data = read_half(addr); /* LDRH */
|
||||
else if (type == 2) data = (int8_t) read_byte(addr); /* LDRSB */
|
||||
else data = (int16_t)read_half(addr); /* LDRSH */
|
||||
set_reg(data_reg, data);
|
||||
} else if (type == 1) { /* STRH */
|
||||
write_half(addr, reg(data_reg));
|
||||
} else {
|
||||
if (data_reg & 1) error("LDRD/STRD with odd-numbered data register");
|
||||
if (type == 2) { /* LDRD */
|
||||
if ((base_reg & ~1) == data_reg && writeback)
|
||||
error("Load instruction modifies base register twice");
|
||||
uint32_t low = read_word(addr);
|
||||
uint32_t high = read_word(addr + 4);
|
||||
set_reg(data_reg, low);
|
||||
set_reg(data_reg + 1, high);
|
||||
} else { /* STRD */
|
||||
write_word(addr, reg(data_reg));
|
||||
write_word(addr + 4, reg(data_reg + 1));
|
||||
}
|
||||
}
|
||||
if (writeback)
|
||||
set_reg(base_reg, addr + offset);
|
||||
}
|
||||
}
|
||||
else if((insn & 0xD900000) == 0x1000000)
|
||||
{
|
||||
// BLX, MRS, MSR, SMUL, etc.
|
||||
if ((insn & 0xFFFFFD0) == 0x12FFF10) {
|
||||
/* B(L)X: Branch(, link,) and exchange T bit */
|
||||
uint32_t target = reg_pc(insn & 15);
|
||||
if (insn & 0x20)
|
||||
arm.reg[14] = arm.reg[15];
|
||||
set_reg_bx(15, target);
|
||||
} else if ((insn & 0xFBF0FFF) == 0x10F0000) {
|
||||
/* MRS: Move reg <- status */
|
||||
set_reg(insn >> 12 & 15, (insn & 0x0400000) ? get_spsr() : get_cpsr());
|
||||
} else if ((insn & 0xFB0FFF0) == 0x120F000 ||
|
||||
(insn & 0xFB0F000) == 0x320F000) {
|
||||
/* MSR: Move status <- reg/imm */
|
||||
uint32_t val, mask = 0;
|
||||
if (insn & 0x2000000)
|
||||
val = rotated_imm(i, false);
|
||||
else
|
||||
val = reg(insn & 15);
|
||||
if (insn & 0x0080000) mask |= 0xFF000000;
|
||||
if (insn & 0x0040000) mask |= 0x00FF0000;
|
||||
if (insn & 0x0020000) mask |= 0x0000FF00;
|
||||
if (insn & 0x0010000) mask |= 0x000000FF;
|
||||
if (insn & 0x0400000)
|
||||
set_spsr(val, mask);
|
||||
else
|
||||
set_cpsr(val, mask);
|
||||
} else if ((insn & 0xF900090) == 0x1000080) {
|
||||
int32_t left = reg(insn & 15);
|
||||
int16_t right = reg((insn >> 8) & 15) >> ((insn & 0x40) ? 16 : 0);
|
||||
int32_t product;
|
||||
int type = insn >> 21 & 3;
|
||||
|
||||
if (type == 1) {
|
||||
/* SMULW<y>, SMLAW<y>: Signed 32x16 to 48 multiply, uses only top 32 bits */
|
||||
product = (int64_t)left * right >> 16;
|
||||
if (!(insn & 0x20))
|
||||
goto accumulate;
|
||||
} else {
|
||||
/* SMUL<x><y>, SMLA<x><y>, SMLAL<x><y>: Signed 16x16 to 32 multiply */
|
||||
product = (int16_t)(left >> ((insn & 0x20) ? 16 : 0)) * right;
|
||||
}
|
||||
if (type == 2) {
|
||||
/* SMLAL<x><y>: 64-bit accumulate */
|
||||
uint32_t reg_lo = insn >> 12 & 15;
|
||||
uint32_t reg_hi = insn >> 16 & 15;
|
||||
int64_t sum;
|
||||
if (reg_lo == reg_hi)
|
||||
error("RdLo and RdHi cannot be same for 64-bit accumulate");
|
||||
sum = product + ((uint64_t)reg(reg_hi) << 32 | reg(reg_lo));
|
||||
set_reg(reg_lo, sum);
|
||||
set_reg(reg_hi, sum >> 32);
|
||||
} else if (type == 0) accumulate: {
|
||||
/* SMLA<x><y>, SMLAW<y>: 32-bit accumulate */
|
||||
int32_t acc = reg(insn >> 12 & 15);
|
||||
int32_t sum = product + acc;
|
||||
/* Set Q flag on overflow */
|
||||
arm.cpsr_low28 |= ADD_OVERFLOW(product, acc, sum) << 27;
|
||||
set_reg(insn >> 16 & 15, sum);
|
||||
} else {
|
||||
/* SMUL<x><y>, SMULW<y>: No accumulate */
|
||||
set_reg(insn >> 16 & 15, product);
|
||||
}
|
||||
} else if ((insn & 0xF900FF0) == 0x1000050) {
|
||||
/* QADD, QSUB, QDADD, QDSUB: Saturated arithmetic */
|
||||
int32_t left = reg(insn & 15);
|
||||
int32_t right = reg(insn >> 16 & 15);
|
||||
int32_t res, overflow;
|
||||
if (insn & 0x400000) {
|
||||
/* Doubled right operand */
|
||||
res = right << 1;
|
||||
if (ADD_OVERFLOW(right, right, res)) {
|
||||
/* Overflow, set Q flag and saturate */
|
||||
arm.cpsr_low28 |= 1 << 27;
|
||||
res = (res < 0) ? 0x7FFFFFFF : 0x80000000;
|
||||
}
|
||||
right = res;
|
||||
}
|
||||
if (!(insn & 0x200000)) {
|
||||
res = left + right;
|
||||
overflow = ADD_OVERFLOW(left, right, res);
|
||||
} else {
|
||||
res = left - right;
|
||||
overflow = SUB_OVERFLOW(left, right, res);
|
||||
}
|
||||
if (overflow) {
|
||||
/* Set Q flag and saturate */
|
||||
arm.cpsr_low28 |= 1 << 27;
|
||||
res = (res < 0) ? 0x7FFFFFFF : 0x80000000;
|
||||
}
|
||||
set_reg(insn >> 12 & 15, res);
|
||||
} else if ((insn & 0xFFF0FF0) == 0x16F0F10) {
|
||||
/* CLZ: Count leading zeros */
|
||||
int32_t value = reg(insn & 15);
|
||||
uint32_t zeros;
|
||||
for (zeros = 0; zeros < 32 && value >= 0; zeros++)
|
||||
value <<= 1;
|
||||
set_reg(insn >> 12 & 15, zeros);
|
||||
} else if ((insn & 0xFFF000F0) == 0xE1200070) {
|
||||
gui_debug_printf("Software breakpoint at %08x (%04x)\n",
|
||||
arm.reg[15], (insn >> 4 & 0xFFF0) | (insn & 0xF));
|
||||
debugger(DBG_EXEC_BREAKPOINT, 0);
|
||||
} else
|
||||
undefined_instruction();
|
||||
}
|
||||
else if(likely((insn & 0xC000000) == 0x0000000))
|
||||
{
|
||||
// Data processing
|
||||
bool carry = arm.cpsr_c,
|
||||
setcc = i.data_proc.s;
|
||||
|
||||
uint32_t left = reg_pc(i.data_proc.rn),
|
||||
right = addr_mode_1(i, setcc),
|
||||
res = 0;
|
||||
|
||||
switch(i.data_proc.op)
|
||||
{
|
||||
case OP_AND: res = left & right; break;
|
||||
case OP_EOR: res = left ^ right; break;
|
||||
case OP_SUB: res = add( left, ~right, 1, setcc); break;
|
||||
case OP_RSB: res = add(~left, right, 1, setcc); break;
|
||||
case OP_ADD: res = add( left, right, 0, setcc); break;
|
||||
case OP_ADC: res = add( left, right, carry, setcc); break;
|
||||
case OP_SBC: res = add( left, ~right, carry, setcc); break;
|
||||
case OP_RSC: res = add(~left, right, carry, setcc); break;
|
||||
case OP_TST: res = left & right; break;
|
||||
case OP_TEQ: res = left ^ right; break;
|
||||
case OP_CMP: res = add( left, ~right, 1, setcc); break;
|
||||
case OP_CMN: res = add( left, right, 0, setcc); break;
|
||||
case OP_ORR: res = left | right; break;
|
||||
case OP_MOV: res = right; break;
|
||||
case OP_BIC: res = left & ~right; break;
|
||||
case OP_MVN: res = ~right; break;
|
||||
}
|
||||
|
||||
if(i.data_proc.op < OP_TST || i.data_proc.op > OP_CMN)
|
||||
set_reg_pc(i.data_proc.rd, res);
|
||||
|
||||
if(setcc)
|
||||
{
|
||||
// Used for returning from exceptions, for instance
|
||||
if(i.data_proc.rd == 15)
|
||||
set_cpsr_full(get_spsr());
|
||||
else
|
||||
{
|
||||
arm.cpsr_n = res >> 31;
|
||||
arm.cpsr_z = res == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((insn & 0xFF000F0) == 0x7F000F0)
|
||||
undefined_instruction();
|
||||
else if((insn & 0xC000000) == 0x4000000)
|
||||
{
|
||||
// LDR, STRB, etc.
|
||||
uint32_t base = reg_pc(i.mem_proc.rn),
|
||||
offset = addr_mode_2(i);
|
||||
if(!i.mem_proc.u)
|
||||
offset = -offset;
|
||||
|
||||
// Pre-indexed or offset
|
||||
if(i.mem_proc.p)
|
||||
base += offset; // Writeback for pre-indexed handled after access
|
||||
else if(i.mem_proc.w) // Usermode Access
|
||||
mmu_check_priv(base, !i.mem_proc.l);
|
||||
|
||||
// Byte access
|
||||
if(i.mem_proc.b)
|
||||
{
|
||||
if(i.mem_proc.l) set_reg_bx(i.mem_proc.rd, read_byte(base));
|
||||
else write_byte(base, reg_pc_mem(i.mem_proc.rd));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i.mem_proc.l) set_reg_bx(i.mem_proc.rd, read_word(base));
|
||||
else write_word(base, reg_pc_mem(i.mem_proc.rd));
|
||||
}
|
||||
|
||||
// Post-indexed addressing
|
||||
if(!i.mem_proc.p)
|
||||
base += offset;
|
||||
|
||||
// Writeback
|
||||
if(!i.mem_proc.p || i.mem_proc.w)
|
||||
set_reg(i.mem_proc.rn, base);
|
||||
}
|
||||
else if((insn & 0xE000000) == 0x8000000)
|
||||
{
|
||||
// LDM, STM, etc.
|
||||
int base_reg = insn >> 16 & 15;
|
||||
uint32_t addr = reg(base_reg);
|
||||
uint32_t new_base = addr;
|
||||
int count = __builtin_popcount(i.mem_multi.reglist);
|
||||
|
||||
if (i.mem_multi.u) { // Increasing
|
||||
if (i.mem_multi.w) // Writeback
|
||||
new_base += count * 4;
|
||||
if (i.mem_multi.p) // Preincrement
|
||||
addr += 4;
|
||||
} else { // Decreasing
|
||||
addr -= count * 4;
|
||||
if (i.mem_multi.w) // Writeback
|
||||
new_base = addr;
|
||||
if (!i.mem_multi.p) // Postdecrement
|
||||
addr += 4;
|
||||
}
|
||||
|
||||
for (unsigned reg = 0, reglist = i.mem_multi.reglist; reglist && reg < 15; reglist >>= 1, reg++) {
|
||||
if ((reglist & 1) == 0)
|
||||
continue;
|
||||
|
||||
uint32_t *reg_ptr = &arm.reg[reg];
|
||||
if (i.mem_multi.s && !i.mem_multi.w && !(i.mem_multi.reglist & (1<<15))) {
|
||||
// User-mode registers
|
||||
int mode = arm.cpsr_low28 & 0x1F;
|
||||
if (reg >= 13) {
|
||||
if (mode != MODE_USR && mode != MODE_SYS) reg_ptr = &arm.r13_usr[reg - 13];
|
||||
} else if (reg >= 8) {
|
||||
if (mode == MODE_FIQ) reg_ptr = &arm.r8_usr[reg - 8];
|
||||
}
|
||||
}
|
||||
if (i.mem_multi.l) { // Load
|
||||
if (reg_ptr == &arm.reg[base_reg]) {
|
||||
if (i.mem_multi.w) // Writeback
|
||||
error("Load instruction modifies base register twice");
|
||||
reg_ptr = &new_base;
|
||||
}
|
||||
*reg_ptr = read_word(addr);
|
||||
} else { // Store
|
||||
write_word(addr, *reg_ptr);
|
||||
}
|
||||
addr += 4;
|
||||
}
|
||||
if (i.mem_multi.reglist & (1 << 15)) {
|
||||
if (i.mem_multi.l) // Load
|
||||
set_reg_bx(15, read_word(addr));
|
||||
else // Store
|
||||
write_word(addr, reg_pc_mem(15));
|
||||
}
|
||||
arm.reg[base_reg] = new_base;
|
||||
if (i.mem_multi.l && i.mem_multi.s && i.mem_multi.reglist & (1<<15))
|
||||
set_cpsr_full(get_spsr());
|
||||
}
|
||||
else if((insn & 0xE000000) == 0xA000000)
|
||||
{
|
||||
// B and BL
|
||||
if(i.branch.l)
|
||||
arm.reg[14] = arm.reg[15];
|
||||
arm.reg[15] += (int32_t) (i.branch.immed << 8) >> 6;
|
||||
arm.reg[15] += 4;
|
||||
}
|
||||
else if((insn & 0xF000F10) == 0xE000F10)
|
||||
do_cp15_instruction(i);
|
||||
else if((insn & 0xF000F10) == 0xE000E10)
|
||||
do_cp14_instruction(i);
|
||||
else if((insn & 0xF000000) == 0xF000000)
|
||||
cpu_exception(EX_SWI);
|
||||
else
|
||||
undefined_instruction();
|
||||
}
|
||||
11
src/armv5te/armsnippets.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Declarations for armsnippets */
|
||||
|
||||
#ifndef _H_ARMSNIPPETS
|
||||
#define _H_ARMSNIPPETS
|
||||
|
||||
//#include <stdbool.h>
|
||||
|
||||
#define armloader_cb()
|
||||
//bool armloader_load_snippet(enum SNIPPETS snippet, struct armloader_load_params params[], unsigned params_num, void (*callback)(struct arm_state *));
|
||||
|
||||
#endif
|
||||
167
src/armv5te/asmcode.c
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "asmcode.h"
|
||||
#include "debug.h"
|
||||
#include "mmu.h"
|
||||
#include "mem.h"
|
||||
|
||||
//TODO: Read breakpoints, alignment checks
|
||||
|
||||
#if defined(NO_TRANSLATION)
|
||||
void flush_translations() {}
|
||||
#endif
|
||||
|
||||
uint32_t FASTCALL read_word(uint32_t addr)
|
||||
{
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1));
|
||||
|
||||
//If the sum doesn't contain the address directly
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID) //Invalid entry
|
||||
{
|
||||
addr_cache_miss(addr, false, data_abort);
|
||||
return read_word(addr);
|
||||
}
|
||||
else //Physical address
|
||||
{
|
||||
entry &= ~AC_FLAGS;
|
||||
entry += addr;
|
||||
return mmio_read_word(entry);
|
||||
}
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
|
||||
return *(uint32_t*)entry;
|
||||
}
|
||||
|
||||
uint32_t FASTCALL read_byte(uint32_t addr)
|
||||
{
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1));
|
||||
|
||||
//If the sum doesn't contain the address directly
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID) //Invalid entry
|
||||
{
|
||||
addr_cache_miss(addr, false, data_abort);
|
||||
return read_byte(addr);
|
||||
}
|
||||
else //Physical address
|
||||
{
|
||||
entry &= ~AC_FLAGS;
|
||||
entry += addr;
|
||||
return mmio_read_byte(entry);
|
||||
}
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
|
||||
return *(uint8_t*)entry;
|
||||
}
|
||||
|
||||
uint32_t FASTCALL read_half(uint32_t addr)
|
||||
{
|
||||
addr &= ~1;
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1));
|
||||
|
||||
//If the sum doesn't contain the address directly
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID) //Invalid entry
|
||||
{
|
||||
addr_cache_miss(addr, false, data_abort);
|
||||
return read_half(addr);
|
||||
}
|
||||
else //Physical address
|
||||
{
|
||||
entry &= ~AC_FLAGS;
|
||||
entry += addr;
|
||||
return mmio_read_half(entry);
|
||||
}
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
|
||||
return *(uint16_t*)entry;
|
||||
}
|
||||
|
||||
void FASTCALL write_byte(uint32_t addr, uint32_t value)
|
||||
{
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1) + 1);
|
||||
|
||||
//If the sum doesn't contain the address directly
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID) //Invalid entry
|
||||
{
|
||||
addr_cache_miss(addr, true, data_abort);
|
||||
return write_byte(addr, value);
|
||||
}
|
||||
else //Physical address
|
||||
{
|
||||
entry &= ~AC_FLAGS;
|
||||
entry += addr;
|
||||
return mmio_write_byte(entry, value);
|
||||
}
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
|
||||
if(RAM_FLAGS(entry & ~3) & DO_WRITE_ACTION)
|
||||
write_action((void*) entry);
|
||||
*(uint8_t*)entry = value;
|
||||
}
|
||||
|
||||
void FASTCALL write_half(uint32_t addr, uint32_t value)
|
||||
{
|
||||
addr &= ~1;
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1) + 1);
|
||||
|
||||
//If the sum doesn't contain the address directly
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID) //Invalid entry
|
||||
{
|
||||
addr_cache_miss(addr, true, data_abort);
|
||||
return write_half(addr, value);
|
||||
}
|
||||
else //Physical address
|
||||
{
|
||||
entry &= ~AC_FLAGS;
|
||||
entry += addr;
|
||||
return mmio_write_half(entry, value);
|
||||
}
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
|
||||
if(RAM_FLAGS(entry & ~3) & DO_WRITE_ACTION)
|
||||
write_action((void*) entry);
|
||||
*(uint16_t*)entry = value;
|
||||
}
|
||||
|
||||
void FASTCALL write_word(uint32_t addr, uint32_t value)
|
||||
{
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1) + 1);
|
||||
|
||||
//If the sum doesn't contain the address directly
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID) //Invalid entry
|
||||
{
|
||||
addr_cache_miss(addr, true, data_abort);
|
||||
return write_word(addr, value);
|
||||
}
|
||||
else //Physical address
|
||||
{
|
||||
entry &= ~AC_FLAGS;
|
||||
entry += addr;
|
||||
return mmio_write_word(entry, value);
|
||||
}
|
||||
}
|
||||
entry += addr;
|
||||
|
||||
if(RAM_FLAGS(entry & ~3) & DO_WRITE_ACTION)
|
||||
write_action((void*) entry);
|
||||
*(uint32_t*)entry = value;
|
||||
}
|
||||
50
src/armv5te/asmcode.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Declarations for asmcode.S */
|
||||
|
||||
#ifndef _H_ASMCODE
|
||||
#define _H_ASMCODE
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
// Supply the pointer to the instruction directly to avoid read_instruction
|
||||
void translation_enter(void *ptr) __asm__("translation_enter");
|
||||
#define TRANSLATION_ENTER_HAS_PTR 1
|
||||
#else
|
||||
void translation_enter() __asm__("translation_enter");
|
||||
#define TRANSLATION_ENTER_HAS_PTR 0
|
||||
#endif
|
||||
|
||||
// Jump to the translated code starting at ptr.
|
||||
// Checks for cycle_count_delta and exits if necessary.
|
||||
void translation_jmp(void *ptr) __asm__("translation_jmp");
|
||||
// Checks whether code at ptr is now translated and if so, jumps to it
|
||||
void translation_jmp_ptr(void *ptr) __asm__("translation_jmp_ptr");
|
||||
|
||||
void * FASTCALL read_instruction(uint32_t addr) __asm__("read_instruction");
|
||||
uint32_t FASTCALL read_byte(uint32_t addr) __asm__("read_byte");
|
||||
uint32_t FASTCALL read_half(uint32_t addr) __asm__("read_half");
|
||||
uint32_t FASTCALL read_word(uint32_t addr) __asm__("read_word");
|
||||
void FASTCALL write_byte(uint32_t addr, uint32_t value) __asm__("write_byte");
|
||||
void FASTCALL write_half(uint32_t addr, uint32_t value) __asm__("write_half");
|
||||
void FASTCALL write_word(uint32_t addr, uint32_t value) __asm__("write_word");
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
|
||||
// For some JITs there's in internal version called by JIT'ed code that can't be called
|
||||
// from outside the JIT'ed code
|
||||
uint32_t FASTCALL read_byte_asm(uint32_t addr) __asm__("read_byte_asm");
|
||||
uint32_t FASTCALL read_half_asm(uint32_t addr) __asm__("read_half_asm");
|
||||
uint32_t FASTCALL read_word_asm(uint32_t addr) __asm__("read_word_asm");
|
||||
void FASTCALL write_byte_asm(uint32_t addr, uint32_t value) __asm__("write_byte_asm");
|
||||
void FASTCALL write_half_asm(uint32_t addr, uint32_t value) __asm__("write_half_asm");
|
||||
void FASTCALL write_word_asm(uint32_t addr, uint32_t value) __asm__("write_word_asm");
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
400
src/armv5te/asmcode_aarch64.S
Normal file
@@ -0,0 +1,400 @@
|
||||
.macro loadsym reg, name
|
||||
#ifdef __clang__
|
||||
adrp \reg, \name\()@PAGE
|
||||
add \reg, \reg, \name\()@PAGEOFF
|
||||
#else
|
||||
adrp \reg, \name
|
||||
add \reg, \reg, #:lo12:\name
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.data
|
||||
.align 3
|
||||
|
||||
.global arm
|
||||
.global cycle_count_delta
|
||||
.global cpu_events
|
||||
.global addr_cache
|
||||
|
||||
translation_sp: .global translation_sp
|
||||
.xword 0
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
.global data_abort
|
||||
|
||||
translation_enter: .global translation_enter
|
||||
stp x19, x30, [sp, #-16]!
|
||||
stp x21, x22, [sp, #-16]!
|
||||
stp x23, x24, [sp, #-16]!
|
||||
stp x25, x26, [sp, #-16]!
|
||||
|
||||
// Store s into translation_sp
|
||||
mov x1, sp
|
||||
loadsym x2, translation_sp
|
||||
str x1, [x2]
|
||||
|
||||
loadsym x19, arm
|
||||
loadsym x26, addr_cache
|
||||
ldr x26, [x26]
|
||||
|
||||
bl load_virt
|
||||
b translation_next_enter
|
||||
|
||||
// Enter translation, check for thumb
|
||||
translation_next_bx: .global translation_next_bx
|
||||
tbnz w0, #0, to_thumb // if(pc & 1) goto to_thumb;
|
||||
|
||||
// Enter translation; sets arm.reg[15] = w0
|
||||
translation_next: .global translation_next
|
||||
mrs x17, nzcv
|
||||
str w0, [x19, #15*4]
|
||||
|
||||
mov w1, w0
|
||||
|
||||
lsr x0, x0, #10
|
||||
lsl x0, x0, #4
|
||||
ldr x0, [x26, x0] // x0 = addr_cache[(x0 >> 10) << 1]
|
||||
tbnz x0, #0, save_return // if(x0 & 1) goto save_return;
|
||||
|
||||
// Load RAM_FLAGS
|
||||
add x0, x0, x1 // x0 = pointer to memory at x0
|
||||
|
||||
// Enter translation at x0 (has to be ptr to arm.reg[15]'s memory)
|
||||
translation_next_enter:
|
||||
loadsym x23, cpu_events
|
||||
ldr w23, [x23]
|
||||
cbnz w23, save_return // if(cpu_events) goto save_return;
|
||||
|
||||
mov x21, #80*1024*1024
|
||||
ldr w21, [x0, x21] // w21 = RAM_FLAGS(x0)
|
||||
tbz w21, #5, save_return // if((RAM_FLAGS(x0) & RF_CODE_TRANSLATED) == 0) goto save_return;
|
||||
lsr w21, w21, #9 // w21 = w21 >> RFS_TRANSLATION_INDEX
|
||||
|
||||
loadsym x23, translation_table
|
||||
add x23, x23, x21, lsl #5 // x23 = &translation_table[RAM_FLAGS(x0) >> RFS_TRANSLATION_INDEX]
|
||||
|
||||
ldr x24, [x23, #1*8] // x24 = x3->jump_table
|
||||
ldp x25, x21, [x23, #2*8] // x25 = x23->start_ptr; x21 = x23->end_ptr
|
||||
|
||||
sub x21, x21, x0 // x21 = end_ptr - insn_ptr
|
||||
lsr x21, x21, #2 // x21: number of instructions until the end
|
||||
|
||||
sub x25, x0, x25 // x25 = insn_ptr - start_ptr
|
||||
//lsr x25, x25, #2 // x25 = count of instructions
|
||||
//lsl x25, x25, #3
|
||||
lsl x25, x25, #1
|
||||
ldr x0, [x24, x25] // x0 = jump_table[(insn_ptr - start_ptr) / 4]
|
||||
|
||||
// add number of instructions to cycle_count_delta
|
||||
loadsym x24, cycle_count_delta
|
||||
ldr w25, [x24]
|
||||
add w25, w25, w21
|
||||
str w25, [x24]
|
||||
cmp w25, #0
|
||||
bpl save_return // if(cycle_count_delta > 0) goto save_return;
|
||||
|
||||
msr nzcv, x17
|
||||
br x0
|
||||
|
||||
translation_jmp_ptr: .global translation_jmp_ptr
|
||||
mrs x17, nzcv
|
||||
|
||||
b translation_next_enter
|
||||
|
||||
translation_jmp: .global translation_jmp
|
||||
mrs x17, nzcv
|
||||
|
||||
// add number of instructions to cycle_count_delta
|
||||
loadsym x24, cycle_count_delta
|
||||
ldr w25, [x24]
|
||||
adds w25, w25, #4 // We don't know how much will be executed, so use a possible number
|
||||
bpl save_return
|
||||
str w25, [x24]
|
||||
|
||||
msr nzcv, x17
|
||||
|
||||
br x0
|
||||
|
||||
to_thumb:
|
||||
mrs x17, nzcv
|
||||
sub w0, w0, #1
|
||||
str w0, [x19, #15*4] // arm.reg[15] = w0 - 1
|
||||
ldr w1, [x19, #16*4]
|
||||
orr w1, w1, #0x20
|
||||
str w1, [x19, #16*4] // arm.cpsr_low28 |= 0x20
|
||||
|
||||
save_return:
|
||||
loadsym x0, translation_sp
|
||||
mov x1, #0
|
||||
str x1, [x0]
|
||||
|
||||
bl save_virt
|
||||
|
||||
ldp x25, x26, [sp], #16
|
||||
ldp x23, x24, [sp], #16
|
||||
ldp x21, x22, [sp], #16
|
||||
ldp x19, x30, [sp], #16
|
||||
ret
|
||||
|
||||
// Saves the virtual CPU state
|
||||
save_virt:
|
||||
stp w2, w3, [x19, #0*4]
|
||||
stp w4, w5, [x19, #2*4]
|
||||
stp w6, w7, [x19, #4*4]
|
||||
stp w8, w9, [x19, #6*4]
|
||||
stp w10, w11, [x19, #8*4]
|
||||
stp w12, w13, [x19, #10*4]
|
||||
stp w14, w15, [x19, #12*4]
|
||||
str w16, [x19, #14*4]
|
||||
// Save nzcv (in x17) to struct arm_state again
|
||||
ubfx x2, x17, #31, #1
|
||||
ubfx x3, x17, #30, #1
|
||||
ubfx x4, x17, #29, #1
|
||||
ubfx x5, x17, #28, #1
|
||||
strb w2, [x19, #17*4+0]
|
||||
strb w3, [x19, #17*4+1]
|
||||
strb w4, [x19, #17*4+2]
|
||||
strb w5, [x19, #17*4+3]
|
||||
ret
|
||||
|
||||
// Loads the virtual CPU state
|
||||
// x19 has to be a pointer to the arm_state
|
||||
load_virt:
|
||||
// Assemble virtual cpsr_nzcv in x17
|
||||
ldrb w17, [x19, #17*4+0] // x17 = bit 31
|
||||
ldrb w3, [x19, #17*4+1] // w3 = bit 30
|
||||
ldrb w4, [x19, #17*4+2] // w4 = bit 29
|
||||
ldrb w5, [x19, #17*4+3] // w5 = bit 28
|
||||
lsl w17, w17, #31
|
||||
bfi w17, w3, #30, #1
|
||||
bfi w17, w4, #29, #1
|
||||
bfi w17, w5, #28, #1
|
||||
ldp w2, w3, [x19, #0*4]
|
||||
ldp w4, w5, [x19, #2*4]
|
||||
ldp w6, w7, [x19, #4*4]
|
||||
ldp w8, w9, [x19, #6*4]
|
||||
ldp w10, w11, [x19, #8*4]
|
||||
ldp w12, w13, [x19, #10*4]
|
||||
ldp w14, w15, [x19, #12*4]
|
||||
ldr w16, [x19, #14*4]
|
||||
ret
|
||||
|
||||
read_word_asm: .global read_word_asm
|
||||
lsr w22, w0, #10
|
||||
add x21, x26, x22, lsl #4 // x21 = &addr_cache[(x0 >> 10) << 1]
|
||||
0: ldr x22, [x21] // x22 = *x21
|
||||
tbnz x22, #0, 1f
|
||||
ldr w0, [x22, x0]
|
||||
ret
|
||||
|
||||
// Not cached
|
||||
1: tbnz x22, #1, 2f
|
||||
// MMIO
|
||||
bic x22, x22, #3
|
||||
stp x30, x23, [sp, #-16]!
|
||||
add x0, x0, x22
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
bl mmio_read_word
|
||||
bl load_virt
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
ret
|
||||
|
||||
// Invalid
|
||||
2: stp x30, x23, [sp, #-16]!
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
mov x1, #0
|
||||
loadsym x2, data_abort
|
||||
bl addr_cache_miss
|
||||
bl load_virt
|
||||
ldp x0, x1, [sp], #16
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
b 0b // Try again
|
||||
|
||||
read_half_asm: .global read_half_asm
|
||||
bic w22, w22, #1
|
||||
lsr w22, w0, #10
|
||||
add x21, x26, x22, lsl #4 // x21 = &addr_cache[(x0 >> 10) << 1]
|
||||
0: ldr x22, [x21] // x22 = *x21
|
||||
tbnz x22, #0, 1f
|
||||
ldrh w0, [x22, x0]
|
||||
ret
|
||||
|
||||
// Not cached
|
||||
1: tbnz x22, #1, 2f
|
||||
// MMIO
|
||||
bic x22, x22, #3
|
||||
stp x30, x23, [sp, #-16]!
|
||||
add x0, x0, x22
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
bl mmio_read_half
|
||||
bl load_virt
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
ret
|
||||
|
||||
// Invalid
|
||||
2: stp x30, x23, [sp, #-16]!
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
mov x1, #0
|
||||
loadsym x2, data_abort
|
||||
bl addr_cache_miss
|
||||
bl load_virt
|
||||
ldp x0, x1, [sp], #16
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
b 0b // Try again
|
||||
|
||||
read_byte_asm: .global read_byte_asm
|
||||
lsr w22, w0, #10
|
||||
add x21, x26, x22, lsl #4 // x21 = &addr_cache[(x0 >> 10) << 1]
|
||||
0: ldr x22, [x21] // x22 = *x21
|
||||
tbnz x22, #0, 1f
|
||||
ldrb w0, [x22, x0]
|
||||
ret
|
||||
|
||||
// Not cached
|
||||
1: tbnz x22, #1, 2f
|
||||
// MMIO
|
||||
bic x22, x22, #3
|
||||
stp x30, x23, [sp, #-16]!
|
||||
add x0, x0, x22
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
bl mmio_read_byte
|
||||
bl load_virt
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
ret
|
||||
|
||||
// Invalid
|
||||
2: stp x30, x23, [sp, #-16]!
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
mov x1, #0
|
||||
loadsym x2, data_abort
|
||||
bl addr_cache_miss
|
||||
bl load_virt
|
||||
ldp x0, x1, [sp], #16
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
b 0b // Try again
|
||||
|
||||
write_word_asm: .global write_word_asm
|
||||
lsr w22, w0, #10
|
||||
add x21, x26, x22, lsl #4 // x21 = &addr_cache[(x0 >> 10) << 1]
|
||||
0: ldr x22, [x21, #8] // x22 = *(x21+1)
|
||||
tbnz x22, #0, 1f
|
||||
str w1, [x22, x0]
|
||||
ret
|
||||
|
||||
// Not cached
|
||||
1: tbnz x22, #1, 2f
|
||||
// MMIO
|
||||
bic x22, x22, #3
|
||||
stp x30, x23, [sp, #-16]!
|
||||
add x0, x0, x22
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
bl mmio_write_word
|
||||
bl load_virt
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
ret
|
||||
|
||||
// Invalid
|
||||
2: stp x30, x23, [sp, #-16]!
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
mov x1, #1
|
||||
loadsym x2, data_abort
|
||||
bl addr_cache_miss
|
||||
bl load_virt
|
||||
ldp x0, x1, [sp], #16
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
b 0b // Try again
|
||||
|
||||
write_half_asm: .global write_half_asm
|
||||
bic w22, w22, #1
|
||||
lsr w22, w0, #10
|
||||
add x21, x26, x22, lsl #4 // x21 = &addr_cache[(x0 >> 10) << 1]
|
||||
0: ldr x22, [x21, #8] // x22 = *(x21+1)
|
||||
tbnz x22, #0, 1f
|
||||
strh w1, [x22, x0]
|
||||
ret
|
||||
|
||||
// Not cached
|
||||
1: tbnz x22, #1, 2f
|
||||
// MMIO
|
||||
bic x22, x22, #3
|
||||
stp x30, x23, [sp, #-16]!
|
||||
add x0, x0, x22
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
bl mmio_write_half
|
||||
bl load_virt
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
ret
|
||||
|
||||
// Invalid
|
||||
2: stp x30, x23, [sp, #-16]!
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
mov x1, #1
|
||||
loadsym x2, data_abort
|
||||
bl addr_cache_miss
|
||||
bl load_virt
|
||||
ldp x0, x1, [sp], #16
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
b 0b // Try again
|
||||
|
||||
write_byte_asm: .global write_byte_asm
|
||||
lsr w22, w0, #10
|
||||
add x21, x26, x22, lsl #4 // x21 = &addr_cache[(x0 >> 10) << 1]
|
||||
0: ldr x22, [x21, #8] // x22 = *(x21+1)
|
||||
tbnz x22, #0, 1f
|
||||
strb w1, [x22, x0]
|
||||
ret
|
||||
|
||||
// Not cached
|
||||
1: tbnz x22, #1, 2f
|
||||
// MMIO
|
||||
bic x22, x22, #3
|
||||
stp x30, x23, [sp, #-16]!
|
||||
add x0, x0, x22
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
bl mmio_write_byte
|
||||
bl load_virt
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
ret
|
||||
|
||||
// Invalid
|
||||
2: stp x30, x23, [sp, #-16]!
|
||||
stp x0, x1, [sp, #-16]!
|
||||
mrs x17, nzcv
|
||||
bl save_virt
|
||||
mov x1, #1
|
||||
loadsym x2, data_abort
|
||||
bl addr_cache_miss
|
||||
bl load_virt
|
||||
ldp x0, x1, [sp], #16
|
||||
ldp x30, x23, [sp], #16
|
||||
msr nzcv, x17
|
||||
b 0b // Try again
|
||||
334
src/armv5te/asmcode_arm.S
Normal file
@@ -0,0 +1,334 @@
|
||||
.data
|
||||
translation_sp: .global translation_sp
|
||||
.word 0
|
||||
.global arm
|
||||
.global get_cpsr_flags
|
||||
.global set_cpsr_flags
|
||||
.global cycle_count_delta
|
||||
.global cpu_events
|
||||
.global read_instruction
|
||||
|
||||
.text
|
||||
|
||||
#ifdef __clang__
|
||||
#define streqh strheq
|
||||
#define streqb strbeq
|
||||
#define ldreqh ldrheq
|
||||
#define ldreqb ldrbeq
|
||||
#endif
|
||||
|
||||
#define RF_CODE_TRANSLATED 32
|
||||
#define RFS_TRANSLATION_INDEX 9
|
||||
|
||||
#define AC_INVALID 0b10
|
||||
#define AC_NOT_PTR 0b01
|
||||
#define AC_FLAGS (AC_INVALID|AC_NOT_PTR)
|
||||
|
||||
#if defined(__clang__)
|
||||
/* On iOS, .text relocations are permitted and due to
|
||||
a bug it's unable to handle our way of
|
||||
avoiding them anyway... */
|
||||
|
||||
.macro sym name, no=1
|
||||
.endm
|
||||
|
||||
.macro loadsym reg, name, no=1
|
||||
ldr \reg, =\name
|
||||
.endm
|
||||
#else
|
||||
|
||||
/* What you can see here is a really bad way of avoiding
|
||||
relocations in the .text section.
|
||||
For each use of an external symbol, you need to insert
|
||||
a sym (name), (number) here, which generates a word containing the
|
||||
distance to the symbol relative to pc.
|
||||
To use it, use loadsym (reg), (name), (number).
|
||||
The whole process is a way of working around
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=18009
|
||||
*/
|
||||
|
||||
.macro sym name, no=1
|
||||
addr_\name\()_\no\(): .word \name - _tmp_\name\()_\no - 8
|
||||
.endm
|
||||
|
||||
.macro loadsym reg, name, no=1
|
||||
ldr \reg, addr_\name\()_\no
|
||||
_tmp_\name\()_\no: add \reg, \reg, pc
|
||||
.endm
|
||||
|
||||
sym translation_sp
|
||||
sym arm
|
||||
sym cpu_events
|
||||
sym translation_table
|
||||
sym cycle_count_delta, 2
|
||||
sym translation_sp, 2
|
||||
//sym cpu_events, 2
|
||||
sym cycle_count_delta, 3
|
||||
sym addr_cache
|
||||
sym data_abort
|
||||
sym addr_cache, 2
|
||||
sym data_abort, 2
|
||||
sym addr_cache, 3
|
||||
sym data_abort, 3
|
||||
sym addr_cache, 4
|
||||
sym data_abort, 4
|
||||
sym addr_cache, 5
|
||||
sym data_abort, 5
|
||||
sym addr_cache, 6
|
||||
sym data_abort, 6
|
||||
|
||||
#endif
|
||||
|
||||
// r0: pointer to the instruction
|
||||
translation_enter: .global translation_enter
|
||||
push {r4-r11, lr}
|
||||
mov r4, r0
|
||||
loadsym r0, translation_sp
|
||||
str sp, [r0]
|
||||
|
||||
bl get_cpsr
|
||||
mov r11, r0 // r11 = cpsr
|
||||
|
||||
mov r0, r4
|
||||
|
||||
add r1, r0, #80*1024*1024 // r1 = &(RAM_FLAGS(r0))
|
||||
ldr r1, [r1]
|
||||
|
||||
loadsym r10, arm // r10 is a pointer to the global arm_state
|
||||
b translation_next_enter
|
||||
|
||||
// r0: pc
|
||||
translation_next_bx: .global translation_next_bx
|
||||
tst r0, #1
|
||||
bne to_thumb
|
||||
|
||||
// r0: pc
|
||||
translation_next: .global translation_next
|
||||
str r0, [r10, #15*4] // save to arm.reg[15]
|
||||
|
||||
bl read_instruction // r0 = pointer to ARM code
|
||||
cmp r0, #0
|
||||
beq save_return
|
||||
|
||||
translation_jmp_ptr: .global translation_jmp_ptr
|
||||
add r1, r0, #80*1024*1024 // r1 = &(RAM_FLAGS(r0))
|
||||
ldr r1, [r1]
|
||||
tst r1, #RF_CODE_TRANSLATED
|
||||
beq save_return // not translated
|
||||
|
||||
// r0: pointer to instruction
|
||||
// r1: RAM_FLAGS(r0)
|
||||
translation_next_enter:
|
||||
loadsym r2, cpu_events
|
||||
ldr r2, [r2]
|
||||
cmp r2, #0
|
||||
bne save_return
|
||||
|
||||
mov r1, r1, lsr #RFS_TRANSLATION_INDEX // r1 is translation index
|
||||
mov r1, r1, lsl #4
|
||||
loadsym r2, translation_table
|
||||
add r1, r2, r1 // r1 points to struct translation now
|
||||
|
||||
ldr r2, [r1, #1*4] // load translation.jump_table
|
||||
ldr r3, [r1, #2*4] // load translation.start_ptr
|
||||
ldr r4, [r1, #3*4] // load translation.end_ptr
|
||||
|
||||
sub r4, r4, r0 // r4 = end_ptr - pc_ptr
|
||||
mov r4, r4, lsr #2 // r4 = number of instructions to the end
|
||||
loadsym r6, cycle_count_delta, 2
|
||||
ldr r5, [r6]
|
||||
add r5, r5, r4 // add r4 to cycle_count_delta
|
||||
str r5, [r6]
|
||||
cmp r5, #0
|
||||
bpl save_return
|
||||
|
||||
sub r0, r0, r3 // r0 = pc_ptr - start_ptr
|
||||
msr cpsr_f, r11
|
||||
ldr pc, [r2, r0] // jump to jump_table[r0]
|
||||
|
||||
to_thumb:
|
||||
sub r0, r0, #1
|
||||
str r0, [r10, #15*4] // arm.reg[PC] = r0
|
||||
ldr r1, [r10, #16*4]
|
||||
orr r1, r1, #0x20 // Set thumb bit
|
||||
str r1, [r10, #16*4]
|
||||
b save_return
|
||||
|
||||
// Invoked from within translated code to jump to other, already translated code
|
||||
// Target address of translated code is in r0 - only r10 and r11 have to be preserved
|
||||
// This is used to check for events and leave the translation to process them.
|
||||
// arm.reg[15] must be set already!
|
||||
translation_jmp: .global translation_jmp
|
||||
/* loadsym r1, cpu_events, 2
|
||||
ldr r2, [r1]
|
||||
cmp r2, #0
|
||||
bne save_return*/
|
||||
|
||||
loadsym r1, cycle_count_delta, 3
|
||||
ldr r2, [r1]
|
||||
add r2, #4 // We don't know how much will be executed, so use a possible number
|
||||
str r2, [r1]
|
||||
cmp r2, #0
|
||||
bpl save_return
|
||||
|
||||
msr cpsr_f, r11
|
||||
bx r0 // Jump to the target
|
||||
|
||||
// Save flags and leave, arm.reg[15] must be set already!
|
||||
save_return:
|
||||
loadsym r1, translation_sp, 2
|
||||
mov r0, #0
|
||||
str r0, [r1]
|
||||
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
mov r0, r11 // apply arm.cpsr_flags to arm.cpsr_*
|
||||
|
||||
pop {r4-r11, lr}
|
||||
|
||||
b set_cpsr_flags
|
||||
|
||||
// Below is basically a handcoded assembly version of asmcode.c
|
||||
//TODO: Invoke write_action for translation invalidation!
|
||||
|
||||
write_word_asm: .global write_word_asm
|
||||
// r0 is address, r1 is value
|
||||
loadsym r2, addr_cache
|
||||
ldr r2, [r2]
|
||||
mov r3, r0, lsr #9
|
||||
orr r3, r3, #1
|
||||
ldr r3, [r2, r3, lsl #2] // r3 contains ac_entry
|
||||
tst r3, #AC_FLAGS
|
||||
streq r1, [r3, r0]
|
||||
bxeq lr
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
tst r3, #AC_INVALID
|
||||
bne write_word_invalid
|
||||
bic r3, #AC_FLAGS
|
||||
add r0, r3, r0
|
||||
b mmio_write_word
|
||||
write_word_invalid:
|
||||
push {r0, r1, r2, lr} //r2 for stack alignment
|
||||
mov r1, #1
|
||||
loadsym r2, data_abort
|
||||
bl addr_cache_miss
|
||||
pop {r0, r1, r2, lr}
|
||||
b write_word_asm
|
||||
|
||||
write_half_asm: .global write_half_asm
|
||||
// r0 is address, r1 is value
|
||||
loadsym r2, addr_cache, 2
|
||||
bic r0, r0, #1
|
||||
ldr r2, [r2]
|
||||
mov r3, r0, lsr #9
|
||||
orr r3, r3, #1
|
||||
ldr r3, [r2, r3, lsl #2] // r3 contains ac_entry
|
||||
tst r3, #AC_FLAGS
|
||||
streqh r1, [r3, r0]
|
||||
bxeq lr
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
tst r3, #AC_INVALID
|
||||
bne write_half_invalid
|
||||
bic r3, #AC_FLAGS
|
||||
add r0, r3, r0
|
||||
b mmio_write_half
|
||||
write_half_invalid:
|
||||
push {r0, r1, r2, lr} //r2 for stack alignment
|
||||
mov r1, #1
|
||||
loadsym r2, data_abort, 2
|
||||
bl addr_cache_miss
|
||||
pop {r0, r1, r2, lr}
|
||||
b write_half_asm
|
||||
|
||||
write_byte_asm: .global write_byte_asm
|
||||
// r0 is address, r1 is value
|
||||
loadsym r2, addr_cache, 3
|
||||
ldr r2, [r2]
|
||||
mov r3, r0, lsr #9
|
||||
orr r3, r3, #1
|
||||
ldr r3, [r2, r3, lsl #2] // r3 contains ac_entry
|
||||
tst r3, #AC_FLAGS
|
||||
streqb r1, [r3, r0]
|
||||
bxeq lr
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
tst r3, #AC_INVALID
|
||||
bne write_byte_invalid
|
||||
bic r3, #AC_FLAGS
|
||||
add r0, r3, r0
|
||||
b mmio_write_byte
|
||||
write_byte_invalid:
|
||||
push {r0, r1, r2, lr} //r2 for stack alignment
|
||||
mov r1, #1
|
||||
loadsym r2, data_abort, 3
|
||||
bl addr_cache_miss
|
||||
pop {r0, r1, r2, lr}
|
||||
b write_byte_asm
|
||||
|
||||
read_word_asm: .global read_word_asm
|
||||
// r0 is address
|
||||
loadsym r2, addr_cache, 4
|
||||
ldr r2, [r2]
|
||||
mov r3, r0, lsr #10
|
||||
ldr r3, [r2, r3, lsl #3] // r3 contains ac_entry
|
||||
tst r3, #AC_FLAGS
|
||||
ldreq r0, [r3, r0]
|
||||
bxeq lr
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
tst r3, #AC_INVALID
|
||||
bne read_word_invalid
|
||||
bic r3, #AC_FLAGS
|
||||
add r0, r3, r0
|
||||
b mmio_read_word
|
||||
read_word_invalid:
|
||||
push {r0, lr}
|
||||
mov r1, #0
|
||||
loadsym r2, data_abort, 4
|
||||
bl addr_cache_miss
|
||||
pop {r0, lr}
|
||||
b read_word_asm
|
||||
|
||||
read_half_asm: .global read_half_asm
|
||||
// r0 is address
|
||||
loadsym r2, addr_cache, 5
|
||||
bic r0, r0, #1
|
||||
ldr r2, [r2]
|
||||
mov r3, r0, lsr #10
|
||||
ldr r3, [r2, r3, lsl #3] // r3 contains ac_entry
|
||||
tst r3, #AC_FLAGS
|
||||
ldreqh r0, [r3, r0]
|
||||
bxeq lr
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
tst r3, #AC_INVALID
|
||||
bne read_half_invalid
|
||||
bic r3, #AC_FLAGS
|
||||
add r0, r3, r0
|
||||
b mmio_read_half
|
||||
read_half_invalid:
|
||||
push {r0, lr}
|
||||
mov r1, #0
|
||||
loadsym r2, data_abort, 5
|
||||
bl addr_cache_miss
|
||||
pop {r0, lr}
|
||||
b read_half_asm
|
||||
|
||||
read_byte_asm: .global read_byte_asm
|
||||
// r0 is address
|
||||
loadsym r2, addr_cache, 6
|
||||
ldr r2, [r2]
|
||||
mov r3, r0, lsr #10
|
||||
ldr r3, [r2, r3, lsl #3] // r3 contains ac_entry
|
||||
tst r3, #AC_FLAGS
|
||||
ldreqb r0, [r3, r0]
|
||||
bxeq lr
|
||||
str r11, [r10, #18*4] // save to arm.cpsr_flags
|
||||
tst r3, #AC_INVALID
|
||||
bne read_byte_invalid
|
||||
bic r3, #AC_FLAGS
|
||||
add r0, r3, r0
|
||||
b mmio_read_byte
|
||||
read_byte_invalid:
|
||||
push {r0, lr}
|
||||
mov r1, #0
|
||||
loadsym r2, data_abort, 6
|
||||
bl addr_cache_miss
|
||||
pop {r0, lr}
|
||||
b read_byte_asm
|
||||
496
src/armv5te/asmcode_x86.S
Normal file
@@ -0,0 +1,496 @@
|
||||
// arm_state structure offsets
|
||||
#define ARM_PC 60
|
||||
#define ARM_CPSR 64
|
||||
#define ARM_FLAG_C 70
|
||||
#define ARM_CONTROL 72
|
||||
|
||||
// translation structure offsets
|
||||
#define TRANS_JUMP_TABLE 4
|
||||
#define TRANS_END_PTR 12
|
||||
|
||||
#define RAM_FLAGS (80*1024*1024) // = MEM_MAXSIZE
|
||||
#define RF_READ_BREAKPOINT 1
|
||||
#define RF_WRITE_BREAKPOINT 2
|
||||
#define RF_EXEC_BREAKPOINT 4
|
||||
#define RF_EXEC_DEBUG_NEXT 8
|
||||
#define RF_CODE_TRANSLATED 32
|
||||
#define RF_CODE_NO_TRANSLATE 64
|
||||
#define RF_READ_ONLY 128
|
||||
#define RF_ARMLOADER_CB 256
|
||||
#define RFS_TRANSLATION_INDEX 9
|
||||
|
||||
#define WRITE_SPECIAL_FLAGS 2+32+64
|
||||
|
||||
// List of locations of addresses which need to be relocated to addr_cache
|
||||
// (necessary since it's now allocated at runtime)
|
||||
.data
|
||||
.globl ac_reloc_start
|
||||
ac_reloc_start:
|
||||
|
||||
.macro AC_RELOC; 0: .data; .long 0b - 4; .text; .endm
|
||||
|
||||
.text
|
||||
.globl translation_enter
|
||||
translation_enter:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
movl %esp, in_translation_esp
|
||||
|
||||
movl $arm, %ebx
|
||||
movl ARM_PC(%ebx), %eax
|
||||
jmp translation_next
|
||||
|
||||
.globl translation_next_bx
|
||||
translation_next_bx:
|
||||
testb $1, %al
|
||||
jne switch_to_thumb
|
||||
|
||||
.globl translation_next
|
||||
translation_next:
|
||||
movl %eax, ARM_PC(%ebx)
|
||||
|
||||
cmpl $0, cycle_count_delta
|
||||
jns return
|
||||
|
||||
cmpl $0, cpu_events
|
||||
jnz return
|
||||
|
||||
// eax = VM_MEM_PTR(eax)
|
||||
movl %eax, %ecx
|
||||
shrl $10, %ecx
|
||||
addl 0(, %ecx, 8), %eax
|
||||
AC_RELOC
|
||||
testl $0x80000003, %eax
|
||||
jnz return
|
||||
addr_ok:
|
||||
|
||||
movl RAM_FLAGS(%eax), %edx
|
||||
testb $RF_CODE_TRANSLATED, %dl
|
||||
jz return // Not translated
|
||||
|
||||
movl %eax, in_translation_pc_ptr
|
||||
|
||||
shrl $RFS_TRANSLATION_INDEX, %edx
|
||||
shll $4, %edx
|
||||
addl $translation_table, %edx
|
||||
|
||||
// Add one cycle for each instruction from this point to the end
|
||||
movl TRANS_END_PTR(%edx), %ecx
|
||||
subl %eax, %ecx
|
||||
shrl $2, %ecx
|
||||
addl %ecx, cycle_count_delta
|
||||
|
||||
movl TRANS_JUMP_TABLE(%edx), %edx
|
||||
jmp *(%edx, %eax)
|
||||
|
||||
return:
|
||||
andl $0, in_translation_esp
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
switch_to_thumb:
|
||||
decl %eax
|
||||
movl %eax, ARM_PC(%ebx)
|
||||
orb $0x20, ARM_CPSR(%ebx)
|
||||
jmp return
|
||||
|
||||
// These shift procedures are called only from translated code,
|
||||
// so they may assume that %ebx == _arm
|
||||
.align 4
|
||||
.globl arm_shift_proc
|
||||
arm_shift_proc:
|
||||
.long lsl
|
||||
.long lsr
|
||||
.long asr
|
||||
.long 0
|
||||
.long lsl_carry
|
||||
.long lsr_carry
|
||||
.long asr_carry
|
||||
.long ror_carry
|
||||
|
||||
.text
|
||||
lsl:
|
||||
cmpb $32, %cl
|
||||
jae ls_32
|
||||
shll %cl, %eax
|
||||
ret
|
||||
|
||||
lsr:
|
||||
cmpb $32, %cl
|
||||
jae ls_32
|
||||
shrl %cl, %eax
|
||||
ret
|
||||
ls_32:
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
|
||||
asr:
|
||||
cmpb $32, %cl
|
||||
jae asr_32
|
||||
sarl %cl, %eax
|
||||
ret
|
||||
asr_32:
|
||||
sarl $31, %eax
|
||||
ret
|
||||
|
||||
lsl_carry:
|
||||
cmpb $32, %cl
|
||||
jae lsl_carry_32
|
||||
testb %cl, %cl
|
||||
je lsl_carry_zero
|
||||
shll %cl, %eax
|
||||
setc ARM_FLAG_C(%ebx)
|
||||
lsl_carry_zero:
|
||||
ret
|
||||
lsl_carry_32:
|
||||
jne ls_carry_33
|
||||
shrl $1, %eax
|
||||
setc ARM_FLAG_C(%ebx)
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
|
||||
lsr_carry:
|
||||
cmpb $32, %cl
|
||||
jae lsr_carry_32
|
||||
testb %cl, %cl
|
||||
je lsr_carry_zero
|
||||
shrl %cl, %eax
|
||||
setc ARM_FLAG_C(%ebx)
|
||||
lsr_carry_zero:
|
||||
ret
|
||||
lsr_carry_32:
|
||||
jne ls_carry_33
|
||||
shll $1, %eax
|
||||
setc ARM_FLAG_C(%ebx)
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
ls_carry_33:
|
||||
xorl %eax, %eax
|
||||
movb %al, ARM_FLAG_C(%ebx)
|
||||
ret
|
||||
|
||||
asr_carry:
|
||||
cmpb $32, %cl
|
||||
jae asr_carry_32
|
||||
testb %cl, %cl
|
||||
je asr_carry_zero
|
||||
sarl %cl, %eax
|
||||
setc ARM_FLAG_C(%ebx)
|
||||
asr_carry_zero:
|
||||
ret
|
||||
asr_carry_32:
|
||||
sarl $31, %eax
|
||||
sets ARM_FLAG_C(%ebx)
|
||||
ret
|
||||
|
||||
ror_carry:
|
||||
testb $31, %cl
|
||||
jz ror_carry_mult_32
|
||||
rorl %cl, %eax
|
||||
setc ARM_FLAG_C(%ebx)
|
||||
ror_carry_zero:
|
||||
ret
|
||||
ror_carry_mult_32:
|
||||
testb %cl, %cl
|
||||
je ror_carry_zero
|
||||
testl %eax, %eax
|
||||
sets ARM_FLAG_C(%ebx)
|
||||
ret
|
||||
|
||||
// uint32_t FASTCALL read_byte(uint32_t addr);
|
||||
.globl read_byte
|
||||
.align 16
|
||||
read_byte:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 0(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
js rb_slow
|
||||
movl %ecx, %edx
|
||||
andl $-4, %edx
|
||||
testb $RF_READ_BREAKPOINT, RAM_FLAGS(%edx)
|
||||
jnz rb_special
|
||||
rb_fast:
|
||||
movzbl (%ecx), %eax
|
||||
ret
|
||||
rb_special:
|
||||
call read_special
|
||||
jmp rb_fast
|
||||
rb_slow:
|
||||
movl 0(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
shll $10, %eax
|
||||
jc rb_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_read_byte
|
||||
rb_miss:
|
||||
call read_miss
|
||||
jmp read_byte
|
||||
|
||||
// uint32_t FASTCALL read_half(uint32_t addr);
|
||||
.globl read_half
|
||||
.align 16
|
||||
read_half:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 0(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
testl $0x80000001, %ecx
|
||||
jnz rh_slow
|
||||
movl %ecx, %edx
|
||||
andl $-4, %edx
|
||||
testb $RF_READ_BREAKPOINT, RAM_FLAGS(%edx)
|
||||
jnz rh_special
|
||||
rh_fast:
|
||||
movzwl (%ecx), %eax
|
||||
ret
|
||||
rh_special:
|
||||
call read_special
|
||||
jmp rh_fast
|
||||
rh_slow:
|
||||
movl 0(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
testl $1, %ecx
|
||||
jnz rh_unaligned
|
||||
shll $10, %eax
|
||||
jc rh_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_read_half
|
||||
rh_miss:
|
||||
call read_miss
|
||||
jmp read_half
|
||||
rh_unaligned:
|
||||
call align_fault
|
||||
decl %ecx
|
||||
jmp read_half
|
||||
|
||||
// uint32_t FASTCALL read_word(uint32_t addr);
|
||||
.globl read_word
|
||||
.align 16
|
||||
read_word:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 0(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
testl $0x80000003, %ecx
|
||||
jnz rw_slow
|
||||
testb $RF_READ_BREAKPOINT, RAM_FLAGS(%ecx)
|
||||
jnz rw_special
|
||||
rw_fast:
|
||||
movl (%ecx), %eax
|
||||
ret
|
||||
rw_special:
|
||||
call read_special
|
||||
jmp rw_fast
|
||||
rw_slow:
|
||||
movl 0(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
testl $3, %ecx
|
||||
jnz rw_unaligned
|
||||
shll $10, %eax
|
||||
jc rw_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_read_word
|
||||
rw_miss:
|
||||
call read_miss
|
||||
jmp read_word
|
||||
rw_unaligned:
|
||||
call align_fault
|
||||
andl $-4, %ecx
|
||||
jmp read_word
|
||||
|
||||
// uint32_t FASTCALL read_word_ldr(uint32_t addr);
|
||||
.globl read_word_ldr
|
||||
.align 16
|
||||
read_word_ldr:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 0(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
testl $0x80000003, %ecx
|
||||
jnz rwl_slow
|
||||
testb $RF_READ_BREAKPOINT, RAM_FLAGS(%ecx)
|
||||
jnz rw_special
|
||||
movl (%ecx), %eax
|
||||
ret
|
||||
rwl_slow:
|
||||
movl 0(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
testl $3, %ecx
|
||||
jnz rwl_unaligned
|
||||
shll $10, %eax
|
||||
jc rw_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_read_word
|
||||
rwl_unaligned:
|
||||
pushl %ecx
|
||||
call rw_unaligned
|
||||
popl %ecx
|
||||
shll $3, %ecx // Unaligned ldr rotates the word so that
|
||||
rorl %cl, %eax // addressed byte ends up in low position
|
||||
ret
|
||||
|
||||
read_special:
|
||||
pushl %ecx
|
||||
pushl %ecx
|
||||
call read_action
|
||||
popl %ecx
|
||||
popl %ecx
|
||||
ret
|
||||
read_miss:
|
||||
pushl %ecx
|
||||
pushl $data_abort
|
||||
pushl $0
|
||||
pushl %ecx
|
||||
call addr_cache_miss
|
||||
addl $12, %esp
|
||||
popl %ecx
|
||||
ret
|
||||
|
||||
// void FASTCALL write_byte(uint32_t addr, uint8_t value);
|
||||
.globl write_byte
|
||||
.align 16
|
||||
write_byte:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 4(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
js wb_slow
|
||||
movl %ecx, %eax
|
||||
andl $-4, %eax
|
||||
testb $WRITE_SPECIAL_FLAGS, RAM_FLAGS(%eax)
|
||||
jnz wb_special
|
||||
wb_fast:
|
||||
movb %dl, (%ecx)
|
||||
ret
|
||||
wb_special:
|
||||
call write_special
|
||||
jmp wb_fast
|
||||
wb_slow:
|
||||
movl 4(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
shll $10, %eax
|
||||
jc wb_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_write_byte
|
||||
wb_miss:
|
||||
call write_miss
|
||||
jmp write_byte
|
||||
|
||||
// void FASTCALL write_half(uint32_t addr, uint16_t value);
|
||||
.globl write_half
|
||||
.align 16
|
||||
write_half:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 4(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
testl $0x80000001, %ecx
|
||||
jnz wh_slow
|
||||
movl %ecx, %eax
|
||||
andl $-4, %eax
|
||||
testb $WRITE_SPECIAL_FLAGS, RAM_FLAGS(%eax)
|
||||
jnz wh_special
|
||||
wh_fast:
|
||||
movw %dx, (%ecx)
|
||||
ret
|
||||
wh_special:
|
||||
call write_special
|
||||
jmp wh_fast
|
||||
wh_slow:
|
||||
movl 4(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
testl $1, %ecx
|
||||
jnz wh_unaligned
|
||||
shll $10, %eax
|
||||
jc wh_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_write_half
|
||||
wh_miss:
|
||||
call write_miss
|
||||
jmp write_half
|
||||
wh_unaligned:
|
||||
call align_fault
|
||||
decl %ecx
|
||||
jmp write_half
|
||||
|
||||
// void FASTCALL write_word(uint32_t addr, uint32_t value);
|
||||
.globl write_word
|
||||
.align 16
|
||||
write_word:
|
||||
movl %ecx, %eax
|
||||
shrl $10, %eax
|
||||
addl 4(, %eax, 8), %ecx
|
||||
AC_RELOC
|
||||
testl $0x80000003, %ecx
|
||||
jnz ww_slow
|
||||
testb $WRITE_SPECIAL_FLAGS, RAM_FLAGS(%ecx)
|
||||
jnz ww_special
|
||||
ww_fast:
|
||||
movl %edx, (%ecx)
|
||||
ret
|
||||
ww_special:
|
||||
call write_special
|
||||
jmp ww_fast
|
||||
ww_slow:
|
||||
movl 4(, %eax, 8), %eax
|
||||
AC_RELOC
|
||||
subl %eax, %ecx
|
||||
testl $3, %ecx
|
||||
jnz ww_unaligned
|
||||
shll $10, %eax
|
||||
jc ww_miss
|
||||
addl %eax, %ecx
|
||||
jmp mmio_write_word
|
||||
ww_miss:
|
||||
call write_miss
|
||||
jmp write_word
|
||||
ww_unaligned:
|
||||
call align_fault
|
||||
andl $-4, %ecx
|
||||
jmp write_word
|
||||
|
||||
write_special:
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ecx
|
||||
call write_action
|
||||
popl %ecx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
ret
|
||||
write_miss:
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl $data_abort
|
||||
pushl $1
|
||||
pushl %ecx
|
||||
call addr_cache_miss
|
||||
addl $12, %esp
|
||||
popl %ecx
|
||||
popl %edx
|
||||
ret
|
||||
|
||||
align_fault:
|
||||
testb $2, arm+ARM_CONTROL
|
||||
jz 1f
|
||||
pushl $1
|
||||
pushl %ecx
|
||||
call data_abort
|
||||
1: ret
|
||||
|
||||
.data
|
||||
.globl ac_reloc_end
|
||||
ac_reloc_end:
|
||||
335
src/armv5te/asmcode_x86_64.S
Normal file
@@ -0,0 +1,335 @@
|
||||
// arm_state structure offsets
|
||||
#define ARM_PC 60
|
||||
#define ARM_CPSR 64
|
||||
#define ARM_FLAG_C 70
|
||||
#define ARM_CONTROL 72
|
||||
|
||||
// translation structure offsets
|
||||
#define TRANS_JUMP_TABLE 0x08
|
||||
#define TRANS_START_PTR 0x10
|
||||
#define TRANS_END_PTR 0x18
|
||||
|
||||
// RAM_FLAGS used to have "// = MEM_MAXSIZE" at the end but the clang assembler copys the "//" into the macro, commenting out the arguments of the opcodes that use it
|
||||
#define RAM_FLAGS (80*1024*1024)
|
||||
#define RF_READ_BREAKPOINT 1
|
||||
#define RF_WRITE_BREAKPOINT 2
|
||||
#define RF_EXEC_BREAKPOINT 4
|
||||
#define RF_EXEC_DEBUG_NEXT 8
|
||||
#define RF_CODE_TRANSLATED 32
|
||||
#define RF_CODE_NO_TRANSLATE 64
|
||||
#define RF_READ_ONLY 128
|
||||
#define RF_ARMLOADER_CB 256
|
||||
#define RFS_TRANSLATION_INDEX 9
|
||||
|
||||
#define DO_READ_ACTION (RF_READ_BREAKPOINT)
|
||||
#define DO_WRITE_ACTION (RF_WRITE_BREAKPOINT | RF_CODE_TRANSLATED | RF_CODE_NO_TRANSLATE)
|
||||
|
||||
translation_enter: .global translation_enter
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
push %rbx
|
||||
push %rsi
|
||||
push %rdi
|
||||
mov %rsp, in_translation_rsp(%rip)
|
||||
|
||||
lea arm(%rip), %rbx
|
||||
mov ARM_PC(%rbx), %eax
|
||||
jmp translation_next
|
||||
|
||||
translation_next_bx: .global translation_next_bx
|
||||
testb $1, %al
|
||||
jne switch_to_thumb
|
||||
|
||||
translation_next: .global translation_next
|
||||
mov %eax, ARM_PC(%rbx)
|
||||
|
||||
lea cycle_count_delta(%rip), %r8
|
||||
cmpl $0, (%r8)
|
||||
jns return
|
||||
|
||||
lea cpu_events(%rip), %r8
|
||||
cmpl $0, (%r8)
|
||||
jnz return
|
||||
|
||||
mov ARM_PC(%rbx), %edi
|
||||
push %rdi // For 16 byte stack alignment (call pushes 8 itself)
|
||||
call read_instruction
|
||||
pop %rdi
|
||||
cmp $0, %rax
|
||||
jz return
|
||||
|
||||
addr_ok:
|
||||
movl RAM_FLAGS(%rax), %edx
|
||||
testb $RF_CODE_TRANSLATED, %dl
|
||||
jz return // Not translated
|
||||
|
||||
lea in_translation_pc_ptr(%rip), %r8
|
||||
mov %rax, (%r8)
|
||||
|
||||
shr $RFS_TRANSLATION_INDEX, %rdx
|
||||
shl $5, %rdx
|
||||
lea translation_table(%rip), %r8
|
||||
add %r8, %rdx
|
||||
|
||||
// Add one cycle for each instruction from this point to the end
|
||||
mov TRANS_END_PTR(%rdx), %rcx
|
||||
sub %rax, %rcx
|
||||
shr $2, %rcx
|
||||
lea cycle_count_delta(%rip), %r8
|
||||
add %ecx, (%r8)
|
||||
|
||||
mov %rax, %rcx
|
||||
sub TRANS_START_PTR(%rdx), %rcx
|
||||
mov TRANS_JUMP_TABLE(%rdx), %rdx
|
||||
jmp *(%rdx, %rcx, 2)
|
||||
//That is the same as
|
||||
//shr $2, %rcx
|
||||
//jmp *(%rdx, %rcx, 8)
|
||||
|
||||
return:
|
||||
lea in_translation_rsp(%rip), %r8
|
||||
movq $0, (%r8)
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
switch_to_thumb:
|
||||
dec %eax
|
||||
mov %eax, ARM_PC(%rbx)
|
||||
orb $0x20, ARM_CPSR(%rbx)
|
||||
jmp return
|
||||
|
||||
.data
|
||||
// These shift procedures are called only from translated code,
|
||||
// so they may assume that %rbx == _arm
|
||||
.align 4
|
||||
arm_shift_proc: .global arm_shift_proc
|
||||
.quad lsl
|
||||
.quad lsr
|
||||
.quad asr
|
||||
.quad 0
|
||||
.quad lsl_carry
|
||||
.quad lsr_carry
|
||||
.quad asr_carry
|
||||
.quad ror_carry
|
||||
|
||||
.text
|
||||
lsl:
|
||||
cmpb $32, %cl
|
||||
jae ls_32
|
||||
shl %cl, %eax
|
||||
ret
|
||||
|
||||
lsr:
|
||||
cmpb $32, %cl
|
||||
jae ls_32
|
||||
shr %cl, %eax
|
||||
ret
|
||||
ls_32:
|
||||
xor %eax, %eax
|
||||
ret
|
||||
|
||||
asr:
|
||||
cmpb $32, %cl
|
||||
jae asr_32
|
||||
sar %cl, %eax
|
||||
ret
|
||||
asr_32:
|
||||
sar $31, %eax
|
||||
ret
|
||||
|
||||
lsl_carry:
|
||||
cmpb $32, %cl
|
||||
jae lsl_carry_32
|
||||
testb %cl, %cl
|
||||
je lsl_carry_zero
|
||||
shl %cl, %eax
|
||||
setc ARM_FLAG_C(%rbx)
|
||||
lsl_carry_zero:
|
||||
ret
|
||||
lsl_carry_32:
|
||||
jne ls_carry_33
|
||||
shr $1, %eax
|
||||
setc ARM_FLAG_C(%rbx)
|
||||
xor %eax, %eax
|
||||
ret
|
||||
|
||||
lsr_carry:
|
||||
cmpb $32, %cl
|
||||
jae lsr_carry_32
|
||||
testb %cl, %cl
|
||||
je lsr_carry_zero
|
||||
shr %cl, %eax
|
||||
setc ARM_FLAG_C(%rbx)
|
||||
lsr_carry_zero:
|
||||
ret
|
||||
lsr_carry_32:
|
||||
jne ls_carry_33
|
||||
shl $1, %eax
|
||||
setc ARM_FLAG_C(%rbx)
|
||||
xor %eax, %eax
|
||||
ret
|
||||
ls_carry_33:
|
||||
xor %eax, %eax
|
||||
movb %al, ARM_FLAG_C(%rbx)
|
||||
ret
|
||||
|
||||
asr_carry:
|
||||
cmpb $32, %cl
|
||||
jae asr_carry_32
|
||||
testb %cl, %cl
|
||||
je asr_carry_zero
|
||||
sar %cl, %eax
|
||||
setc ARM_FLAG_C(%rbx)
|
||||
asr_carry_zero:
|
||||
ret
|
||||
asr_carry_32:
|
||||
sar $31, %eax
|
||||
sets ARM_FLAG_C(%rbx)
|
||||
ret
|
||||
|
||||
ror_carry:
|
||||
testb $31, %cl
|
||||
jz ror_carry_mult_32
|
||||
ror %cl, %eax
|
||||
setc ARM_FLAG_C(%rbx)
|
||||
ror_carry_zero:
|
||||
ret
|
||||
ror_carry_mult_32:
|
||||
testb %cl, %cl
|
||||
je ror_carry_zero
|
||||
test %eax, %eax
|
||||
sets ARM_FLAG_C(%rbx)
|
||||
ret
|
||||
|
||||
read_word_asm: .global read_word_asm
|
||||
mov %rdi, %rax
|
||||
shr $10, %rax
|
||||
shl $1, %rax
|
||||
mov addr_cache(%rip), %r8
|
||||
mov (%r8, %rax, 8), %rax
|
||||
test $3, %rax
|
||||
jnz rwa_miss
|
||||
movl (%rax, %rdi), %eax
|
||||
ret
|
||||
rwa_miss:
|
||||
push %rdx
|
||||
push %rcx
|
||||
call read_word
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
|
||||
write_word_asm: .global write_word_asm
|
||||
mov %rdi, %rax
|
||||
shr $10, %rax
|
||||
shl $1, %rax
|
||||
add $1, %rax
|
||||
mov addr_cache(%rip), %r8
|
||||
mov (%r8, %rax, 8), %rax
|
||||
test $3, %rax
|
||||
jnz wwa_miss
|
||||
movl %esi, (%rax, %rdi)
|
||||
testq $DO_WRITE_ACTION, RAM_FLAGS(%rax, %rdi)
|
||||
jnz write_action_asm
|
||||
ret
|
||||
wwa_miss:
|
||||
push %rdx
|
||||
push %rcx
|
||||
call write_word
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
|
||||
read_half_asm: .global read_half_asm
|
||||
and $-2, %rdi
|
||||
mov %rdi, %rax
|
||||
shr $10, %rax
|
||||
shl $1, %rax
|
||||
mov addr_cache(%rip), %r8
|
||||
mov (%r8, %rax, 8), %rax
|
||||
test $3, %rax
|
||||
jnz rha_miss
|
||||
movzwl (%rax, %rdi), %eax
|
||||
ret
|
||||
rha_miss:
|
||||
push %rdx
|
||||
push %rcx
|
||||
call read_half
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
|
||||
write_half_asm: .global write_half_asm
|
||||
and $-2, %rdi
|
||||
mov %rdi, %rax
|
||||
shr $10, %rax
|
||||
shl $1, %rax
|
||||
add $1, %rax
|
||||
mov addr_cache(%rip), %r8
|
||||
mov (%r8, %rax, 8), %rax
|
||||
test $3, %rax
|
||||
jnz wha_miss
|
||||
movw %si, (%rax, %rdi)
|
||||
testq $DO_WRITE_ACTION, RAM_FLAGS(%rax, %rdi)
|
||||
jnz write_action_asm
|
||||
ret
|
||||
wha_miss:
|
||||
push %rdx
|
||||
push %rcx
|
||||
call write_half
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
|
||||
read_byte_asm: .global read_byte_asm
|
||||
mov %rdi, %rax
|
||||
shr $10, %rax
|
||||
shl $1, %rax
|
||||
mov addr_cache(%rip), %r8
|
||||
mov (%r8, %rax, 8), %rax
|
||||
test $3, %rax
|
||||
jnz rba_miss
|
||||
movzb (%rax, %rdi), %rax
|
||||
ret
|
||||
rba_miss:
|
||||
push %rdx
|
||||
push %rcx
|
||||
call read_byte
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
|
||||
write_byte_asm: .global write_byte_asm
|
||||
mov %rdi, %rax
|
||||
shr $10, %rax
|
||||
shl $1, %rax
|
||||
add $1, %rax
|
||||
mov addr_cache(%rip), %r8
|
||||
mov (%r8, %rax, 8), %rax
|
||||
test $3, %rax
|
||||
jnz wba_miss
|
||||
xchg %rsi, %rdx // Can't use %rsi directly
|
||||
movb %dl, (%rax, %rdi)
|
||||
xchg %rsi, %rdx
|
||||
testq $DO_WRITE_ACTION, RAM_FLAGS(%rax, %rdi)
|
||||
jnz write_action_asm
|
||||
ret
|
||||
wba_miss:
|
||||
push %rdx
|
||||
push %rcx
|
||||
call write_byte
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
|
||||
write_action_asm:
|
||||
add %rax, %rdi
|
||||
push %rdx
|
||||
push %rcx
|
||||
call write_action
|
||||
pop %rcx
|
||||
pop %rdx
|
||||
ret
|
||||
81
src/armv5te/bitfield.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef BITFIELD_H
|
||||
#define BITFIELD_H
|
||||
|
||||
/* Portable and safe implementation of C bitfields
|
||||
Source: http://blog.codef00.com/2014/12/06/portable-bitfields-using-c11/ */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
//Mac OS RetroArch port is lacking <type_traits>
|
||||
template<bool B, class T, class F>
|
||||
struct typeConditional { typedef T type; };
|
||||
|
||||
template<class T, class F>
|
||||
struct typeConditional<false, T, F> { typedef F type; };
|
||||
|
||||
template <size_t LastBit>
|
||||
struct MinimumTypeHelper {
|
||||
typedef
|
||||
typename typeConditional<LastBit == 0 , void,
|
||||
typename typeConditional<LastBit <= 8 , uint8_t,
|
||||
typename typeConditional<LastBit <= 16, uint16_t,
|
||||
typename typeConditional<LastBit <= 32, uint32_t,
|
||||
typename typeConditional<LastBit <= 64, uint64_t,
|
||||
void>::type>::type>::type>::type>::type type;
|
||||
};
|
||||
|
||||
template <size_t Index, size_t Bits = 1>
|
||||
class BitField {
|
||||
private:
|
||||
enum {
|
||||
Mask = (1u << Bits) - 1u
|
||||
};
|
||||
|
||||
typedef typename MinimumTypeHelper<Index + Bits>::type T;
|
||||
public:
|
||||
template <class T2>
|
||||
BitField &operator=(T2 value) {
|
||||
value_ = (value_ & ~(Mask << Index)) | ((value & Mask) << Index);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
T2 as() { return (value_ >> Index) & Mask; }
|
||||
operator T() const { return (value_ >> Index) & Mask; }
|
||||
explicit operator bool() const { return value_ & (Mask << Index); }
|
||||
BitField &operator++() { return *this = *this + 1; }
|
||||
T operator++(int) { T r = *this; ++*this; return r; }
|
||||
BitField &operator--() { return *this = *this - 1; }
|
||||
T operator--(int) { T r = *this; ++*this; return r; }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
|
||||
template <size_t Index>
|
||||
class BitField<Index, 1> {
|
||||
private:
|
||||
enum {
|
||||
Bits = 1,
|
||||
Mask = 0x01
|
||||
};
|
||||
|
||||
typedef typename MinimumTypeHelper<Index + Bits>::type T;
|
||||
public:
|
||||
template <typename T2>
|
||||
T2 as() { return (value_ >> Index) & Mask; }
|
||||
BitField &operator=(bool value) {
|
||||
value_ = (value_ & ~(Mask << Index)) | (value << Index);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const { return value_ & (Mask << Index); }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
#endif // BITFIELD_H
|
||||
|
||||
170
src/armv5te/coproc.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include "cpu.h"
|
||||
#include "cpudefs.h"
|
||||
#include "mmu.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../pxa260/pxa260.h"
|
||||
#include "../pxa260/pxa260_PwrClk.h"
|
||||
}
|
||||
|
||||
|
||||
void do_cp15_mrc(uint32_t insn)
|
||||
{
|
||||
uint32_t value;
|
||||
switch (insn & 0xEF00EF) {
|
||||
case 0x000000: /* MRC p15, 0, <Rd>, c0, c0, 0: ID Code Register */
|
||||
//value = 0x41069264; /* ARM926EJ-S revision 4 */
|
||||
//value = 0x69052100;//Intel PXA260 "01101001000001010010000100000000"
|
||||
value = 0x69052D05;//Intel PXA261 "01101001000001010010110100000101"
|
||||
break;
|
||||
case 0x000010: /* MRC p15, 0, <Rd>, c0, c0, 1: Cache Type Register */
|
||||
value = 0x1D112152; /* ICache: 16KB 4-way 8 word, DCache: 8KB 4-way 8 word */
|
||||
break;
|
||||
case 0x000020: /* MRC p15, 0, <Rd>, c0, c0, 2: TCM Status Register */
|
||||
value = 0;
|
||||
break;
|
||||
case 0x010000: /* MRC p15, 0, <Rd>, c1, c0, 0: Control Register */
|
||||
value = arm.control;
|
||||
break;
|
||||
case 0x020000: /* MRC p15, 0, <Rd>, c2, c0, 0: Translation Table Base Register */
|
||||
value = arm.translation_table_base;
|
||||
break;
|
||||
case 0x030000: /* MRC p15, 0, <Rd>, c3, c0, 0: Domain Access Control Register */
|
||||
value = arm.domain_access_control;
|
||||
break;
|
||||
case 0x050000: /* MRC p15, 0, <Rd>, c5, c0, 0: Data Fault Status Register */
|
||||
value = arm.data_fault_status;
|
||||
break;
|
||||
case 0x050020: /* MRC p15, 0, <Rd>, c5, c0, 1: Instruction Fault Status Register */
|
||||
value = arm.instruction_fault_status;
|
||||
break;
|
||||
case 0x060000: /* MRC p15, 0, <Rd>, c6, c0, 0: Fault Address Register */
|
||||
value = arm.fault_address;
|
||||
break;
|
||||
case 0x07006A: /* MRC p15, 0, <Rd>, c7, c10, 3: Test and clean DCache */
|
||||
value = 1 << 30;
|
||||
break;
|
||||
case 0x07006E: /* MRC p15, 0, <Rd>, c7, c14, 3: Test, clean, and invalidate DCache */
|
||||
value = 1 << 30;
|
||||
break;
|
||||
case 0x0D0000: /* MRC p15, 0, <Rd>, c13, c0, 0: Read FCSE PID */
|
||||
value = 0;
|
||||
break;
|
||||
case 0x0F0000: /* MRC p15, 0, <Rd>, c15, c0, 0: Debug Override Register */
|
||||
// Unimplemented
|
||||
value = 0;
|
||||
break;
|
||||
case 0x0F0001: /* MRC p15, 0, <Rd>, c15, c1, 0: Unknown */
|
||||
//TODO: Unknown(implmentation defined cp15 register)
|
||||
value = 0;
|
||||
break;
|
||||
default:
|
||||
warn("Unknown coprocessor instruction MRC %08X", insn);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
if ((insn >> 12 & 15) == 15) {
|
||||
arm.cpsr_n = value >> 31 & 1;
|
||||
arm.cpsr_z = value >> 30 & 1;
|
||||
arm.cpsr_c = value >> 29 & 1;
|
||||
arm.cpsr_v = value >> 28 & 1;
|
||||
} else
|
||||
arm.reg[insn >> 12 & 15] = value;
|
||||
}
|
||||
|
||||
void do_cp15_mcr(uint32_t insn)
|
||||
{
|
||||
uint32_t value = reg(insn >> 12 & 15);
|
||||
switch (insn & 0xEF00EF) {
|
||||
case 0x010000: { /* MCR p15, 0, <Rd>, c1, c0, 0: Control Register */
|
||||
uint32_t change = value ^ arm.control;
|
||||
//TODO: actually implement this register fully
|
||||
/*
|
||||
if ((value & 0xFFFF8CF0) != 0x00050070)
|
||||
error("Bad or unimplemented control register value: %x (unsupported: %x)\n", value, (value & 0xFFFF8CF8) ^ 0x00050078);
|
||||
*/
|
||||
arm.control = value;
|
||||
if (change & 1){
|
||||
// MMU is being turned on or off
|
||||
addr_cache_flush();
|
||||
emuprintf("Turned MMU %s\n", value & 1 ? "on" : "off");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x020000: /* MCR p15, 0, <Rd>, c2, c0, 0: Translation Table Base Register */
|
||||
arm.translation_table_base = value & ~0x3FFF;
|
||||
addr_cache_flush();
|
||||
break;
|
||||
case 0x030000: /* MCR p15, 0, <Rd>, c3, c0, 0: Domain Access Control Register */
|
||||
arm.domain_access_control = value;
|
||||
addr_cache_flush();
|
||||
break;
|
||||
case 0x050000: /* MCR p15, 0, <Rd>, c5, c0, 0: Data Fault Status Register */
|
||||
arm.data_fault_status = value;
|
||||
break;
|
||||
case 0x050020: /* MCR p15, 0, <Rd>, c5, c0, 1: Instruction Fault Status Register */
|
||||
arm.instruction_fault_status = value;
|
||||
break;
|
||||
case 0x060000: /* MCR p15, 0, <Rd>, c6, c0, 0: Fault Address Register */
|
||||
arm.fault_address = value;
|
||||
break;
|
||||
case 0x070080: /* MCR p15, 0, <Rd>, c7, c0, 4: Wait for interrupt */
|
||||
cycle_count_delta = 0;
|
||||
if (arm.interrupts == 0) {
|
||||
arm.reg[15] -= 4;
|
||||
cpu_events |= EVENT_WAITING;
|
||||
}
|
||||
break;
|
||||
case 0x080005: /* MCR p15, 0, <Rd>, c8, c5, 0: Invalidate instruction TLB */
|
||||
case 0x080007: /* MCR p15, 0, <Rd>, c8, c7, 0: Invalidate TLB */
|
||||
case 0x080025: /* MCR p15, 0, <Rd>, c8, c5, 1: Invalidate instruction TLB entry */
|
||||
case 0x080027: /* MCR p15, 0, <Rd>, c8, c7, 1: Invalidate TLB (used by polydumper) */
|
||||
case 0x070005: /* MCR p15, 0, <Rd>, c7, c5, 0: Invalidate ICache */
|
||||
case 0x070025: /* MCR p15, 0, <Rd>, c7, c5, 1: Invalidate ICache line */
|
||||
case 0x070007: /* MCR p15, 0, <Rd>, c7, c7, 0: Invalidate ICache and DCache */
|
||||
addr_cache_flush();
|
||||
break;
|
||||
|
||||
case 0x080006: /* MCR p15, 0, <Rd>, c8, c6, 0: Invalidate data TLB */
|
||||
case 0x080026: /* MCR p15, 0, <Rd>, c8, c6, 1: Invalidate data TLB entry */
|
||||
case 0x070026: /* MCR p15, 0, <Rd>, c7, c6, 1: Invalidate single DCache entry */
|
||||
case 0x07002A: /* MCR p15, 0, <Rd>, c7, c10, 1: Clean DCache line */
|
||||
case 0x07002E: /* MCR p15, 0, <Rd>, c7, c14, 1: Clean and invalidate single DCache entry */
|
||||
case 0x07008A: /* MCR p15, 0, <Rd>, c7, c10, 4: Drain write buffer */
|
||||
case 0x0F0000: /* MCR p15, 0, <Rd>, c15, c0, 0: Debug Override Register */
|
||||
#ifdef SUPPORT_LINUX
|
||||
// Normally ignored, but somehow needed for linux to boot correctly
|
||||
addr_cache_flush();
|
||||
#endif
|
||||
break;
|
||||
case 0x0F0001: /* MCR p15, 0, <Rd>, c15, c1, 0: Unknown */
|
||||
//TODO: Unknown(implmentation defined cp15 register)
|
||||
break;
|
||||
default:
|
||||
warn("Unknown coprocessor instruction MCR %08X", insn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void do_cp15_instruction(Instruction i)
|
||||
{
|
||||
uint32_t insn = i.raw;
|
||||
if(insn & 0x00100000)
|
||||
return do_cp15_mrc(insn);
|
||||
else
|
||||
return do_cp15_mcr(insn);
|
||||
}
|
||||
|
||||
void do_cp14_instruction(Instruction i)
|
||||
{
|
||||
uint32_t instr = i.raw;
|
||||
bool specialInstr = i.cond == 0xF;
|
||||
bool success;
|
||||
|
||||
success = pxa260pwrClkPrvCoprocRegXferFunc(&pxa260PwrClk, specialInstr, (instr & 0x00100000) != 0, (instr >> 21) & 0x07, (instr >> 12) & 0x0F, (instr >> 16) & 0x0F, instr & 0x0F, (instr >> 5) & 0x07);
|
||||
|
||||
//fail if instr dosent actully exist
|
||||
if(!success)
|
||||
undefined_instruction();
|
||||
}
|
||||
|
||||
428
src/armv5te/cpu.cpp
Normal file
@@ -0,0 +1,428 @@
|
||||
#include <algorithm>
|
||||
//#include <mutex>
|
||||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
// Uncomment the following line to measure the time until the OS is loaded
|
||||
// #define BENCHMARK
|
||||
#ifdef BENCHMARK
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "armsnippets.h"
|
||||
#include "asmcode.h"
|
||||
#include "cpu.h"
|
||||
#include "cpudefs.h"
|
||||
#include "debug.h"
|
||||
#include "emu.h"
|
||||
#include "mem.h"
|
||||
#include "mmu.h"
|
||||
#include "translate.h"
|
||||
|
||||
// Global CPU state
|
||||
struct arm_state arm;
|
||||
|
||||
void cpu_arm_loop()
|
||||
{
|
||||
while (!exiting && cycle_count_delta < 0 && current_instr_size == 4)
|
||||
{
|
||||
arm.reg[15] &= ~0x3; // Align PC
|
||||
Instruction *p = static_cast<Instruction*>(read_instruction(arm.reg[15]));
|
||||
|
||||
#ifdef BENCHMARK
|
||||
static clock_t start = 0;
|
||||
if(arm.reg[15] == 0)
|
||||
{
|
||||
start = clock();
|
||||
turbo_mode = true;
|
||||
}
|
||||
else if(arm.reg[15] == 0x10000000 || arm.reg[15] == 0x11800000)
|
||||
{
|
||||
clock_t diff = clock() - start;
|
||||
printf("%ld ms\n", diff / 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t *flags_ptr = &RAM_FLAGS(p);
|
||||
|
||||
// Check for pending events
|
||||
if(cpu_events)
|
||||
{
|
||||
// Events other than DEBUG_STEP are handled outside
|
||||
if(cpu_events & ~EVENT_DEBUG_STEP)
|
||||
break;
|
||||
goto enter_debugger;
|
||||
}
|
||||
|
||||
// TODO: Other flags
|
||||
if(*flags_ptr & (RF_EXEC_BREAKPOINT | RF_EXEC_DEBUG_NEXT | RF_ARMLOADER_CB))
|
||||
{
|
||||
if(*flags_ptr & RF_ARMLOADER_CB)
|
||||
{
|
||||
*flags_ptr &= ~RF_ARMLOADER_CB;
|
||||
armloader_cb();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*flags_ptr & RF_EXEC_BREAKPOINT)
|
||||
gui_debug_printf("Breakpoint at 0x%08x\n", arm.reg[15]);
|
||||
enter_debugger:
|
||||
uint32_t pc = arm.reg[15];
|
||||
debugger(DBG_EXEC_BREAKPOINT, 0);
|
||||
if(arm.reg[15] != pc)
|
||||
continue; // Debugger changed PC
|
||||
}
|
||||
}
|
||||
#ifndef NO_TRANSLATION
|
||||
else if(do_translate && !(*flags_ptr & DONT_TRANSLATE) && (*flags_ptr & RF_CODE_EXECUTED))
|
||||
translate(arm.reg[15], &p->raw);
|
||||
|
||||
// If the instruction is translated, use the translation
|
||||
if((~cpu_events & EVENT_DEBUG_STEP) && *flags_ptr & RF_CODE_TRANSLATED)
|
||||
{
|
||||
#if TRANSLATION_ENTER_HAS_PTR
|
||||
translation_enter(p);
|
||||
#else
|
||||
translation_enter();
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
*flags_ptr |= RF_CODE_EXECUTED;
|
||||
#endif
|
||||
|
||||
/*
|
||||
//TODO: remove this, causes slowdown
|
||||
if(arm.reg[15] == 0x200AC088)
|
||||
emuprintf("HAL state set:%d\n", arm.reg[0]);
|
||||
*/
|
||||
|
||||
arm.reg[15] += 4; // Increment now to account for the pipeline
|
||||
++cycle_count_delta;
|
||||
do_arm_instruction(*p);
|
||||
}
|
||||
}
|
||||
|
||||
// Makes arm.reg[15] point to the current instruction
|
||||
void fix_pc_for_fault()
|
||||
{
|
||||
#ifndef NO_TRANSLATION
|
||||
translate_fix_pc();
|
||||
#endif
|
||||
|
||||
arm.reg[15] -= current_instr_size;
|
||||
}
|
||||
|
||||
void prefetch_abort(uint32_t mva, uint8_t status)
|
||||
{
|
||||
warn("Prefetch abort: address=%08x status=%02x\n", mva, status);
|
||||
arm.reg[15] += 4;
|
||||
// Fault address register not changed
|
||||
arm.instruction_fault_status = status;
|
||||
cpu_exception(EX_PREFETCH_ABORT);
|
||||
if (mva == arm.reg[15])
|
||||
error("Abort occurred with exception vectors unmapped");
|
||||
longjmp(restart_after_exception, 1);
|
||||
}
|
||||
|
||||
void data_abort(uint32_t mva, uint8_t status)
|
||||
{
|
||||
fix_pc_for_fault();
|
||||
warn("Data abort: address=%08x status=%02x instruction at %08x\n", mva, status, arm.reg[15]);
|
||||
arm.reg[15] += 8;
|
||||
arm.fault_address = mva;
|
||||
arm.data_fault_status = status;
|
||||
cpu_exception(EX_DATA_ABORT);
|
||||
longjmp(restart_after_exception, 1);
|
||||
}
|
||||
|
||||
void undefined_instruction()
|
||||
{
|
||||
fix_pc_for_fault();
|
||||
if(current_instr_size == 4)
|
||||
warn("Undefined instruction 0x%08X at 0x%08X\n", read_word(arm.reg[15]), arm.reg[15]);
|
||||
else
|
||||
warn("Undefined instruction 0x%04X at 0x%08X\n", read_half(arm.reg[15]), arm.reg[15]);
|
||||
arm.reg[15] += current_instr_size;
|
||||
cpu_exception(EX_UNDEFINED);
|
||||
longjmp(restart_after_exception, 1);
|
||||
}
|
||||
|
||||
void *try_ptr(uint32_t addr)
|
||||
{
|
||||
//There are two different addr_cache formats...
|
||||
#ifdef AC_FLAGS
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1));
|
||||
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID)
|
||||
return addr_cache_miss(addr, false, nullptr);
|
||||
else // MMIO stuff
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
return (void*)entry;
|
||||
#else
|
||||
void *ptr = &addr_cache[(addr >> 10) << 1][addr];
|
||||
if(unlikely((uintptr_t)ptr & AC_NOT_PTR))
|
||||
ptr = addr_cache_miss(addr, false, nullptr);
|
||||
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void * FASTCALL read_instruction(uint32_t addr)
|
||||
{
|
||||
//There are two different addr_cache formats...
|
||||
#ifdef AC_FLAGS
|
||||
uintptr_t entry = *(uintptr_t*)(addr_cache + ((addr >> 10) << 1));
|
||||
|
||||
if(unlikely(entry & AC_FLAGS))
|
||||
{
|
||||
if(entry & AC_INVALID)
|
||||
return addr_cache_miss(addr, false, prefetch_abort);
|
||||
else // Executing MMIO stuff
|
||||
error("PC in MMIO range: 0x%x\n", addr);
|
||||
}
|
||||
|
||||
entry += addr;
|
||||
return (void*)entry;
|
||||
#else
|
||||
void *ptr = &addr_cache[(addr >> 10) << 1][addr];
|
||||
if(unlikely((uintptr_t)ptr & AC_NOT_PTR))
|
||||
{
|
||||
ptr = addr_cache_miss(addr, false, prefetch_abort);
|
||||
if (!ptr)
|
||||
error("Bad PC: %08x\n", addr);
|
||||
}
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update cpu_events
|
||||
void cpu_int_check()
|
||||
{
|
||||
//events arnt threaded like this in Mu, plus this breaks the RetroArch build, some undefined reference thing
|
||||
//static std::mutex mut;
|
||||
//std::lock_guard<std::mutex> lg(mut);
|
||||
|
||||
if (arm.interrupts & ~arm.cpsr_low28 & 0x80)
|
||||
cpu_events |= EVENT_IRQ;
|
||||
else
|
||||
cpu_events &= ~EVENT_IRQ;
|
||||
|
||||
if (arm.interrupts & ~arm.cpsr_low28 & 0x40)
|
||||
cpu_events |= EVENT_FIQ;
|
||||
else
|
||||
cpu_events &= ~EVENT_FIQ;
|
||||
}
|
||||
|
||||
static const constexpr uint8_t exc_flags[] = {
|
||||
MODE_SVC | 0xC0, /* Reset */
|
||||
MODE_UND | 0x80, /* Undefined instruction */
|
||||
MODE_SVC | 0x80, /* Software interrupt */
|
||||
MODE_ABT | 0x80, /* Prefetch abort */
|
||||
MODE_ABT | 0x80, /* Data abort */
|
||||
0, /* Reserved */
|
||||
MODE_IRQ | 0x80, /* IRQ */
|
||||
MODE_FIQ | 0xC0, /* FIQ */
|
||||
};
|
||||
|
||||
void cpu_exception(int type)
|
||||
{
|
||||
/* Switch mode, disable interrupts */
|
||||
uint32_t old_cpsr = get_cpsr();
|
||||
set_cpsr_full((old_cpsr & ~0x3F) | exc_flags[type]);
|
||||
*ptr_spsr() = old_cpsr;
|
||||
|
||||
/* Branch-and-link to exception handler */
|
||||
arm.reg[14] = arm.reg[15];
|
||||
arm.reg[15] = type << 2;
|
||||
if (arm.control & 0x2000) /* High vectors */
|
||||
arm.reg[15] += 0xFFFF0000;
|
||||
}
|
||||
|
||||
uint32_t get_cpsr_flags()
|
||||
{
|
||||
return arm.cpsr_n << 31
|
||||
| arm.cpsr_z << 30
|
||||
| arm.cpsr_c << 29
|
||||
| arm.cpsr_v << 28;
|
||||
}
|
||||
|
||||
void set_cpsr_flags(uint32_t flags)
|
||||
{
|
||||
arm.cpsr_n = (flags >> 31) & 1;
|
||||
arm.cpsr_z = (flags >> 30) & 1;
|
||||
arm.cpsr_c = (flags >> 29) & 1;
|
||||
arm.cpsr_v = (flags >> 28) & 1;
|
||||
}
|
||||
|
||||
// Get full CPSR register
|
||||
uint32_t get_cpsr()
|
||||
{
|
||||
return arm.cpsr_n << 31
|
||||
| arm.cpsr_z << 30
|
||||
| arm.cpsr_c << 29
|
||||
| arm.cpsr_v << 28
|
||||
| arm.cpsr_low28;
|
||||
}
|
||||
|
||||
void set_cpsr_full(uint32_t cpsr)
|
||||
{
|
||||
uint8_t old_mode = arm.cpsr_low28 & 0x1F,
|
||||
new_mode = cpsr & 0x1F;
|
||||
|
||||
if(old_mode == new_mode)
|
||||
goto same_mode;
|
||||
|
||||
// Only FIQ mode has more than 2 regs banked
|
||||
if(old_mode == MODE_FIQ)
|
||||
std::copy(arm.reg + 8, arm.reg + 13, arm.r8_fiq);
|
||||
else
|
||||
std::copy(arm.reg + 8, arm.reg + 13, arm.r8_usr);
|
||||
|
||||
switch(old_mode)
|
||||
{
|
||||
case MODE_USR: case MODE_SYS:
|
||||
std::copy(arm.reg + 13, arm.reg + 15, arm.r13_usr);
|
||||
break;
|
||||
case MODE_FIQ:
|
||||
std::copy(arm.reg + 13, arm.reg + 15, arm.r13_fiq);
|
||||
break;
|
||||
case MODE_IRQ:
|
||||
std::copy(arm.reg + 13, arm.reg + 15, arm.r13_irq);
|
||||
break;
|
||||
case MODE_SVC:
|
||||
std::copy(arm.reg + 13, arm.reg + 15, arm.r13_svc);
|
||||
break;
|
||||
case MODE_ABT:
|
||||
std::copy(arm.reg + 13, arm.reg + 15, arm.r13_abt);
|
||||
break;
|
||||
case MODE_UND:
|
||||
std::copy(arm.reg + 13, arm.reg + 15, arm.r13_und);
|
||||
break;
|
||||
default: assert(false);
|
||||
}
|
||||
|
||||
if(new_mode == MODE_FIQ)
|
||||
std::copy(arm.r8_fiq, arm.r8_fiq + 5, arm.reg + 8);
|
||||
else
|
||||
std::copy(arm.r8_usr, arm.r8_usr + 5, arm.reg + 8);
|
||||
|
||||
switch(new_mode)
|
||||
{
|
||||
case MODE_USR: case MODE_SYS:
|
||||
std::copy(arm.r13_usr, arm.r13_usr + 2, arm.reg + 13);
|
||||
break;
|
||||
case MODE_FIQ:
|
||||
std::copy(arm.r13_fiq, arm.r13_fiq + 2, arm.reg + 13);
|
||||
break;
|
||||
case MODE_IRQ:
|
||||
std::copy(arm.r13_irq, arm.r13_irq + 2, arm.reg + 13);
|
||||
break;
|
||||
case MODE_SVC:
|
||||
std::copy(arm.r13_svc, arm.r13_svc + 2, arm.reg + 13);
|
||||
break;
|
||||
case MODE_ABT:
|
||||
std::copy(arm.r13_abt, arm.r13_abt + 2, arm.reg + 13);
|
||||
break;
|
||||
case MODE_UND:
|
||||
std::copy(arm.r13_und, arm.r13_und + 2, arm.reg + 13);
|
||||
break;
|
||||
default: error("Invalid mode 0x%x\n", new_mode);
|
||||
}
|
||||
|
||||
// Access permissions are different
|
||||
if((old_mode == MODE_USR) ^ (new_mode == MODE_USR))
|
||||
addr_cache_flush();
|
||||
|
||||
same_mode:
|
||||
if(cpsr & 0x01000000)
|
||||
error("Jazelle not implemented!");
|
||||
|
||||
arm.cpsr_n = (cpsr >> 31) & 1;
|
||||
arm.cpsr_z = (cpsr >> 30) & 1;
|
||||
arm.cpsr_c = (cpsr >> 29) & 1;
|
||||
arm.cpsr_v = (cpsr >> 28) & 1;
|
||||
arm.cpsr_low28 = cpsr & 0x090000FF; // Mask off reserved bits
|
||||
cpu_int_check();
|
||||
}
|
||||
|
||||
void FASTCALL set_cpsr(uint32_t cpsr, uint32_t mask) {
|
||||
if (!(arm.cpsr_low28 & 0x0F)) {
|
||||
/* User mode. Don't change privileged or execution state bits */
|
||||
mask &= ~0x010000FF;
|
||||
}
|
||||
cpsr = (cpsr & mask) | (get_cpsr() & ~mask);
|
||||
if (cpsr & 0x20)
|
||||
error("Cannot set T bit with MSR instruction");
|
||||
set_cpsr_full(cpsr);
|
||||
}
|
||||
|
||||
uint32_t *ptr_spsr()
|
||||
{
|
||||
switch (arm.cpsr_low28 & 0x1F)
|
||||
{
|
||||
case MODE_FIQ: return &arm.spsr_fiq;
|
||||
case MODE_IRQ: return &arm.spsr_irq;
|
||||
case MODE_SVC: return &arm.spsr_svc;
|
||||
case MODE_ABT: return &arm.spsr_abt;
|
||||
case MODE_UND: return &arm.spsr_und;
|
||||
}
|
||||
error("Attempted to access SPSR from user or system mode");
|
||||
}
|
||||
|
||||
uint32_t get_spsr() {
|
||||
return *ptr_spsr();
|
||||
}
|
||||
|
||||
void FASTCALL set_spsr(uint32_t spsr, uint32_t mask) {
|
||||
*ptr_spsr() ^= (*ptr_spsr() ^ spsr) & mask;
|
||||
}
|
||||
|
||||
uint32_t reg(uint8_t i)
|
||||
{
|
||||
if(unlikely(i == 15))
|
||||
error("PC invalid in this context!\n");
|
||||
return arm.reg[i];
|
||||
}
|
||||
|
||||
uint32_t reg_pc(uint8_t i)
|
||||
{
|
||||
if(unlikely(i == 15))
|
||||
return arm.reg[15] + 4;
|
||||
return arm.reg[i];
|
||||
}
|
||||
|
||||
uint32_t reg_pc_mem(uint8_t i)
|
||||
{
|
||||
if(unlikely(i == 15))
|
||||
return arm.reg[15] + 8;
|
||||
return arm.reg[i];
|
||||
}
|
||||
|
||||
void set_reg(uint8_t i, uint32_t value)
|
||||
{
|
||||
if(unlikely(i == 15))
|
||||
error("PC invalid in this context!\n");
|
||||
arm.reg[i] = value;
|
||||
}
|
||||
|
||||
void set_reg_pc(uint8_t i, uint32_t value)
|
||||
{
|
||||
arm.reg[i] = value;
|
||||
}
|
||||
|
||||
void set_reg_bx(uint8_t i, uint32_t value)
|
||||
{
|
||||
arm.reg[i] = value;
|
||||
|
||||
if(i == 15 && (value & 1))
|
||||
{
|
||||
arm.cpsr_low28 |= 0x20; // Enter Thumb mode
|
||||
arm.reg[15] -= 1;
|
||||
}
|
||||
}
|
||||
110
src/armv5te/cpu.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* Declarations for cpu.c */
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct arm_state { // Remember to update asmcode.S if this gets rearranged
|
||||
uint32_t reg[16]; // Registers for current mode.
|
||||
|
||||
uint32_t cpsr_low28; // CPSR bits 0-27
|
||||
uint8_t cpsr_n; // CPSR bit 31
|
||||
uint8_t cpsr_z; // CPSR bit 30
|
||||
uint8_t cpsr_c; // CPSR bit 29
|
||||
uint8_t cpsr_v; // CPSR bit 28
|
||||
|
||||
#if defined(__arm__)
|
||||
uint32_t cpsr_flags; // Only used in ARM translations
|
||||
#endif
|
||||
|
||||
/* CP15 registers */
|
||||
uint32_t control;
|
||||
uint32_t translation_table_base;
|
||||
uint32_t domain_access_control;
|
||||
uint8_t data_fault_status, instruction_fault_status, pad1, pad2; // pad1 and pad2 for better alignment
|
||||
uint32_t fault_address;
|
||||
|
||||
uint32_t r8_usr[5], r13_usr[2];
|
||||
uint32_t r8_fiq[5], r13_fiq[2], spsr_fiq;
|
||||
uint32_t r13_irq[2], spsr_irq;
|
||||
uint32_t r13_svc[2], spsr_svc;
|
||||
uint32_t r13_abt[2], spsr_abt;
|
||||
uint32_t r13_und[2], spsr_und;
|
||||
|
||||
uint8_t interrupts;
|
||||
uint32_t cpu_events_state; // Only used for suspend and resume!
|
||||
}
|
||||
#ifndef __EMSCRIPTEN__
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
arm_state;
|
||||
extern struct arm_state arm __asm__("arm");
|
||||
|
||||
#define MODE_USR 0x10
|
||||
#define MODE_FIQ 0x11
|
||||
#define MODE_IRQ 0x12
|
||||
#define MODE_SVC 0x13
|
||||
#define MODE_ABT 0x17
|
||||
#define MODE_UND 0x1B
|
||||
#define MODE_SYS 0x1F
|
||||
#define PRIVILEGED_MODE() (arm.cpsr_low28 & 3)
|
||||
#define USER_MODE() (!(arm.cpsr_low28 & 3))
|
||||
|
||||
#define EX_RESET 0
|
||||
#define EX_UNDEFINED 1
|
||||
#define EX_SWI 2
|
||||
#define EX_PREFETCH_ABORT 3
|
||||
#define EX_DATA_ABORT 4
|
||||
#define EX_IRQ 6
|
||||
#define EX_FIQ 7
|
||||
|
||||
#define current_instr_size ((arm.cpsr_low28 & 0x20) ? 2 /* thumb */ : 4)
|
||||
|
||||
// Needed for the assembler calling convention
|
||||
#ifdef __i386__
|
||||
#ifdef FASTCALL
|
||||
#undef FASTCALL
|
||||
#endif
|
||||
#define FASTCALL __attribute__((fastcall))
|
||||
#else
|
||||
#define FASTCALL
|
||||
#endif
|
||||
|
||||
void cpu_int_check();
|
||||
uint32_t get_cpsr() __asm__("get_cpsr");
|
||||
void set_cpsr_full(uint32_t cpsr);
|
||||
void FASTCALL set_cpsr(uint32_t cpsr, uint32_t mask);
|
||||
uint32_t get_spsr();
|
||||
void FASTCALL set_spsr(uint32_t cpsr, uint32_t mask);
|
||||
uint32_t *ptr_spsr();
|
||||
uint32_t get_cpsr_flags();
|
||||
void set_cpsr_flags(uint32_t flags) __asm__("set_cpsr_flags");
|
||||
void cpu_exception(int type);
|
||||
void fix_pc_for_fault();
|
||||
void *try_ptr(uint32_t addr);
|
||||
void cpu_interpret_instruction(uint32_t insn);
|
||||
void cpu_arm_loop();
|
||||
void cpu_thumb_loop();
|
||||
typedef void fault_proc(uint32_t mva, uint8_t status);
|
||||
fault_proc prefetch_abort, data_abort __asm__("data_abort");
|
||||
void undefined_instruction();
|
||||
|
||||
uint32_t reg(uint8_t i);
|
||||
uint32_t reg_pc(uint8_t i);
|
||||
uint32_t reg_pc_mem(uint8_t i);
|
||||
void set_reg(uint8_t i, uint32_t value);
|
||||
void set_reg_pc(uint8_t i, uint32_t value);
|
||||
void set_reg_bx(uint8_t i, uint32_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
157
src/armv5te/cpudefs.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#ifndef CPUDEFS_H
|
||||
#define CPUDEFS_H
|
||||
|
||||
#include "bitfield.h"
|
||||
|
||||
// Structure of instructions, enums etc.
|
||||
|
||||
union Instruction {
|
||||
uint32_t raw;
|
||||
|
||||
BitField<28, 4> cond;
|
||||
BitField<0, 28> rest;
|
||||
|
||||
union {
|
||||
BitField<24> l;
|
||||
BitField<0, 24> immed;
|
||||
} branch;
|
||||
|
||||
union {
|
||||
BitField<0, 4> rm;
|
||||
BitField<5> l;
|
||||
} bx;
|
||||
|
||||
union {
|
||||
BitField<21, 4> op;
|
||||
BitField<20> s;
|
||||
BitField<16, 4> rn;
|
||||
BitField<12, 4> rd;
|
||||
BitField<25> imm;
|
||||
|
||||
// If imm
|
||||
BitField<0, 8> immed_8;
|
||||
BitField<8, 4> rotate_imm;
|
||||
// else
|
||||
BitField<4> reg_shift;
|
||||
BitField<0, 4> rm;
|
||||
BitField<5, 2> shift;
|
||||
// If reg_shift
|
||||
BitField<8, 4> rs;
|
||||
// else
|
||||
BitField<7, 5> shift_imm;
|
||||
} data_proc; // ADD, MOV, etc.
|
||||
|
||||
union {
|
||||
BitField<25> not_imm;
|
||||
BitField<24> p;
|
||||
BitField<23> u;
|
||||
BitField<22> b;
|
||||
BitField<21> w;
|
||||
BitField<20> l;
|
||||
BitField<16, 4> rn;
|
||||
BitField<12, 4> rd;
|
||||
|
||||
// If not_imm == 0
|
||||
BitField<0, 12> immed;
|
||||
// else
|
||||
BitField<0, 4> rm;
|
||||
BitField<5, 2> shift;
|
||||
BitField<7, 5> shift_imm;
|
||||
} mem_proc; // LDR, STRB, etc.
|
||||
|
||||
union {
|
||||
BitField<24> p;
|
||||
BitField<23> u;
|
||||
BitField<22> i;
|
||||
BitField<21> w;
|
||||
BitField<20> l;
|
||||
BitField<16, 4> rn;
|
||||
BitField<12, 4> rd;
|
||||
|
||||
BitField<6> s;
|
||||
BitField<5> h;
|
||||
|
||||
// If i
|
||||
BitField<8, 4> immed_h;
|
||||
BitField<0, 4> immed_l;
|
||||
// else
|
||||
BitField<0, 4> rm;
|
||||
} mem_proc2; // LDRH, STRSH, etc.
|
||||
|
||||
union {
|
||||
BitField<23> l;
|
||||
BitField<21> a;
|
||||
BitField<20> s;
|
||||
|
||||
BitField<8, 4> rs;
|
||||
BitField<0, 4> rm;
|
||||
|
||||
// If l
|
||||
BitField<16, 4> rdhi;
|
||||
BitField<12, 4> rdlo;
|
||||
// else
|
||||
BitField<16, 4> rd;
|
||||
BitField<12, 4> rn;
|
||||
} mult;
|
||||
|
||||
union {
|
||||
BitField<22> r;
|
||||
BitField<12, 4> rd;
|
||||
} mrs;
|
||||
|
||||
union {
|
||||
BitField<24> p;
|
||||
BitField<23> u;
|
||||
BitField<22> s;
|
||||
BitField<21> w;
|
||||
BitField<20> l;
|
||||
BitField<16, 4> rn;
|
||||
BitField<0, 16> reglist;
|
||||
} mem_multi;
|
||||
};
|
||||
|
||||
enum Condition {
|
||||
CC_EQ=0, CC_NE,
|
||||
CC_CS, CC_CC,
|
||||
CC_MI, CC_PL,
|
||||
CC_VS, CC_VC,
|
||||
CC_HI, CC_LS,
|
||||
CC_GE, CC_LT,
|
||||
CC_GT, CC_LE,
|
||||
CC_AL, CC_NV
|
||||
};
|
||||
|
||||
enum ShiftType {
|
||||
SH_LSL=0,
|
||||
SH_LSR,
|
||||
SH_ASR,
|
||||
SH_ROR // RRX if count == 0
|
||||
};
|
||||
|
||||
enum DataOp {
|
||||
OP_AND=0,
|
||||
OP_EOR,
|
||||
OP_SUB,
|
||||
OP_RSB,
|
||||
OP_ADD,
|
||||
OP_ADC,
|
||||
OP_SBC,
|
||||
OP_RSC,
|
||||
OP_TST,
|
||||
OP_TEQ,
|
||||
OP_CMP,
|
||||
OP_CMN,
|
||||
OP_ORR,
|
||||
OP_MOV,
|
||||
OP_BIC,
|
||||
OP_MVN
|
||||
};
|
||||
|
||||
// Defined in arm_interpreter.cpp
|
||||
void do_arm_instruction(Instruction i);
|
||||
// Defined in coproc.cpp
|
||||
void do_cp15_instruction(Instruction i);
|
||||
void do_cp14_instruction(Instruction i);
|
||||
|
||||
#endif // CPUDEFS_H
|
||||
|
||||
58
src/armv5te/debug.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* Declarations for debug.c */
|
||||
#ifndef _H_DEBUG
|
||||
#define _H_DEBUG
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string>
|
||||
//extern std::string ln_target_folder;
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern FILE *debugger_input;
|
||||
|
||||
/*
|
||||
extern bool gdb_connected;
|
||||
extern bool in_debugger;
|
||||
extern int rdbg_port;
|
||||
*/
|
||||
#define gdb_connected false
|
||||
#define in_debugger false
|
||||
#define rdbg_port 0
|
||||
|
||||
enum DBG_REASON {
|
||||
DBG_USER,
|
||||
DBG_EXCEPTION,
|
||||
DBG_EXEC_BREAKPOINT,
|
||||
DBG_READ_BREAKPOINT,
|
||||
DBG_WRITE_BREAKPOINT,
|
||||
};
|
||||
|
||||
/*
|
||||
void *virt_mem_ptr(uint32_t addr, uint32_t size);
|
||||
void backtrace(uint32_t fp);
|
||||
int process_debug_cmd(char *cmdline);
|
||||
void debugger(enum DBG_REASON reason, uint32_t addr);
|
||||
void rdebug_recv(void);
|
||||
bool rdebug_bind(unsigned int port);
|
||||
void rdebug_quit();
|
||||
*/
|
||||
#define virt_mem_ptr(x, y) NULL
|
||||
#define backtrace(x)
|
||||
#define process_debug_cmd(x) 0
|
||||
#define debugger(x, y)
|
||||
#define rdebug_recv()
|
||||
#define rdebug_bind(x) false
|
||||
#define rdebug_quit()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
551
src/armv5te/disasm.c
Normal file
@@ -0,0 +1,551 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "disasm.h"
|
||||
#include "emu.h"
|
||||
|
||||
static char *strcpy2(char *dest, const char *src) {
|
||||
while ((*dest = *src)) { dest++; src++; }
|
||||
return dest;
|
||||
}
|
||||
|
||||
const char reg_name[16][4] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"
|
||||
};
|
||||
|
||||
static const char condcode[16][3] = {
|
||||
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
|
||||
"hi", "ls", "ge", "lt", "gt", "le", "", "2"
|
||||
};
|
||||
|
||||
enum suffix {
|
||||
none_,
|
||||
XY, // halfword signed mul
|
||||
Y, // halfword signed mul
|
||||
S, // Bit 20 S: alu, MUL etc
|
||||
B, // Bit 22 B: LDR/STR, SWP
|
||||
BT, // Bit 21 T: LDR/STR with postindex (bit 24=0)
|
||||
M, // Bit 23-24 DA/IA/DB/IB
|
||||
H, // H/SB/SH
|
||||
D, // double-word insn
|
||||
L, // Bit 22 L: LDC/STC
|
||||
};
|
||||
|
||||
enum operand {
|
||||
none,
|
||||
REG0, // Bits 0-3 specify register
|
||||
REG8, // Bits 8-11 specify register
|
||||
REG12, // Bits 12-15 specify register
|
||||
REG16, // Bits 16-19 specify register
|
||||
PSR,
|
||||
SHFOP, // Bits 0-11 specify shifted reg or immediate
|
||||
IMMED, // Bits 0-11 specify rotated immediate
|
||||
MEM,
|
||||
MEMH,
|
||||
MEM16,
|
||||
MULTI,
|
||||
BRCH, // Bits 0-23 specify branch target
|
||||
BRCHT, // Bits 0-24 specify branch target for THUMB code
|
||||
COPR, // Bits 8-11 specify coprocessor number
|
||||
CDP, MRC, MRRC, MEMC,
|
||||
BKPT, SWI,
|
||||
};
|
||||
|
||||
static const struct arm_insn {
|
||||
uint32_t mask;
|
||||
uint32_t value;
|
||||
char name[7];
|
||||
uint8_t suffix;
|
||||
uint8_t op1, op2, op3, op4;
|
||||
} table[] = {
|
||||
{0xFD70F000,0xF550F000, "pld", 0, MEM, none, none, none },
|
||||
{0xFE000000,0xFA000000, "blx", 0, BRCHT, none, none, none },
|
||||
|
||||
/* Coprocessor instructions may have any condition field */
|
||||
{ 0xFF00000, 0xC400000, "mcrr", 0, COPR, MRRC, none, none },
|
||||
{ 0xFF00000, 0xC500000, "mrrc", 0, COPR, MRRC, none, none },
|
||||
{ 0xE100000, 0xC000000, "stc", L, COPR, MEMC, none, none },
|
||||
{ 0xE100000, 0xC100000, "ldc", L, COPR, MEMC, none, none },
|
||||
{ 0xF000010, 0xE000000, "cdp", 0, COPR, CDP, none, none },
|
||||
{ 0xF100010, 0xE000010, "mcr", 0, COPR, MRC, none, none },
|
||||
{ 0xF100010, 0xE100010, "mrc", 0, COPR, MRC, none, none },
|
||||
|
||||
/* No other instructions are valid with condition field 1111 */
|
||||
{0xF0000000,0xF0000000, "???", 0, none, none, none, none },
|
||||
|
||||
{ 0xFE0F0F0, 0x0000090, "mul", S, REG16, REG0, REG8, none },
|
||||
{ 0xFE000F0, 0x0200090, "mla", S, REG16, REG0, REG8, REG12 },
|
||||
{ 0xFE000F0, 0x0800090, "umull", S, REG12, REG16, REG0, REG8 },
|
||||
{ 0xFE000F0, 0x0A00090, "umlal", S, REG12, REG16, REG0, REG8 },
|
||||
{ 0xFE000F0, 0x0C00090, "smull", S, REG12, REG16, REG0, REG8 },
|
||||
{ 0xFE000F0, 0x0E00090, "smlal", S, REG12, REG16, REG0, REG8 },
|
||||
{ 0xFB00FF0, 0x1000090, "swp", B, REG12, REG0, MEM16, none },
|
||||
{ 0xE0000F0, 0x0000090, "???", 0, none, none, none, none },
|
||||
|
||||
{ 0xE1000F0, 0x00000B0, "str", H, REG12, MEMH, none, none },
|
||||
{ 0xE1010F0, 0x00000D0, "ldr", D, REG12, MEMH, none, none },
|
||||
{ 0xE1010F0, 0x00000F0, "str", D, REG12, MEMH, none, none },
|
||||
{ 0xE1000F0, 0x01000B0, "ldr", H, REG12, MEMH, none, none },
|
||||
{ 0xE1000F0, 0x01000D0, "ldr", H, REG12, MEMH, none, none },
|
||||
{ 0xE1000F0, 0x01000F0, "ldr", H, REG12, MEMH, none, none },
|
||||
|
||||
{ 0xFBF0FFF, 0x10F0000, "mrs", 0, REG12, PSR, none, none },
|
||||
{ 0xFB0FFF0, 0x120F000, "msr", 0, PSR, REG0, none, none },
|
||||
{ 0xFF00FF0, 0x1000050, "qadd", 0, REG12, REG0, REG16, none },
|
||||
{ 0xFF00FF0, 0x1200050, "qsub", 0, REG12, REG0, REG16, none },
|
||||
{ 0xFF00FF0, 0x1400050, "qdadd", 0, REG12, REG0, REG16, none },
|
||||
{ 0xFF00FF0, 0x1600050, "qdsub", 0, REG12, REG0, REG16, none },
|
||||
{0xFFF000F0,0xE1200070, "bkpt", 0, BKPT, none, none, none },
|
||||
|
||||
{ 0xFB0F000, 0x320F000, "msr", 0, PSR, IMMED, none, none },
|
||||
|
||||
{ 0xFF00090, 0x1000080, "smla", XY,REG16, REG0, REG8, REG12 },
|
||||
{ 0xFF000B0, 0x1200080, "smlaw", Y, REG16, REG0, REG8, REG12 },
|
||||
{ 0xFF0F0B0, 0x12000A0, "smulw", Y, REG16, REG0, REG8, none },
|
||||
{ 0xFF00090, 0x1400080, "smlal", XY,REG12, REG16, REG0, REG8 },
|
||||
{ 0xFF0F090, 0x1600080, "smul", XY,REG16, REG0, REG8, none },
|
||||
|
||||
{ 0xFFFFFF0, 0x12FFF10, "bx", 0, REG0, none, none, none },
|
||||
{ 0xFFFFFF0, 0x12FFF20, "bxj", 0, REG0, none, none, none },
|
||||
{ 0xFFFFFF0, 0x12FFF30, "blx", 0, REG0, none, none, none },
|
||||
|
||||
{ 0xFFF0FF0, 0x16F0F10, "clz", 0, REG12, REG0, none, none },
|
||||
|
||||
{ 0xDE00000, 0x0000000, "and", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0200000, "eor", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0400000, "sub", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0600000, "rsb", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0800000, "add", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0A00000, "adc", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0C00000, "sbc", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDE00000, 0x0E00000, "rsc", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDF0F000, 0x1100000, "tst", 0, REG16, SHFOP, none, none },
|
||||
{ 0xDF0F000, 0x1300000, "teq", 0, REG16, SHFOP, none, none },
|
||||
{ 0xDF0F000, 0x1500000, "cmp", 0, REG16, SHFOP, none, none },
|
||||
{ 0xDF0F000, 0x1700000, "cmn", 0, REG16, SHFOP, none, none },
|
||||
{ 0xDE00000, 0x1800000, "orr", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDEF0000, 0x1A00000, "mov", S, REG12, SHFOP, none, none },
|
||||
{ 0xDE00000, 0x1C00000, "bic", S, REG12, REG16, SHFOP, none },
|
||||
{ 0xDEF0000, 0x1E00000, "mvn", S, REG12, SHFOP, none, none },
|
||||
|
||||
/* 4000000-9FFFFFF: word-sized memory accesses */
|
||||
{ 0xD100000, 0x4000000, "str", BT,REG12, MEM, none, none },
|
||||
{ 0xD100000, 0x4100000, "ldr", BT,REG12, MEM, none, none },
|
||||
{ 0xD100000, 0x5000000, "str", B, REG12, MEM, none, none },
|
||||
{ 0xD100000, 0x5100000, "ldr", B, REG12, MEM, none, none },
|
||||
{ 0xE100000, 0x8000000, "stm", M, MULTI, none, none, none },
|
||||
{ 0xE100000, 0x8100000, "ldm", M, MULTI, none, none, none },
|
||||
|
||||
/* A000000-BFFFFFF: branches */
|
||||
{ 0xF000000, 0xA000000, "b", 0, BRCH, none, none, none },
|
||||
{ 0xF000000, 0xB000000, "bl", 0, BRCH, none, none, none },
|
||||
|
||||
/* F000000-FFFFFFF: software interrupt */
|
||||
{ 0xF000000, 0xF000000, "swi", 0, SWI, none, none, none },
|
||||
|
||||
/* Catch-all */
|
||||
{ 0x0000000, 0x0000000, "???", 0, none, none, none, none },
|
||||
};
|
||||
|
||||
static char *do_shift(char *out, uint32_t insn) {
|
||||
static const char shifts[4][4] = { "lsl", "lsr", "asr", "ror" };
|
||||
int shift = insn >> 7 & 31;
|
||||
int stype = insn >> 5 & 3;
|
||||
|
||||
out = strcpy2(out, reg_name[insn & 15]);
|
||||
if (insn & 0x10) {
|
||||
// shift by register (for data processing only, not load/store)
|
||||
if (shift & 1) {
|
||||
*out++ = '?';
|
||||
return out;
|
||||
}
|
||||
out += sprintf(out, " %s %s", shifts[stype], reg_name[shift >> 1]);
|
||||
} else {
|
||||
// shift by immediate
|
||||
int shift = insn >> 7 & 31;
|
||||
int stype = insn >> 5 & 3;
|
||||
if (shift == 0) {
|
||||
if (stype == 0) {
|
||||
// lsl #0 is a no-op
|
||||
return out;
|
||||
} else if (stype == 3) {
|
||||
// ror #0
|
||||
return strcpy2(out, " rrx");
|
||||
} else {
|
||||
// lsr #0 and asr #0 act like shift of 32
|
||||
shift = 32;
|
||||
}
|
||||
}
|
||||
out += sprintf(out, " %s #%d", shifts[stype], shift);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static char *do_reglist(char *out, int regs) {
|
||||
int i;
|
||||
*out++ = '{';
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (regs >> i & 1) {
|
||||
out = strcpy2(out, reg_name[i]);
|
||||
if (regs >> i & 2) {
|
||||
*out++ = '-';
|
||||
while (regs >> ++i & 1);
|
||||
out = strcpy2(out, reg_name[i-1]);
|
||||
}
|
||||
*out++ = ',';
|
||||
}
|
||||
}
|
||||
out[-1] = '}';
|
||||
*out = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
uint32_t disasm_arm_insn(uint32_t pc) {
|
||||
uint32_t *pc_ptr = virt_mem_ptr(pc, 4);
|
||||
if(!pc_ptr)
|
||||
return 0;
|
||||
|
||||
return disasm_arm_insn2(pc, pc_ptr);
|
||||
}
|
||||
|
||||
uint32_t disasm_arm_insn2(uint32_t pc, uint32_t *pc_ptr) {
|
||||
char buf[80];
|
||||
|
||||
uint32_t insn = *pc_ptr;
|
||||
char *out = buf + sprintf(buf, "%08x: %08x\t", pc, insn);
|
||||
|
||||
int i;
|
||||
|
||||
const struct arm_insn *t = table;
|
||||
while ((insn & t->mask) != t->value)
|
||||
t++;
|
||||
|
||||
out = strcpy2(out, t->name);
|
||||
|
||||
switch (t->suffix) {
|
||||
case XY:
|
||||
*out++ = (insn & (1 << 5)) ? 't' : 'b';
|
||||
/* fallthrough */
|
||||
case Y:
|
||||
*out++ = (insn & (1 << 6)) ? 't' : 'b';
|
||||
}
|
||||
|
||||
if (!(t->mask & 0xF0000000))
|
||||
out = strcpy2(out, condcode[insn >> 28]);
|
||||
|
||||
switch (t->suffix) {
|
||||
case S:
|
||||
if (insn & (1 << 20)) *out++ = 's';
|
||||
break;
|
||||
case B:
|
||||
if (insn & (1 << 22)) *out++ = 'b';
|
||||
break;
|
||||
case BT:
|
||||
if (insn & (1 << 22)) *out++ = 'b';
|
||||
if (insn & (1 << 21)) *out++ = 't';
|
||||
break;
|
||||
case M:
|
||||
*out++ = (insn & (1 << 23)) ? 'i' : 'd';
|
||||
*out++ = (insn & (1 << 24)) ? 'b' : 'a';
|
||||
break;
|
||||
case H:
|
||||
if (insn & (1 << 6)) *out++ = 's';
|
||||
*out++ = (insn & (1 << 5)) ? 'h' : 'b';
|
||||
break;
|
||||
case D:
|
||||
*out++ = 'd';
|
||||
break;
|
||||
case L:
|
||||
if (insn & (1 << 22)) *out++ = 'l';
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4 && (&t->op1)[i] != none; i++) {
|
||||
*out++ = i ? ',' : '\t';
|
||||
switch ((&t->op1)[i]) {
|
||||
case REG0: out = strcpy2(out, reg_name[insn & 15]); break;
|
||||
case REG8: out = strcpy2(out, reg_name[insn >> 8 & 15]); break;
|
||||
case REG12: out = strcpy2(out, reg_name[insn >> 12 & 15]); break;
|
||||
case REG16: out = strcpy2(out, reg_name[insn >> 16 & 15]); break;
|
||||
case SHFOP:
|
||||
if (!(insn & (1 << 25))) {
|
||||
out = do_shift(out, insn);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case IMMED: {
|
||||
uint32_t imm = insn & 255, shift = insn >> 7 & 30;
|
||||
out += sprintf(out, "%08x", imm >> shift | imm << (32 - shift));
|
||||
break;
|
||||
}
|
||||
case PSR:
|
||||
*out++ = (insn & (1 << 22)) ? 's' : 'c';
|
||||
*out++ = 'p'; *out++ = 's'; *out++ = 'r';
|
||||
if (~insn >> 16 & 15) {
|
||||
*out++ = '_';
|
||||
if (insn & (1 << 19)) *out++ = 'f';
|
||||
if (insn & (1 << 18)) *out++ = 's';
|
||||
if (insn & (1 << 17)) *out++ = 'x';
|
||||
if (insn & (1 << 16)) *out++ = 'c';
|
||||
}
|
||||
break;
|
||||
case MEM:
|
||||
*out++ = '[';
|
||||
out = strcpy2(out, reg_name[insn >> 16 & 15]);
|
||||
if ((insn & 0x32F0000) == 0x10F0000) {
|
||||
// immediate, offset mode, PC relative
|
||||
int addr = insn & 0xFFF;
|
||||
if (!(insn & (1 << 23))) addr = -addr;
|
||||
addr += pc + 8;
|
||||
out -= 2;
|
||||
out += sprintf(out, "%08x]", addr);
|
||||
uint32_t *ptr = virt_mem_ptr(addr, 4);
|
||||
if (ptr)
|
||||
out += sprintf(out, " = %08x", *ptr);
|
||||
} else {
|
||||
if (!(insn & (1 << 24))) // post-index
|
||||
*out++ = ']';
|
||||
*out++ = ' ';
|
||||
*out++ = (insn & (1 << 23)) ? '+' : '-';
|
||||
*out++ = ' ';
|
||||
if (insn & (1 << 25)) {
|
||||
// register offset
|
||||
if (insn & 0x10) {
|
||||
// register shifted by register not allowed
|
||||
*out++ = '?';
|
||||
} else {
|
||||
out = do_shift(out, insn);
|
||||
}
|
||||
} else {
|
||||
// immediate offset
|
||||
if ((insn & 0xFFF) || !(insn & (1 << 23)))
|
||||
out += sprintf(out, "%03x", insn & 0xFFF);
|
||||
else
|
||||
// don't display an added offset of 0
|
||||
out -= 3;
|
||||
}
|
||||
if (insn & (1 << 24)) { // pre-index
|
||||
*out++ = ']';
|
||||
if (insn & (1 << 21)) // writeback
|
||||
*out++ = '!';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEMH:
|
||||
*out++ = '[';
|
||||
out = strcpy2(out, reg_name[insn >> 16 & 15]);
|
||||
if (!(insn & (1 << 24))) // post-index
|
||||
*out++ = ']';
|
||||
*out++ = ' ';
|
||||
*out++ = (insn & (1 << 23)) ? '+' : '-';
|
||||
*out++ = ' ';
|
||||
if (insn & (1 << 22)) {
|
||||
// immediate offset
|
||||
uint32_t imm = (insn & 0x0F) | (insn >> 4 & 0xF0);
|
||||
if (imm || !(insn & (1 << 23)))
|
||||
out += sprintf(out, "%03x", imm);
|
||||
else
|
||||
// don't display an added offset of 0
|
||||
out -= 3;
|
||||
} else {
|
||||
// register offset
|
||||
out = strcpy2(out, reg_name[insn & 15]);
|
||||
}
|
||||
if (insn & (1 << 24)) { // pre-index
|
||||
*out++ = ']';
|
||||
if (insn & (1 << 21)) // writeback
|
||||
*out++ = '!';
|
||||
} else { // post-index
|
||||
// writeback assumed, setting W bit is invalid.
|
||||
if (insn & (1 << 21))
|
||||
*out++ = '?';
|
||||
}
|
||||
break;
|
||||
case MEM16:
|
||||
out += sprintf(out, "[%s]", reg_name[insn >> 16 & 15]);
|
||||
break;
|
||||
case MULTI:
|
||||
out = strcpy2(out, reg_name[insn >> 16 & 15]);
|
||||
if (insn & (1 << 21)) // Writeback
|
||||
*out++ = '!';
|
||||
*out++ = ',';
|
||||
out = do_reglist(out, insn & 0xFFFF);
|
||||
if (insn & (1 << 22)) // Load PSR or force user mode
|
||||
*out++ = '^';
|
||||
break;
|
||||
case BRCH:
|
||||
out += sprintf(out, "%08x", pc + 8 + ((int)insn << 8 >> 6));
|
||||
break;
|
||||
case BRCHT:
|
||||
out += sprintf(out, "%08x", pc + 8 + ((int)insn << 8 >> 6 | (insn >> 23 & 2)));
|
||||
break;
|
||||
case COPR:
|
||||
out += sprintf(out, "p%d", insn >> 8 & 15);
|
||||
break;
|
||||
case CDP:
|
||||
out += sprintf(out, "%d,c%d,c%d,c%d,%d", insn >> 20 & 15,
|
||||
insn >> 12 & 15, insn >> 16 & 15, insn & 15, insn >> 5 & 7);
|
||||
break;
|
||||
case MRC:
|
||||
out += sprintf(out, "%d,%s,c%d,c%d,%d", insn >> 21 & 7,
|
||||
reg_name[insn >> 12 & 15], insn >> 16 & 15, insn & 15, insn >> 5 & 7);
|
||||
break;
|
||||
case MRRC:
|
||||
out += sprintf(out, "%d,%s,%s,c%d", insn >> 4 & 15,
|
||||
reg_name[insn >> 12 & 15], reg_name[insn >> 16 & 15], insn & 15);
|
||||
break;
|
||||
case MEMC:
|
||||
out += sprintf(out, "c%d,[%s", insn >> 12 & 15,
|
||||
reg_name[insn >> 16 & 15]);
|
||||
if (!(insn & (1 << 24))) { // Post-indexed or unindexed
|
||||
*out++ = ']';
|
||||
if (!(insn & (1 << 21))) {
|
||||
// Unindexed addressing
|
||||
if (!(insn & (1 << 23)))
|
||||
*out++ = '?';
|
||||
out += sprintf(out, ",{%02x}", insn & 0xFF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(insn & (1 << 23)) || insn & 0xFF)
|
||||
out += sprintf(out, " %c %03x",
|
||||
(insn & (1 << 23)) ? '+' : '-',
|
||||
(insn & 0xFF) << 2);
|
||||
if (insn & (1 << 24)) { // Pre-indexed or offset
|
||||
*out++ = ']';
|
||||
if (insn & (1 << 21)) // Writeback (pre-indexed)
|
||||
*out++ = '!';
|
||||
}
|
||||
break;
|
||||
case BKPT:
|
||||
out += sprintf(out, "%04x", (insn >> 4 & 0xFFF0) | (insn & 0x0F));
|
||||
break;
|
||||
case SWI:
|
||||
out += sprintf(out, "%06x", insn & 0xFFFFFF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*out = '\0';
|
||||
gui_debug_printf(buf);
|
||||
gui_debug_printf("\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint32_t disasm_thumb_insn(uint32_t pc) {
|
||||
char buf[80];
|
||||
uint16_t *pc_ptr = virt_mem_ptr(pc, 2);
|
||||
if (!pc_ptr)
|
||||
return 0;
|
||||
|
||||
uint16_t insn = *pc_ptr;
|
||||
char *out = buf + sprintf(buf, "%08x: %04x \t", pc, insn);
|
||||
|
||||
if (insn < 0x1800) {
|
||||
static const char name[][4] = { "lsl", "lsr", "asr" };
|
||||
sprintf(out, "%s\tr%d,r%d,%02x", name[insn >> 11],
|
||||
insn & 7, insn >> 3 & 7, insn >> 6 & 31);
|
||||
} else if (insn < 0x2000) {
|
||||
sprintf(out, "%s\tr%d,r%d,%s%d",
|
||||
(insn & 0x0200) ? "sub" : "add",
|
||||
insn & 7, insn >> 3 & 7,
|
||||
(insn & 0x400) ? "" : "r", insn >> 6 & 7);
|
||||
} else if (insn < 0x4000) {
|
||||
static const char name[][4] = { "mov", "cmp", "add", "sub" };
|
||||
sprintf(out, "%s\tr%d,%02x", name[insn >> 11 & 3],
|
||||
insn >> 8 & 7, insn & 0xFF);
|
||||
} else if (insn < 0x4400) {
|
||||
static const char name[][4] = {
|
||||
"and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror",
|
||||
"tst", "neg", "cmp", "cmn", "orr", "mul", "bic", "mvn"
|
||||
};
|
||||
sprintf(out, "%s\tr%d,r%d", name[insn >> 6 & 15], insn & 7, insn >> 3 & 7);
|
||||
} else if (insn < 0x4700) {
|
||||
static const char name[][4] = { "add", "cmp", "mov" };
|
||||
int rd = (insn & 7) | (insn >> 4 & 8);
|
||||
int rn = insn >> 3 & 15;
|
||||
if (!((rd | rn) & 8))
|
||||
goto invalid;
|
||||
sprintf(out, "%s\t%s,%s", name[insn >> 8 & 3], reg_name[rd], reg_name[rn]);
|
||||
} else if (insn < 0x4800) {
|
||||
if (insn & 7)
|
||||
goto invalid;
|
||||
sprintf(out, "%s\t%s", (insn & 0x80) ? "blx" : "bx", reg_name[insn >> 3 & 15]);
|
||||
} else if (insn < 0x5000) {
|
||||
int addr = ((pc + 4) & -4) + ((insn & 0xFF) << 2);
|
||||
out += sprintf(out, "ldr\tr%d,[%08x]", insn >> 8 & 7, addr);
|
||||
uint32_t *ptr = virt_mem_ptr(addr, 4);
|
||||
if (ptr)
|
||||
sprintf(out, " = %08x", *ptr);
|
||||
} else if (insn < 0x6000) {
|
||||
static const char name[][6] = {
|
||||
"str", "strh", "strb", "ldrsb",
|
||||
"ldr", "ldrh", "ldrb", "ldrsh"
|
||||
};
|
||||
sprintf(out, "%s\tr%d,[r%d + r%d]", name[insn >> 9 & 7],
|
||||
insn & 7, insn >> 3 & 7, insn >> 6 & 7);
|
||||
} else if (insn < 0x9000) {
|
||||
static const char name[][5] = { "str", "ldr", "strb", "ldrb", "strh", "ldrh" };
|
||||
int type = (insn - 0x6000) >> 11;
|
||||
sprintf(out, "%s\tr%d,[r%d + %03x]", name[type],
|
||||
insn & 7, insn >> 3 & 7,
|
||||
(insn >> 6 & 31) << (0x12 >> (type & 6) & 3));
|
||||
} else if (insn < 0xA000) {
|
||||
sprintf(out, "%s\tr%d,[sp + %03x]",
|
||||
(insn & 0x800) ? "ldr" : "str",
|
||||
insn >> 8 & 7, (insn & 0xFF) << 2);
|
||||
} else if (insn < 0xB000) {
|
||||
sprintf(out, "add\tr%d,%s,%03x",
|
||||
insn >> 8 & 7,
|
||||
(insn & 0x800) ? "sp" : "pc", (insn & 0xFF) << 2);
|
||||
} else if (insn < 0xB100) {
|
||||
sprintf(out, "%s\tsp,%03x",
|
||||
(insn & 0x80) ? "sub" : "add", (insn & 0x7F) << 2);
|
||||
} else if (insn < 0xB400) {
|
||||
goto invalid;
|
||||
} else if (insn < 0xB600) {
|
||||
out = strcpy2(out, "push\t");
|
||||
do_reglist(out, (insn & 0xFF) | (insn & 0x100) << (14 - 8));
|
||||
} else if (insn < 0xBC00) {
|
||||
goto invalid;
|
||||
} else if (insn < 0xBE00) {
|
||||
out = strcpy2(out, "pop\t");
|
||||
do_reglist(out, (insn & 0xFF) | (insn & 0x100) << (15 - 8));
|
||||
} else if (insn < 0xBF00) {
|
||||
sprintf(out, "bkpt\t%02x", insn & 0xFF);
|
||||
} else if (insn < 0xC000) {
|
||||
goto invalid;
|
||||
} else if (insn < 0xD000) {
|
||||
out += sprintf(out, "%smia\tr%d!,", (insn & 0x800) ? "ld" : "st", insn >> 8 & 7);
|
||||
do_reglist(out, insn & 0xFF);
|
||||
} else if (insn < 0xDE00) {
|
||||
sprintf(out, "b%s\t%08x", condcode[insn >> 8 & 15], pc + 4 + ((int8_t)insn << 1));
|
||||
} else if (insn < 0xDF00) {
|
||||
invalid:
|
||||
sprintf(out, "???");
|
||||
} else if (insn < 0xE000) {
|
||||
sprintf(out, "swi\t%02x", insn & 0xFF);
|
||||
} else if (insn < 0xE800) {
|
||||
sprintf(out, "b\t%08x", pc + 4 + ((int32_t)insn << 21 >> 20));
|
||||
} else if (insn < 0xF000) {
|
||||
sprintf(out, "(blx\tlr + %03x)", (insn & 0x7FF) << 1);
|
||||
} else if (insn < 0xF800) {
|
||||
int32_t target = (int32_t)insn << 21 >> 9;
|
||||
/* Check next instruction to see if this is part of a BL or BLX pair */
|
||||
pc_ptr = virt_mem_ptr(pc + 2, 2);
|
||||
if (pc_ptr && ((insn = *pc_ptr) & 0xE800) == 0xE800) {
|
||||
/* It is; show both instructions combined as one */
|
||||
target += pc + 4 + ((insn & 0x7FF) << 1);
|
||||
if (!(insn & 0x1000)) target &= ~3;
|
||||
sprintf(out - 5, "%04x\t%s\t%08x", insn,
|
||||
(insn & 0x1000) ? "bl" : "blx", target);
|
||||
gui_debug_printf("%s\n", buf);
|
||||
return 4;
|
||||
}
|
||||
sprintf(out, "(add\tlr,pc,%08x)", target);
|
||||
} else {
|
||||
sprintf(out, "(bl\tlr + %03x)", (insn & 0x7FF) << 1);
|
||||
}
|
||||
gui_debug_printf("%s\n", buf);
|
||||
return 2;
|
||||
}
|
||||
18
src/armv5te/disasm.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _H_DISASM
|
||||
#define _H_DISASM
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char reg_name[16][4];
|
||||
|
||||
uint32_t disasm_arm_insn(uint32_t pc);
|
||||
uint32_t disasm_arm_insn2(uint32_t pc, uint32_t *pc_ptr);
|
||||
uint32_t disasm_thumb_insn(uint32_t pc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
56
src/armv5te/emu.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef _H_EMU
|
||||
#define _H_EMU
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "../emulator.h"
|
||||
#include "../portability.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline uint16_t BSWAP16(uint16_t x) { return x << 8 | x >> 8; }
|
||||
#define BSWAP32(x) __builtin_bswap32(x)
|
||||
|
||||
extern int cycle_count_delta __asm__("cycle_count_delta");
|
||||
extern uint32_t cpu_events __asm__("cpu_events");
|
||||
#define EVENT_IRQ 1
|
||||
#define EVENT_FIQ 2
|
||||
#define EVENT_RESET 4
|
||||
#define EVENT_DEBUG_STEP 8
|
||||
#define EVENT_WAITING 16
|
||||
|
||||
// Settings
|
||||
extern bool exiting;
|
||||
extern bool do_translate;
|
||||
|
||||
enum { LOG_CPU, LOG_IO, LOG_FLASH, LOG_INTS, LOG_ICOUNT, LOG_USB, LOG_GDB, MAX_LOG };
|
||||
#define LOG_TYPE_TBL "CIFQ#UG"
|
||||
//void logprintf(int type, const char *str, ...);
|
||||
//void emuprintf(const char *format, ...);
|
||||
#define logprintf(type, ...) debugLog(__VA_ARGS__)
|
||||
#define emuprintf(...) debugLog(__VA_ARGS__)
|
||||
|
||||
//void warn(const char *fmt, ...);
|
||||
//__attribute__((noreturn)) void error(const char *fmt, ...);
|
||||
#define warn(...) debugLog(__VA_ARGS__)
|
||||
#define error(...) abort()
|
||||
|
||||
extern jmp_buf restart_after_exception;
|
||||
|
||||
// GUI callbacks
|
||||
#define gui_debug_printf(...) debugLog(__VA_ARGS__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
src/armv5te/emuVarPool.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "mem.h"
|
||||
#include "emu.h"
|
||||
|
||||
|
||||
/* cycle_count_delta is a (usually negative) number telling what the time is relative
|
||||
* to the next scheduled event. See sched.c */
|
||||
int cycle_count_delta;
|
||||
|
||||
bool exiting;
|
||||
bool do_translate;
|
||||
|
||||
jmp_buf restart_after_exception;
|
||||
|
||||
uint32_t cpu_events;
|
||||