Compare commits
101 Commits
Author | SHA1 | Date |
---|---|---|
Steven Hugg | d733a2cd27 | |
Steven Hugg | 098dcda93a | |
Steven Hugg | 886e19611e | |
Steven Hugg | 02986aed38 | |
Steven Hugg | d5b5734ef9 | |
Steven Hugg | 579e58e966 | |
Steven Hugg | 47a7aa5a83 | |
Steven Hugg | 9142328468 | |
Steven Hugg | 70eee2bdae | |
Steven Hugg | 949e216c69 | |
Steven Hugg | b160fb2ef2 | |
Steven Hugg | 63ee25741b | |
Steven Hugg | 8bdbae36e3 | |
Steven Hugg | c0909bef1b | |
Steven Hugg | 8023d56b88 | |
Steven Hugg | 45bc17d7ee | |
Steven Hugg | 8452fe73a1 | |
Steven Hugg | dff5c73d6a | |
Steven Hugg | f8462de014 | |
Steven Hugg | d08d73f422 | |
Steven Hugg | 0ede0e514b | |
Steven Hugg | dbe73c4fb2 | |
Steven Hugg | 9ecfb3cfa8 | |
Steven Hugg | 312cb3d025 | |
Steven Hugg | bd63ef1268 | |
Steven Hugg | 2e0382b0a6 | |
Steven Hugg | 611c174aed | |
Steven Hugg | d9001df5d4 | |
Steven Hugg | e6c3dc98e1 | |
Steven Hugg | 43d844fa79 | |
Steven Hugg | c5bcd8ad9b | |
Steven Hugg | c189875be3 | |
Steven Hugg | 16fcf33881 | |
Steven Hugg | 8091985fde | |
Steven Hugg | c9354a83ea | |
Steven Hugg | 73c7ac5941 | |
Steven Hugg | 19e3bbbea3 | |
Steven Hugg | 12957d7740 | |
Steven Hugg | a252ea65bd | |
Steven Hugg | 1c0b3e2fdd | |
Steven Hugg | 44271fe9b8 | |
Steven Hugg | f6452a719f | |
Steven Hugg | de6250b0cd | |
Steven Hugg | c6345ec728 | |
Steven Hugg | d31a8c4efe | |
Steven Hugg | 3a08c24869 | |
Steven Hugg | 99370530f5 | |
Steven Hugg | fe6a8a6514 | |
Steven Hugg | a2d818c3e5 | |
Steven Hugg | fbd9089a8d | |
Steven Hugg | f18365cf9f | |
Steven Hugg | 99f7ff41bb | |
Steven Hugg | 2de919a225 | |
Steven Hugg | dd96813b76 | |
Steven Hugg | fc432a3bbf | |
Steven Hugg | 483675fded | |
Steven Hugg | 64ef7cc885 | |
Steven Hugg | 69600744df | |
Steven Hugg | 5bc85161eb | |
Steven Hugg | d11c1d1664 | |
Steven Hugg | 64f27879d7 | |
Steven Hugg | 92fde04422 | |
Steven Hugg | d5460c991f | |
Steven Hugg | 73c74c519e | |
Steven Hugg | 2e2996bd73 | |
Steven Hugg | 9e6fc9a0e3 | |
Steven Hugg | 0bf41a39c7 | |
Steven Hugg | ac9c14351f | |
Steven Hugg | f4d9124102 | |
Steven Hugg | 70fdb68622 | |
Steven Hugg | 3dba86c75d | |
Steven Hugg | cc385b7d98 | |
Steven Hugg | 3cea5a7d15 | |
Steven Hugg | b131d29663 | |
Steven Hugg | d4b8473b86 | |
Steven Hugg | 02834db8a1 | |
Steven Hugg | 37633d8875 | |
Steven Hugg | 5a93bc8b75 | |
Steven Hugg | 47cabad5ec | |
Steven Hugg | de12d20459 | |
Steven Hugg | c186d478fb | |
Steven Hugg | 3bacf50409 | |
Steven Hugg | ac8f7c3f8b | |
Steven Hugg | ee3ced574b | |
Steven Hugg | ba179160d6 | |
Steven Hugg | 5d11dd37df | |
Steven Hugg | 61443f586f | |
Steven Hugg | 0f011ee856 | |
Steven Hugg | 13656092c5 | |
Steven Hugg | f30850fdf1 | |
Steven Hugg | b707c5bf09 | |
Steven Hugg | 232c027445 | |
Steven Hugg | 7bd5bffab5 | |
Steven Hugg | a3d7cc7dca | |
Steven Hugg | 3972da4a13 | |
Steven Hugg | a5a8b94991 | |
Steven Hugg | 63d3b88a7a | |
Steven Hugg | 9d39edf452 | |
Steven Hugg | 2f8a5bee84 | |
Steven Hugg | e724ccb7d2 | |
Steven Hugg | 3671054b16 |
|
@ -17,9 +17,9 @@ jobs:
|
|||
node-version: [16.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
|
41
README.md
41
README.md
|
@ -13,7 +13,7 @@
|
|||
To clone just the main branch:
|
||||
|
||||
```sh
|
||||
git clone -b master --single-branch git://github.com/sehugg/8bitworkshop.git
|
||||
git clone -b master --single-branch git@github.com:sehugg/8bitworkshop.git
|
||||
```
|
||||
|
||||
To build the 8bitworkshop IDE:
|
||||
|
@ -27,7 +27,7 @@ npm run build
|
|||
|
||||
To use GitHub integration locally, download the Firebase config file, e.g. https://8bitworkshop.com/v[version]/config.js
|
||||
|
||||
### Start Server
|
||||
### Start Local Web Server
|
||||
|
||||
Start a web server on http://localhost:8000/ while TypeScript compiles in the background:
|
||||
|
||||
|
@ -45,20 +45,22 @@ Note: Github tests may fail due to lack of API key.
|
|||
|
||||
## License
|
||||
|
||||
Copyright © 2016-2022 [Steven Hugg](https://github.com/sehugg).
|
||||
Copyright © 2016-2024 [Steven E. Hugg](https://github.com/sehugg).
|
||||
|
||||
This project is [GPL-3.0](https://github.com/sehugg/8bitworkshop/blob/master/LICENSE) licensed.
|
||||
|
||||
Dependencies retain their original licenses.
|
||||
This project, unless specifically noted, is multi-licensed.
|
||||
You may choose to adhere to the terms of either the [GPL-3.0](https://github.com/sehugg/8bitworkshop/blob/master/LICENSE) License for the entire project or respect the individual licenses of its dependencies and included code samples, as applicable.
|
||||
|
||||
All included code samples (all files under the presets/ directory) are licensed under
|
||||
This project includes various dependencies, modules, and components that retain their original licenses.
|
||||
For detailed licensing information for each dependency, please refer to the respective files and documentation.
|
||||
|
||||
All included code samples located in the presets/ directory are licensed under
|
||||
[CC0](https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
unless otherwise licensed.
|
||||
unless a different license is explicitly stated within the specific code sample.
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
The IDE uses custom forks for many of these, found at https://github.com/sehugg?tab=repositories
|
||||
|
||||
### Emulators
|
||||
|
||||
* https://javatari.org/
|
||||
|
@ -69,6 +71,7 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
|
|||
* http://www.twitchasylum.com/jsvecx/
|
||||
* https://github.com/curiousdannii/ifvms.js/
|
||||
* https://6502ts.github.io/typedoc/stellerator-embedded/
|
||||
* https://github.com/yhzmr442/jspce
|
||||
|
||||
### Compilers
|
||||
|
||||
|
@ -82,6 +85,8 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
|
|||
* https://github.com/dmsc/fastbasic
|
||||
* https://github.com/wiz-lang/wiz
|
||||
* https://github.com/sylefeb/Silice
|
||||
* https://github.com/steux/cc7800
|
||||
* https://bellard.org/tcc/
|
||||
|
||||
### Assemblers/Linkers
|
||||
|
||||
|
@ -110,4 +115,22 @@ The IDE uses custom forks for many of these, found at https://github.com/sehugg?
|
|||
* https://github.com/sehugg/8bitworkshop-compilers
|
||||
* https://github.com/sehugg/8bit-tools
|
||||
* https://github.com/sehugg/awesome-8bitgamedev
|
||||
* https://github.com/sehugg?tab=repositories
|
||||
|
||||
|
||||
## Tool Server (experimental)
|
||||
|
||||
This is an experimental feature that relies on a Docker container to provide compiler tools like [llvm-mos](https://github.com/llvm-mos/llvm-mos-sdk).
|
||||
Right now, you have to run locally and build your own docker container.
|
||||
|
||||
```sh
|
||||
docker build -t 8bitws-server-debian scripts/docker
|
||||
docker run -p 3009:3009 8bitws-server-debian
|
||||
echo '{"REMOTE_URL":"http://localhost:3009/build"}' > remote.json
|
||||
```
|
||||
|
||||
Then add "&tool=llvm-mos" to your URL, like
|
||||
[this](http://localhost:8000/?platform=c64&file=sprite_collision.c&tool=llvm-mos).
|
||||
You can also rename your C files to have the suffix "-llvm.c".
|
||||
Right now only the platforms c64, atari8, nes (NROM), and pce are supported.
|
||||
Not very many of the current examples work with the new toolchain.
|
||||
|
|
11
css/ui.css
11
css/ui.css
|
@ -127,13 +127,15 @@ div.mem_info {
|
|||
bottom: 10px;
|
||||
background-color: #333;
|
||||
color: #66ff66;
|
||||
white-space: pre;
|
||||
padding: 20px;
|
||||
z-index: 12;
|
||||
font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
|
||||
font-size: 12pt;
|
||||
box-shadow: 0px 0px 8px rgba(0,0,0,.5);
|
||||
max-height: 90vh;
|
||||
}
|
||||
div.mem_info_msg {
|
||||
white-space: pre;
|
||||
padding: 20px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
div.mem_info a {
|
||||
|
@ -148,6 +150,9 @@ div.mem_info a:hover {
|
|||
div.mem_info a.selected {
|
||||
color: #ffffff;
|
||||
}
|
||||
div.mem_info button {
|
||||
color: #fff;
|
||||
}
|
||||
.mem_info_links {
|
||||
text-align:right;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ gcc6809 - need to check this out
|
|||
SmallerC - https://github.com/alexfru/SmallerC
|
||||
|
||||
vbcc - Targets 68K, patch for z-machine
|
||||
http://sun.hasenbraten.de/vbcc/\
|
||||
http://sun.hasenbraten.de/vbcc/
|
||||
|
||||
|
||||
OTHER COMPILERS
|
||||
|
|
|
@ -367,6 +367,22 @@ Programmatic Asset Language
|
|||
- RLE compression
|
||||
- check constraints
|
||||
|
||||
https://github.com/endojs/endo/blob/master/packages/ses/README.md
|
||||
|
||||
- CPU-independent IR
|
||||
- structured assembler IR
|
||||
- ECS/macros module
|
||||
- HLL
|
||||
- static analysis module
|
||||
- linker/placement module
|
||||
- inlining, data reuse
|
||||
- nested tag for segments
|
||||
- binary generation module
|
||||
- remote fetch module
|
||||
- asset module (bitmaps, sprites, tiles, palettes, compression...)
|
||||
- asset editor UI
|
||||
- debugging API (custom state, per-cycle watchpoints)
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
@ -540,7 +556,6 @@ Should call trap() every cycle or insn of frame, or exit when returns true?
|
|||
|
||||
BETTER DEBUGGING
|
||||
|
||||
Need to mark start/end columns, not just line number
|
||||
Know if we are actively debugging or trap occurred
|
||||
isRunning() = stopped, running, waiting, debugging...
|
||||
Showing running PC may be distracting, maybe lines visited?
|
||||
|
@ -561,3 +576,4 @@ preprocessor differences (#define FOO 1 so #if works)
|
|||
extern void do_func(void)
|
||||
#pragma warnings
|
||||
CFG files
|
||||
|
||||
|
|
60
index.html
60
index.html
|
@ -23,16 +23,6 @@ body {
|
|||
</style>
|
||||
<link rel="stylesheet" href="css/ui.css">
|
||||
|
||||
<!-- google analytics -->
|
||||
<script>
|
||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||
if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||
ga('create', 'UA-54497476-9', 'auto');
|
||||
ga('set', 'anonymizeIp', true);
|
||||
}
|
||||
</script>
|
||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -132,7 +122,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
<a tabindex="-1" href="#">About</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" target="_8bws_help" href="https://8bitworkshop.com/">Website</a></li>
|
||||
<li><a class="dropdown-item" target="_8bws_help" href="https://twitter.com/8bitworkshop">Twitter</a></li>
|
||||
<li><a class="dropdown-item" target="_8bws_help" href="https://oldbytes.space/@8bitworkshop">Mastodon</a></li>
|
||||
<li><a class="dropdown-item" target="_8bws_help" href="https://8bitworkshop.com/docs/blog.html">Latest News</a></li>
|
||||
<li><a class="dropdown-item" target="_8bws_help" href="https://github.com/sehugg/8bitworkshop/issues/new">Report an Issue</a></li>
|
||||
</ul>
|
||||
|
@ -160,7 +150,9 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
<li><a class="dropdown-item" href="?platform=sms-sg1000-libcv">Sega SG-1000</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=sms-sms-libcv">Sega Master System</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=sms-gg-libcv">Sega Game Gear</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=atari8-5200">Atari 5200</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=atari7800">Atari 7800</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=pce">PC Engine</a></li>
|
||||
<!--
|
||||
<li><a class="dropdown-item" href="?platform=vectrex">Vectrex</a></li>
|
||||
-->
|
||||
|
@ -175,7 +167,6 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
<li><a class="dropdown-item" href="?platform=msx-libcv">MSX (libCV)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=apple2">Apple ][+</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=zx">ZX Spectrum</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=cpc.6128">Amstrad CPC6128</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -203,7 +194,6 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="?platform=basic">BASIC</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=zmachine">Z-Machine</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=markdown">Markdown Text Editor</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
|
@ -218,6 +208,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||
<hr>
|
||||
<li><a class="dropdown-item" href="?platform=williams">Williams (6809)</a></li>
|
||||
<li><a class="dropdown-item" href="?platform=x86">x86 (FreeDOS)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -249,25 +240,25 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="booksMenuButton">
|
||||
<li>
|
||||
<a class="dropdown-item dropdown-link book-vcs" target="_book_a2600" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=pzp-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01N4DSRIZ&linkId=04d39e274c06e6c93b93d20a9a977111">
|
||||
<a class="dropdown-item dropdown-link book-vcs" target="_book_a2600" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=1789&creative=9325&linkCode=as2&creativeASIN=B01N4DSRIZ">
|
||||
<img src="images/book_a2600.png"/>
|
||||
<span class="book-title">Making Games For The Atari 2600</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item dropdown-link book-arcade" target="_book_arcade" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=b27709c022d2ebe639e90316d9f4fd5b">
|
||||
<a class="dropdown-item dropdown-link book-arcade" target="_book_arcade" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2">
|
||||
<img src="images/book_arcade.png"/>
|
||||
<span class="book-title">Making 8-bit Arcade Games in C</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item dropdown-link book-verilog" target="_book_verilog" href="https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1728619440&linkCode=as2&tag=pzp-20&linkId=7237a25861cb6b49a4128ba53d84c3e2">
|
||||
<a class="dropdown-item dropdown-link book-verilog" target="_book_verilog" href="https://www.amazon.com/gp/product/1728619440/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1728619440&linkCode=as2">
|
||||
<img src="images/book_verilog.png"/>
|
||||
<span class="book-title">Designing Video Game Hardware in Verilog</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item dropdown-link book-nes" target="_book_nes" href="https://www.amazon.com/gp/product/1075952727/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1075952727&linkCode=as2&tag=pzp-20&linkId=633176e8b36fea7f927020e2c322d80a">
|
||||
<a class="dropdown-item dropdown-link book-nes" target="_book_nes" href="https://www.amazon.com/gp/product/1075952727/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1075952727&linkCode=as2">
|
||||
<img src="images/book_nes.png"/>
|
||||
<span class="book-title">Making Games For The NES</span>
|
||||
</a>
|
||||
|
@ -323,7 +314,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
<span class="control-def"><span class="control-key">←↑↓→</span> Joystick</span>
|
||||
<span class="control-def"><span class="control-key small">Space</span> Button</span>
|
||||
</div>
|
||||
<div class="emucontrols-nes emucontrols-atari7800 text-center small control-insns" style="display:none">
|
||||
<div class="emucontrols-nes emucontrols-atari7800 emucontrols-pce text-center small control-insns" style="display:none">
|
||||
<span class="control-def"><span class="control-key">←↑↓→</span> Joypad</span>
|
||||
<span class="control-def"><span class="control-key small">Space</span> Button A</span>
|
||||
<span class="control-def"><span class="control-key small">Shift</span> Button B</span>
|
||||
|
@ -387,6 +378,8 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
|||
</div>
|
||||
</div>
|
||||
<div id="mem_info" class="mem_info" style="display:none">
|
||||
<div><button type="button" class="close" onclick="$('.mem_info').hide()" aria-hidden="true">×</button></div>
|
||||
<div id="mem_info_msg" class="mem_info_msg"></div>
|
||||
</div>
|
||||
<div id="error_alert" class="alert alert-danger alert-dismissable" style="position:absolute;right:0;top:0;display:none">
|
||||
<button type="button" class="close" onclick="$('.alert').hide()" aria-hidden="true">×</button>
|
||||
|
@ -585,26 +578,19 @@ $( ".dropdown-submenu" ).click(function(event) {
|
|||
</script>
|
||||
|
||||
<!-- Sentry error reporting -->
|
||||
<script
|
||||
src="https://browser.sentry-cdn.com/6.4.1/bundle.min.js"
|
||||
integrity="sha384-THoc7rflwZFKTdZNgv6jLFFDn299Uv3t1SW5B4yGLvLiCRTYP9ys6vXZcMl95TQF"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script src='https://js.sentry-cdn.com/1fdd10e76a524c6e8d1e0a47f215fb28.min.js' crossorigin="anonymous"></script>
|
||||
<script>
|
||||
if (window.Sentry) Sentry.init({
|
||||
dsn: 'https://bf329df3d1b34afa9f5b5e8ecd80ad11@o320878.ingest.sentry.io/1813925',
|
||||
beforeBreadcrumb(breadcrumb, hint) {
|
||||
if (breadcrumb.category === 'xhr' && typeof breadcrumb.data.url === 'string') {
|
||||
if (breadcrumb.data.url.startsWith('http')) return null; // discard external scripts
|
||||
}
|
||||
return breadcrumb;
|
||||
},
|
||||
beforeSend(event, hint) {
|
||||
const error = hint.originalException;
|
||||
if (error && error.hasOwnProperty('$loc')) return null; // ignore EmuHalt
|
||||
return event;
|
||||
},
|
||||
});
|
||||
if (window.Sentry) Sentry.onLoad(function() {
|
||||
Sentry.init({
|
||||
sampleRate: window.location.host.endsWith('8bitworkshop.com') ? 0.5 : 0.05,
|
||||
beforeSend(event, hint) {
|
||||
const error = hint.originalException;
|
||||
if (error && error.hasOwnProperty('$loc')) return null; // ignore EmuHalt
|
||||
if (error && error.squelchError) return null; // ignore EmuHalt
|
||||
return event;
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9d124f087e1f0c7f74f9244b9679cc62e71fa524
|
||||
Subproject commit 113cd5741e5c414bbbe47ef8be7a896652d48f64
|
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,7 @@
|
|||
|
||||
test_settings: {
|
||||
default: {
|
||||
launch_url: 'https://8bitworkshop.com',
|
||||
launch_url: 'https://sehugg.github.io/8bitworkshop/'
|
||||
},
|
||||
|
||||
safari: {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "8bitworkshop",
|
||||
"version": "3.10.0",
|
||||
"version": "3.11.0",
|
||||
"author": "Steven Hugg",
|
||||
"category": "Development",
|
||||
"description": "8bitworkshop.com retro programming IDE",
|
||||
|
@ -10,27 +10,20 @@
|
|||
},
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@types/chroma-js": "^2.1.3",
|
||||
"@types/dompurify": "^2.3.4",
|
||||
"@types/emscripten": "^1.39.5",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@wasmer/wasi": "^0.12.0",
|
||||
"@wasmer/wasmfs": "^0.12.0",
|
||||
"atob": "^2.1.x",
|
||||
"binaryen": "^101.0.0",
|
||||
"chroma-js": "^2.1.2",
|
||||
"btoa": "^1.2.x",
|
||||
"clipboard": "^2.0.6",
|
||||
"dompurify": "^2.4.0",
|
||||
"error-stack-parser": "^2.0.6",
|
||||
"fast-png": "^5.0.4",
|
||||
"file-saver": "^2.0.5",
|
||||
"jquery": "^3.6.0",
|
||||
"jquery": "^3.6.3",
|
||||
"jszip": "^3.7.0",
|
||||
"localforage": "^1.9.0",
|
||||
"mousetrap": "^1.6.5",
|
||||
"octokat": "^0.10.0",
|
||||
"preact": "^10.5.14",
|
||||
"split.js": "^1.6.2",
|
||||
"yufka": "^2.0.1"
|
||||
"split.js": "^1.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bootbox": "^5.1.3",
|
||||
|
@ -40,36 +33,41 @@
|
|||
"@types/jquery": "^3.5.5",
|
||||
"@types/mocha": "^9.1.0",
|
||||
"@types/node": "^14.14.20",
|
||||
"atob": "^2.1.x",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootstrap-tourist": "^0.2.1",
|
||||
"btoa": "^1.2.x",
|
||||
"command-exists": "^1.2.9",
|
||||
"esbuild": "^0.12.16",
|
||||
"jsdom": "^12.2.0",
|
||||
"cors": "^2.8.5",
|
||||
"esbuild": "^0.12.29",
|
||||
"express": "^4.18.2",
|
||||
"fast-png": "^5.0.4",
|
||||
"jsdom": "^21.1.0",
|
||||
"lzg": "^1.0.x",
|
||||
"mocha": "^9.2.0",
|
||||
"mocha-simple-html-reporter": "^2.0.0",
|
||||
"typescript": "^4.4.4",
|
||||
"typescript": "^5.2.2",
|
||||
"typescript-formatter": "^7.2.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"chromedriver": "*",
|
||||
"heapdump": "^0.3.15",
|
||||
"jsfuzz": "^1.0.14",
|
||||
"nightwatch": "*",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rgbquant": "^1.1.2",
|
||||
"typedoc": "^0.22.11"
|
||||
"nightwatch": "*"
|
||||
},
|
||||
"overrides": {
|
||||
"fetch-vcr": {
|
||||
"node-fetch": "2.6.7"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "make prepare",
|
||||
"test": "npm run test-node",
|
||||
"tsbuild": "tsc --build tsconfig.json",
|
||||
"esbuild": "npm run esbuild-worker && npm run esbuild-ui",
|
||||
"esbuild": "npm run esbuild-worker && npm run esbuild-ui && npm run esbuild-server",
|
||||
"esbuild-clean": "rm -f ./gen/*.*",
|
||||
"esbuild-server": "esbuild src/worker/server/server.ts --platform=node --bundle --sourcemap --target=es2020 --outfile=./gen/server/server.js",
|
||||
"esbuild-worker": "esbuild src/worker/workermain.ts --bundle --sourcemap --target=es2017 --outfile=./gen/worker/bundle.js",
|
||||
"esbuild-ui": "esbuild src/ide/ui.ts src/ide/embedui.ts --splitting --format=esm --bundle --minify --sourcemap --target=es2017 --outdir=./gen/ --external:path --external:fs",
|
||||
"server": "npm run esbuild-server && rm -fr ./server-root/sessions && node gen/server/server.js",
|
||||
"test-one": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000",
|
||||
"test-node": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 test/cli gen/test",
|
||||
"test-profile": "NODE_PATH=$(pwd) mocha --recursive --timeout 60000 --prof test/cli gen/test",
|
||||
|
@ -97,7 +95,7 @@
|
|||
"build": {
|
||||
"appId": "com.8bitworkshop.ide",
|
||||
"icon": "meta/icons/8bitworkshop-icon-1024.png",
|
||||
"copyright": "Copyright (c) 2021 Puzzling Plans LLC",
|
||||
"copyright": "Copyright (c) 2023 Puzzling Plans LLC",
|
||||
"linux": {
|
||||
"category": "Development"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
/*
|
||||
Test of the LZ4 decompression library
|
||||
with a hires graphics image.
|
||||
*/
|
||||
|
||||
// CC65 config, reserves space for the HGR1 screen buffer
|
||||
#define CFGFILE apple2-hgr.cfg
|
||||
|
||||
#pragma data-name(push,"HGR")
|
||||
// this segment is required, but we leave it empty
|
||||
// since we're going to decompress the image here
|
||||
#pragma data-name(pop)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
#include <apple2.h>
|
||||
#include <peekpoke.h>
|
||||
#include <lz4.h>
|
||||
|
||||
// STROBE = write any value to an I/O address
|
||||
#define STROBE(addr) __asm__ ("sta %w", addr)
|
||||
|
||||
// start address of the two hi-res graphics regions
|
||||
#define HGR1 0x2000
|
||||
#define HGR2 0x4000
|
||||
|
||||
// the LZ4 compressed data
|
||||
const unsigned char BITMAP_DATA_LZ4[] = {
|
||||
#embed "parrot-apple2.hires.lz4"
|
||||
};
|
||||
|
||||
|
||||
// clear screen and set graphics mode
|
||||
void clear_hgr1() {
|
||||
memset((char*)HGR1, 0, 0x2000); // clear page 1
|
||||
STROBE(0xc052); // turn off mixed-mode
|
||||
STROBE(0xc054); // page 1
|
||||
STROBE(0xc057); // hi-res
|
||||
STROBE(0xc050); // set graphics mode
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
// set hgr1 mode and clear
|
||||
clear_hgr1();
|
||||
// skip the header (usually 11 bytes)
|
||||
decompress_lz4(BITMAP_DATA_LZ4+11, (char*)HGR1, 0x2000);
|
||||
// wait for a key
|
||||
cgetc();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
|
||||
#define SERIAL_OUT ((int*)0x4000048)
|
||||
|
||||
void putchar_(char c) {
|
||||
*SERIAL_OUT = c;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define size 8190
|
||||
#define sizepl 8191
|
||||
|
||||
//#link "serialout.c"
|
||||
|
||||
main() {
|
||||
char flags[sizepl];
|
||||
int i, prime, k, count, iter;
|
||||
printf("Running benchmark...\n");
|
||||
for (iter = 1; iter <= 10; iter ++) {
|
||||
count=0;
|
||||
for (i = 0; i <= size; i++)
|
||||
flags[i] = true;
|
||||
for (i = 0; i <= size; i++) {
|
||||
if (flags[i]) {
|
||||
prime = i + i + 3;
|
||||
k = i + prime;
|
||||
while (k <= size) {
|
||||
flags[k] = false;
|
||||
k += prime;
|
||||
}
|
||||
count = count + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Primes: %d\n", count);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//#link "serialout.c"
|
||||
|
||||
int main() {
|
||||
int x = 2024;
|
||||
printf("Hello World! %d\n", x);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
const char const str[] = "HELLO WORLD!";
|
||||
|
||||
int global = 0x1234;
|
||||
int global2 = 0x123456;
|
||||
|
||||
#define VIDBASE ((int*)0x4000080)
|
||||
|
||||
int vidbuf[160*128];
|
||||
|
||||
int main() {
|
||||
*VIDBASE = (int)vidbuf;
|
||||
global += str[0];
|
||||
global++;
|
||||
global2++;
|
||||
int c = 0xff880000;
|
||||
c += str[0];
|
||||
int* p = (int*) vidbuf;
|
||||
for (int i=0; i<160*128; i++) {
|
||||
p[i] = c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
; 7800.h
|
||||
; Version 1.0, 2019/12/13
|
||||
|
||||
; This file defines hardware registers and memory mapping for the
|
||||
; Atari 7800. It is distributed as a companion machine-specific support package
|
||||
; for the DASM compiler. Updates to this file, DASM, and associated tools are
|
||||
; available at https://github.com/dasm-assembler/dasm
|
||||
|
||||
|
||||
; ******************** 7800 Hardware Adresses ***************************
|
||||
;
|
||||
; MEMORY MAP USAGE OF THE 7800
|
||||
;
|
||||
; 00 - 1F TIA REGISTERS
|
||||
; 20 - 3F MARIA REGISTERS
|
||||
; 40 - FF RAM block 0 (zero page)
|
||||
; 100 - 11F TIA (mirror of 0000-001f)
|
||||
; 120 - 13F MARIA (mirror of 0020-003f)
|
||||
; 140 - 1FF RAM block 1 (stack)
|
||||
; 200 - 21F TIA (mirror of 0000-001f)
|
||||
; 220 - 23F MARIA (mirror of 0020-003f)
|
||||
; 240 - 27F ???
|
||||
; 280 - 2FF RIOT I/O ports and timers
|
||||
; 300 - 31F TIA (mirror of 0000-001f)
|
||||
; 320 - 33F MARIA (mirror of 0020-003f)
|
||||
; 340 - 3FF ???
|
||||
; 400 - 47F unused address space
|
||||
; 480 - 4FF RIOT RAM
|
||||
; 500 - 57F unused address space
|
||||
; 580 - 5FF RIOT RAM (mirror of 0480-04ff)
|
||||
; 600 - 17FF unused address space
|
||||
; 1800 - 203F RAM
|
||||
; 2040 - 20FF RAM block 0 (mirror of 0000-001f)
|
||||
; 2100 - 213F RAM
|
||||
; 2140 - 21FF RAM block 1 (mirror of 0140-01ff)
|
||||
; 2200 - 27FF RAM
|
||||
; 2800 - 2FFF mirror of 1800-27ff
|
||||
; 3000 - 3FFF unused address space
|
||||
; 4000 - FF7F potential cartridge address space
|
||||
; FF80 - FFF9 RESERVED FOR ENCRYPTION
|
||||
; FFFA - FFFF 6502 VECTORS
|
||||
|
||||
|
||||
;****** 00-1F ********* TIA REGISTERS ******************
|
||||
|
||||
INPTCTRL = $01 ;Input control. In same address space as TIA. write-only
|
||||
VBLANK = $01 ;VBLANK. D7=1:dump paddle caps to ground. write-only
|
||||
INPT0 = $08 ;Paddle Control Input 0 read-only
|
||||
INPT1 = $09 ;Paddle Control Input 1 read-only
|
||||
INPT2 = $0A ;Paddle Control Input 2 read-only
|
||||
INPT3 = $0B ;Paddle Control Input 3 read-only
|
||||
|
||||
; ** some common alternate names for INPT0/1/2/3
|
||||
INPT4B = $08 ;Joystick 0 Fire 1 read-only
|
||||
INPT4A = $09 ;Joystick 0 Fire 1 read-only
|
||||
INPT5B = $0A ;Joystick 1 Fire 0 read-only
|
||||
INPT5A = $0B ;Joystick 1 Fire 1 read-only
|
||||
INPT4R = $08 ;Joystick 0 Fire 1 read-only
|
||||
INPT4L = $09 ;Joystick 0 Fire 1 read-only
|
||||
INPT5R = $0A ;Joystick 1 Fire 0 read-only
|
||||
INPT5L = $0B ;Joystick 1 Fire 1 read-only
|
||||
|
||||
INPT4 = $0C ;Player 0 Fire Button Input read-only
|
||||
INPT5 = $0D ;Player 1 Fire Button Input read-only
|
||||
|
||||
AUDC0 = $15 ;Audio Control Channel 0 write-only
|
||||
AUDC1 = $16 ;Audio Control Channel 1 write-only
|
||||
AUDF0 = $17 ;Audio Frequency Channel 0 write-only
|
||||
AUDF1 = $18 ;Audio Frequency Channel 1 write-only
|
||||
AUDV0 = $19 ;Audio Volume Channel 0 write-only
|
||||
AUDV1 = $1A ;Audio Volume Channel 1 write-only
|
||||
|
||||
;****** 20-3F ********* MARIA REGISTERS ***************
|
||||
|
||||
BACKGRND = $20 ;Background Color write-only
|
||||
P0C1 = $21 ;Palette 0 - Color 1 write-only
|
||||
P0C2 = $22 ;Palette 0 - Color 2 write-only
|
||||
P0C3 = $23 ;Palette 0 - Color 3 write-only
|
||||
WSYNC = $24 ;Wait For Sync write-only
|
||||
P1C1 = $25 ;Palette 1 - Color 1 write-only
|
||||
P1C2 = $26 ;Palette 1 - Color 2 write-only
|
||||
P1C3 = $27 ;Palette 1 - Color 3 write-only
|
||||
MSTAT = $28 ;Maria Status read-only
|
||||
P2C1 = $29 ;Palette 2 - Color 1 write-only
|
||||
P2C2 = $2A ;Palette 2 - Color 2 write-only
|
||||
P2C3 = $2B ;Palette 2 - Color 3 write-only
|
||||
DPPH = $2C ;Display List List Pointer High write-only
|
||||
P3C1 = $2D ;Palette 3 - Color 1 write-only
|
||||
P3C2 = $2E ;Palette 3 - Color 2 write-only
|
||||
P3C3 = $2F ;Palette 3 - Color 3 write-only
|
||||
DPPL = $30 ;Display List List Pointer Low write-only
|
||||
P4C1 = $31 ;Palette 4 - Color 1 write-only
|
||||
P4C2 = $32 ;Palette 4 - Color 2 write-only
|
||||
P4C3 = $33 ;Palette 4 - Color 3 write-only
|
||||
CHARBASE = $34 ;Character Base Address write-only
|
||||
CHBASE = $34 ;Character Base Address write-only
|
||||
P5C1 = $35 ;Palette 5 - Color 1 write-only
|
||||
P5C2 = $36 ;Palette 5 - Color 2 write-only
|
||||
P5C3 = $37 ;Palette 5 - Color 3 write-only
|
||||
OFFSET = $38 ;Unused - Store zero here write-only
|
||||
P6C1 = $39 ;Palette 6 - Color 1 write-only
|
||||
P6C2 = $3A ;Palette 6 - Color 2 write-only
|
||||
P6C3 = $3B ;Palette 6 - Color 3 write-only
|
||||
CTRL = $3C ;Maria Control Register write-only
|
||||
P7C1 = $3D ;Palette 7 - Color 1 write-only
|
||||
P7C2 = $3E ;Palette 7 - Color 2 write-only
|
||||
P7C3 = $3F ;Palette 7 - Color 3 write-only
|
||||
|
||||
|
||||
;****** 280-2FF ******* PIA PORTS AND TIMERS ************
|
||||
|
||||
SWCHA = $280 ;P0+P1 Joystick Directional Input read-write
|
||||
CTLSWA = $281 ;I/O Control for SCHWA read-write
|
||||
SWACNT = $281 ;VCS name for above read-write
|
||||
SWCHB = $282 ;Console Switches read-write
|
||||
CTLSWB = $283 ;I/O Control for SCHWB read-write
|
||||
SWBCNT = $283 ;VCS name for above read-write
|
||||
|
||||
INTIM = $284 ;Iterval Timer Read read-only
|
||||
TIM1T = $294 ;Set 1 CLK Interval (838 nsec/interval) write-only
|
||||
TIM8T = $295 ;Set 8 CLK Interval (6.7 usec/interval) write-only
|
||||
TIM64T = $296 ;Set 64 CLK Interval (63.6 usec/interval) write-only
|
||||
T1024T = $297 ;Set 1024 CLK Interval (858.2 usec/interval) write-only
|
||||
TIM64TI = $29E ;Interrupt timer 64T write-only
|
||||
|
||||
;XM
|
||||
XCTRL = $470 ; 7=YM2151 6=RAM@6k 5=RAM@4k 4=pokey@450 3=hsc 2=cart 1=RoF_bank1 0=RoF_bank2
|
||||
|
||||
; Pokey register relative locations, since its base may be different
|
||||
; depending on the hardware.
|
||||
PAUDF0 = $0 ; extra audio channels and frequencies
|
||||
PAUDC0 = $1
|
||||
PAUDF1 = $2
|
||||
PAUDC1 = $3
|
||||
PAUDF2 = $4
|
||||
PAUDC2 = $5
|
||||
PAUDF3 = $6
|
||||
PAUDC3 = $7
|
||||
PAUDCTL = $8 ; Audio Control
|
||||
PRANDOM = $A ; 17 bit polycounter pseudo random
|
||||
PSKCTL = $F ; Serial Port control
|
|
@ -0,0 +1,59 @@
|
|||
// example from https://github.com/steux/cc7800 - license: GPLv3
|
||||
|
||||
#include "prosystem.h"
|
||||
#include "multisprite.h"
|
||||
|
||||
char i, xpos, ypos;
|
||||
|
||||
#define NB_SMALL_SPRITES 128
|
||||
ramchip short sp_xpos[NB_SMALL_SPRITES], sp_ypos[NB_SMALL_SPRITES];
|
||||
ramchip char sp_direction[NB_SMALL_SPRITES];
|
||||
|
||||
const signed short dx[24] = {300, 289, 259, 212, 149, 77, 0, -77, -150, -212, -259, -289, -300, -289, -259, -212, -149, -77, 0, 77, 149, 212, 259, 289};
|
||||
const signed short dy[24] = {0, 124, 240, 339, 415, 463, 480, 463, 415, 339, 240, 124, 0, -124, -239, -339, -415, -463, -480, -463, -415, -339, -240, -124};
|
||||
const char horizontal_pingpong[24] = { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13 };
|
||||
const char vertical_pingpong[24] = { 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
|
||||
// Generated with sprites7800 missile.yaml
|
||||
holeydma reversed scattered(16,1) char missile[16] = {
|
||||
0x18, 0x96, 0x7a, 0x7e, 0x7e, 0x6e, 0x9a, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
multisprite_init();
|
||||
|
||||
*P0C1 = multisprite_color(0x1c); // Yellow
|
||||
*P0C2 = multisprite_color(0x37); // Orange
|
||||
*P0C3 = multisprite_color(0x43); // Red
|
||||
|
||||
// Initialize small sprites
|
||||
for (ypos = 0, xpos = 0, i = 0, X = 0; X != NB_SMALL_SPRITES; xpos++, ypos++, X++) {
|
||||
sp_xpos[X] = xpos << 8;
|
||||
sp_ypos[X] = ypos << 8;
|
||||
sp_direction[X] = i++;
|
||||
if (i == 24) i = 0;
|
||||
}
|
||||
|
||||
// Main loop
|
||||
do {
|
||||
multisprite_flip();
|
||||
for (i = 0; i != NB_SMALL_SPRITES; i++) {
|
||||
X = i;
|
||||
Y = sp_direction[X];
|
||||
sp_xpos[X] += dx[Y];
|
||||
sp_ypos[X] += dy[Y];
|
||||
xpos = sp_xpos[X] >> 8;
|
||||
ypos = sp_ypos[X] >> 8;
|
||||
if ((xpos < 5 && (dx[Y] >> 8) < 0) ||
|
||||
(xpos >= 150 && (dx[Y] >> 8) >= 0)) {
|
||||
sp_direction[X] = horizontal_pingpong[Y];
|
||||
}
|
||||
if ((ypos < 5 && (dy[Y] >> 8) < 0) ||
|
||||
(ypos >= MS_YMAX - 20 && (dy[Y] >> 8) >= 0)) {
|
||||
sp_direction[X] = vertical_pingpong[Y];
|
||||
}
|
||||
multisprite_display_small_sprite(xpos, ypos, missile, 1, 0, 8);
|
||||
}
|
||||
} while(1);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
// example from https://github.com/steux/cc7800 - license: GPLv3
|
||||
|
||||
#include "prosystem.h"
|
||||
#include "gfx.h"
|
||||
#define DMA_CHECK
|
||||
#define VERTICAL_SCROLLING
|
||||
#define _MS_DL_SIZE 64
|
||||
#define _MS_DL_MALLOC(y) ((y == 6 || y == 7 || y == 8)?_MS_DL_SIZE * 2:_MS_DL_SIZE)
|
||||
#include "multisprite.h"
|
||||
|
||||
char i, counter, xpos, ypos;
|
||||
char *ptr;
|
||||
char xchest;
|
||||
|
||||
#define NB_SPRITES 32
|
||||
ramchip short sp_xpos[NB_SPRITES], sp_ypos[NB_SPRITES];
|
||||
ramchip char sp_direction[NB_SPRITES];
|
||||
|
||||
const signed short dx[24] = {300, 289, 259, 212, 149, 77, 0, -77, -150, -212, -259, -289, -300, -289, -259, -212, -149, -77, 0, 77, 149, 212, 259, 289};
|
||||
const signed short dy[24] = {0, 124, 240, 339, 415, 463, 480, 463, 415, 339, 240, 124, 0, -124, -239, -339, -415, -463, -480, -463, -415, -339, -240, -124};
|
||||
const char horizontal_pingpong[24] = { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13 };
|
||||
const char vertical_pingpong[24] = { 0, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
|
||||
const char background[22] = { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0 };
|
||||
#define LTR(x) (((x) - ' ') * 2)
|
||||
const char hello_world[] = { LTR('H'), LTR('E'), LTR('L'), LTR('L'), LTR('O'), LTR(' '), LTR('W'), LTR('O'), LTR('R'), LTR('L'), LTR('D') };
|
||||
|
||||
void main()
|
||||
{
|
||||
counter = 0;
|
||||
|
||||
multisprite_init();
|
||||
multisprite_set_charbase(tiles);
|
||||
|
||||
// Set up a full background
|
||||
for (counter = 0; counter < _MS_DLL_ARRAY_SIZE; counter++) {
|
||||
if (counter & 2) {
|
||||
ptr = background + 2;
|
||||
} else {
|
||||
ptr = background;
|
||||
}
|
||||
multisprite_display_tiles(0, _MS_DLL_ARRAY_SIZE - 1 - counter, ptr, 20, 1);
|
||||
}
|
||||
multisprite_save();
|
||||
|
||||
*P0C1 = multisprite_color(0x1c); // Setup Palette 0: Yellow
|
||||
*P0C2 = multisprite_color(0xc5); // Green
|
||||
*P0C3 = 0x0f; // White
|
||||
|
||||
*P1C1 = multisprite_color(0x55); // Dark pink
|
||||
*P1C2 = multisprite_color(0x5B); // Light pink
|
||||
|
||||
*P2C1 = multisprite_color(0x32);
|
||||
*P2C2 = multisprite_color(0x3D);
|
||||
*P2C3 = multisprite_color(0x37);
|
||||
|
||||
*P3C1 = multisprite_color(0x92);
|
||||
*P3C2 = multisprite_color(0x97);
|
||||
*P3C3 = multisprite_color(0x9D);
|
||||
|
||||
// Initialize sprites
|
||||
for (ypos = 0, xpos = 0, i = 0, X = 0; X != NB_SPRITES; xpos++, ypos++, X++) {
|
||||
sp_xpos[X] = xpos << 8;
|
||||
sp_ypos[X] = ypos << 8;
|
||||
sp_direction[X] = i++;
|
||||
if (i == 24) i = 0;
|
||||
}
|
||||
|
||||
// Main loop
|
||||
do {
|
||||
// Prepare scrolling data
|
||||
if (multisprite_vscroll_buffer_empty()) {
|
||||
if (counter & 2) {
|
||||
ptr = background + 2;
|
||||
} else {
|
||||
ptr = background;
|
||||
}
|
||||
multisprite_vscroll_buffer_tiles(0, ptr, 20, 1);
|
||||
multisprite_vscroll_buffer_sprite(xchest, chest, 2, 3);
|
||||
xchest += 45;
|
||||
counter++;
|
||||
}
|
||||
|
||||
while (*MSTAT & 0x80);
|
||||
multisprite_flip();
|
||||
multisprite_vertical_scrolling(-1);
|
||||
multisprite_reserve_dma(104, sizeof(hello_world), 2);
|
||||
for (i = 0; i != NB_SPRITES; i++) {
|
||||
X = i;
|
||||
Y = sp_direction[X];
|
||||
sp_xpos[X] += dx[Y];
|
||||
sp_ypos[X] += dy[Y];
|
||||
xpos = sp_xpos[X] >> 8;
|
||||
ypos = sp_ypos[X] >> 8;
|
||||
if ((xpos < 5 && (dx[Y] >> 8) < 0) ||
|
||||
(xpos >= 150 && (dx[Y] >> 8) >= 0)) {
|
||||
sp_direction[X] = horizontal_pingpong[Y];
|
||||
}
|
||||
if ((ypos < 5 && (dy[Y] >> 8) < 0) ||
|
||||
(ypos >= MS_YMAX - 20 && (dy[Y] >> 8) >= 0)) {
|
||||
sp_direction[X] = vertical_pingpong[Y];
|
||||
}
|
||||
multisprite_display_sprite(xpos, ypos, bb_char1, 2, 0);
|
||||
}
|
||||
for (xpos = 40, i = 0; i != sizeof(hello_world); xpos += 8, i++) {
|
||||
ptr = chars0 + hello_world[X = i];
|
||||
multisprite_display_sprite_fast(xpos, 104, ptr, 2, 2);
|
||||
}
|
||||
} while(1);
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
// example from https://github.com/steux/cc7800 - license: GPLv3
|
||||
|
||||
reversed scattered(16,4) char tiles[64] = {
|
||||
0x5a, 0x5a, 0x95, 0x95, 0x69, 0x69, 0x65, 0x65, 0x69, 0x69, 0x95, 0x95, 0xa5, 0xa5, 0x65, 0x65,
|
||||
0xa5, 0xa5, 0xa9, 0xa9, 0x96, 0x96, 0xa6, 0xa6, 0x96, 0x96, 0xa9, 0xa9, 0x5a, 0x5a, 0xa6, 0xa6,
|
||||
0x5a, 0x5a, 0x95, 0x95, 0x69, 0x69, 0x65, 0x65, 0x69, 0x69, 0x95, 0x95, 0xa5, 0xa5, 0x65, 0x65,
|
||||
0xa5, 0xa5, 0xa9, 0xa9, 0x96, 0x96, 0xa6, 0xa6, 0x96, 0x96, 0xa9, 0xa9, 0x5a, 0x5a, 0xa6, 0xa6
|
||||
};
|
||||
holeydma reversed scattered(16,32) char chars0[512] = {
|
||||
0x00, 0x00, 0x05, 0x00, 0x50, 0x50, 0x51, 0x40, 0x05, 0x00, 0x50, 0x10, 0x15, 0x40, 0x00, 0x50,
|
||||
0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0x00, 0x50, 0x50, 0x51, 0x40, 0x05, 0x00, 0x50, 0x10, 0x15, 0x40, 0x00, 0x50,
|
||||
0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x09, 0x00, 0x60, 0x90, 0x62, 0x40, 0x16, 0x60, 0x90, 0x60, 0x5f, 0x90, 0x01, 0xb0,
|
||||
0x06, 0xc0, 0x36, 0x00, 0x90, 0x60, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24,
|
||||
0x00, 0x00, 0x05, 0x00, 0x50, 0x50, 0x51, 0x80, 0x25, 0x50, 0x50, 0x50, 0x90, 0x60, 0x01, 0x40,
|
||||
0x05, 0x00, 0x05, 0x00, 0x50, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x09, 0x00, 0x50, 0x92, 0x65, 0x90, 0x6f, 0xf0, 0xf2, 0x70, 0xd9, 0x70, 0x09, 0xc0,
|
||||
0x27, 0x00, 0x0e, 0x40, 0xd6, 0x70, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
|
||||
0x00, 0x00, 0x06, 0x00, 0x90, 0x61, 0x99, 0x60, 0x50, 0x00, 0x01, 0x80, 0x26, 0x40, 0x06, 0x00,
|
||||
0x18, 0x00, 0x01, 0x80, 0x25, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90,
|
||||
0x00, 0x00, 0x06, 0x00, 0xf0, 0xf3, 0x6e, 0x70, 0xe6, 0x40, 0x06, 0xc0, 0x26, 0xc0, 0x0f, 0x00,
|
||||
0x24, 0x00, 0x02, 0x42, 0x66, 0x64, 0x66, 0x60, 0x00, 0x00, 0x66, 0x60, 0x00, 0x00, 0x02, 0x70,
|
||||
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x40, 0x26, 0x40, 0x06, 0x00, 0x26, 0x00, 0x00, 0x00,
|
||||
0x24, 0x00, 0x02, 0x42, 0x66, 0x64, 0x66, 0x60, 0x00, 0x00, 0x66, 0x60, 0x00, 0x00, 0x02, 0x40,
|
||||
0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x6a, 0x60, 0x3f, 0xa0, 0x1b, 0x00, 0x6d, 0xa0, 0x00, 0x00,
|
||||
0x28, 0x00, 0x02, 0x83, 0xda, 0x7c, 0xf6, 0xf0, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x09, 0xc0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa6, 0x90, 0x00, 0x90, 0x28, 0x00, 0x92, 0x60, 0x00, 0x00,
|
||||
0x24, 0x00, 0x01, 0x80, 0x29, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xae, 0xb0, 0x6a, 0xb0, 0xac, 0xa0, 0xa2, 0x70, 0x00, 0x00,
|
||||
0x36, 0x00, 0x0a, 0xc0, 0xaf, 0xa0, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x27, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x40, 0xa6, 0x80, 0x90, 0x60, 0x62, 0x80, 0x00, 0x00,
|
||||
0x0a, 0x00, 0x06, 0x00, 0x90, 0x60, 0x09, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa2, 0x80, 0xfa, 0xc0, 0xb0, 0xa0, 0xea, 0xa0, 0x00, 0x00,
|
||||
0x0e, 0x80, 0x2b, 0x00, 0xf0, 0xf0, 0x0f, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xac, 0x00,
|
||||
0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa2, 0x80, 0x0a, 0x00, 0x80, 0xa0, 0x2a, 0xa0, 0x00, 0x00,
|
||||
0x02, 0x80, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xa0, 0x00,
|
||||
0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf3, 0xc0, 0x0f, 0x00, 0xc0, 0xf0, 0x3f, 0xf0, 0x00, 0x00,
|
||||
0x03, 0xc0, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xf0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
holeydma reversed scattered(16,32) char chars1[512] = {
|
||||
0x15, 0x40, 0x05, 0x00, 0x15, 0x40, 0x15, 0x40, 0x01, 0x40, 0x55, 0x50, 0x15, 0x40, 0x55, 0x50,
|
||||
0x15, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x54, 0x00, 0x15, 0x40,
|
||||
0x15, 0x40, 0x05, 0x00, 0x15, 0x40, 0x15, 0x40, 0x01, 0x40, 0x55, 0x50, 0x15, 0x40, 0x55, 0x50,
|
||||
0x15, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x54, 0x00, 0x15, 0x40,
|
||||
0x5a, 0x70, 0x0d, 0x00, 0x7a, 0xd0, 0x7a, 0x50, 0x07, 0x40, 0xda, 0xa0, 0x5a, 0xd0, 0x7a, 0xd0,
|
||||
0x7a, 0x50, 0xda, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa0, 0x00, 0x00, 0xa7, 0x00, 0xda, 0x70,
|
||||
0x70, 0xd0, 0x05, 0x00, 0x50, 0x50, 0x50, 0xd0, 0x05, 0x40, 0x50, 0x00, 0xd0, 0x70, 0x50, 0x50,
|
||||
0x50, 0xd0, 0x70, 0x50, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x50, 0x50,
|
||||
0x51, 0x70, 0x1d, 0x00, 0xa0, 0xd0, 0xa0, 0xd0, 0x37, 0x40, 0xd7, 0x40, 0xd0, 0xa0, 0xa1, 0xe0,
|
||||
0x70, 0xd0, 0x70, 0x50, 0x07, 0x00, 0x0d, 0x00, 0x1e, 0x00, 0x75, 0xd0, 0x0b, 0x40, 0xa0, 0x70,
|
||||
0xd3, 0x50, 0x37, 0x00, 0x00, 0x70, 0x00, 0x70, 0x1d, 0xc0, 0x75, 0xc0, 0x70, 0x00, 0x03, 0x40,
|
||||
0xd0, 0x70, 0x50, 0xd0, 0x05, 0x00, 0x07, 0x00, 0x14, 0x00, 0xdd, 0x70, 0x01, 0xc0, 0x00, 0xd0,
|
||||
0x76, 0xd0, 0x27, 0x00, 0x03, 0x60, 0x07, 0x60, 0x6b, 0x40, 0xaa, 0x70, 0x77, 0x40, 0x07, 0x80,
|
||||
0xb7, 0x60, 0xb7, 0x70, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0xaa, 0xa0, 0x02, 0x70, 0x03, 0x60,
|
||||
0xdc, 0x70, 0x07, 0x00, 0x03, 0x40, 0x07, 0x40, 0x43, 0x40, 0x00, 0x70, 0x77, 0x40, 0x07, 0x00,
|
||||
0x37, 0x40, 0x37, 0x70, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x70, 0x03, 0x40,
|
||||
0xd8, 0xf0, 0x0d, 0x00, 0x36, 0x80, 0x0a, 0x70, 0xf7, 0xf0, 0x00, 0x70, 0x7a, 0xf0, 0x07, 0x00,
|
||||
0x7a, 0x70, 0x2a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0xdf, 0x70, 0x03, 0xe0, 0x0d, 0x80,
|
||||
0xf0, 0x70, 0x0f, 0x00, 0x1c, 0x00, 0x00, 0xd0, 0x7d, 0xd0, 0x00, 0xf0, 0xd0, 0x70, 0x0f, 0x00,
|
||||
0xf0, 0xd0, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x7d, 0xf0, 0x03, 0x40, 0x07, 0x00,
|
||||
0xf0, 0xd0, 0x0f, 0x00, 0xf8, 0x00, 0xf0, 0xf0, 0xab, 0xe0, 0xf0, 0xf0, 0xf0, 0x70, 0x0f, 0x00,
|
||||
0xf0, 0xf0, 0x70, 0xf0, 0x0f, 0x00, 0x0f, 0x00, 0x2f, 0x00, 0xaa, 0xa0, 0x0f, 0x80, 0x0a, 0x00,
|
||||
0xd0, 0xf0, 0x0f, 0x00, 0xd0, 0x00, 0xf0, 0x70, 0x03, 0xc0, 0xd0, 0x70, 0x70, 0xf0, 0x0d, 0x00,
|
||||
0x70, 0x70, 0xf0, 0xd0, 0x0f, 0x00, 0x0d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0xbd, 0xe0, 0xff, 0xf0, 0xff, 0xf0, 0xbf, 0xe0, 0x03, 0xc0, 0xbf, 0xe0, 0xbf, 0xe0, 0x0f, 0x00,
|
||||
0xbf, 0xe0, 0xbf, 0xe0, 0x0a, 0x00, 0x3e, 0x00, 0x0b, 0xf0, 0x00, 0x00, 0xfe, 0x00, 0x0d, 0x00,
|
||||
0x3f, 0xc0, 0xff, 0xf0, 0xff, 0xf0, 0x3f, 0xc0, 0x03, 0xc0, 0x3f, 0xc0, 0x3f, 0xc0, 0x0f, 0x00,
|
||||
0x3f, 0xc0, 0x3f, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x03, 0xf0, 0x00, 0x00, 0xfc, 0x00, 0x0f, 0x00,
|
||||
0x2a, 0x80, 0xaa, 0xa0, 0xaa, 0xa0, 0x2a, 0x80, 0x02, 0x80, 0x2a, 0x80, 0x2a, 0x80, 0x0a, 0x00,
|
||||
0x2a, 0x80, 0x2a, 0x80, 0x00, 0x00, 0x28, 0x00, 0x02, 0xa0, 0x00, 0x00, 0xa8, 0x00, 0x0a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
holeydma reversed scattered(16,32) char chars2[512] = {
|
||||
0x15, 0x40, 0x05, 0x00, 0x55, 0x40, 0x15, 0x40, 0x55, 0x00, 0x55, 0x50, 0x55, 0x50, 0x15, 0x40,
|
||||
0x50, 0x50, 0x15, 0x40, 0x05, 0x50, 0x50, 0x50, 0x50, 0x00, 0x50, 0x14, 0x50, 0x50, 0x15, 0x40,
|
||||
0x15, 0x40, 0x05, 0x00, 0x55, 0x40, 0x15, 0x40, 0x55, 0x00, 0x55, 0x50, 0x55, 0x50, 0x15, 0x40,
|
||||
0x50, 0x50, 0x15, 0x40, 0x05, 0x50, 0x50, 0x50, 0x50, 0x00, 0x50, 0x14, 0x50, 0x50, 0x15, 0x40,
|
||||
0x5a, 0x70, 0x1d, 0xc0, 0x7a, 0xd0, 0x7a, 0x50, 0xdb, 0x40, 0xda, 0xa0, 0x5a, 0xa0, 0x7a, 0xd0,
|
||||
0x70, 0x50, 0x27, 0x80, 0x09, 0x60, 0x51, 0xe0, 0x70, 0x00, 0x74, 0x5c, 0xd4, 0x70, 0xda, 0x70,
|
||||
0x70, 0xd0, 0x15, 0x40, 0x50, 0x50, 0x50, 0xd0, 0x71, 0x40, 0x50, 0x00, 0xd0, 0x00, 0x50, 0x50,
|
||||
0x50, 0xd0, 0x05, 0x00, 0x03, 0x40, 0xd1, 0x40, 0x50, 0x00, 0x54, 0xd4, 0x74, 0x50, 0x50, 0x50,
|
||||
0x51, 0x70, 0xda, 0x70, 0x50, 0xd0, 0x70, 0xa0, 0x72, 0x50, 0xd0, 0x00, 0xd0, 0x00, 0x50, 0xa0,
|
||||
0x70, 0xd0, 0x07, 0x00, 0x03, 0x40, 0xdd, 0x80, 0x50, 0x00, 0x75, 0xdc, 0x77, 0x50, 0xd0, 0x70,
|
||||
0xd3, 0x50, 0x70, 0x50, 0xd0, 0x70, 0xd0, 0x00, 0x50, 0xd0, 0x70, 0x00, 0x70, 0x00, 0xd0, 0x00,
|
||||
0xd0, 0x70, 0x0d, 0x00, 0x01, 0xc0, 0x77, 0x00, 0xd0, 0x00, 0xdd, 0x74, 0x5d, 0xd0, 0x70, 0xd0,
|
||||
0x73, 0xd0, 0x77, 0x70, 0x77, 0x60, 0x70, 0x00, 0x70, 0x70, 0x77, 0x00, 0x77, 0x00, 0x73, 0x70,
|
||||
0x77, 0x70, 0x07, 0x00, 0x03, 0x40, 0x76, 0x00, 0x70, 0x00, 0x7b, 0xb4, 0x77, 0x70, 0x70, 0x70,
|
||||
0xd1, 0x70, 0x77, 0x70, 0x77, 0x40, 0x70, 0x00, 0x70, 0x70, 0x77, 0x00, 0x77, 0x00, 0x73, 0x70,
|
||||
0x77, 0x70, 0x07, 0x00, 0x03, 0x40, 0x74, 0x00, 0x70, 0x00, 0x73, 0x34, 0x77, 0x70, 0x70, 0x70,
|
||||
0xd2, 0xa0, 0x7a, 0xf0, 0xfa, 0xd0, 0x70, 0x00, 0xf0, 0xf0, 0xda, 0x00, 0x7a, 0x00, 0xf2, 0xd0,
|
||||
0x7a, 0x70, 0x07, 0x00, 0x03, 0x40, 0xf7, 0x00, 0x70, 0x00, 0xd2, 0x3c, 0xfb, 0xd0, 0x70, 0xf0,
|
||||
0xf0, 0x00, 0xd0, 0x70, 0xd0, 0x70, 0xf0, 0x00, 0x70, 0xd0, 0x70, 0x00, 0xd0, 0x00, 0xd0, 0x70,
|
||||
0xf0, 0xd0, 0x0d, 0x00, 0x01, 0xc0, 0xdf, 0x00, 0xf0, 0x00, 0x70, 0x34, 0xd3, 0x70, 0xf0, 0xd0,
|
||||
0xf0, 0x10, 0xf0, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0x73, 0xe0, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0xf0,
|
||||
0xf0, 0xf0, 0x0f, 0x00, 0xf3, 0xc0, 0xfb, 0xc0, 0xf0, 0x00, 0xf0, 0x3c, 0xf2, 0xf0, 0xf0, 0xf0,
|
||||
0xd0, 0x30, 0xd0, 0xf0, 0xd0, 0x70, 0xf0, 0x70, 0xf3, 0xc0, 0xd0, 0x00, 0x70, 0x00, 0xd0, 0xd0,
|
||||
0x70, 0x70, 0x07, 0x00, 0xd3, 0x40, 0xd1, 0xc0, 0x70, 0x00, 0xd0, 0x34, 0xd0, 0xf0, 0xf0, 0xf0,
|
||||
0xbd, 0xe0, 0xf0, 0xf0, 0xff, 0xe0, 0xbf, 0xe0, 0xff, 0x80, 0xff, 0xf0, 0xf0, 0x00, 0xbf, 0xe0,
|
||||
0xf0, 0xf0, 0x3f, 0xc0, 0xbf, 0x80, 0xf2, 0xf0, 0xff, 0xf0, 0xf0, 0x3c, 0xf0, 0xf0, 0xbd, 0xe0,
|
||||
0x3f, 0xc0, 0xf0, 0xf0, 0xff, 0xc0, 0x3f, 0xc0, 0xff, 0x00, 0xff, 0xf0, 0xf0, 0x00, 0x3f, 0xc0,
|
||||
0xf0, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0x3c, 0xf0, 0xf0, 0x3f, 0xc0,
|
||||
0x2a, 0x80, 0xa0, 0xa0, 0xaa, 0x80, 0x2a, 0x80, 0xaa, 0x00, 0xaa, 0xa0, 0xa0, 0x00, 0x2a, 0x80,
|
||||
0xa0, 0xa0, 0x2a, 0x80, 0x2a, 0x00, 0xa0, 0xa0, 0xaa, 0xa0, 0xa0, 0x28, 0xa0, 0xa0, 0x2a, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
holeydma reversed scattered(16,32) char chars3[512] = {
|
||||
0x55, 0x40, 0x15, 0x40, 0x55, 0x40, 0x15, 0x40, 0x55, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x14,
|
||||
0x50, 0x50, 0x50, 0x50, 0x55, 0x50, 0x15, 0x40, 0x00, 0x50, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x55, 0x40, 0x15, 0x40, 0x55, 0x40, 0x15, 0x40, 0x55, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x14,
|
||||
0x50, 0x50, 0x50, 0x50, 0x55, 0x50, 0x15, 0x40, 0x00, 0x50, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5a, 0x70, 0x5a, 0xd0, 0x7a, 0xd0, 0x7a, 0x50, 0xa7, 0xa0, 0xd0, 0x70, 0x50, 0xd0, 0x70, 0x1c,
|
||||
0x70, 0x50, 0xd0, 0x70, 0xaa, 0x70, 0x1e, 0x80, 0x01, 0xac, 0x2b, 0x40, 0x07, 0x00, 0x0c, 0x00,
|
||||
0x70, 0xd0, 0xd0, 0x70, 0x50, 0x50, 0x50, 0xd0, 0x05, 0x00, 0x50, 0x50, 0xd0, 0x70, 0x50, 0x14,
|
||||
0x50, 0xd0, 0x70, 0x50, 0x00, 0x50, 0x14, 0x00, 0x01, 0x04, 0x01, 0xc0, 0x05, 0x00, 0x04, 0x00,
|
||||
0x50, 0x70, 0xd0, 0x70, 0x50, 0xd0, 0x70, 0xa0, 0x07, 0x00, 0xd0, 0x70, 0xd0, 0x70, 0x50, 0x14,
|
||||
0xb5, 0xe0, 0x70, 0x50, 0x03, 0x60, 0x1c, 0x00, 0x0d, 0x08, 0x01, 0xc0, 0x37, 0x40, 0x14, 0x00,
|
||||
0xd0, 0x50, 0x70, 0x50, 0xd0, 0x70, 0xd0, 0x00, 0x0d, 0x00, 0x70, 0xd0, 0x70, 0x50, 0xd0, 0x34,
|
||||
0x1d, 0x40, 0x50, 0xd0, 0x01, 0xc0, 0x34, 0x00, 0x07, 0x00, 0x01, 0x40, 0x1d, 0xc0, 0x34, 0x00,
|
||||
0x77, 0xe0, 0x70, 0x70, 0x77, 0x60, 0xb7, 0x40, 0x07, 0x00, 0x70, 0x70, 0x70, 0x70, 0x73, 0x34,
|
||||
0x27, 0x80, 0xb7, 0x60, 0x07, 0x80, 0x34, 0x00, 0x37, 0x70, 0x03, 0x40, 0x77, 0x70, 0x77, 0x74,
|
||||
0xdd, 0x40, 0x70, 0x70, 0x77, 0x40, 0x37, 0x40, 0x07, 0x00, 0x70, 0x70, 0x70, 0x70, 0x73, 0x34,
|
||||
0x07, 0x00, 0x37, 0x40, 0x07, 0x00, 0x34, 0x00, 0x37, 0x70, 0x03, 0x40, 0x77, 0x70, 0x77, 0x74,
|
||||
0xda, 0x80, 0x70, 0xf0, 0xf7, 0x80, 0x2a, 0x70, 0x07, 0x00, 0xd0, 0x70, 0x70, 0xf0, 0xf7, 0xdc,
|
||||
0x3f, 0x40, 0x27, 0x80, 0x1e, 0x00, 0x34, 0x00, 0x2d, 0xa0, 0x03, 0x40, 0xa7, 0xa0, 0x7d, 0xf4,
|
||||
0xf0, 0x00, 0xd0, 0x70, 0xdf, 0x00, 0x00, 0xd0, 0x0d, 0x00, 0x70, 0xf0, 0xd0, 0x70, 0xdf, 0x7c,
|
||||
0x37, 0xc0, 0x0d, 0x00, 0x3c, 0x00, 0x1c, 0x00, 0x07, 0x00, 0x01, 0xc0, 0x0f, 0x00, 0xf7, 0xdc,
|
||||
0xf0, 0x00, 0xbf, 0x60, 0xfb, 0xc0, 0xf0, 0xf0, 0x0f, 0x00, 0xf0, 0xf0, 0xbf, 0x60, 0xfe, 0xfc,
|
||||
0xfa, 0xf0, 0x0f, 0x00, 0xf8, 0x00, 0x3c, 0x00, 0x3e, 0x0c, 0x03, 0xc0, 0x0f, 0x00, 0xb6, 0xa8,
|
||||
0xd0, 0x00, 0x1f, 0xc0, 0xd3, 0x40, 0xf0, 0x70, 0x07, 0x00, 0xd0, 0x70, 0x3f, 0xc0, 0xdc, 0xdc,
|
||||
0x70, 0x70, 0x07, 0x00, 0xd0, 0x00, 0x1c, 0x00, 0x34, 0x0c, 0x03, 0x40, 0x0d, 0x00, 0x3c, 0x00,
|
||||
0xf0, 0x00, 0x2b, 0xf0, 0xf2, 0xf0, 0xbf, 0xe0, 0x0f, 0x00, 0xbf, 0xe0, 0x2f, 0x80, 0xf8, 0xbc,
|
||||
0xf0, 0xf0, 0x0f, 0x00, 0xff, 0xf0, 0x3f, 0xc0, 0xff, 0xf8, 0x3f, 0xc0, 0x0f, 0x00, 0x2c, 0x00,
|
||||
0xf0, 0x00, 0x03, 0xf0, 0xf0, 0xf0, 0x3f, 0xc0, 0x0f, 0x00, 0x3f, 0xc0, 0x0f, 0x00, 0xf0, 0x3c,
|
||||
0xf0, 0xf0, 0x0f, 0x00, 0xff, 0xf0, 0x3f, 0xc0, 0xff, 0xf0, 0x3f, 0xc0, 0x0f, 0x00, 0x0c, 0x00,
|
||||
0xa0, 0x00, 0x02, 0xa0, 0xa0, 0xa0, 0x2a, 0x80, 0x0a, 0x00, 0x2a, 0x80, 0x0a, 0x00, 0xa0, 0x28,
|
||||
0xa0, 0xa0, 0x0a, 0x00, 0xaa, 0xa0, 0x2a, 0x80, 0xaa, 0xa0, 0x2a, 0x80, 0x0a, 0x00, 0x08, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
holeydma reversed scattered(16,2) char bb_char1[32] = {
|
||||
0x01, 0x00, 0x01, 0x40, 0x0a, 0x94, 0x2a, 0x90, 0x3b, 0xa0, 0xc8, 0xe5, 0xc8, 0xe4, 0xc8, 0xd0,
|
||||
0xc8, 0xe5, 0xbb, 0x84, 0x0c, 0x20, 0x2a, 0x90, 0x0e, 0x50, 0x3f, 0x94, 0x3d, 0x68, 0x5d, 0x6a
|
||||
};
|
||||
reversed scattered(16,2) char chest[32] = {
|
||||
0x00, 0x00, 0x05, 0x50, 0x2b, 0xf4, 0x96, 0xfc, 0x69, 0xbd, 0xbe, 0x6a, 0x55, 0x55, 0xaa, 0xbf,
|
||||
0xd5, 0xd5, 0xd9, 0xb7, 0xef, 0x9d, 0xef, 0x9d, 0xef, 0x9d, 0xdd, 0x9d, 0xd5, 0xf7, 0xff, 0x95
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
// example from https://github.com/steux/cc7800 - license: GPLv3
|
||||
|
||||
#include "conio.h"
|
||||
|
||||
char i;
|
||||
|
||||
void main()
|
||||
{
|
||||
clrscr();
|
||||
for (i = 0; i != 8; i++) {
|
||||
textcolor(i);
|
||||
gotoxy(0, i);
|
||||
cputs("Hello World!");
|
||||
}
|
||||
while(1);
|
||||
}
|
|
@ -6,66 +6,11 @@
|
|||
;
|
||||
|
||||
processor 6502
|
||||
|
||||
; ************ Hardware Adresses ***************************
|
||||
|
||||
INPTCTRL equ $01 ;Input control
|
||||
AUDC0 equ $15 ;Audio Control Channel 0
|
||||
AUDC1 equ $16 ;Audio Control Channel 1
|
||||
AUDF0 equ $17 ;Audio Frequency Channel 0
|
||||
AUDF1 equ $18 ;Audio Frequency Channel 1
|
||||
AUDV0 equ $19 ;Audio Volume Channel 0
|
||||
AUDV1 equ $1A ;Audio Volume Channel 1
|
||||
INPT0 equ $08 ;Paddle Control Input 0
|
||||
INPT1 equ $09 ;Paddle Control Input 1
|
||||
INPT2 equ $0A ;Paddle Control Input 2
|
||||
INPT3 equ $0B ;Paddle Control Input 3
|
||||
INPT4 equ $0C ;Player 0 Fire Button Input
|
||||
INPT5 equ $0D ;Player 1 Fire Button Input
|
||||
|
||||
BACKGRND equ $20 ;Background Color
|
||||
P0C1 equ $21 ;Palette 0 - Color 1
|
||||
P0C2 equ $22 ;Palette 0 - Color 2
|
||||
P0C3 equ $23 ;Palette 0 - Color 3
|
||||
WSYNC equ $24 ;Wait For Sync
|
||||
P1C1 equ $25 ;Palette 1 - Color 1
|
||||
P1C2 equ $26 ;Palette 1 - Color 2
|
||||
P1C3 equ $27 ;Palette 1 - Color 3
|
||||
MSTAT equ $28 ;Maria Status
|
||||
P2C1 equ $29 ;Palette 2 - Color 1
|
||||
P2C2 equ $2A ;Palette 2 - Color 2
|
||||
P2C3 equ $2B ;Palette 2 - Color 3
|
||||
DPPH equ $2C ;Display List List Pointer High
|
||||
P3C1 equ $2D ;Palette 3 - Color 1
|
||||
P3C2 equ $2E ;Palette 3 - Color 2
|
||||
P3C3 equ $2F ;Palette 3 - Color 3
|
||||
DPPL equ $30 ;Display List List Pointer Low
|
||||
P4C1 equ $31 ;Palette 4 - Color 1
|
||||
P4C2 equ $32 ;Palette 4 - Color 2
|
||||
P4C3 equ $33 ;Palette 4 - Color 3
|
||||
CHARBASE equ $34 ;Character Base Address
|
||||
P5C1 equ $35 ;Palette 5 - Color 1
|
||||
P5C2 equ $36 ;Palette 5 - Color 2
|
||||
P5C3 equ $37 ;Palette 5 - Color 3
|
||||
OFFSET equ $38 ;Unused - Store zero here
|
||||
P6C1 equ $39 ;Palette 6 - Color 1
|
||||
P6C2 equ $3A ;Palette 6 - Color 2
|
||||
P6C3 equ $3B ;Palette 6 - Color 3
|
||||
CTRL equ $3C ;Maria Control Register
|
||||
P7C1 equ $3D ;Palette 7 - Color 1
|
||||
P7C2 equ $3E ;Palette 7 - Color 2
|
||||
P7C3 equ $3F ;Palette 7 - Color 3
|
||||
|
||||
SWCHA equ $280 ;P0, P1 Joystick Directional Input
|
||||
SWCHB equ $282 ;Console Switches
|
||||
CTLSWA equ $281 ;I/O Control for SCHWA
|
||||
CTLSWB equ $283 ;I/O Control for SCHWB
|
||||
|
||||
SEG.U data
|
||||
|
||||
include "7800.h"
|
||||
|
||||
;******* Vairables ********************************
|
||||
|
||||
SEG.U data
|
||||
org $40
|
||||
|
||||
xpos ds.b 1 ;X Position of sprite
|
||||
|
@ -75,12 +20,9 @@ dlpnt ds.w 1
|
|||
dlend ds.b 12 ;Index of end of each DL
|
||||
|
||||
|
||||
|
||||
|
||||
;**********************************************************
|
||||
|
||||
SEG code
|
||||
|
||||
SEG code
|
||||
org $4000 ;Start of code
|
||||
|
||||
START
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
// example from https://github.com/steux/cc7800 - license: GPLv3
|
||||
|
||||
#include "conio.h"
|
||||
#include "assert.h"
|
||||
|
||||
char i;
|
||||
|
||||
reversed scattered(8,1) char special_char[8] = {
|
||||
0x66, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
clrscr();
|
||||
// Draw a square
|
||||
gotoxy(0, 0);
|
||||
textcolor(7);
|
||||
putch(CONIO_TL_CORNER);
|
||||
for (i = 0; i != 20; i++) {
|
||||
putch(CONIO_HBAR);
|
||||
}
|
||||
putch(CONIO_TR_CORNER);
|
||||
for (i = 0; i != 8; i++) {
|
||||
gotoxy(0, i + 1);
|
||||
putch(CONIO_VBAR);
|
||||
gotoxy(21, i + 1);
|
||||
putch(CONIO_VBAR);
|
||||
}
|
||||
gotoxy(0, 9);
|
||||
putch(CONIO_BL_CORNER);
|
||||
for (i = 0; i != 20; i++) {
|
||||
putch(CONIO_HBAR);
|
||||
}
|
||||
putch(CONIO_BR_CORNER);
|
||||
// Write some text
|
||||
for (i = 0; i != 8; i++) {
|
||||
textcolor(i);
|
||||
gotoxy(i + 1, i + 1);
|
||||
cputs("Hello World!");
|
||||
}
|
||||
// Long text test
|
||||
gotoxy(0, 10);
|
||||
cputs("This is a long text that fits in a line.");
|
||||
|
||||
gotoxy(10, 11);
|
||||
cputs("World!");
|
||||
gotoxy(4, 11);
|
||||
cputs("Hello");
|
||||
|
||||
gotoxy(10, 12);
|
||||
cputs("World!");
|
||||
gotoxy(4, 12);
|
||||
textcolor(4);
|
||||
cputs("Hello");
|
||||
|
||||
gotoxy(0, 13);
|
||||
for (i = 0; i != 8; i++) {
|
||||
textcolor(i);
|
||||
putch('!');
|
||||
}
|
||||
|
||||
gotoxy(0, 14);
|
||||
for (i = 0; i != 8; i++) {
|
||||
textcolor(7 - i);
|
||||
putch(128); // Special character
|
||||
}
|
||||
|
||||
while(1);
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
|
||||
AUDF0 = $d200
|
||||
AUDC0 = $d201
|
||||
AUDCTL = $d208
|
||||
|
||||
.data
|
||||
|
||||
Chan0dur: .res 4 ; current note duration channel 0
|
||||
Chan0note: .res 4 ; current note pitch channel 0
|
||||
Chan0duty: .res 4 ; current duty bits channel 0
|
||||
DurationTimer: .res 1 ; duration until next cmd
|
||||
CurChannel: .res 1 ; next channel to add note
|
||||
Volume: .res 1 ; initial volume of note (0-31)
|
||||
|
||||
; set_irq() saves/restores entire zeropage segment
|
||||
; which we don't want!
|
||||
; so we have to set this with an equate
|
||||
SongPtr = $fe
|
||||
;.segment "EXTZP"
|
||||
;SongPtr: .res 2 ; ptr to next song byte
|
||||
|
||||
.code
|
||||
|
||||
; Update channel pitch in AUDF0
|
||||
; 8-bit rotation of duty cycle bits
|
||||
.export _music_duty
|
||||
_music_duty:
|
||||
ldx #3
|
||||
ldy #0
|
||||
@loop:
|
||||
lda Chan0dur,x
|
||||
beq :++
|
||||
lda Chan0duty,x
|
||||
asl
|
||||
bcc :+
|
||||
ora #1
|
||||
: sta Chan0duty,x
|
||||
lda Chan0note,x
|
||||
beq :+
|
||||
; If next bit is set, add 1 to AUDF0
|
||||
adc #0
|
||||
sta AUDF0,y
|
||||
:
|
||||
iny
|
||||
iny
|
||||
dex
|
||||
bpl @loop
|
||||
rts
|
||||
|
||||
; Decrement the volumes for each channel
|
||||
.export _music_tick
|
||||
_music_tick:
|
||||
ldx #3
|
||||
ldy #0
|
||||
@loop1:
|
||||
lda Chan0dur,x
|
||||
beq :+
|
||||
lsr
|
||||
ora #$a0
|
||||
sta AUDC0,y
|
||||
dec Chan0dur,x
|
||||
:
|
||||
iny
|
||||
iny
|
||||
dex
|
||||
bpl @loop1
|
||||
|
||||
; Also decrement next-note timer, fetch next note
|
||||
lda DurationTimer
|
||||
bmi @Done
|
||||
beq @NextData
|
||||
dec DurationTimer
|
||||
rts
|
||||
|
||||
; Timer ran out, so fetch next note
|
||||
@NextData:
|
||||
ldx #0
|
||||
lda (SongPtr,x)
|
||||
bmi @LoadDuration
|
||||
; < $80, play next note
|
||||
ldx CurChannel ; next channel
|
||||
tay
|
||||
jsr music_do_note
|
||||
inx
|
||||
txa
|
||||
and #3
|
||||
sta CurChannel ; inc next channel
|
||||
jsr @IncDataPtr
|
||||
jmp @NextData
|
||||
; >= $80, load next duration
|
||||
@LoadDuration:
|
||||
cmp #$ff ; $ff = end of song
|
||||
bne @NoResetTrack
|
||||
sta DurationTimer
|
||||
jmp music_done
|
||||
@NoResetTrack:
|
||||
and #$7f
|
||||
; asl
|
||||
sta DurationTimer ; store duration * 2
|
||||
@IncDataPtr:
|
||||
; increment song pointer
|
||||
inc SongPtr
|
||||
bne @Done
|
||||
inc SongPtr+1
|
||||
@Done:
|
||||
rts
|
||||
|
||||
music_do_note:
|
||||
; Play a note
|
||||
; X = channel (0,1)
|
||||
; Y = note index (0-63)
|
||||
lda FREQZ,y
|
||||
sta Chan0note,x
|
||||
lda DUTYZ,y
|
||||
sta Chan0duty,x
|
||||
lda Volume
|
||||
sta Chan0dur,x
|
||||
rts
|
||||
|
||||
music_done:
|
||||
rts
|
||||
|
||||
.export _music_start
|
||||
_music_start:
|
||||
sta SongPtr
|
||||
stx SongPtr+1
|
||||
lda #24
|
||||
sta Volume
|
||||
lda #0
|
||||
sta DurationTimer
|
||||
sta CurChannel
|
||||
ldx #3
|
||||
: sta Chan0dur,x
|
||||
dex
|
||||
bpl :-
|
||||
lda #$01
|
||||
sta AUDCTL
|
||||
rts
|
||||
|
||||
.export _music_get_ptr
|
||||
_music_get_ptr:
|
||||
lda SongPtr
|
||||
ldx SongPtr+1
|
||||
rts
|
||||
|
||||
.export _music_is_done
|
||||
_music_is_done:
|
||||
ldx #0
|
||||
lda (SongPtr,x)
|
||||
cmp #$ff
|
||||
php
|
||||
pla
|
||||
lsr
|
||||
and #1
|
||||
rts
|
||||
|
||||
; Table of AUDF base values for each note
|
||||
FREQZ:
|
||||
.byte 254, 254, 254, 255, 240, 227, 214, 202, 190, 180, 169, 160, 151, 142, 134, 127, 119, 113, 106, 100, 94, 89, 84, 79, 75, 70, 66, 63, 59, 56, 52, 49, 47, 44, 41, 39, 37, 34, 32, 31, 29, 27, 25, 24, 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7
|
||||
|
||||
; Table of duty-cycle bits for each note
|
||||
DUTYZ:
|
||||
.byte 0, 0, 0, 0, 181, 1, 17, 1, 219, 0, 239, 17, 17, 181, 181, 0, 239, 0, 181, 181, 239, 85, 73, 181, 1, 239, 219, 0, 73, 0, 239, 219, 0, 17, 219, 73, 0, 239, 239, 0, 17, 85, 239, 73, 0, 181, 73, 1, 0, 0, 0, 0, 1, 17, 85, 219, 0, 73, 181, 1, 85, 0, 85, 0
|
||||
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,7 @@
|
|||
|
||||
* = $0801
|
||||
!word Start
|
||||
!byte $00,$00,$9e
|
||||
!text "2066"
|
||||
!byte $00,$00,$00
|
||||
* = $0812
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
struct CoordXY {
|
||||
x : u8,
|
||||
y : u8
|
||||
}
|
||||
|
||||
struct SIDVoice {
|
||||
freq : u16, /* Frequency */
|
||||
pw : u16, /* Pulse width */
|
||||
ctrl : u16, /* Control register */
|
||||
ad : u16, /* Attack/decay */
|
||||
sr : u16 /* Sustain/release */
|
||||
}
|
||||
|
||||
typealias SpriteData : [u8; 64];
|
||||
|
||||
union VICBank {
|
||||
spritedata : [SpriteData; 256],
|
||||
data : [u8; 0x4000]
|
||||
}
|
||||
|
||||
namespace c64 {
|
||||
extern var colorram @ 0xD800 : [u8; 0x400];
|
||||
|
||||
namespace color {
|
||||
let BLACK = 0x00;
|
||||
let WHITE = 0x01;
|
||||
let RED = 0x02;
|
||||
let CYAN = 0x03;
|
||||
let PURPLE = 0x04;
|
||||
let GREEN = 0x05;
|
||||
let BLUE = 0x06;
|
||||
let YELLOW = 0x07;
|
||||
let ORANGE = 0x08;
|
||||
let BROWN = 0x09;
|
||||
let LIGHTRED = 0x0A;
|
||||
let GRAY1 = 0x0B;
|
||||
let GRAY2 = 0x0C;
|
||||
let LIGHTGREEN = 0x0D;
|
||||
let LIGHTBLUE = 0x0E;
|
||||
let GRAY3 = 0x0F;
|
||||
}
|
||||
|
||||
namespace vic {
|
||||
namespace sprite {
|
||||
extern var pos @ 0xD000 : [CoordXY; 8];
|
||||
extern var coord @ 0xD000 : [u8; 16];
|
||||
extern var hi_x @ 0xD010 : u8;
|
||||
extern var enable @ 0xD015 : u8;
|
||||
extern var expand_y @ 0xD017 : u8;
|
||||
extern var priority @ 0xD01B : u8;
|
||||
extern var multicolor @ 0xD01C : u8;
|
||||
extern var expand_x @ 0xD01D : u8;
|
||||
extern var coll @ 0xD01E : u8;
|
||||
extern var coll_bg @ 0xD01F : u8;
|
||||
extern var mcolor @ 0xD025 : [u8; 2];
|
||||
extern var color @ 0xD027 : [u8; 8];
|
||||
}
|
||||
extern var control1 @ 0xD011 : u8;
|
||||
extern var rasterline @ 0xD012 : u8;
|
||||
extern var lightpen @ 0xD013 : CoordXY;
|
||||
extern var control2 @ 0xD016 : u8;
|
||||
extern var mem @ 0xD018 : u8;
|
||||
extern var irr @ 0xD019 : u8;
|
||||
extern var imr @ 0xD01A : u8;
|
||||
extern var bordercolor @ 0xD020 : u8;
|
||||
extern var bgcolor @ 0xD021 : [u8; 4];
|
||||
}
|
||||
|
||||
namespace sid {
|
||||
extern writeonly v1 @ 0xd400 : [SIDVoice; 3];
|
||||
|
||||
extern writeonly flt_freq @ 0xd415 : u16;/* Filter frequency */
|
||||
extern writeonly flt_ctrl @ 0xd417 : u8; /* Filter control register */
|
||||
extern writeonly amp @ 0xd418 : u8; /* Amplitude */
|
||||
extern writeonly ad1 @ 0xd419 : u8; /* A/D converter 1 */
|
||||
extern writeonly ad2 @ 0xd41a : u8; /* A/D converter 2 */
|
||||
extern writeonly noise @ 0xd41b : u8; /* Noise generator */
|
||||
extern const read3 @ 0xd41c : u8; /* Value of voice 3 */
|
||||
}
|
||||
|
||||
namespace cia1 {
|
||||
// CIA1 Registers
|
||||
extern writeonly port_a @ 0xDC00 : u8;
|
||||
extern const port_b @ 0xDC01 : u8;
|
||||
extern writeonly data_direction_a @ 0xDC02 : u8;
|
||||
extern writeonly data_direction_b @ 0xDC03 : u8;
|
||||
extern const timer_a_lo @ 0xDC04 : u8;
|
||||
extern const timer_a_hi @ 0xDC05 : u8;
|
||||
extern const timer_b_lo @ 0xDC06 : u8;
|
||||
extern const timer_b_hi @ 0xDC07 : u8;
|
||||
extern const sdr @ 0xDC0C : u8;
|
||||
extern const icr @ 0xDC0D : u8;
|
||||
extern const cra @ 0xDC0E : u8;
|
||||
extern const crb @ 0xDC0F : u8;
|
||||
}
|
||||
|
||||
namespace cia2 {
|
||||
// CIA2 Registers
|
||||
extern writeonly port_a @ 0xDD00 : u8;
|
||||
extern const port_b @ 0xDD01 : u8;
|
||||
extern writeonly data_direction_a @ 0xDD02 : u8;
|
||||
extern writeonly data_direction_b @ 0xDD03 : u8;
|
||||
extern const timer_a_lo @ 0xDD04 : u8;
|
||||
extern const timer_a_hi @ 0xDD05 : u8;
|
||||
extern const timer_b_lo @ 0xDD06 : u8;
|
||||
extern const timer_b_hi @ 0xDD07 : u8;
|
||||
extern const sdr @ 0xDD0C : u8;
|
||||
extern const icr @ 0xDD0D : u8;
|
||||
extern const cra @ 0xDD0E : u8;
|
||||
extern const crb @ 0xDD0F : u8;
|
||||
}
|
||||
|
||||
namespace kernal {
|
||||
let ioinit = 0xFDA3 as func;
|
||||
let rantam = 0xFD50 as func;
|
||||
let restor = 0xFD15 as func;
|
||||
let cint = 0xFF5B as func;
|
||||
let scnkey = 0xEA87 as func;
|
||||
let chrin = 0xF157 as func : u8 in a;
|
||||
let chrout = 0xF1CA as func(char : u8 in a);
|
||||
let screen = 0xE505 as func : u16 in xy;
|
||||
let plot_save = 0xE50A as func(save : bool in carry) : u16 in xy;
|
||||
let plot_restore = 0xE50A as func(x : u8 in x, y : u8 in y, save : bool in carry);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
* = $7ffe
|
||||
; 2-byte load address for ROM image
|
||||
!word $8000
|
||||
; http://swut.net/c64cart-howto.html
|
||||
; https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
|
||||
!word CartKReset ; cold start vector
|
||||
!word CartWStart ; warm start vector
|
||||
!byte $c3, $c2, $cd, $38, $30 ; "CBM80"
|
||||
CartKReset
|
||||
STX $D016 ; Turn on VIC for PAL / NTSC check
|
||||
JSR $FDA3 ; IOINIT - Init CIA chips
|
||||
JSR $FD50 ; RANTAM - Clear/test system RAM
|
||||
JSR $FD15 ; RESTOR - Init KERNAL RAM vectors
|
||||
JSR $FF5B ; CINT - Init VIC and screen editor
|
||||
CLI ; Re-enable IRQ interrupts
|
||||
CartBReset
|
||||
; init BASIC?
|
||||
!ifdef CART_INIT_BASIC {
|
||||
JSR $E453 ; Init BASIC RAM vectors
|
||||
JSR $E3BF ; Main BASIC RAM Init routine
|
||||
JSR $E422 ; Power-up message / NEW command
|
||||
LDX #$FB
|
||||
TXS ; Reduce stack pointer for BASIC
|
||||
; don't init BASIC, just NOP
|
||||
} else {
|
||||
!fill 12, $ea ; nop
|
||||
}
|
||||
CartWStart
|
||||
; should be * = $x025
|
|
@ -6,7 +6,7 @@ void raster_wait(byte line) {
|
|||
}
|
||||
|
||||
void wait_vblank(void) {
|
||||
raster_wait(255);
|
||||
raster_wait(250);
|
||||
}
|
||||
|
||||
static byte VIC_BANK_PAGE[4] = {
|
||||
|
@ -21,8 +21,20 @@ char* get_screen_memory() {
|
|||
return ((VIC.addr & 0xf0) << 6) + get_vic_bank_start();
|
||||
}
|
||||
|
||||
#ifdef __CC65__
|
||||
char __fastcall__ poll_keyboard() {
|
||||
asm("jmp $f142");
|
||||
return __A__;
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_raster_irq(char scanline) {
|
||||
// deactivate CIA interrupts (keyboard, etc)
|
||||
CIA1.icr = 0x7f;
|
||||
// set raster line for interrupt
|
||||
VIC.ctrl1 &= 0x7f; // clear raster line bit 8
|
||||
VIC.rasterline = scanline;
|
||||
// activate VIC raster interrupts
|
||||
VIC.imr = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <peekpoke.h>
|
||||
#include <string.h>
|
||||
#include <c64.h>
|
||||
|
||||
#ifdef __CC65__
|
||||
#include <conio.h>
|
||||
#include <joystick.h>
|
||||
#endif
|
||||
|
||||
typedef uint8_t byte; // 8-bit unsigned
|
||||
typedef int8_t sbyte; // 8-bit signed
|
||||
|
@ -21,14 +24,43 @@ typedef enum { false, true } bool; // boolean
|
|||
|
||||
///// MACROS /////
|
||||
|
||||
// VIC Control Register 1 Flags
|
||||
#define VIC_CTRL1_RST8 0x80 // Bit 8 of RASTER (read) or raster line interrupt set (write)
|
||||
#define VIC_CTRL1_ECM 0x40 // Extended Color Mode
|
||||
#define VIC_CTRL1_BMM 0x20 // Bitmap Mode
|
||||
#define VIC_CTRL1_DEN 0x10 // Display Enable
|
||||
#define VIC_CTRL1_RSEL 0x08 // Row Select (25 or 24 rows)
|
||||
#define VIC_CTRL1_YSCROLL_MASK 0x07 // Vertical Fine Scrolling
|
||||
|
||||
// VIC Control Register 2 Flags
|
||||
#define VIC_CTRL2_RES 0x20 // Chip reset
|
||||
#define VIC_CTRL2_MCM 0x10 // Multicolor Mode Enable
|
||||
#define VIC_CTRL2_CSEL 0x08 // Column Select (40 or 38 columns)
|
||||
#define VIC_CTRL2_XSCROLL_MASK 0x07 // Horizontal Fine Scrolling
|
||||
|
||||
// VIC Memory Control Register Flags
|
||||
#define VIC_ADDR_VM_MASK 0xf0 // Video Matrix Base Address Mask (character data)
|
||||
#define VIC_ADDR_CB_MASK 0x0e // Character Bank Base Address Mask (screen memory)
|
||||
|
||||
// VIC Interrupt Register Flags
|
||||
#define VIC_IRR_IRQ 0x80 // Interrupt Request
|
||||
#define VIC_IRR_ILP 0x08 // Light Pen Interrupt
|
||||
#define VIC_IRR_IMMC 0x04 // Sprite-Sprite Collision Interrupt
|
||||
#define VIC_IRR_IMBC 0x02 // Sprite-Background Collision Interrupt
|
||||
#define VIC_IRR_IRST 0x01 // Raster Line Interrupt
|
||||
|
||||
// VIC Interrupt Mask Register Flags
|
||||
#define VIC_IMR_ELP 0x08 // Enable Light Pen Interrupt
|
||||
#define VIC_IMR_EMMC 0x04 // Enable Sprite-Sprite Collision Interrupt
|
||||
#define VIC_IMR_EMBC 0x02 // Enable Sprite-Background Collision Interrupt
|
||||
#define VIC_IMR_ERST 0x01 // Enable Raster Interrupt
|
||||
|
||||
// lookup screen address macro
|
||||
#define SCRNADR(base,col,row) ((base)+(col)+(row)*40)
|
||||
|
||||
// default screen base address on startup
|
||||
#define DEFAULT_SCREEN ((void*)0x400)
|
||||
|
||||
// wait until next frame, same as waitvsync()
|
||||
#define wait_vblank waitvsync
|
||||
// is raster line > 255?
|
||||
#define RASTER_HIBIT (VIC.ctrl1 & 0x80)
|
||||
|
||||
|
@ -46,10 +78,10 @@ typedef enum { false, true } bool; // boolean
|
|||
|
||||
// set scrolling registers
|
||||
#define SET_SCROLL_Y(_y) \
|
||||
VIC.ctrl1 = (VIC.ctrl1 & 0xf8) | (_y);
|
||||
VIC.ctrl1 = (VIC.ctrl1 & 0xf8) | (_y & 7);
|
||||
|
||||
#define SET_SCROLL_X(_x) \
|
||||
VIC.ctrl2 = (VIC.ctrl2 & 0xf8) | (_x);
|
||||
VIC.ctrl2 = (VIC.ctrl2 & 0xf8) | (_x & 7);
|
||||
|
||||
|
||||
// enable RAM from 0xa000-0xffff, disable interrupts
|
||||
|
@ -68,13 +100,42 @@ typedef enum { false, true } bool; // boolean
|
|||
// wait until specific raster line
|
||||
void raster_wait(byte line);
|
||||
|
||||
// wait until end of frame
|
||||
void wait_vblank();
|
||||
|
||||
// get current VIC bank start address
|
||||
char* get_vic_bank_start();
|
||||
|
||||
// get current screen memory address
|
||||
char* get_screen_memory();
|
||||
|
||||
// read joystick fast
|
||||
#define READ_STICK(index) ~PEEK(0xdc01-(index))
|
||||
|
||||
#define STICK_UP(joy) ((joy & 0x1) != 0)
|
||||
#define STICK_DOWN(joy) ((joy & 0x2) != 0)
|
||||
#define STICK_LEFT(joy) ((joy & 0x4) != 0)
|
||||
#define STICK_RIGHT(joy) ((joy & 0x8) != 0)
|
||||
#define STICK_BUTTON(joy) ((joy & 0x10) != 0)
|
||||
#define STICK_MOVED(joy) ((joy & 0x1f) != 0)
|
||||
|
||||
#ifdef __CC65__
|
||||
// return key in buffer, or 0 if none (BIOS call)
|
||||
char __fastcall__ poll_keyboard();
|
||||
#endif
|
||||
|
||||
#ifndef __CC65__
|
||||
inline void clrscr() {
|
||||
__asm__ volatile ("jsr $E544" : : : "a","x","y"); // regs clobbered
|
||||
}
|
||||
inline void waitvsync() {
|
||||
raster_wait(255);
|
||||
}
|
||||
#endif
|
||||
|
||||
// for use with set_irq()
|
||||
// sets up the VIC to send raster interrupts
|
||||
// and disables CIA interrupts
|
||||
void set_raster_irq(char scanline);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
!src "cartheader.acme"
|
||||
|
||||
!address {
|
||||
Temp = $02
|
||||
}
|
||||
|
||||
Start:
|
||||
sei ; turn off interrupts
|
||||
ldy #0
|
||||
Loop:
|
||||
lda Message,y ; load message byte
|
||||
beq EOM ; 0 = end of string
|
||||
clc
|
||||
adc #$40
|
||||
sta $400+41,y ; store to screen
|
||||
iny
|
||||
bne Loop ; next character
|
||||
EOM:
|
||||
|
||||
Wait1:
|
||||
lda $d011
|
||||
bmi Wait1 ; wait for line < 256
|
||||
Wait2:
|
||||
lda $d012 ; get current scanline
|
||||
Wait3:
|
||||
cmp $d012
|
||||
beq Wait3 ; wait for scanline to change
|
||||
lsr ; divide by 2
|
||||
lsr ; divide by 2
|
||||
clc
|
||||
adc Temp ; add to frame counter
|
||||
sta $d020 ; set border color
|
||||
lda $d011 ; get status bits
|
||||
bpl Wait2 ; repeat until line >= 256
|
||||
sty $d020 ; reset border color
|
||||
dec Temp ; change frame counter
|
||||
jmp Wait1 ; endless loop
|
||||
|
||||
Message:
|
||||
!scr "HELLO WORLD", 0
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
|
||||
|
||||
import "c64.wiz";
|
||||
|
||||
bank zeropage @ 0x02 : [vardata; 254];
|
||||
bank stackpage @ 0x100 : [vardata; 256];
|
||||
bank textscrn @ 0x400 : [vardata; 0x400];
|
||||
bank ram @ 0x2000 : [vardata; 0x7800];
|
||||
bank prghdr @ 0x7ff : [prgdata; 0x2];
|
||||
bank prg @ 0x801 : [varinitdata; 0x7000];
|
||||
|
||||
in textscrn {
|
||||
var scrn: [u8; 40*25];
|
||||
var _unused: [u8; 16];
|
||||
var spriteptr: [u8; 8];
|
||||
}
|
||||
|
||||
extern var vicbank @ 0x0000 : VICBank;
|
||||
|
||||
// PRG file header
|
||||
in prghdr {
|
||||
const prgstart : u16 = 0x801;
|
||||
}
|
||||
|
||||
// BASIC header
|
||||
in prg {
|
||||
namespace prgheader {
|
||||
const nextline = &BASIC_END;
|
||||
const linenum : u16 = 10;
|
||||
const sysstmt = "\x9e 2062\0";
|
||||
BASIC_END:
|
||||
const hdrend : u16 = 0;
|
||||
}
|
||||
PRG_START:
|
||||
/*
|
||||
c64.kernal.ioinit();
|
||||
c64.kernal.rantam();
|
||||
c64.kernal.restor();
|
||||
c64.kernal.cint();
|
||||
*/
|
||||
c64.vic.bordercolor = a = c64.color.ORANGE;
|
||||
c64.kernal.chrout('A');
|
||||
for x in 0..250 {
|
||||
// scrn[x] = a = x;
|
||||
// (&scrn[40*8])[x] = a = x;
|
||||
// (0x600 as *u8)[x] = a = x;
|
||||
(&scrn[40*12])[x] = a = message[x] + 0xc0;
|
||||
}
|
||||
for x in 0..255 {
|
||||
a = message[x];
|
||||
break if zero;
|
||||
a += 0xc0;
|
||||
(&scrn[40*20])[x] = a;
|
||||
}
|
||||
upandaway();
|
||||
return;
|
||||
|
||||
const message = "HELLO WORLD!\0";
|
||||
|
||||
const SPRITE : [u8; 3*21] = [
|
||||
/*{w:24,h:21,bpp:1,brev:1}*/
|
||||
0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xE0,
|
||||
0x03,0xE7,0xE0,0x07,0xD9,0xF0,0x07,0xDF,0xF0,
|
||||
0x07,0xD9,0xF0,0x03,0xE7,0xE0,0x03,0xFF,0xE0,
|
||||
0x03,0xFF,0xE0,0x02,0xFF,0xA0,0x01,0x7F,0x40,
|
||||
0x01,0x3E,0x40,0x00,0x9C,0x80,0x00,0x9C,0x80,
|
||||
0x00,0x49,0x00,0x00,0x49,0x00,0x00,0x3E,0x00,
|
||||
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
|
||||
];
|
||||
|
||||
const yValues : [u8] = [
|
||||
32, 35, 38, 41, 44, 47, 49, 52,
|
||||
54, 56, 58, 60, 61, 62, 63, 63,
|
||||
64, 63, 63, 62, 61, 60, 58, 56,
|
||||
54, 52, 49, 47, 44, 41, 38, 35,
|
||||
32, 28, 25, 22, 19, 16, 14, 11,
|
||||
9, 7, 5, 3, 2, 1, 0, 0,
|
||||
0, 0, 0, 1, 2, 3, 5, 7,
|
||||
9, 11, 14, 16, 19, 22, 25, 28
|
||||
];
|
||||
|
||||
const pwr2 : [u8] = [
|
||||
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
|
||||
];
|
||||
|
||||
in zeropage {
|
||||
var b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 : u8;
|
||||
var w0 @ &b0, w2 @ &b2, w4 @ &b4, w6 @ &b6, w8 @ &b8, w10 @ &b10 : u16;
|
||||
var ptr0 @ &b0, ptr2 @ &b2, ptr4 @ &b4, ptr6 @ &b6, ptr8 @ &b8, ptr10 @ &b10 : *u8;
|
||||
}
|
||||
|
||||
inline func rasterWait(line : u8 in a) {
|
||||
while (c64.vic.rasterline < line) { }
|
||||
}
|
||||
|
||||
func upandaway() {
|
||||
//unsigned char n, t;
|
||||
//int rx, x;
|
||||
//char sx, msb;
|
||||
var xp : u16 in w0;
|
||||
var rx : u16 in w2;
|
||||
var msb : u8 in b4;
|
||||
let sprdata = &vicbank.spritedata[13] as *u8;
|
||||
|
||||
c64.vic.bgcolor[0] = a = 3;
|
||||
nointerrupt = true; // clear interrupts to avoid glitching
|
||||
|
||||
for y in 0..(sizeof(typeof(SPRITE)) - 1) {
|
||||
sprdata[y] = a = SPRITE[y];
|
||||
//POKE(832 + n, sprite[n]);
|
||||
}
|
||||
c64.vic.sprite.enable = a = 255;
|
||||
for x in 0..7 {
|
||||
spriteptr[x] = a = 13;
|
||||
y = a = x<<1;
|
||||
c64.vic.sprite.coord[y] = a = 50;
|
||||
y ++;
|
||||
c64.vic.sprite.coord[y] = a = 50;
|
||||
//POKE(2040 + t, 13); // Set sprite x data from 13th block for all sprites
|
||||
}
|
||||
do {
|
||||
<:xp = a = 0;
|
||||
>:xp = a = 0;
|
||||
//while (xp < 550) {
|
||||
while (true) {
|
||||
<:xp = a = <:xp + 1;
|
||||
>:xp = a = >:xp +# 0;
|
||||
msb = a = 0; // MSB of X coordinates
|
||||
// Wait until raster hits position 250 before drawing upper sprites
|
||||
rasterWait(250);
|
||||
// Set border color, which indicates the raster position
|
||||
c64.vic.bordercolor = a = 1;
|
||||
<:rx = a = <:xp;
|
||||
>:rx = a = >:xp;
|
||||
for x in 0..7 {
|
||||
<:rx = a = <:rx - 24;
|
||||
>:rx = a = >:rx -# 0;
|
||||
//if (rx >= 0 && rx < 366)
|
||||
if (true) {
|
||||
// if (rx > 255)
|
||||
a = >:rx;
|
||||
if (!zero) {
|
||||
// Set MSB of x coordinate for sprite if x position > 255
|
||||
a = msb;
|
||||
a |= pwr2[x];
|
||||
msb = a;
|
||||
}
|
||||
y = a = x<<1;
|
||||
c64.vic.sprite.coord[y] = a = <:rx;
|
||||
// Y position is an indirect Sinus function of X, using array
|
||||
// index for retrieving the Y value
|
||||
y = a = <:rx & 63;
|
||||
a = yValues[y] + 40;
|
||||
push(a);
|
||||
y = a = (x<<1) + 1;
|
||||
a = pop();
|
||||
c64.vic.sprite.coord[y] = a;
|
||||
} else {
|
||||
c64.vic.sprite.pos[y].x = 0;
|
||||
}
|
||||
}
|
||||
c64.vic.sprite.hi_x = a = msb; // Set MSB of x coordinate
|
||||
// Wait until raster hits position 135 before drawing lower sprites
|
||||
rasterWait(135);
|
||||
c64.vic.bordercolor = a = 2; // Set border color
|
||||
for x in 0..7 {
|
||||
// Add 128 to current sprite Y position
|
||||
y = a = (x<<1) + 1;
|
||||
c64.vic.sprite.coord[y] = a = c64.vic.sprite.coord[y]+128;
|
||||
}
|
||||
cmp(a = >:xp, >:550);
|
||||
if (zero) {
|
||||
cmp(a = <:xp, <:550);
|
||||
break if zero;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <c64.h>
|
||||
#include <cbm_petscii_charmap.h>
|
||||
|
||||
void main(void) {
|
||||
clrscr(); // clear screen
|
||||
puts("Hello World!\n"); // write message at cursor
|
||||
chline(12); // horizontal line
|
||||
bordercolor(COLOR_LIGHTBLUE); // set color to blue
|
||||
bgcolor(COLOR_GREEN); // set background color
|
||||
textcolor(COLOR_YELLOW); // set text color
|
||||
puts("\nThis text is yellow!\n"); // write message
|
||||
cgetc(); // wait for input
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,294 @@
|
|||
|
||||
|
||||
; Generated by CharPad 2.8, Subchrist Software, 2021.
|
||||
; Assemble with 64TASS or similar.
|
||||
|
||||
|
||||
; Character display mode : Multi-colour.
|
||||
|
||||
; Character colouring method : Per-Tile.
|
||||
|
||||
|
||||
; Colour values...
|
||||
|
||||
COLR_SCREEN = 11
|
||||
COLR_CHAR_DEF = 13
|
||||
COLR_CHAR_MC1 = 0
|
||||
COLR_CHAR_MC2 = 1
|
||||
|
||||
|
||||
; Quantities and dimensions...
|
||||
|
||||
CHAR_COUNT = 256
|
||||
TILE_COUNT = 16
|
||||
TILE_WID = 4
|
||||
TILE_HEI = 4
|
||||
MAP_WID = 16
|
||||
MAP_HEI = 16
|
||||
MAP_WID_CHRS = 64
|
||||
MAP_HEI_CHRS = 64
|
||||
MAP_WID_PXLS = 512
|
||||
MAP_HEI_PXLS = 512
|
||||
|
||||
|
||||
; Data block sizes (in bytes)...
|
||||
|
||||
SZ_CHARSET_DATA = 2048 ; ($800)
|
||||
SZ_CHARSET_ATTRIB_DATA = 256 ; ($100)
|
||||
SZ_TILESET_DATA = 256 ; ($100)
|
||||
SZ_TILESET_ATTRIB_DATA = 16 ; ($10)
|
||||
SZ_MAP_DATA = 256 ; ($100)
|
||||
|
||||
|
||||
|
||||
|
||||
; * INSERT EXAMPLE PROGRAM HERE! * (Or just include this file in your project).
|
||||
|
||||
.global _charset_data
|
||||
.global _chartileset_data
|
||||
.global _charset_attrib_data
|
||||
.global _chartileset_colour_data
|
||||
.global _map_row_pointers
|
||||
.global _map_data
|
||||
|
||||
|
||||
; CHARSET IMAGE DATA...
|
||||
; 256 images, 8 bytes per image, total size is 2048 ($800) bytes.
|
||||
|
||||
_charset_data:
|
||||
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$C0,$91,$95,$91,$80,$C0,$F2,$F5
|
||||
.byte $03,$11,$55,$11,$01,$03,$AF,$4F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
|
||||
.byte $AA,$AA,$88,$22,$CC,$33,$DD,$55,$AA,$AA,$88,$22,$CC,$33,$DD,$55
|
||||
.byte $AA,$AA,$88,$22,$CC,$33,$DD,$55,$AA,$AA,$88,$22,$CC,$33,$DD,$55
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $AA,$BB,$FE,$FF,$FF,$CF,$33,$55,$AA,$BB,$FE,$FF,$FF,$CF,$33,$55
|
||||
.byte $AA,$BB,$FE,$FF,$FF,$CF,$33,$55,$AA,$BB,$FE,$FF,$FF,$CF,$33,$55
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $AA,$AF,$B3,$AC,$B0,$AC,$B0,$AC,$AA,$FD,$35,$11,$05,$11,$05,$11
|
||||
.byte $AA,$BF,$B3,$BC,$B0,$BC,$B0,$BC,$AA,$FD,$35,$11,$05,$11,$05,$11
|
||||
.byte $B0,$AC,$B0,$AC,$B0,$AD,$B4,$95,$05,$11,$05,$11,$05,$11,$45,$55
|
||||
.byte $B0,$BC,$B0,$BC,$B0,$BD,$B4,$95,$05,$11,$05,$11,$05,$11,$45,$55
|
||||
.byte $AA,$BF,$B3,$BC,$B0,$BC,$B0,$BC,$AA,$FD,$35,$11,$05,$11,$05,$11
|
||||
.byte $AA,$BF,$B3,$BC,$B0,$BC,$B0,$BC,$AA,$FD,$35,$11,$05,$11,$05,$11
|
||||
.byte $B0,$BC,$B0,$BC,$B0,$BD,$B4,$95,$05,$11,$05,$11,$05,$11,$45,$55
|
||||
.byte $B0,$BC,$B0,$BC,$B0,$BD,$B4,$95,$05,$11,$05,$11,$05,$11,$45,$55
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $AA,$BB,$FE,$FF,$FF,$CF,$33,$55,$AA,$BB,$FE,$FF,$FF,$CF,$33,$55
|
||||
.byte $AA,$BB,$FE,$FF,$FF,$CF,$33,$55,$AA,$BB,$FE,$FF,$FF,$CF,$33,$55
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $02,$02,$02,$02,$02,$02,$02,$02,$D0,$D0,$D0,$EA,$FF,$D5,$D0,$D0
|
||||
.byte $0B,$0B,$0B,$AB,$FF,$5B,$0B,$0B,$40,$40,$40,$40,$40,$40,$40,$40
|
||||
.byte $AA,$00,$B3,$EF,$BF,$EF,$9D,$55,$AA,$00,$33,$FF,$FF,$FF,$DD,$55
|
||||
.byte $AA,$00,$33,$FF,$FF,$FF,$DD,$55,$AA,$00,$31,$FF,$FD,$F7,$DD,$55
|
||||
.byte $EF,$BF,$EF,$BB,$EF,$BF,$EF,$BB,$DF,$FD,$F4,$DD,$FF,$FD,$F4,$DD
|
||||
.byte $55,$15,$45,$15,$51,$15,$45,$15,$55,$55,$55,$55,$55,$55,$55,$55
|
||||
.byte $EF,$BF,$EF,$BB,$EF,$BF,$EF,$BB,$DF,$FD,$F4,$DD,$FF,$FD,$F4,$DD
|
||||
.byte $55,$15,$45,$15,$51,$15,$45,$15,$55,$55,$55,$55,$55,$55,$55,$55
|
||||
.byte $EF,$BF,$EF,$BB,$EF,$BF,$EF,$BB,$DF,$FD,$F4,$DD,$FF,$FD,$F4,$D1
|
||||
.byte $55,$15,$45,$15,$51,$15,$45,$15,$55,$55,$55,$55,$55,$55,$55,$55
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$02,$02,$02,$0B,$0B,$2F,$BF,$00,$00,$00,$00,$80,$80,$E0,$F8
|
||||
.byte $00,$02,$02,$02,$0B,$0B,$2F,$BF,$00,$00,$00,$00,$80,$80,$E0,$F8
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$FF,$FF,$FE,$FE,$FC,$FD,$F9,$F9
|
||||
.byte $FF,$FF,$7F,$7F,$3F,$BF,$9F,$9F,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$F1,$F1,$E0,$E1,$C1,$C0,$FF,$FF
|
||||
.byte $8F,$8F,$07,$87,$83,$03,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $AA,$25,$0B,$02,$00,$02,$09,$24,$AA,$56,$F9,$E7,$9F,$6F,$1B,$06
|
||||
.byte $AA,$95,$6F,$DB,$F6,$F9,$E4,$90,$AA,$58,$E0,$80,$00,$80,$60,$18
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$02,$02,$0B,$0B,$2F,$2F,$BF,$BF
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $02,$02,$0B,$0B,$2F,$2F,$BF,$BF,$FD,$FD,$F4,$F4,$D0,$D0,$40,$40
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$02,$02,$0B,$0B,$2F,$2F,$BF,$BF
|
||||
.byte $FD,$FD,$F4,$F4,$D0,$D0,$40,$40,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $02,$02,$0B,$0B,$2F,$2F,$BF,$95,$FD,$FD,$F4,$F4,$D0,$D0,$40,$40
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $80,$80,$E0,$E0,$F8,$F8,$FE,$FE,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $7F,$7F,$1F,$1F,$07,$07,$01,$01,$80,$80,$E0,$E0,$F8,$F8,$FE,$FE
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$7F,$7F,$1F,$1F,$07,$07,$01,$01
|
||||
.byte $80,$80,$E0,$E0,$F8,$F8,$FE,$FE,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $7F,$7F,$1F,$1F,$07,$07,$01,$01,$80,$80,$E0,$E0,$F8,$F8,$FE,$56
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$01,$03,$01,$01,$03,$03,$07,$0F,$5E,$FA,$EA
|
||||
.byte $00,$00,$00,$40,$C0,$D5,$BF,$AD,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$7A,$1E,$0F,$3D,$34,$D0,$40,$00
|
||||
.byte $B4,$D0,$C0,$F0,$70,$1C,$04,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$80,$E0,$FA,$D5,$40,$00,$00,$00,$00,$00,$AA,$55,$00,$00,$00
|
||||
.byte $00,$00,$00,$AA,$55,$00,$00,$00,$00,$02,$0B,$AF,$57,$01,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
|
||||
|
||||
; CHARSET IMAGE ATTRIBUTE DATA...
|
||||
; 256 attributes, 1 attribute per image, 8 bits per attribute, total size is 256 ($100) bytes.
|
||||
; nb. Upper nybbles = material, lower nybbles = colour.
|
||||
|
||||
_charset_attrib_data:
|
||||
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
.byte $03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03
|
||||
|
||||
|
||||
; CHARTILESET DATA...
|
||||
; 16 tiles, 4x4 (16) cells per tile, 8 bits per cell, total size is 256 ($100) bytes.
|
||||
|
||||
_chartileset_data:
|
||||
|
||||
.byte $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F
|
||||
.byte $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F
|
||||
.byte $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2A,$2B,$2C,$2D,$2E,$2F
|
||||
.byte $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F
|
||||
.byte $40,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4A,$4B,$4C,$4D,$4E,$4F
|
||||
.byte $50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5A,$5B,$5C,$5D,$5E,$5F
|
||||
.byte $60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6A,$6B,$6C,$6D,$6E,$6F
|
||||
.byte $70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7A,$7B,$7C,$7D,$7E,$7F
|
||||
.byte $80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F
|
||||
.byte $90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F
|
||||
.byte $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7,$A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF
|
||||
.byte $B0,$B1,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC,$BD,$BE,$BF
|
||||
.byte $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF
|
||||
.byte $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7,$D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF
|
||||
.byte $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7,$E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF
|
||||
.byte $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF
|
||||
|
||||
|
||||
; CHARTILESET COLOUR DATA...
|
||||
; 16 colours, 1 colour per tile, 8 bits per colour, total size is 16 ($10) bytes.
|
||||
; nb. Lower nybbles = colour, upper nybbles are unused.
|
||||
|
||||
_chartileset_colour_data:
|
||||
|
||||
.byte $03,$03,$03,$0B,$0D,$0B,$0D,$0D,$0D,$0A,$06,$0C,$0C,$0C,$0F,$0D
|
||||
|
||||
|
||||
; CHARTILESET TAG DATA...
|
||||
; 16 tags, 1 tag per tile, 8 bits per tag, total size is 16 ($10) bytes.
|
||||
|
||||
_chartileset_tag_data:
|
||||
|
||||
.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
|
||||
|
||||
|
||||
; MAP DATA...
|
||||
; 16x16 (256) cells, 8 bits per cell, total size is 256 ($100) bytes.
|
||||
|
||||
_map_data:
|
||||
map_data:
|
||||
|
||||
.byte $01,$01,$02,$01,$01,$01,$01,$01,$02,$01,$01,$01,$01,$01,$01,$01
|
||||
.byte $05,$03,$03,$03,$06,$03,$05,$03,$03,$03,$03,$03,$03,$03,$03,$05
|
||||
.byte $05,$00,$00,$04,$06,$06,$06,$09,$08,$00,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$0F,$04,$04,$07,$07,$07,$04,$08,$0F,$00,$0B,$00,$0C,$05,$05
|
||||
.byte $05,$00,$00,$05,$05,$05,$05,$05,$05,$00,$00,$05,$05,$00,$00,$05
|
||||
.byte $05,$0E,$0A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$05,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$00,$00,$04,$00,$04,$00,$04,$04,$07,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$0E,$00,$00,$00,$00,$00,$00,$00,$06,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$05,$00,$07,$04,$04,$0F,$0F,$0F,$07,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$00,$0A,$06,$00,$00,$00,$00,$00,$06,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$00,$09,$04,$04,$04,$07,$00,$00,$06,$00,$00,$00,$00,$00,$05
|
||||
.byte $05,$00,$05,$00,$00,$00,$06,$00,$00,$05,$0D,$00,$00,$00,$00,$05
|
||||
.byte $05,$00,$00,$00,$00,$05,$05,$00,$00,$00,$00,$05,$0D,$00,$00,$05
|
||||
.byte $05,$00,$00,$00,$05,$05,$00,$00,$00,$00,$00,$00,$00,$05,$00,$05
|
||||
.byte $05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05,$05
|
||||
|
||||
.global _map_row_pointers
|
||||
_map_row_pointers:
|
||||
.word map_data + 0*16
|
||||
.word map_data + 1*16
|
||||
.word map_data + 2*16
|
||||
.word map_data + 3*16
|
||||
.word map_data + 4*16
|
||||
.word map_data + 5*16
|
||||
.word map_data + 6*16
|
||||
.word map_data + 7*16
|
||||
.word map_data + 8*16
|
||||
.word map_data + 9*16
|
||||
.word map_data + 10*16
|
||||
.word map_data + 11*16
|
||||
.word map_data + 12*16
|
||||
.word map_data + 13*16
|
||||
.word map_data + 14*16
|
||||
.word map_data + 15*16
|
|
@ -1,9 +1,12 @@
|
|||
|
||||
VIC_BASE = $0
|
||||
VIC_SCRN_BASE = VIC_BASE + $400
|
||||
|
||||
MAX_MSPRITES = 28
|
||||
|
||||
MIN_Y_SPACING = 35
|
||||
|
||||
DEBUG = 1
|
||||
DEBUG = 0
|
||||
|
||||
.code
|
||||
|
||||
|
@ -31,7 +34,7 @@ _msprite_render_section:
|
|||
adc #MIN_Y_SPACING
|
||||
sta bailout_line
|
||||
@loop:
|
||||
.ifdef DEBUG
|
||||
.if DEBUG
|
||||
inc $d020
|
||||
.endif
|
||||
lda $d012
|
||||
|
@ -66,7 +69,7 @@ _msprite_render_section:
|
|||
sta $d027,x
|
||||
; POKE(0x7f8+j, msprite_shape[i]);
|
||||
lda _msprite_shape,y
|
||||
sta $07f8,x
|
||||
sta VIC_SCRN_BASE + $03f8,x
|
||||
; set hi X bit
|
||||
lda _msprite_x_hi,y
|
||||
lsr
|
||||
|
@ -83,7 +86,7 @@ _msprite_render_section:
|
|||
sta j ; next h/w sprite
|
||||
jmp @loop
|
||||
@loopexit:
|
||||
.ifdef DEBUG
|
||||
.if DEBUG
|
||||
lda #0
|
||||
sta $d020
|
||||
.endif
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_MSPRITES 28
|
||||
|
||||
extern byte msprite_order[MAX_MSPRITES];
|
||||
extern byte msprite_x_lo[MAX_MSPRITES];
|
||||
extern byte msprite_x_hi[MAX_MSPRITES];
|
||||
extern byte msprite_y[MAX_MSPRITES];
|
||||
extern byte msprite_color[MAX_MSPRITES];
|
||||
extern byte msprite_shape[MAX_MSPRITES];
|
||||
//extern byte msprite_flags[MAX_MSPRITES];
|
||||
extern byte msprite_xvel_lo[MAX_MSPRITES];
|
||||
extern byte msprite_xvel_hi[MAX_MSPRITES];
|
||||
extern byte msprite_yvel_lo[MAX_MSPRITES];
|
||||
extern byte msprite_yvel_hi[MAX_MSPRITES];
|
||||
|
||||
extern byte msprite_last_y;
|
||||
|
||||
void __fastcall__ msprite_render_init();
|
||||
void __fastcall__ msprite_render_section();
|
||||
void __fastcall__ msprite_sort();
|
||||
void __fastcall__ msprite_add_velocity(byte numsprites);
|
||||
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,300 @@
|
|||
/*****************************************************************************\
|
||||
** plasma test program for cc65. **
|
||||
** **
|
||||
** (w)2001 by groepaz **
|
||||
** **
|
||||
** Cleanup and porting by Ullrich von Bassewitz. **
|
||||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <conio.h>
|
||||
#include <cc65.h>
|
||||
|
||||
|
||||
|
||||
#if defined(__C64__) || defined(__C128__)
|
||||
# define SCREEN1 0xE000
|
||||
# define SCREEN2 0xE400
|
||||
# define CHARSET 0xE800
|
||||
# define outb(addr,val) (*(addr)) = (val)
|
||||
# define inb(addr) (*(addr))
|
||||
#elif defined(__CBM510__)
|
||||
# define SCREEN1 0xF000
|
||||
# define SCREEN2 0xF400
|
||||
# define CHARSET 0xE000
|
||||
# define outb(addr,val) pokebsys ((unsigned)(addr), val)
|
||||
# define inb(addr) peekbsys ((unsigned)(addr))
|
||||
#elif defined(__PLUS4__)
|
||||
# define SCREEN1 0x6400
|
||||
# define SCREEN2 0x6C00
|
||||
# define CHARSET 0x7000
|
||||
# define outb(addr,val) (*(addr)) = (val)
|
||||
# define inb(addr) (*(addr))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Values for the VIC address register to switch between the two pages */
|
||||
#if defined(__PLUS4__)
|
||||
#define PAGE1 ((SCREEN1 >> 8) & 0xF8)
|
||||
#define PAGE2 ((SCREEN2 >> 8) & 0xF8)
|
||||
#define CHARADR ((CHARSET >> 8) & 0xFC)
|
||||
#else
|
||||
#define PAGE1 ((SCREEN1 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E)
|
||||
#define PAGE2 ((SCREEN2 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Use static local variables for speed */
|
||||
#pragma static-locals (1);
|
||||
|
||||
|
||||
static const unsigned char sinustable[0x100] = {
|
||||
0x80, 0x7d, 0x7a, 0x77, 0x74, 0x70, 0x6d, 0x6a,
|
||||
0x67, 0x64, 0x61, 0x5e, 0x5b, 0x58, 0x55, 0x52,
|
||||
0x4f, 0x4d, 0x4a, 0x47, 0x44, 0x41, 0x3f, 0x3c,
|
||||
0x39, 0x37, 0x34, 0x32, 0x2f, 0x2d, 0x2b, 0x28,
|
||||
0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1a, 0x18,
|
||||
0x16, 0x15, 0x13, 0x11, 0x10, 0x0f, 0x0d, 0x0c,
|
||||
0x0b, 0x0a, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04,
|
||||
0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03,
|
||||
0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0a,
|
||||
0x0b, 0x0c, 0x0d, 0x0f, 0x10, 0x11, 0x13, 0x15,
|
||||
0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24,
|
||||
0x26, 0x28, 0x2b, 0x2d, 0x2f, 0x32, 0x34, 0x37,
|
||||
0x39, 0x3c, 0x3f, 0x41, 0x44, 0x47, 0x4a, 0x4d,
|
||||
0x4f, 0x52, 0x55, 0x58, 0x5b, 0x5e, 0x61, 0x64,
|
||||
0x67, 0x6a, 0x6d, 0x70, 0x74, 0x77, 0x7a, 0x7d,
|
||||
0x80, 0x83, 0x86, 0x89, 0x8c, 0x90, 0x93, 0x96,
|
||||
0x99, 0x9c, 0x9f, 0xa2, 0xa5, 0xa8, 0xab, 0xae,
|
||||
0xb1, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc1, 0xc4,
|
||||
0xc7, 0xc9, 0xcc, 0xce, 0xd1, 0xd3, 0xd5, 0xd8,
|
||||
0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8,
|
||||
0xea, 0xeb, 0xed, 0xef, 0xf0, 0xf1, 0xf3, 0xf4,
|
||||
0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfa, 0xfb, 0xfc,
|
||||
0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd,
|
||||
0xfd, 0xfc, 0xfb, 0xfa, 0xfa, 0xf9, 0xf8, 0xf6,
|
||||
0xf5, 0xf4, 0xf3, 0xf1, 0xf0, 0xef, 0xed, 0xeb,
|
||||
0xea, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, 0xde, 0xdc,
|
||||
0xda, 0xd8, 0xd5, 0xd3, 0xd1, 0xce, 0xcc, 0xc9,
|
||||
0xc7, 0xc4, 0xc1, 0xbf, 0xbc, 0xb9, 0xb6, 0xb3,
|
||||
0xb1, 0xae, 0xab, 0xa8, 0xa5, 0xa2, 0x9f, 0x9c,
|
||||
0x99, 0x96, 0x93, 0x90, 0x8c, 0x89, 0x86, 0x83
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void doplasma (register unsigned char* scrn)
|
||||
{
|
||||
unsigned char xbuf[40];
|
||||
unsigned char ybuf[25];
|
||||
unsigned char c1a,c1b;
|
||||
unsigned char c2a,c2b;
|
||||
unsigned char c1A,c1B;
|
||||
unsigned char c2A,c2B;
|
||||
register unsigned char i, ii;
|
||||
|
||||
c1a = c1A;
|
||||
c1b = c1B;
|
||||
for (ii = 0; ii < 25; ++ii) {
|
||||
ybuf[ii] = (sinustable[c1a] + sinustable[c1b]);
|
||||
c1a += 4;
|
||||
c1b += 9;
|
||||
}
|
||||
c1A += 3;
|
||||
c1B -= 5;
|
||||
c2a = c2A;
|
||||
c2b = c2B;
|
||||
for (i = 0; i < 40; ++i) {
|
||||
xbuf[i] = (sinustable[c2a] + sinustable[c2b]);
|
||||
c2a += 3;
|
||||
c2b += 7;
|
||||
}
|
||||
c2A += 2;
|
||||
c2B -= 3;
|
||||
for (ii = 0; ii < 25; ++ii) {
|
||||
/* Unrolling the following loop will give a speed increase of
|
||||
** nearly 100% (~24fps), but it will also increase the code
|
||||
** size a lot.
|
||||
*/
|
||||
for (i = 0; i < 40; ++i, ++scrn) {
|
||||
*scrn = (xbuf[i] + ybuf[ii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void makechar (void)
|
||||
{
|
||||
static const unsigned char bittab[8] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
|
||||
};
|
||||
unsigned char i, ii, b, s;
|
||||
unsigned c;
|
||||
|
||||
gotoxy (0, 1);
|
||||
for (c = 0; c < 0x100; ++c) {
|
||||
s = sinustable[c];
|
||||
for (i = 0; i < 8; ++i){
|
||||
b = 0;
|
||||
for (ii = 0; ii < 8; ++ii) {
|
||||
if ((rand() & 0xFFu) > s) {
|
||||
b |= bittab[ii];
|
||||
}
|
||||
}
|
||||
((unsigned char*)CHARSET) [(c*8) + i] = b;
|
||||
}
|
||||
if ((c & 0x07) == 0) {
|
||||
cputc ('.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (void)
|
||||
{
|
||||
unsigned char border;
|
||||
unsigned char background;
|
||||
unsigned char text;
|
||||
unsigned char v;
|
||||
clock_t t;
|
||||
unsigned long f = 0;
|
||||
unsigned long sec;
|
||||
unsigned sec10;
|
||||
unsigned long fps;
|
||||
unsigned fps10;
|
||||
|
||||
|
||||
#if defined(__C64__)
|
||||
unsigned char block;
|
||||
#endif
|
||||
#if defined(__C128__)
|
||||
unsigned char block;
|
||||
unsigned char initflag;
|
||||
unsigned char graphflag;
|
||||
#endif
|
||||
#if defined(__PLUS4__)
|
||||
unsigned int i;
|
||||
unsigned char v2;
|
||||
#endif
|
||||
|
||||
clrscr ();
|
||||
cprintf ("Making charset, mompls");
|
||||
makechar();
|
||||
|
||||
/* Set the border and background colors */
|
||||
border = bordercolor (COLOR_BLUE);
|
||||
background = bgcolor (COLOR_BLUE);
|
||||
text = textcolor (COLOR_BLACK);
|
||||
clrscr ();
|
||||
|
||||
#if defined(__C64__) || defined(__C128__)
|
||||
/* Move the VIC 16K block */
|
||||
block = inb (&CIA2.pra);
|
||||
outb (&CIA2.pra, (block & 0xFC) | ((SCREEN1 >> 14) ^ 0x03));
|
||||
#endif
|
||||
#if defined(__C128__)
|
||||
/* Save and change some flags, so that kernal/basic interrupt handler will
|
||||
** not interfere with our routine.
|
||||
*/
|
||||
initflag = *(unsigned char*) 0xA04;
|
||||
*(unsigned char*) 0xA04 &= 0xFE;
|
||||
graphflag = *(unsigned char*) 0xD8;
|
||||
*(unsigned char*) 0xD8 = 0xFF;
|
||||
#endif
|
||||
|
||||
/* Remember the VIC address register */
|
||||
#if defined(__PLUS4__)
|
||||
v = inb (&TED.char_addr);
|
||||
v2 = inb (&TED.video_addr);
|
||||
#else
|
||||
v = inb (&VIC.addr);
|
||||
#endif
|
||||
|
||||
#if defined(__PLUS4__)
|
||||
for (i=0;i<1000;i++) {
|
||||
((unsigned char *) (SCREEN1-0x0400))[i] = 0;
|
||||
((unsigned char *) (SCREEN2-0x0400))[i] = 0;
|
||||
}
|
||||
outb (&TED.char_addr, CHARADR);
|
||||
#endif
|
||||
|
||||
/* Run the demo until a key was hit */
|
||||
t = clock ();
|
||||
while (!kbhit()) {
|
||||
/* Build page 1, then make it visible */
|
||||
doplasma ((unsigned char*)SCREEN1);
|
||||
#if defined(__PLUS4__)
|
||||
outb (&TED.video_addr, PAGE1);
|
||||
#else
|
||||
outb (&VIC.addr, PAGE1);
|
||||
#endif
|
||||
|
||||
/* Build page 2, then make it visible */
|
||||
doplasma ((unsigned char*)SCREEN2);
|
||||
#if defined(__PLUS4__)
|
||||
outb (&TED.video_addr, PAGE2);
|
||||
#else
|
||||
outb (&VIC.addr, PAGE2);
|
||||
#endif
|
||||
|
||||
/* Count frames */
|
||||
f += 2;
|
||||
}
|
||||
t = clock() - t;
|
||||
|
||||
/* Switch back the VIC screen */
|
||||
#if defined(__PLUS4__)
|
||||
outb (&TED.video_addr, v2);
|
||||
outb (&TED.char_addr, v);
|
||||
#else
|
||||
outb (&VIC.addr, v);
|
||||
#endif
|
||||
|
||||
#if defined(__C64__) || defined(__C128__)
|
||||
/* Move back the VIC 16K block */
|
||||
outb (&CIA2.pra, block);
|
||||
#endif
|
||||
#if defined(__C128__)
|
||||
/* Restore the flags */
|
||||
*(unsigned char*) 0xA04 = initflag;
|
||||
*(unsigned char*) 0xD8 = graphflag;
|
||||
#endif
|
||||
|
||||
/* Fetch the character from the keyboard buffer and discard it */
|
||||
(void) cgetc();
|
||||
|
||||
/* Reset screen colors */
|
||||
bordercolor (border);
|
||||
bgcolor (background);
|
||||
textcolor (text);
|
||||
clrscr ();
|
||||
|
||||
/* Calculate stats */
|
||||
sec = (t * 10) / CLK_TCK;
|
||||
sec10 = sec % 10;
|
||||
sec /= 10;
|
||||
fps = (f * (CLK_TCK * 10)) / t;
|
||||
fps10 = fps % 10;
|
||||
fps /= 10;
|
||||
|
||||
/* Output stats */
|
||||
gotoxy (0, 0); cprintf ("time : %lu.%us", sec, sec10);
|
||||
gotoxy (0, 1); cprintf ("frames: %lu", f);
|
||||
gotoxy (0, 2); cprintf ("fps : %lu.%u", fps, fps10);
|
||||
|
||||
if (doesclrscrafterexit ()) {
|
||||
cputsxy (0, 4, "Press any key when done...");
|
||||
(void) cgetc ();
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
; use CC65's interrupter (slower)
|
||||
USE_INTERRUPTOR = 0
|
||||
|
||||
.segment "DATA"
|
||||
|
@ -9,39 +10,41 @@ NextDlist: .word NullDlist-1
|
|||
.segment "CODE"
|
||||
|
||||
.global ___dlist_setup
|
||||
.global ___dlist_done
|
||||
.global DLIST_IRQ_NEXT
|
||||
.global DLIST_IRQ_RESTART
|
||||
|
||||
.if USE_INTERRUPTOR
|
||||
.interruptor DLIST_IRQ
|
||||
.endif
|
||||
|
||||
___dlist_setup:
|
||||
SEI ; set interrupt bit, make the CPU ignore interrupt requests
|
||||
sei ; set interrupt bit, make the CPU ignore interrupt requests
|
||||
|
||||
sta StartDlist+0 ; save XA as pointer to start of dlist
|
||||
stx StartDlist+1
|
||||
|
||||
LDA #%01111111 ; switch off interrupt signals from CIA-1
|
||||
STA $DC0D
|
||||
lda #%01111111 ; switch off interrupt signals from CIA-1
|
||||
sta $DC0D
|
||||
|
||||
AND $D011 ; clear most significant bit of VIC's raster register
|
||||
STA $D011
|
||||
and $D011 ; clear most significant bit of VIC's raster register
|
||||
sta $D011
|
||||
|
||||
LDA $DC0D ; acknowledge pending interrupts from CIA-1
|
||||
LDA $DD0D ; acknowledge pending interrupts from CIA-2
|
||||
lda $DC0D ; acknowledge pending interrupts from CIA-1
|
||||
lda $DD0D ; acknowledge pending interrupts from CIA-2
|
||||
|
||||
LDA #252 ; set rasterline where interrupt shall occur
|
||||
STA $D012
|
||||
lda #252 ; set rasterline where interrupt shall occur
|
||||
sta $D012
|
||||
|
||||
.if !USE_INTERRUPTOR
|
||||
LDA #<DLIST_IRQ ; set interrupt vectors, pointing to interrupt service routine below
|
||||
STA $0314
|
||||
LDA #>DLIST_IRQ
|
||||
STA $0315
|
||||
lda #<DLIST_IRQ ; set interrupt vectors, pointing to interrupt service routine below
|
||||
sta $0314
|
||||
lda #>DLIST_IRQ
|
||||
sta $0315
|
||||
.endif
|
||||
|
||||
LDA #%00000001 ; enable raster interrupt signals from VIC
|
||||
STA $D01A
|
||||
lda #%00000001 ; enable raster interrupt signals from VIC
|
||||
sta $D01A
|
||||
cli
|
||||
rts
|
||||
|
||||
|
@ -54,26 +57,21 @@ DLIST_CALL:
|
|||
rts
|
||||
|
||||
DLIST_IRQ_RESTART:
|
||||
sta $d012
|
||||
sta $D012 ; set IRQ raster line
|
||||
lda StartDlist+0
|
||||
sta NextDlist+0
|
||||
lda StartDlist+1
|
||||
sta NextDlist+1
|
||||
bne DLIST_ACK
|
||||
|
||||
DLIST_IRQ_STOP:
|
||||
lda #0 ; disable raster interrupt signals from VIC
|
||||
sta $D01A
|
||||
bne DLIST_ACK
|
||||
|
||||
DLIST_IRQ_NEXT:
|
||||
sta $d012
|
||||
sta $D012
|
||||
pla
|
||||
sta NextDlist+0
|
||||
pla
|
||||
sta NextDlist+1
|
||||
DLIST_ACK:
|
||||
ASL $D019 ; acknowledge the interrupt by clearing the VIC's interrupt flag
|
||||
asl $D019 ; acknowledge the interrupt by clearing the VIC's interrupt flag
|
||||
.if USE_INTERRUPTOR
|
||||
clc
|
||||
rts
|
||||
|
@ -84,9 +82,30 @@ DLIST_ACK:
|
|||
tax
|
||||
pla
|
||||
rti ; return from interrupt
|
||||
; JMP $EA31 ; jump into KERNAL's standard interrupt service routine to handle keyboard scan, cursor display etc.
|
||||
.endif
|
||||
|
||||
___dlist_done:
|
||||
php
|
||||
sei ; disable interrupts
|
||||
lda #$0 ; disable raster interrupt signals from VIC
|
||||
sta $D01A
|
||||
lda #$ff
|
||||
sta $DC0D
|
||||
.if !USE_INTERRUPTOR
|
||||
lda #$31 ; set interrupt vectors back to KERNAL
|
||||
sta $0314
|
||||
lda #$ea
|
||||
sta $0315
|
||||
.else
|
||||
lda #<(NullDlist-1)
|
||||
sta StartDlist
|
||||
lda #>(NullDlist-1)
|
||||
sta StartDlist+1
|
||||
.endif
|
||||
plp
|
||||
rts
|
||||
|
||||
|
||||
NullDlist:
|
||||
lda #252
|
||||
jmp DLIST_IRQ_RESTART
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// internal function, use macro instead
|
||||
void __dlist_setup(void* ptr);
|
||||
void __dlist_done();
|
||||
|
||||
// initialize display list with function 'func'
|
||||
#define DLIST_SETUP(func) \
|
||||
|
@ -19,5 +20,7 @@ void __dlist_setup(void* ptr);
|
|||
__A__ = line; \
|
||||
asm ("jmp DLIST_IRQ_RESTART");
|
||||
|
||||
// stop display list
|
||||
#define DLIST_DONE() __dlist_done();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include <cbm_screen_charmap.h>
|
||||
|
||||
void main(void) {
|
||||
unsigned int i;
|
||||
|
||||
clrscr(); // clear the screen
|
||||
|
||||
POKE(0x400, 'A'); // write to first byte of screen memory
|
||||
POKE(0x400, 65); // character code for 'A'
|
||||
POKE(0x400 + 40*24 + 39, 'Z'); // row 24, column 39
|
||||
|
||||
// fill with random characters
|
||||
for (i=0; i<40*25; i++)
|
||||
POKE(0x400 + i, 205 + (rand() & 1));
|
||||
|
||||
// set character set to uppercase + graphics characters
|
||||
SET_VIC_BITMAP(0x1000);
|
||||
|
||||
// set color map underlying characters
|
||||
for (i=0; i<40*25; i++)
|
||||
COLOR_RAM[i] = COLOR_GREEN;
|
||||
|
||||
// infinite loop (avoid "ready" prompt)
|
||||
while (1);
|
||||
}
|
|
@ -63,8 +63,8 @@ void main(void) {
|
|||
|
||||
// infinite loop
|
||||
while (1) {
|
||||
// wait for vsync
|
||||
waitvsync();
|
||||
// wait for end of frame
|
||||
wait_vblank();
|
||||
// scroll one pixel to the left
|
||||
// and move screen memory every 8 pixels
|
||||
scroll_one_pixel_left();
|
||||
|
|
|
@ -23,8 +23,8 @@ void scroll_one_pixel_left() {
|
|||
src = scrnbuf[visbuf] + (scroll_x & 7) * 128;
|
||||
// destination = hidden buffer
|
||||
dst = scrnbuf[visbuf ^ 1] + (scroll_x & 7) * 128;
|
||||
// wait for vsync
|
||||
waitvsync();
|
||||
// wait for end of frame
|
||||
wait_vblank();
|
||||
// scroll hidden buffer
|
||||
memcpy(dst, src+1, 128);
|
||||
// every 8 pixels, switch visible and hidden buffers
|
||||
|
|
|
@ -17,8 +17,8 @@ void scroll_update_regs() {
|
|||
void scroll_swap() {
|
||||
// swap hidden and visible buffers
|
||||
hidbuf ^= 1;
|
||||
// wait for vblank and update registers
|
||||
waitvsync();
|
||||
// wait for end of frame and update registers
|
||||
wait_vblank();
|
||||
scroll_update_regs();
|
||||
SET_VIC_SCREEN(hidbuf ? 0x8000 : 0x8400);
|
||||
}
|
||||
|
|
|
@ -83,8 +83,8 @@ void main(void) {
|
|||
// animate sprite in shadow sprite ram
|
||||
sprite_draw(0, n++, 70, 192);
|
||||
sprite_draw(0, 172, 145, 192);
|
||||
// wait for vblank
|
||||
waitvsync();
|
||||
// wait for end of frame
|
||||
wait_vblank();
|
||||
// update scroll registers
|
||||
// and swap screens if we must
|
||||
scroll_update();
|
||||
|
|
|
@ -118,7 +118,7 @@ void main(void) {
|
|||
// animate sprite in shadow sprite ram
|
||||
update_player();
|
||||
// wait for end of frame
|
||||
waitvsync();
|
||||
wait_vblank();
|
||||
// then update sprite registers
|
||||
sprite_update(visbuf);
|
||||
// update scroll registers
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "scrolling.h"
|
||||
|
||||
#define VICBANK 0x8000
|
||||
#define BUFFER_A (byte*) 0x8000
|
||||
#define BUFFER_B (byte*) 0x8400
|
||||
|
||||
sbyte scroll_fine_x;
|
||||
sbyte scroll_fine_y;
|
||||
byte origin_x;
|
||||
byte origin_y;
|
||||
byte* hidbuf;
|
||||
byte* visbuf;
|
||||
byte colorbuf[COLS*ROWS];
|
||||
int pixofs_x;
|
||||
int pixofs_y;
|
||||
sbyte fine_correct_x;
|
||||
sbyte fine_correct_y;
|
||||
|
||||
byte scroll_dir;
|
||||
byte scroll_seq;
|
||||
|
||||
//
|
||||
|
||||
static void wait_offscreen(void) {
|
||||
while (VIC.rasterline < 250 && VIC.rasterline > 40) ;
|
||||
}
|
||||
|
||||
void scroll_swap(void) {
|
||||
byte* tmp;
|
||||
// swap hidden and visible buffers
|
||||
tmp = hidbuf;
|
||||
hidbuf = visbuf;
|
||||
visbuf = tmp;
|
||||
// set VIC bank address
|
||||
wait_offscreen();
|
||||
VIC.addr = (VIC.addr & 0xf) | (((word)visbuf >> 8) << 2);
|
||||
}
|
||||
|
||||
void copy_color_ram_slow() {
|
||||
memcpy(COLOR_RAM, colorbuf, COLS*ROWS);
|
||||
}
|
||||
|
||||
void copy_color_ram_fast() {
|
||||
// fast copy loop for upper 1/2 of color ram
|
||||
asm("ldy #0");
|
||||
asm("@loop:");
|
||||
asm("lda %v,y", colorbuf);
|
||||
asm("sta $d800,y");
|
||||
asm("lda %v + $100,y", colorbuf);
|
||||
asm("sta $d900,y");
|
||||
asm("iny");
|
||||
asm("bne @loop");
|
||||
// second loop for lower 1/2 of color ram
|
||||
asm("@loop2:");
|
||||
asm("lda %v + $200,y", colorbuf);
|
||||
asm("sta $da00,y");
|
||||
asm("lda %v + $300,y", colorbuf);
|
||||
asm("sta $db00,y");
|
||||
asm("@skip: iny");
|
||||
asm("bne @loop2");
|
||||
}
|
||||
|
||||
void copy_to_hidden_buffer_slow() {
|
||||
memcpy(hidbuf, visbuf, COLS*ROWS);
|
||||
}
|
||||
|
||||
void copy_to_hidden_buffer_fast() {
|
||||
// self-modifying code
|
||||
asm("ldy %v+1", visbuf);
|
||||
asm("sty @loop+2+6*0");
|
||||
asm("iny");
|
||||
asm("sty @loop+2+6*1");
|
||||
asm("iny");
|
||||
asm("sty @loop+2+6*2");
|
||||
asm("iny");
|
||||
asm("sty @skip-1-3");
|
||||
asm("ldy %v+1", hidbuf);
|
||||
asm("sty @loop+5+6*0");
|
||||
asm("iny");
|
||||
asm("sty @loop+5+6*1");
|
||||
asm("iny");
|
||||
asm("sty @loop+5+6*2");
|
||||
asm("iny");
|
||||
asm("sty @skip-1");
|
||||
// fast copy loop
|
||||
asm("ldy #0");
|
||||
asm("@loop:");
|
||||
asm("lda $8000,y");
|
||||
asm("sta $8000,y");
|
||||
asm("lda $8100,y");
|
||||
asm("sta $8100,y");
|
||||
asm("lda $8200,y");
|
||||
asm("sta $8200,y");
|
||||
asm("cpy #$e8");
|
||||
asm("bcs @skip");
|
||||
asm("lda $8300,y");
|
||||
asm("sta $8300,y");
|
||||
asm("@skip: iny");
|
||||
asm("bne @loop");
|
||||
}
|
||||
|
||||
void scroll_start(byte dir) {
|
||||
if (scroll_seq == 0 && dir) {
|
||||
scroll_dir = dir;
|
||||
scroll_seq = 8;
|
||||
// correct sprites b/c our fine offset is one pixel
|
||||
// off depending on last scroll direction
|
||||
if (dir & SCROLL_LEFT) fine_correct_x = 1;
|
||||
else if (dir & SCROLL_RIGHT) fine_correct_x = 0;
|
||||
if (dir & SCROLL_UP) fine_correct_y = 1;
|
||||
else if (dir & SCROLL_DOWN) fine_correct_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_step_move_buffer(char* src, char* dst) {
|
||||
word size = COLS*ROWS;
|
||||
if (scroll_dir & SCROLL_LEFT) {
|
||||
++src;
|
||||
--size;
|
||||
}
|
||||
if (scroll_dir & SCROLL_RIGHT) {
|
||||
++dst;
|
||||
--size;
|
||||
}
|
||||
if (scroll_dir & SCROLL_UP) {
|
||||
src += COLS;
|
||||
size -= COLS;
|
||||
}
|
||||
if (scroll_dir & SCROLL_DOWN) {
|
||||
dst += COLS;
|
||||
size -= COLS;
|
||||
}
|
||||
memmove(dst, src, size);
|
||||
}
|
||||
|
||||
void scroll_step_draw_cells() {
|
||||
if (scroll_dir & SCROLL_UP) ++origin_y;
|
||||
if (scroll_dir & SCROLL_DOWN) --origin_y;
|
||||
if (scroll_dir & SCROLL_LEFT) {
|
||||
++origin_x;
|
||||
scroll_draw_column(COLS-1);
|
||||
}
|
||||
if (scroll_dir & SCROLL_RIGHT) {
|
||||
--origin_x;
|
||||
scroll_draw_column(0);
|
||||
}
|
||||
if (scroll_dir & SCROLL_UP) {
|
||||
scroll_draw_row(ROWS-1);
|
||||
}
|
||||
if (scroll_dir & SCROLL_DOWN) {
|
||||
scroll_draw_row(0);
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_step_move_sprites() {
|
||||
// copy sprites from visible to hidden buffer
|
||||
memcpy(hidbuf + 0x3f8, visbuf + 0x3f8, 8);
|
||||
}
|
||||
|
||||
void scroll_update_pixofs() {
|
||||
// fine scroll starts at 8-5 = 32107 or 12-8 = 45670
|
||||
if (scroll_dir & SCROLL_LEFT) {
|
||||
pixofs_x -= 1;
|
||||
scroll_fine_x = (scroll_seq - 5) & 7;
|
||||
}
|
||||
if (scroll_dir & SCROLL_RIGHT) {
|
||||
pixofs_x += 1;
|
||||
scroll_fine_x = (12 - scroll_seq) & 7;
|
||||
}
|
||||
if (scroll_dir & SCROLL_UP) {
|
||||
pixofs_y -= 1;
|
||||
scroll_fine_y = (scroll_seq - 5) & 7;
|
||||
}
|
||||
if (scroll_dir & SCROLL_DOWN) {
|
||||
pixofs_y += 1;
|
||||
scroll_fine_y = (12 - scroll_seq) & 7;
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_offset_sprites(byte delta) {
|
||||
byte dx = 0;
|
||||
byte dy = 0;
|
||||
// fine scroll starts at 8-5 = 32107 or 12-8 = 45670
|
||||
if (scroll_dir & SCROLL_LEFT) {
|
||||
dx = -delta;
|
||||
}
|
||||
if (scroll_dir & SCROLL_RIGHT) {
|
||||
dx = delta;
|
||||
}
|
||||
if (scroll_dir & SCROLL_UP) {
|
||||
dy = -delta;
|
||||
}
|
||||
if (scroll_dir & SCROLL_DOWN) {
|
||||
dy = delta;
|
||||
}
|
||||
VIC.spr_pos[0].x += dx;
|
||||
VIC.spr_pos[1].x += dx;
|
||||
VIC.spr_pos[0].y += dy;
|
||||
VIC.spr_pos[1].y += dy;
|
||||
}
|
||||
|
||||
void scroll_update_scroll_regs() {
|
||||
wait_offscreen();
|
||||
VIC.ctrl1 = (VIC.ctrl1 & 0xf8) | scroll_fine_y;
|
||||
VIC.ctrl2 = (VIC.ctrl2 & 0xf8) | scroll_fine_x;
|
||||
}
|
||||
|
||||
void scroll_next_step(void) {
|
||||
switch (--scroll_seq) {
|
||||
case 7:
|
||||
scroll_step_move_buffer(visbuf, hidbuf);
|
||||
break;
|
||||
case 6:
|
||||
scroll_step_move_buffer(colorbuf, colorbuf);
|
||||
break;
|
||||
case 5:
|
||||
scroll_step_draw_cells();
|
||||
break;
|
||||
case 4:
|
||||
scroll_step_move_sprites();
|
||||
break;
|
||||
case 3:
|
||||
scroll_swap();
|
||||
copy_color_ram_fast();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_update(void) {
|
||||
if (scroll_seq) {
|
||||
scroll_update_pixofs();
|
||||
scroll_update_scroll_regs();
|
||||
scroll_offset_sprites(1);
|
||||
scroll_next_step();
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_finish(void) {
|
||||
while (scroll_seq) {
|
||||
scroll_update_pixofs();
|
||||
if (scroll_seq == 4) { scroll_offset_sprites(8); }
|
||||
scroll_next_step();
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_setup(void) {
|
||||
origin_x = origin_y = 0;
|
||||
pixofs_x = pixofs_y = 0;
|
||||
scroll_fine_x = scroll_fine_y = 3;
|
||||
scroll_dir = 0;
|
||||
scroll_seq = 0;
|
||||
|
||||
// setup screen buffer addresses
|
||||
hidbuf = BUFFER_A;
|
||||
visbuf = BUFFER_B;
|
||||
|
||||
memset(BUFFER_A, 0, 0x800);
|
||||
memset(colorbuf, 0, sizeof(colorbuf));
|
||||
|
||||
SET_VIC_BANK(VICBANK);
|
||||
|
||||
// set up 24 line / 38 column mode to hide edges
|
||||
VIC.ctrl1 &= ~0x08; // 24 lines
|
||||
VIC.ctrl2 &= ~0x08; // 38 columns
|
||||
}
|
||||
|
||||
void scroll_refresh(void) {
|
||||
byte i;
|
||||
for (i=0; i<25; i++) {
|
||||
scroll_draw_row(i);
|
||||
}
|
||||
scroll_swap();
|
||||
copy_color_ram_fast();
|
||||
copy_to_hidden_buffer_fast();
|
||||
scroll_dir = 0;
|
||||
scroll_seq = 0;
|
||||
scroll_fine_x = scroll_fine_y = 3;
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <c64.h>
|
||||
#include <cbm_petscii_charmap.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <joystick.h>
|
||||
|
||||
//#resource "c64-sid.cfg"
|
||||
#define CFGFILE c64-sid.cfg
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include "scrolling.h"
|
||||
//#link "scrolling.c"
|
||||
|
||||
#include "sprites.h"
|
||||
//#link "sprites.c"
|
||||
|
||||
//#link "level1.ca65"
|
||||
|
||||
extern const byte charset_data[];
|
||||
extern const byte charset_attrib_data[];
|
||||
extern const byte chartileset_data[];
|
||||
extern const byte chartileset_tag_data[];
|
||||
extern const byte* map_row_pointers[];
|
||||
|
||||
#define MAP_COLS 28
|
||||
#define MAP_ROWS 11
|
||||
|
||||
static void draw_cell(word ofs, byte x, byte y) {
|
||||
sbyte xx = x + origin_x;
|
||||
sbyte yy = y + origin_y;
|
||||
sbyte col = xx >> 2;
|
||||
sbyte row = yy >> 2;
|
||||
byte xofs = xx & 3;
|
||||
byte yofs = yy & 3;
|
||||
char ch;
|
||||
char color;
|
||||
if (col < 0 || col >= MAP_COLS || row < 0 || row >= MAP_ROWS) {
|
||||
ch = 0;
|
||||
color = 0;
|
||||
} else {
|
||||
byte tileindex = map_row_pointers[row][col];
|
||||
ch = chartileset_data[xofs + yofs*4 + tileindex*16];
|
||||
color = charset_attrib_data[ch];
|
||||
}
|
||||
hidbuf[ofs] = ch;
|
||||
colorbuf[ofs] = color;
|
||||
}
|
||||
|
||||
void scroll_draw_column(byte col) {
|
||||
byte y;
|
||||
word ofs = col;
|
||||
for (y=0; y<ROWS; y++) {
|
||||
draw_cell(ofs, col, y);
|
||||
ofs += COLS;
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_draw_row(byte row) {
|
||||
byte x;
|
||||
word ofs = row * COLS;
|
||||
for (x=0; x<COLS; x++) {
|
||||
draw_cell(ofs, x, row);
|
||||
++ofs;
|
||||
}
|
||||
}
|
||||
|
||||
/*{w:24,h:21,bpp:1,brev:1}*/
|
||||
const char SPRITE1[3*21] = {
|
||||
0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xE0,
|
||||
0x03,0xE7,0xE0,0x07,0xD9,0xF0,0x07,0xDF,0xF0,
|
||||
0x07,0xD9,0xF0,0x03,0xE7,0xE0,0x03,0xFF,0xE0,
|
||||
0x03,0xFF,0xE0,0x02,0xFF,0xA0,0x01,0x7F,0x40,
|
||||
0x01,0x3E,0x40,0x00,0x9C,0x80,0x00,0x9C,0x80,
|
||||
0x00,0x49,0x00,0x00,0x49,0x00,0x00,0x3E,0x00,
|
||||
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
|
||||
};
|
||||
|
||||
int playerx = 0;
|
||||
int playery = 0;
|
||||
int camerax = 0;
|
||||
int cameray = 0;
|
||||
|
||||
void update_player() {
|
||||
sprite_draw(0, playerx-camerax+172, playery-cameray+140, 255);
|
||||
}
|
||||
|
||||
void camera_follow(byte moving) {
|
||||
int dx, dy;
|
||||
dx = camerax - playerx;
|
||||
dy = cameray - playery;
|
||||
if (moving && abs(dx) < 32 && abs(dy) < 32) return;
|
||||
dx >>= 4;
|
||||
dy >>= 4;
|
||||
if (dx) {
|
||||
if (dx > 8) dx = 8;
|
||||
else if (dx < -8) dx = -8;
|
||||
camerax -= dx;
|
||||
scroll_horiz(dx);
|
||||
}
|
||||
if (dy) {
|
||||
if (dy > 8) dy = 8;
|
||||
else if (dy < -8) dy = -8;
|
||||
cameray -= dy;
|
||||
scroll_vert(dy);
|
||||
}
|
||||
}
|
||||
|
||||
void refresh_world(void) {
|
||||
byte i;
|
||||
for (i=0; i<25; i++) {
|
||||
scroll_draw_row(i);
|
||||
}
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
|
||||
clrscr();
|
||||
|
||||
// setup scrolling library
|
||||
scroll_setup();
|
||||
|
||||
// multicolor character mode
|
||||
VIC.ctrl2 |= 0x10;
|
||||
VIC.bgcolor0 = 6;
|
||||
VIC.bgcolor1 = 0;
|
||||
VIC.bgcolor2 = 1;
|
||||
|
||||
// select character set @ 0x8800
|
||||
VIC.addr = 0x12;
|
||||
memcpy((char*)0x8800, charset_data, 520);
|
||||
|
||||
// setup sprite library and copy sprite to VIC bank
|
||||
sprite_clear();
|
||||
sprite_set_shapes(SPRITE1, 255, 1);
|
||||
sprshad.spr_color[0] = 13;
|
||||
|
||||
// install the joystick driver
|
||||
joy_install (joy_static_stddrv);
|
||||
|
||||
// repaint screen memory w/ the map
|
||||
refresh_world();
|
||||
|
||||
// infinite loop
|
||||
while (1) {
|
||||
static char speed;
|
||||
static char joy;
|
||||
static bool slowframe = false;
|
||||
// get joystick bits
|
||||
joy = joy_read(0);
|
||||
// speed up scrolling while button pressed
|
||||
speed = JOY_BTN_1(joy) ? 3 : 1;
|
||||
// if we copied screen memory last frame,
|
||||
// double speed of player for this frame
|
||||
if (slowframe) speed *= 2;
|
||||
// move sprite based on arrow keys
|
||||
if (JOY_LEFT(joy)) playerx -= speed;
|
||||
if (JOY_RIGHT(joy)) playerx += speed;
|
||||
if (JOY_UP(joy)) playery -= speed;
|
||||
if (JOY_DOWN(joy)) playery += speed;
|
||||
// move the camera?
|
||||
camera_follow(joy);
|
||||
slowframe = swap_needed;
|
||||
// animate sprite in shadow sprite ram
|
||||
update_player();
|
||||
// wait for vblank
|
||||
wait_vblank();
|
||||
// then update sprite registers
|
||||
sprite_update(visbuf);
|
||||
// update scroll registers
|
||||
// and swap screens if we must
|
||||
scroll_update();
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
//#link "common.c"
|
||||
|
||||
#include <tgi.h>
|
||||
#include <6502.h>
|
||||
|
||||
//#resource "c64-sid.cfg"
|
||||
#define CFGFILE c64-sid.cfg
|
||||
|
@ -57,6 +58,11 @@ void show_envelope() {
|
|||
if (++sweep == 320) sweep = 0;
|
||||
}
|
||||
|
||||
char music_update() {
|
||||
sid_update();
|
||||
return IRQ_NOT_HANDLED;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
// install TGI graphics driver
|
||||
tgi_install(tgi_static_stddrv);
|
||||
|
@ -71,6 +77,9 @@ void main(void) {
|
|||
// install joystick driver
|
||||
joy_install(joy_static_stddrv);
|
||||
|
||||
// set IRQ routine called every frame
|
||||
set_irq(music_update, (void*)0x9f00, 0x100);
|
||||
|
||||
while (1) {
|
||||
// play sound effect when joystick is moved
|
||||
byte joy = joy_read(0);
|
||||
|
@ -81,8 +90,6 @@ void main(void) {
|
|||
}
|
||||
// sync with frame rate
|
||||
waitvsync();
|
||||
// update SID player
|
||||
sid_update();
|
||||
// update graphs
|
||||
show_envelope();
|
||||
show_signal();
|
||||
|
|
|
@ -124,6 +124,7 @@ void update_scoreboard() {
|
|||
|
||||
void add_score(int delta) {
|
||||
score = bcd_add(score, delta);
|
||||
update_scoreboard();
|
||||
}
|
||||
|
||||
// clear scoreboard and draw initial strings
|
||||
|
@ -242,13 +243,13 @@ void scroll_one_pixel_left() {
|
|||
}
|
||||
}
|
||||
|
||||
void detect_player_collision(byte bgcoll, byte sprcoll) {
|
||||
void detect_player_collision(byte bg_coll, byte spr_coll) {
|
||||
// did we hit a powerup? (#0 and #1)
|
||||
bool hit_powerup = (sprcoll & 0b011) == 0b011;
|
||||
bool hit_powerup = (spr_coll & 0b011) == 0b011;
|
||||
// did player and obstacle sprite (#0 and #2) collide?
|
||||
bool hit_obstacle = (sprcoll & 0b101) == 0b101;
|
||||
bool hit_obstacle = (spr_coll & 0b101) == 0b101;
|
||||
// did player (#0) collide with background?
|
||||
hit_obstacle |= (bgcoll & 0b001) != 0;
|
||||
hit_obstacle |= (bg_coll & 0b001) != 0;
|
||||
// did we hit anything bad?
|
||||
if (hit_obstacle) {
|
||||
// make player fall downward and backward
|
||||
|
@ -257,7 +258,6 @@ void detect_player_collision(byte bgcoll, byte sprcoll) {
|
|||
sprshad.spr_color[PLAYER_INDEX] = COLOR_LIGHTRED;
|
||||
SID_PLAY_TONE(500);
|
||||
if (score != 0) { add_score(0x9999); } // BCD -1
|
||||
update_scoreboard();
|
||||
} else {
|
||||
sprshad.spr_color[PLAYER_INDEX] = COLOR_GREEN;
|
||||
}
|
||||
|
@ -266,7 +266,6 @@ void detect_player_collision(byte bgcoll, byte sprcoll) {
|
|||
sprshad.spr_color[POWERUP_INDEX] += 1; // cycle colors
|
||||
SID_PLAY_TONE(8000);
|
||||
add_score(1);
|
||||
update_scoreboard();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,15 +311,15 @@ void main() {
|
|||
// game loop, repeat forever
|
||||
while (1) {
|
||||
// saved collision flags
|
||||
byte sprcoll, bgcoll;
|
||||
byte spr_coll, bg_coll;
|
||||
|
||||
// wait for end of frame
|
||||
waitvsync();
|
||||
|
||||
//--- START TIME CRITICAL SECTION
|
||||
// grab and reset collision flags
|
||||
sprcoll = VIC.spr_coll;
|
||||
bgcoll = VIC.spr_bg_coll;
|
||||
spr_coll = VIC.spr_coll;
|
||||
bg_coll = VIC.spr_bg_coll;
|
||||
|
||||
// update sprite registers from sprite shadow buffer
|
||||
sprite_update(DEFAULT_SCREEN);
|
||||
|
@ -330,7 +329,7 @@ void main() {
|
|||
//--- END TIME CRITICAL SECTION
|
||||
|
||||
// use collision flags to see if player collided
|
||||
detect_player_collision(bgcoll, sprcoll);
|
||||
detect_player_collision(bg_coll, spr_coll);
|
||||
|
||||
// get joystick bits and move player
|
||||
move_player(joy_read(0));
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
SID.amp = (volume) | ((filters)<<4);
|
||||
|
||||
// stop voice
|
||||
#define SID_STOP(voice) \
|
||||
SID.voice.ctrl &= ~SID_GATE;
|
||||
#define SID_STOP(voice, options) \
|
||||
SID.voice.ctrl = options & ~SID_GATE;
|
||||
|
||||
// start voice
|
||||
#define SID_START(voice) \
|
||||
SID.voice.ctrl |= SID_GATE;
|
||||
#define SID_START(voice, options) \
|
||||
SID.voice.ctrl = options | SID_GATE;
|
||||
|
||||
// set ADSR envelope
|
||||
#define SID_ADSR(voice,attack,decay,sustain,release) \
|
||||
|
@ -38,17 +38,13 @@
|
|||
#define SID_PULSEWIDTH(voice,_pw) \
|
||||
SID.voice.pw = (_pw);
|
||||
|
||||
// set wave shape and options
|
||||
#define SID_WAVE(voice,options) \
|
||||
SID.voice.ctrl = (SID.voice.ctrl & 1) | (options)
|
||||
|
||||
// play a quick square wave pulse
|
||||
#define SID_PULSE_DECAY(voice, freq) \
|
||||
SID_STOP(voice) \
|
||||
SID_STOP(voice,0) \
|
||||
SID_FREQ(voice,freq); \
|
||||
SID_PULSEWIDTH(voice,0x200); \
|
||||
SID_ADSR(voice,8,8,0,4); \
|
||||
SID_WAVE(voice,SID_SQUARE|SID_GATE); \
|
||||
SID_ADSR(voice,3,8,0,4); \
|
||||
SID_START(voice,SID_SQUARE); \
|
||||
|
||||
// play a tone if one is not already playing
|
||||
#define SID_PLAY_TONE(freq) \
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
!src "basicheader.acme"
|
||||
|
||||
Start:
|
||||
jsr $e544 ; clear screen
|
||||
ldy #0
|
||||
Loop:
|
||||
lda Message,y ; load message byte
|
||||
beq EOM ; 0 = end of string
|
||||
sta $400+41,y ; store to screen
|
||||
iny
|
||||
bne Loop ; next character
|
||||
EOM:
|
||||
jmp EOM ; infinite loop
|
||||
|
||||
Message:
|
||||
!scr "hello world!", 0
|
||||
|
|
@ -96,7 +96,7 @@ void iterate_game(void) {
|
|||
collide_sprites(spr_coll);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
int main(void) {
|
||||
|
||||
clrscr();
|
||||
VIC.bordercolor = 0;
|
||||
|
@ -117,5 +117,6 @@ void main(void) {
|
|||
while (1) {
|
||||
iterate_game();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
//#link "common.c"
|
||||
#include "common.h"
|
||||
|
||||
//#link "rasterirq.ca65"
|
||||
#include "rasterirq.h"
|
||||
|
||||
//#link "sprites.c"
|
||||
#include "sprites.h"
|
||||
|
||||
#include <cbm_petscii_charmap.h>
|
||||
#include <cc65.h>
|
||||
|
||||
/*{w:24,h:21,bpp:1,brev:1}*/
|
||||
const char spriteshape[3*21] = {
|
||||
0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xE0,
|
||||
0x03,0xE7,0xE0,0x07,0xD9,0xF0,0x07,0xDF,0xF0,
|
||||
0x07,0xD9,0xF0,0x03,0xE7,0xE0,0x03,0xFF,0xE0,
|
||||
0x03,0xFF,0xE0,0x02,0xFF,0xA0,0x01,0x7F,0x40,
|
||||
0x01,0x3E,0x40,0x00,0x9C,0x80,0x00,0x9C,0x80,
|
||||
0x00,0x49,0x00,0x00,0x49,0x00,0x00,0x3E,0x00,
|
||||
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
|
||||
};
|
||||
|
||||
void sprite_stretch() {
|
||||
// get current raster line
|
||||
asm("lda $d012");
|
||||
// sprite Y expand bits = 255
|
||||
asm("ldx #$ff");
|
||||
asm("stx $d017");
|
||||
// wait for next raster line
|
||||
asm("@loop:");
|
||||
asm("cmp $d012");
|
||||
asm("beq @loop");
|
||||
// sprite Y expand bits = 0
|
||||
asm("inx");
|
||||
asm("stx $d017");
|
||||
}
|
||||
|
||||
void dlist_example(void) {
|
||||
|
||||
// stretch for the next 40 lines
|
||||
while (VIC.rasterline != 160) {
|
||||
sprite_stretch();
|
||||
}
|
||||
|
||||
VIC.spr0_y+=3;
|
||||
VIC.spr7_y-=2;
|
||||
|
||||
DLIST_RESTART(8*15);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
byte i;
|
||||
|
||||
clrscr();
|
||||
VIC.bordercolor = 0;
|
||||
|
||||
sprite_clear();
|
||||
sprite_set_shapes(spriteshape, 192, 1);
|
||||
|
||||
sprshad.spr_exp_x = 0xff;
|
||||
for (i=0; i<8; i++) {
|
||||
sprshad.spr_color[i] = i|8;
|
||||
sprite_draw(i, i*38+24, 120-i, 192);
|
||||
}
|
||||
sprite_update(DEFAULT_SCREEN);
|
||||
|
||||
DLIST_SETUP(dlist_example);
|
||||
|
||||
while (1) {
|
||||
if (STICK_MOVED(READ_STICK(0))) break;
|
||||
}
|
||||
|
||||
DLIST_DONE();
|
||||
}
|
|
@ -10,8 +10,8 @@ void sprite_clear(void) {
|
|||
|
||||
void sprite_update(byte* screenmem) {
|
||||
memcpy(screenmem + 0x3f8, sprshad.spr_shapes, 8);
|
||||
memcpy(VIC.spr_pos, sprshad.spr_pos, 16);
|
||||
memcpy(VIC.spr_color, sprshad.spr_color, 8);
|
||||
memcpy((void*)VIC.spr_pos, sprshad.spr_pos, 16);
|
||||
memcpy((void*)VIC.spr_color, sprshad.spr_color, 8);
|
||||
VIC.spr_ena = sprshad.spr_ena;
|
||||
VIC.spr_hi_x = sprshad.spr_hi_x;
|
||||
VIC.spr_exp_x = sprshad.spr_exp_x;
|
||||
|
@ -63,7 +63,6 @@ byte sprite_get_closest_collision(byte i, byte spr_coll) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0xff;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
//#link "common.c"
|
||||
#include "common.h"
|
||||
|
||||
//#link "rasterirq.ca65"
|
||||
#include "rasterirq.h"
|
||||
|
||||
//#link "sprites.c"
|
||||
#include "sprites.h"
|
||||
|
||||
#include <cbm_petscii_charmap.h>
|
||||
#include <cc65.h>
|
||||
|
||||
/*{w:24,h:21,bpp:1,brev:1}*/
|
||||
const char spriteshape[3*21] = {
|
||||
0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xE0,
|
||||
0x03,0xE7,0xE0,0x07,0xD9,0xF0,0x07,0xDF,0xF0,
|
||||
0x07,0xD9,0xF0,0x03,0xE7,0xE0,0x03,0xFF,0xE0,
|
||||
0x03,0xFF,0xE0,0x02,0xFF,0xA0,0x01,0x7F,0x40,
|
||||
0x01,0x3E,0x40,0x00,0x9C,0x80,0x00,0x9C,0x80,
|
||||
0x00,0x49,0x00,0x00,0x49,0x00,0x00,0x3E,0x00,
|
||||
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
|
||||
};
|
||||
|
||||
byte scroll_x = 0;
|
||||
byte scroll_y = 0;
|
||||
|
||||
void dlist_example(void) {
|
||||
VIC.ctrl1 = VIC_CTRL1_DEN | VIC_CTRL1_RSEL;
|
||||
VIC.bordercolor = 5;
|
||||
|
||||
// Flexible line distance (FLD)
|
||||
// this adds a gap of 1-6 scanlines
|
||||
DLIST_NEXT(150);
|
||||
VIC.ctrl1 = (scroll_y & 7) | 0x18;
|
||||
VIC.bordercolor = 2;
|
||||
|
||||
// this opens up the vertical borders
|
||||
// it must be done on the last row (247-249)
|
||||
DLIST_NEXT(249);
|
||||
VIC.ctrl1 = VIC_CTRL1_DEN;
|
||||
|
||||
// move sprites and restart the display list
|
||||
scroll_x++;
|
||||
scroll_y++;
|
||||
VIC.spr0_y++;
|
||||
VIC.spr7_y--;
|
||||
VIC.bordercolor = 4;
|
||||
DLIST_RESTART(30);
|
||||
}
|
||||
|
||||
|
||||
void SieveOfEratosthenes() {
|
||||
const int n = 1023;
|
||||
int primes[1024];
|
||||
int i,p;
|
||||
memset(primes, 1, sizeof(primes));
|
||||
|
||||
for (p = 2; p*p <= n; p++) {
|
||||
if (primes[p]) {
|
||||
for (i = p*p; i <= n; i += p)
|
||||
primes[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (p = 2; p <= n; p++)
|
||||
if (primes[p])
|
||||
printf("%d ", p);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
byte i;
|
||||
|
||||
clrscr();
|
||||
|
||||
sprite_clear();
|
||||
sprite_set_shapes(spriteshape, 192, 1);
|
||||
|
||||
sprshad.spr_exp_x = 0xff;
|
||||
for (i=0; i<8; i++) {
|
||||
sprshad.spr_color[i] = i+3;
|
||||
sprite_draw(i, i*38+24, 248, 192);
|
||||
}
|
||||
sprite_update(DEFAULT_SCREEN);
|
||||
|
||||
DLIST_SETUP(dlist_example);
|
||||
|
||||
// do something complicated while IRQ runs...
|
||||
while (1) {
|
||||
SieveOfEratosthenes();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include "rasterirq.h"
|
||||
//#link "rasterirq.ca65"
|
||||
|
||||
#include "bcd.h"
|
||||
//#link "bcd.c"
|
||||
|
||||
///// DEFINES
|
||||
|
||||
#define GAME_BASE 0x400 // scrolling screen ram
|
||||
#define SCORE_BASE 0x2c00 // scoreboard screen ram
|
||||
|
||||
#define SCROLL_TOP 8 // scroll top row
|
||||
#define SCROLL_ROWS 14 // scroll # of rows
|
||||
#define GROUND_ROW 7 // ground row (+ top row)
|
||||
|
||||
///// VARIABLES
|
||||
|
||||
word scroll_x = 0; // current scroll X position
|
||||
word score = 0; // current player score
|
||||
|
||||
///// FUNCTIONS
|
||||
|
||||
// display list used by rasterirq.h
|
||||
// draws scoreboard and sets scroll register
|
||||
void display_list() {
|
||||
// set x scroll register to scroll value
|
||||
SET_SCROLL_X(scroll_x);
|
||||
// set background color
|
||||
VIC.bgcolor[0] = COLOR_CYAN;
|
||||
// next interrupt is two rows from bottom
|
||||
DLIST_NEXT(250-16);
|
||||
|
||||
// set background color
|
||||
VIC.bgcolor[0] = COLOR_BLUE;
|
||||
// screen memory = 0x2800
|
||||
SET_VIC_SCREEN(SCORE_BASE);
|
||||
// clear x scroll register
|
||||
SET_SCROLL_X(0);
|
||||
// next interrupt is bottom of frame
|
||||
DLIST_NEXT(250);
|
||||
|
||||
// reset screen to 0x400
|
||||
SET_VIC_SCREEN(0x400);
|
||||
// next interrupt is above top of next frame
|
||||
DLIST_RESTART(40);
|
||||
}
|
||||
|
||||
void update_scoreboard() {
|
||||
draw_bcd_word(SCRNADR(SCORE_BASE,7,24), score);
|
||||
}
|
||||
|
||||
void add_score(int delta) {
|
||||
score = bcd_add(score, delta);
|
||||
}
|
||||
|
||||
// clear scoreboard and draw initial strings
|
||||
void init_scoreboard() {
|
||||
memset((void*)SCORE_BASE, ' ', 1024);
|
||||
memcpy((void*)SCRNADR(SCORE_BASE,1,24), "SCORE:", 6);
|
||||
update_scoreboard();
|
||||
}
|
||||
|
||||
byte get_char_for_row(byte row) {
|
||||
// ground?
|
||||
if (row >= GROUND_ROW) { return 253; }
|
||||
// obstacle?
|
||||
if (row >= GROUND_ROW-3) {
|
||||
// only show obstacle for certain values of scroll_x
|
||||
if ((scroll_x & 0b1110000) == 0) { return 247; }
|
||||
}
|
||||
// default is the sky (empty space)
|
||||
return 32;
|
||||
}
|
||||
|
||||
void draw_right_column() {
|
||||
// get the top-right corner address of scroll area
|
||||
word addr = SCRNADR(GAME_BASE, 39, SCROLL_TOP);
|
||||
byte row;
|
||||
// draw one character per row
|
||||
for (row=0; row<SCROLL_ROWS; row++) {
|
||||
POKE(addr, get_char_for_row(row));
|
||||
addr += 40;
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_one_column_left() {
|
||||
// copy several rows of screen memory
|
||||
// backwards one byte
|
||||
const word start = SCRNADR(GAME_BASE, 0, SCROLL_TOP);
|
||||
const word nbytes = SCROLL_ROWS*40-1;
|
||||
memcpy((byte*)start, (byte*)start+1, nbytes);
|
||||
// draw the right column of characters
|
||||
draw_right_column();
|
||||
}
|
||||
|
||||
void scroll_one_pixel_left() {
|
||||
// scroll left one pixel
|
||||
scroll_x -= 1;
|
||||
// set scroll register with lower three bits
|
||||
VIC.ctrl2 = (VIC.ctrl2 & ~7) | (scroll_x & 7);
|
||||
// move screen memory if the scroll register
|
||||
// has just gone past 0 and wrapped to 7
|
||||
if ((scroll_x & 7) == 7) {
|
||||
scroll_one_column_left();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// clear screen, set background color
|
||||
clrscr();
|
||||
VIC.bgcolor[0] = COLOR_CYAN;
|
||||
VIC.bordercolor = COLOR_BLUE;
|
||||
|
||||
// set vertical scroll = 3, 25 rows
|
||||
VIC.ctrl1 = 0b00011011;
|
||||
// set 38 column mode (for X scrolling)
|
||||
VIC.ctrl2 = 0b00000000;
|
||||
// set uniform color of characters
|
||||
memset(COLOR_RAM, COLOR_WHITE, 1000);
|
||||
|
||||
// setup scoreboard
|
||||
init_scoreboard();
|
||||
|
||||
// setup rasterirq library for scoreboard split
|
||||
DLIST_SETUP(display_list);
|
||||
|
||||
// game loop, repeat forever
|
||||
while (1) {
|
||||
// wait for end of frame
|
||||
waitvsync();
|
||||
|
||||
// scroll screen
|
||||
scroll_one_pixel_left();
|
||||
|
||||
// add to score
|
||||
add_score(0x0001);
|
||||
update_scoreboard();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <peekpoke.h>
|
||||
#include <string.h>
|
||||
#include <c64.h>
|
||||
#include <cbm_petscii_charmap.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include <6502.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
char interrupt_handler() {
|
||||
// only needed if CIA interupts are still active
|
||||
if (!(VIC.irr & VIC_IRR_IRST)) return IRQ_NOT_HANDLED;
|
||||
// change colors so we can see where the IRQ fired
|
||||
VIC.bgcolor0++;
|
||||
VIC.bordercolor++;
|
||||
// reading VIC.rasterline returns the current line
|
||||
// setting it changes the line where the IRQ fires
|
||||
if (VIC.rasterline >= 245) {
|
||||
VIC.rasterline = 40;
|
||||
} else {
|
||||
VIC.rasterline = 245;
|
||||
}
|
||||
// acknowledge VIC raster interrupt (bit 0)
|
||||
VIC.irr = 1;
|
||||
// change colors back to where they were
|
||||
VIC.bgcolor0--;
|
||||
VIC.bordercolor--;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
clrscr();
|
||||
printf("\nHello World!\n");
|
||||
|
||||
// set interrupt routine
|
||||
set_irq(interrupt_handler, (void*)0x9f00, 0x100);
|
||||
|
||||
// disable CIA interrupt, activate VIC interrupt
|
||||
set_raster_irq(255);
|
||||
|
||||
while (1) {
|
||||
printf("%d ", VIC.rasterline);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
// sid config so we don't use stack above $8000
|
||||
|
||||
//#resource "c64-sid.cfg"
|
||||
#define CFGFILE c64-sid.cfg
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include "mcbitmap.h"
|
||||
//#link "mcbitmap.c"
|
||||
|
||||
#include <lz4.h>
|
||||
|
||||
// include the LZ4 binary data -> image_c64_multi_lz4[]
|
||||
const char image_c64_multi_lz4[] = {
|
||||
#embed "image-c64.multi.lz4"
|
||||
};
|
||||
|
||||
/*
|
||||
CharData 8000 bytes
|
||||
ScreenData 1000 bytes
|
||||
ColorData 1000 bytes
|
||||
XtraData 2 bytes
|
||||
*/
|
||||
|
||||
void main() {
|
||||
char* const uncomp = (char*)0xb000;
|
||||
char bgcolor;
|
||||
|
||||
// setup VIC for multicolor bitmap
|
||||
// colormap = $c000-$c7ff
|
||||
// bitmap = $e000-$ffff
|
||||
setup_bitmap_multi();
|
||||
// enable HIMEM so we can write to $c000-$ffff
|
||||
ENABLE_HIMEM();
|
||||
// decompress into $8000-$a711
|
||||
decompress_lz4(image_c64_multi_lz4+11, uncomp, 10002);
|
||||
// read background color
|
||||
bgcolor = uncomp[10000];
|
||||
// copy data to destination areas
|
||||
memcpy((void*)MCB_BITMAP, uncomp, 8000);
|
||||
memcpy(COLOR_RAM, uncomp+9000, 1000);
|
||||
memcpy((void*)MCB_COLORS, uncomp+8000, 1000);
|
||||
DISABLE_HIMEM();
|
||||
// set background color
|
||||
VIC.bgcolor0 = bgcolor;
|
||||
// wait for key
|
||||
cgetc();
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
|
||||
// ported from
|
||||
// https://odensskjegg.home.blog/2018/12/29/recreating-the-commodore-64-user-guide-code-samples-in-cc65-part-three-sprites/
|
||||
|
||||
#include "common.h"
|
||||
#include <peekpoke.h>
|
||||
#include <c64.h>
|
||||
|
||||
/*{w:24,h:21,bpp:1,brev:1}*/
|
||||
const char sprite[3*21] = {
|
||||
|
@ -15,7 +17,7 @@ const char sprite[3*21] = {
|
|||
};
|
||||
|
||||
// Pre-calculated sinus values
|
||||
const char yValues[] = {
|
||||
const char yValues[64] = {
|
||||
32, 35, 38, 41, 44, 47, 49, 52,
|
||||
54, 56, 58, 60, 61, 62, 63, 63,
|
||||
64, 63, 63, 62, 61, 60, 58, 56,
|
||||
|
@ -31,58 +33,66 @@ void rasterWait(unsigned char line) {
|
|||
while (VIC.rasterline < line) ;
|
||||
}
|
||||
|
||||
const char LUT[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
|
||||
|
||||
int main (void)
|
||||
{
|
||||
unsigned char n, t;
|
||||
int rx, x;
|
||||
char sx, msb;
|
||||
unsigned char msb;
|
||||
|
||||
VIC.bgcolor0 = 3;
|
||||
VIC.bgcolor0 = COLOR_CYAN; // set background color
|
||||
__asm__("SEI"); // clear interrupts to avoid glitching
|
||||
|
||||
// Set 13th sprite bitmap
|
||||
for (n = 0 ; n < sizeof(sprite) ; n++) {
|
||||
POKE(832 + n, sprite[n]);
|
||||
}
|
||||
// enable all sprites
|
||||
VIC.spr_ena = 255;
|
||||
// Set all sprite pointers to 13th sprite
|
||||
for (t = 0 ; t < 8 ; t++) {
|
||||
POKE(2040 + t, 13); // Set sprite x data from 13th block for all sprites
|
||||
POKE(2040 + t, 13);
|
||||
}
|
||||
do {
|
||||
// loop forever
|
||||
while(1) {
|
||||
for (x = 0 ; x < 550; x++) {
|
||||
msb = 0; // MSB of X coordinates
|
||||
// MSB of each sprite's X coordinate (i.e. if X >= 256)
|
||||
msb = 0;
|
||||
// Wait until raster hits position 250 before drawing upper sprites
|
||||
rasterWait(250);
|
||||
// Set border color, which indicates the raster position
|
||||
VIC.bordercolor = 1;
|
||||
VIC.bordercolor = COLOR_RED;
|
||||
rx = x;
|
||||
// iterate over all 8 sprites
|
||||
for (t = 0 ; t < 8 ; t++) {
|
||||
VIC.bordercolor = t;
|
||||
rx -= 24;
|
||||
if (rx >= 0 && rx < 366) {
|
||||
// Usually I would calculate the sprite X coordinate using
|
||||
// the expression sx = rx % 256, but bitwise operation is
|
||||
// significant faster
|
||||
sx = rx & 255;
|
||||
if (rx > 255) {
|
||||
// Set MSB of x coordinate for sprite if x position > 255
|
||||
msb |= 1 << t;
|
||||
// Set MSB of x coordinate for sprite if x position > 255
|
||||
if (rx >= 256) {
|
||||
msb |= LUT[t]; // look up 1 << t
|
||||
}
|
||||
VIC.spr_pos[t].x = sx;
|
||||
VIC.spr_pos[t].x = rx;
|
||||
// Y position is an indirect Sinus function of X, using array
|
||||
// index for retrieving the Y value
|
||||
VIC.spr_pos[t].y = yValues[sx & 63] + 40;
|
||||
VIC.spr_pos[t].y = yValues[rx & 63] + 40;
|
||||
} else {
|
||||
VIC.spr_pos[t].x = 0;
|
||||
}
|
||||
}
|
||||
VIC.spr_hi_x = msb; // Set MSB of x coordinate
|
||||
// Set MSB of x coordinate
|
||||
VIC.spr_hi_x = msb;
|
||||
// Wait until raster hits position 135 before drawing lower sprites
|
||||
VIC.bordercolor = COLOR_BLUE;
|
||||
rasterWait(135);
|
||||
VIC.bordercolor = 2; // Set border color
|
||||
VIC.bordercolor = COLOR_RED;
|
||||
// Add 128 to current sprite Y positions
|
||||
for (t = 0 ; t < 8 ; t++) {
|
||||
// Add 128 to current sprite Y position
|
||||
VIC.spr_pos[t].y += 128;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -79,21 +79,31 @@ typedef enum {
|
|||
|
||||
void main();
|
||||
|
||||
void start() {
|
||||
void start() __naked {
|
||||
__asm
|
||||
LD SP,#0x4800
|
||||
EI
|
||||
; copy initialized data to RAM
|
||||
LD BC, #l__INITIALIZER+1
|
||||
LD BC, #l__INITIALIZER
|
||||
LD A, B
|
||||
LD DE, #s__INITIALIZED
|
||||
LD HL, #s__INITIALIZER
|
||||
LDIR
|
||||
.skipinit:
|
||||
JP _main
|
||||
; padding to get to offset 0x66
|
||||
.ds 0x66 - (. - _start)
|
||||
__endasm;
|
||||
main();
|
||||
}
|
||||
|
||||
const char __at (0x4000) tilerom[0x1000] = {
|
||||
volatile byte video_framecount = 0; // actual framecount
|
||||
|
||||
// starts at address 0x66
|
||||
void rst_66() __interrupt {
|
||||
video_framecount++;
|
||||
}
|
||||
|
||||
const char __at (0x4000) tilerom[0x1000] = {/*{w:16,h:16,remap:[3,0,1,2,4,5,6,7,8,9,10],brev:1,np:2,pofs:2048,count:64}*/
|
||||
0x00,0xfe,0x82,0x82,0x82,0xfe,0xfe,0x00,0x00,0x00,0xfe,0xfe,0xc0,0x00,0x00,0x00,0x00,0xf2,0xf2,0x92,0x92,0x9e,0x9e,0x00,0x00,0xfe,0xfe,0x92,0x92,0x82,0x00,0x00,0x08,0xfe,0xfe,0x88,0x88,0xf8,0xf8,0x00,0x00,0x9e,0x9e,0x92,0x92,0xf2,0xf2,0x00,0x00,0x9e,0x92,0x92,0x92,0xfe,0xfe,0x00,0x00,0xf0,0xf0,0x9e,0x9e,0x80,0x80,0x00,0x00,0xfe,0x92,0x92,0x92,0xfe,0xfe,0x00,0x00,0xfe,0x92,0x92,0x92,0xf2,0xf0,0x00,0x00,0xfe,0xc8,0x88,0x88,0xfe,0xfe,0x00,0x00,0xee,0x92,0x92,0x92,0xfe,0xfe,0x00,0x00,0x82,0x82,0x82,0x86,0xfe,0xfe,0x00,0x00,0xfc,0x86,0x82,0x82,0xfe,0xfe,0x00,0x00,0x82,0x92,0x92,0x92,0xfe,0xfe,0x00,0x00,0x80,0x90,0x90,0x90,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc8,0x88,0x88,0xfe,0xfe,0x00,0x00,0xee,0x92,0x92,0x92,0xfe,0xfe,0x00,0x00,0x82,0x82,0x82,0x86,0xfe,0xfe,0x00,0x00,0xfc,0x86,0x82,0x82,0xfe,0xfe,0x00,0x00,0x82,0x92,0x92,0x92,0xfe,0xfe,0x00,0x80,0x90,0x90,0x90,0x90,0xfe,0xfe,0x00,0x00,0x9e,0x92,0x82,0x82,0xfe,0xfe,0x00,0xfe,0xfe,0x10,0x10,0x10,0xfe,0xfe,0x00,0x00,0x00,0xbe,0xbe,0x00,0x00,0x00,0x00,0xfc,0xfe,0x06,0x02,0x02,0x02,0x00,0x00,0x00,0x82,0x44,0x28,0x18,0xfe,0xfe,0x00,0x02,0x02,0x02,0x06,0xfe,0xfe,0x00,0x00,0xfe,0x40,0x20,0x18,0x20,0xfe,0xfe,0x00,0xfe,0x0c,0x08,0x10,0x20,0xfe,0xfe,0x00,0xfe,0x82,0x82,0x82,0x86,0xfe,0xfe,0x00,
|
||||
0x00,0xf8,0x88,0x88,0x88,0xfe,0xfe,0x00,0x7e,0x86,0x8a,0x82,0x82,0xfe,0xfe,0x00,0xf8,0x8a,0x8c,0x88,0x88,0xfe,0xfe,0x00,0x00,0x9e,0x96,0x92,0x92,0xf2,0xf2,0x00,0x80,0x80,0xfe,0xfe,0x80,0x80,0x00,0x00,0x00,0xfe,0x06,0x02,0x02,0xfe,0xfe,0x00,0xf0,0x08,0x04,0x06,0x0c,0xf8,0xf0,0x00,0xf8,0x06,0x0c,0x18,0x0c,0xfe,0xf8,0x00,0x82,0x44,0x28,0x38,0x6c,0xc6,0x82,0x00,0x80,0x40,0x30,0x1e,0x3e,0x40,0x80,0x00,0xc2,0xe2,0xb2,0x9e,0x8e,0x86,0x82,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x80,0x78,0x7e,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x78,0x80,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x28,0x07,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0xe0,0xf0,0x07,0x07,0x28,0x10,0x00,0x00,0x00,0x00,0xe0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x04,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0xe0,0xe0,0x07,0x27,0x18,0x00,0x00,0x00,0x00,0x00,0xf0,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x04,0x02,0x03,0x07,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xe0,0x3f,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xf0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x01,0x23,0x3f,0x07,0x00,0x00,0x00,0x00,0x80,0xc0,0xc0,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x13,0x1f,0x07,0x03,0x00,0x00,0x80,0x80,0x80,0xc0,0xe0,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xe0,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x09,0x0f,0x07,0x07,0x00,0x80,0x40,0x80,0x80,0xc0,0xc0,0xc0,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x08,0x04,0x03,0x03,0x03,0x00,0x00,0x10,0x08,0x10,0x60,0xe0,0xe0,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0xe0,0xc0,0xc0,0x80,0x00,0x00,0x00,0x00,
|
||||
|
@ -112,7 +122,8 @@ const char __at (0x4000) tilerom[0x1000] = {
|
|||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x78,0x00,0x02,0x06,0x10,0x01,0x4a,0x00,0x10,0x00,0xa0,0x02,0x14,0x10,0x08,0x00,0x00,0x80,0x01,0x1c,0x40,0x86,0x01,0x81,0x60,0x00,0x04,0x90,0x70,0x08,0x02,0x00,0x40,0x00,0x00,0x40,0x00,0x20,0x00,0x10,0x7c,0x81,0x01,0x01,0x04,0x00,0x08,0x80,0x20,0x04,0x01,0x40,0x04,0x48,0x11,0xa0,0x00,0x02,0x00,0x08,0x84,0x02,0x01,0x00,0x18,0x86,0x80,0x0c,0x11,0x18,0xdb,0x05,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x02,0x00,0x00,0x00,0x00,0x62,0x90,0x01,0x05,0x00,0x01,0x81,0x7c,0x01,0x40,0x00,0xc0,0x00,0x01,0x80,0x80,0x40,0x44,0x80,0x01,0x02,0x64,0x00,0x00,0x48,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x04,0x03,0x00,0x00,0x18,0x00,0x12,0x10,0x0a,0xc2,0x00,0x01,0x00,0x00,0x01,0x00,0x02,0x00,0x21,0x02,0x19,0x8e,0xa2,0x6c,0xe4,0x70,0x00,0x00,0x00,0x00,0x00,0x60,0xe3,0x02,0x60,0x00,0x14,0x20,0x08,0x80,0x00,0x00,0x0e,0x5a,0x5b,0x8a,0x45,0x35,0x04,0x02,0xe0,0x00,0x10,0x90,0x40,0x20,0x00,0x80,0x12,0x15,0x04,0x00,0x00,0x00,0x02,0x02,0xc0,0x60,0x20,0x60,0x20,0x18,0x3c,0x00,0x01,0x0e,0x0a,0x10,0x18,0x10,0x00,0x30,0x05,0x20,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x09,0x08,0x08,0x40,0x40,0x0c,0x10,0x20,0x20,0xd0,0x00,0x08,0x70,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x12,0x0a,0x00,0x10,
|
||||
0x00,0x00,0x60,0x30,0x18,0x08,0x00,0x00,0x10,0x40,0x20,0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x20,0x20,0x00,0x00,0x00,0x40,0x10,0x08,0x0d,0x10,0x00,0x00,0x00,0x00,0x06,0x10,0x00,0x00,0x00,0x05,0x08,0x02,0x44,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x88,0x04,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x00,0x00,0x00,0x08,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x08,0x12,0x24,0x08,0x50,0x00,0x40,0x00,0x00,0x70,0x04,0x00,0x01,0x0e,0x80,0xa8,0x00,0x80,0x20,0x40,0x60,0x00,0x80,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x02,0x00,0x00,0x88,0x00,0x40,0x00,0x39,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x40,0x60,0x38,0x01,0x08,0x04,0x02,0x00,0x30,0x30,0x18,0x04,0x00,0x01,0x00,0x0a,0x0c,0x04,0x02,0x02,0x04,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xe0,0xe5,0x03,0x00,0x00,0x00,0x00,0x0c,0x18,0x40,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x3a,0x00,0x08,0x98,0x70,0x00,0x20,0x0e,0x0e,0x01,0x00,0x00,0x02,0x80,0x90,0x23,0x31,0xbd,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x80,0x87,0x08,0x10,0x20,0x00,0x00,0x00,0x04,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x80,0x00,0x00,0x00,0x40,0x00,0x40,0x10,0x64,0x84,0x00,0x00,0x00,0x00,0x00,0x10,0xc8,0xc1,0xc0,0x38,0x20,0x80,0x50,0x10,0x08,0x00,0x00,0x80,
|
||||
};
|
||||
const char __at (0x5000) palette[32] = {
|
||||
|
||||
const char __at (0x5000) palette[32] = {/*{pal:332,n:4}*/
|
||||
0x00,0x00,0x00,0xf6,0x00,0x16,0xc0,0x3f,
|
||||
0x00,0xd8,0x07,0x3f,0x00,0xc0,0xc4,0x07,
|
||||
0x00,0xc0,0xa0,0x07,0x00,0x00,0x00,0x07,
|
||||
|
@ -134,30 +145,6 @@ byte getchar(byte x, byte y) {
|
|||
return vram[29-x][y];
|
||||
}
|
||||
|
||||
volatile byte video_framecount; // actual framecount
|
||||
|
||||
void _buffer() {
|
||||
__asm
|
||||
; padding to get to offset 0x66
|
||||
ld ix,#0
|
||||
ld ix,#0
|
||||
ld ix,#0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void rst_66() __interrupt {
|
||||
video_framecount++;
|
||||
}
|
||||
|
||||
void reset_video_framecount() __critical {
|
||||
video_framecount = 0;
|
||||
}
|
||||
|
||||
|
||||
void putchar(byte x, byte y, byte ch) {
|
||||
vram[29-x][y] = ch;
|
||||
}
|
||||
|
@ -176,9 +163,10 @@ void putstring(byte x, byte y, const char* string) {
|
|||
}
|
||||
|
||||
void wait_for_frame() {
|
||||
byte initial_framecount = video_framecount;
|
||||
watchdog++;
|
||||
while (video_framecount == initial_framecount);
|
||||
__asm
|
||||
HALT
|
||||
__endasm;
|
||||
}
|
||||
|
||||
///
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
import "pce";
|
||||
|
||||
bank zeropage @ 0x2000 : [vardata; 256];
|
||||
bank stack @ 0x2100 : [vardata; 256];
|
||||
bank prg @ 0xE000 : [constdata; 0x2000];
|
||||
bank chr @ 0x8000 : [constdata; 0x4000];
|
||||
|
||||
in zeropage {
|
||||
var b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 : u8;
|
||||
var w0 @ &b0, w2 @ &b2, w4 @ &b4, w6 @ &b6, w8 @ &b8 : u16;
|
||||
var mosaic : u8;
|
||||
var timer : u8;
|
||||
}
|
||||
|
||||
in prg {
|
||||
#[fallthrough] func main() {
|
||||
// Disable decimal arithmetic.
|
||||
decimal = false;
|
||||
// Disable interrupts.
|
||||
nointerrupt = true;
|
||||
// Enable turbo mode on CPU.
|
||||
turbo_speed = true;
|
||||
// mpr7 = a = 0; by power-on
|
||||
// MPR0 = I/O page
|
||||
mpr0 = a = 0xFF;
|
||||
// MPR1 = RAM
|
||||
mpr1 = a = 0xF8;
|
||||
// MPR4/5 = data bank
|
||||
mpr4 = a = 1;
|
||||
mpr5 = a = 2;
|
||||
// Prepare stack.
|
||||
s = x = 0xFF;
|
||||
|
||||
a = pce.vdc.status;
|
||||
pce.irq.disable = a = pce.irq.INTERRUPT_ALL;
|
||||
pce.irq.acknowledge = a;
|
||||
pce.timer.control = 0;
|
||||
|
||||
vdc_select = pce.vdc.SELECT_CONTROL;
|
||||
vdc_data_l = 0;
|
||||
vdc_data_h = 0;
|
||||
vdc_select = pce.vdc.SELECT_SCANLINE_COMPARE;
|
||||
vdc_data_l = 0;
|
||||
vdc_data_h = 0;
|
||||
vdc_select = pce.vdc.SELECT_SCROLL_X;
|
||||
vdc_data_l = 0;
|
||||
vdc_data_h = 0;
|
||||
vdc_select = pce.vdc.SELECT_SCROLL_Y;
|
||||
vdc_data_l = 0;
|
||||
vdc_data_h = 0;
|
||||
vdc_select = pce.vdc.SELECT_MEMORY_SIZE;
|
||||
vdc_data_l = pce.vdc.DATA_L_MEMORY_SIZE_TILEMAP_32x32;
|
||||
vdc_data_h = 0;
|
||||
vdc_select = pce.vdc.SELECT_HSYNC_SETTING;
|
||||
vdc_data_l = 0x02;
|
||||
vdc_data_h = 0x02;
|
||||
vdc_select = pce.vdc.SELECT_HDISP_SETTING;
|
||||
vdc_data_l = 0x1F;
|
||||
vdc_data_h = 0x04;
|
||||
vdc_select = pce.vdc.SELECT_VSYNC_SETTING;
|
||||
vdc_data_l = 0x07;
|
||||
vdc_data_h = 0x0D;
|
||||
vdc_select = pce.vdc.SELECT_VDISP_HEIGHT;
|
||||
vdc_data_l = 0xDF;
|
||||
vdc_data_h = 0x00;
|
||||
vdc_select = pce.vdc.SELECT_VDISP_END;
|
||||
vdc_data_l = 0x03;
|
||||
vdc_data_h = 0x00;
|
||||
vdc_select = pce.vdc.SELECT_DMA_CONTROL;
|
||||
vdc_data_l = pce.vdc.DATA_L_DMA_CONTROL_SATB_AUTO_TRANSFER;
|
||||
vdc_data_h = 0x00;
|
||||
vdc_select = pce.vdc.SELECT_SATB_SOURCE_ADDRESS;
|
||||
vdc_data_l = 0x00;
|
||||
vdc_data_h = 0x7F;
|
||||
|
||||
pce.vce.control = a = pce.vce.CONTROL_FIELD_EXTRA_LINE;
|
||||
pce.vce.address_l = a = 0;
|
||||
pce.vce.address_h = a = 0;
|
||||
load_alt_inc_repeat(&pce.vce.data_l as u16, &bkg_palette_data as u16, sizeof(typeof(bkg_palette_data)));
|
||||
|
||||
let TILESET_DEST_ADDRESS = 0x1000;
|
||||
vdc_select = pce.vdc.SELECT_VRAM_WRITE_ADDRESS;
|
||||
vdc_data_l = <:TILESET_DEST_ADDRESS;
|
||||
vdc_data_h = >:TILESET_DEST_ADDRESS;
|
||||
vdc_select = pce.vdc.SELECT_VRAM_DATA;
|
||||
load_alt_inc_repeat(&pce.vdc.data_l as u16, &hello_tiles_chr as u16, sizeof(typeof(hello_tiles_chr)));
|
||||
|
||||
let START_X = 10;
|
||||
let START_Y = 13;
|
||||
let TILEMAP_ADDRESS = pce.vdc.DATA_VRAM_ADDRESS_TILEMAP + START_Y * 32 + START_X;
|
||||
let TILE_BASE_INDEX = TILESET_DEST_ADDRESS / 16;
|
||||
|
||||
vdc_select = pce.vdc.SELECT_VRAM_WRITE_ADDRESS;
|
||||
vdc_data_l = <:TILEMAP_ADDRESS;
|
||||
vdc_data_h = >:TILEMAP_ADDRESS;
|
||||
vdc_select = pce.vdc.SELECT_VRAM_DATA;
|
||||
|
||||
x = 0;
|
||||
do {
|
||||
pce.vdc.data_l = a = <:TILE_BASE_INDEX + message[x];
|
||||
pce.vdc.data_h = a = >:TILE_BASE_INDEX +# 0;
|
||||
x++;
|
||||
} while x != message.len;
|
||||
|
||||
vdc_select = pce.vdc.SELECT_CONTROL;
|
||||
vdc_data_l = pce.vdc.DATA_L_CONTROL_ENABLE_BG;
|
||||
vdc_data_h = 0x00;
|
||||
|
||||
while true {}
|
||||
}
|
||||
|
||||
let rgb_pack(r, g, b) = ((r & 0x7) << 3) | ((g & 0x7) << 6) | (b & 0x7);
|
||||
|
||||
const bkg_palette_data : [u16] = [
|
||||
rgb_pack(6, 3, 4), rgb_pack(1, 1, 3), rgb_pack(0, 0, 0), rgb_pack(0, 0, 0),
|
||||
rgb_pack(0, 0, 0), rgb_pack(0, 0, 0), rgb_pack(0, 0, 0), rgb_pack(0, 0, 0),
|
||||
rgb_pack(0, 0, 0), rgb_pack(0, 0, 0), rgb_pack(0, 0, 0), rgb_pack(0, 0, 0),
|
||||
rgb_pack(0, 0, 0), rgb_pack(0, 0, 0), rgb_pack(0, 0, 0), rgb_pack(7, 7, 7),
|
||||
];
|
||||
|
||||
const message = "HELLO WORLD";
|
||||
|
||||
const @ 0xFFFE = main;
|
||||
}
|
||||
|
||||
in chr {
|
||||
const hello_tiles_chr = embed "hello_tiles.chr";
|
||||
const minirpg_sprites_chr = embed "minirpg_sprites.chr";
|
||||
}
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
Text-based version of a Blockade-style game.
|
||||
For more information, see "Making Arcade Games in C".
|
||||
*/
|
||||
|
||||
#include <conio.h>
|
||||
#include <joystick.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define COLS 50
|
||||
#define ROWS 28
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef signed char sbyte;
|
||||
typedef unsigned short word;
|
||||
typedef signed short sword;
|
||||
|
||||
// get the character at a specfic x/y position
|
||||
byte readcharxy(byte x, byte y) {
|
||||
gotoxy(x,y); // set cursor position
|
||||
return cpeekc();
|
||||
}
|
||||
|
||||
void delay(byte count) {
|
||||
while (count--) {
|
||||
waitvsync();
|
||||
}
|
||||
}
|
||||
|
||||
////////// GAME DATA
|
||||
|
||||
typedef struct {
|
||||
byte x;
|
||||
byte y;
|
||||
byte dir;
|
||||
word score;
|
||||
char head_attr;
|
||||
char tail_attr;
|
||||
int collided:1;
|
||||
int human:1;
|
||||
} Player;
|
||||
|
||||
Player players[2];
|
||||
|
||||
byte credits = 0;
|
||||
byte frames_per_move;
|
||||
byte gameover;
|
||||
|
||||
#define START_SPEED 12
|
||||
#define MAX_SPEED 5
|
||||
#define MAX_SCORE 7
|
||||
|
||||
///////////
|
||||
|
||||
const char BOX_CHARS[8] = { '+', '+', '+', '+',
|
||||
'-', '-', '!', '!'};
|
||||
|
||||
void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) {
|
||||
byte x1 = x;
|
||||
cputcxy(x, y, chars[2]);
|
||||
cputcxy(x2, y, chars[3]);
|
||||
cputcxy(x, y2, chars[0]);
|
||||
cputcxy(x2, y2, chars[1]);
|
||||
while (++x < x2) {
|
||||
cputcxy(x, y, chars[5]);
|
||||
cputcxy(x, y2, chars[4]);
|
||||
}
|
||||
while (++y < y2) {
|
||||
cputcxy(x1, y, chars[6]);
|
||||
cputcxy(x2, y, chars[7]);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_playfield() {
|
||||
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
|
||||
cputsxy( 0, 0, "Plyr1:");
|
||||
cputsxy(20, 0, "Plyr2:");
|
||||
cputcxy( 7, 0, players[0].score+'0');
|
||||
cputcxy(27, 0, players[1].score+'0');
|
||||
}
|
||||
|
||||
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
|
||||
const sbyte DIR_X[4] = { 1, 0, -1, 0 };
|
||||
const sbyte DIR_Y[4] = { 0, 1, 0, -1 };
|
||||
|
||||
void init_game() {
|
||||
memset(players, 0, sizeof(players));
|
||||
players[0].head_attr = '1';
|
||||
players[1].head_attr = '2';
|
||||
players[0].tail_attr = '#';
|
||||
players[1].tail_attr = '*';
|
||||
frames_per_move = START_SPEED;
|
||||
}
|
||||
|
||||
void reset_players() {
|
||||
players[0].x = players[0].y = 5;
|
||||
players[0].dir = D_RIGHT;
|
||||
players[1].x = COLS-6;
|
||||
players[1].y = ROWS-6;
|
||||
players[1].dir = D_LEFT;
|
||||
players[0].collided = players[1].collided = 0;
|
||||
}
|
||||
|
||||
void draw_player(Player* p) {
|
||||
cputcxy(p->x, p->y, p->head_attr);
|
||||
}
|
||||
|
||||
void move_player(Player* p) {
|
||||
cputcxy(p->x, p->y, p->tail_attr);
|
||||
p->x += DIR_X[p->dir];
|
||||
p->y += DIR_Y[p->dir];
|
||||
if ((readcharxy(p->x, p->y) & 0x7f) != ' ')
|
||||
p->collided = 1;
|
||||
draw_player(p);
|
||||
}
|
||||
|
||||
void human_control(Player* p) {
|
||||
byte dir = 0xff;
|
||||
char joy;
|
||||
if (!p->human) return;
|
||||
//if (!kbhit()) return;
|
||||
joy = joy_read(0);
|
||||
if (JOY_UP(joy)) dir = D_UP;
|
||||
if (JOY_LEFT(joy)) dir = D_LEFT;
|
||||
if (JOY_RIGHT(joy)) dir = D_RIGHT;
|
||||
if (JOY_DOWN(joy)) dir = D_DOWN;
|
||||
// don't let the player reverse direction
|
||||
if (dir < 0x80 && dir != (p->dir ^ 2)) {
|
||||
p->dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
byte ai_try_dir(Player* p, dir_t dir, byte shift) {
|
||||
byte x,y;
|
||||
dir &= 3;
|
||||
x = p->x + (DIR_X[dir] << shift);
|
||||
y = p->y + (DIR_Y[dir] << shift);
|
||||
if (x < COLS && y < ROWS
|
||||
&& (readcharxy(x, y) & 0x7f) == ' ') {
|
||||
p->dir = dir;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ai_control(Player* p) {
|
||||
dir_t dir;
|
||||
if (p->human) return;
|
||||
dir = p->dir;
|
||||
if (!ai_try_dir(p, dir, 0)) {
|
||||
ai_try_dir(p, dir+1, 0);
|
||||
ai_try_dir(p, dir-1, 0);
|
||||
} else {
|
||||
ai_try_dir(p, dir-1, 0) && ai_try_dir(p, dir-1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir+1, 0) && ai_try_dir(p, dir+1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir, rand() & 3);
|
||||
}
|
||||
}
|
||||
|
||||
void flash_colliders() {
|
||||
byte i;
|
||||
// flash players that collided
|
||||
for (i=0; i<56; i++) {
|
||||
delay(2);
|
||||
revers(players[0].collided && (i&1));
|
||||
draw_player(&players[0]);
|
||||
revers(players[1].collided && (i&1));
|
||||
draw_player(&players[1]);
|
||||
}
|
||||
revers(0);
|
||||
}
|
||||
|
||||
void make_move() {
|
||||
byte i;
|
||||
for (i=0; i<frames_per_move; i++) {
|
||||
human_control(&players[0]);
|
||||
delay(1);
|
||||
}
|
||||
ai_control(&players[0]);
|
||||
ai_control(&players[1]);
|
||||
// if players collide, 2nd player gets the point
|
||||
textcolor(COLOR_CYAN);
|
||||
move_player(&players[1]);
|
||||
textcolor(COLOR_YELLOW);
|
||||
move_player(&players[0]);
|
||||
textcolor(COLOR_WHITE);
|
||||
}
|
||||
|
||||
void declare_winner(byte winner) {
|
||||
byte i;
|
||||
clrscr();
|
||||
for (i=0; i<ROWS/2-3; i++) {
|
||||
draw_box(i,i,COLS-1-i,ROWS-1-i,BOX_CHARS);
|
||||
delay(1);
|
||||
}
|
||||
cputsxy(12,10,"WINNER:");
|
||||
cputsxy(12,13,"PLAYER ");
|
||||
cputcxy(12+7, 13, '1'+winner);
|
||||
delay(200);
|
||||
gameover = 1;
|
||||
}
|
||||
|
||||
void play_round() {
|
||||
reset_players();
|
||||
clrscr();
|
||||
textcolor(COLOR_WHITE);
|
||||
draw_playfield();
|
||||
while (1) {
|
||||
make_move();
|
||||
if (players[0].collided || players[1].collided) break;
|
||||
}
|
||||
flash_colliders();
|
||||
// add scores to players that didn't collide
|
||||
if (players[0].collided) players[1].score++;
|
||||
if (players[1].collided) players[0].score++;
|
||||
// increase speed
|
||||
if (frames_per_move > MAX_SPEED) frames_per_move--;
|
||||
// game over?
|
||||
if (players[0].score != players[1].score) {
|
||||
if (players[0].score >= MAX_SCORE)
|
||||
declare_winner(0);
|
||||
else if (players[1].score >= MAX_SCORE)
|
||||
declare_winner(1);
|
||||
}
|
||||
}
|
||||
|
||||
void play_game() {
|
||||
gameover = 0;
|
||||
init_game();
|
||||
players[0].human = 1;
|
||||
while (!gameover) {
|
||||
play_round();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
joy_install (joy_static_stddrv);
|
||||
play_game();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
#include <conio.h>
|
||||
#include <peekpoke.h>
|
||||
|
||||
int tmp; // need at least 1 variable
|
||||
|
||||
int main() {
|
||||
clrscr();
|
||||
bgcolor(COLOR_BLUE);
|
||||
textcolor(COLOR_WHITE);
|
||||
cputs("\r\n*** HELLO WORLD! ***");
|
||||
while (1) ;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
#include <conio.h>
|
||||
#include <peekpoke.h>
|
||||
|
||||
int tmp; // need at least 1 variable
|
||||
|
||||
int main() {
|
||||
clrscr();
|
||||
bgcolor(COLOR_BLUE);
|
||||
textcolor(COLOR_WHITE);
|
||||
cputs("\r\n*** HELLO WORLD! ***");
|
||||
while (1) ;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,308 @@
|
|||
|
||||
//#resource "vcs-ca65.h"
|
||||
|
||||
import "vcslib.ecs"
|
||||
import "sprites.ecs"
|
||||
import "score.ecs"
|
||||
import "sound.ecs"
|
||||
import "velocity.ecs"
|
||||
import "kernel1.ecs"
|
||||
import "random.ecs"
|
||||
|
||||
demo Main
|
||||
|
||||
using FrameLoop
|
||||
using Kernel2Digit, BCDMath
|
||||
using StandardKernel, Kernel1Sprite
|
||||
using KernelMissile, KernelCollide
|
||||
using SetXPos, SetHorizPos
|
||||
|
||||
entity Blank [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
........ 00
|
||||
---
|
||||
end
|
||||
entity Explode1 [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
x......x 08
|
||||
.x....x. 0a
|
||||
..x..x.. 0c
|
||||
........ 0e
|
||||
xx....xx 0e
|
||||
........ 0e
|
||||
..x..x.. 0c
|
||||
.x....x. 0a
|
||||
x......x 08
|
||||
---
|
||||
end
|
||||
entity Explode2 [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
..x..x.. 08
|
||||
.x....x. 0a
|
||||
x......x 0c
|
||||
...xx... 0e
|
||||
..x..x.. 0e
|
||||
...xx... 0e
|
||||
x......x 0c
|
||||
.x....x. 0a
|
||||
..x..x.. 08
|
||||
---
|
||||
end
|
||||
entity Explode3 [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
x..xx..x 08
|
||||
..x..x.. 0a
|
||||
.x....x. 0c
|
||||
..x..x.. 0e
|
||||
x......x 0e
|
||||
..x..x.. 0e
|
||||
.x....x. 0c
|
||||
..x..x.. 0a
|
||||
x..xx..x 08
|
||||
---
|
||||
end
|
||||
|
||||
entity Weird [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
.x...... 12
|
||||
.xx..... 14
|
||||
.xxx.... 16
|
||||
.x.xx... 18
|
||||
.xx.xx.. 1a
|
||||
.xxx.xx. 1c
|
||||
.x.x.x.x 1e
|
||||
.x.x.x.x 18
|
||||
---
|
||||
end
|
||||
|
||||
entity Cool [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
...xx... 48
|
||||
..xxxx.. 4a
|
||||
.xxxxxx. 4c
|
||||
xxxxxxxx 4e
|
||||
x..xx..x 4e
|
||||
x.xxx.xx 4e
|
||||
xxxxxxxx 4e
|
||||
xxxxxxxx 4e
|
||||
xxxxxxxx 4e
|
||||
xx....xx 4e
|
||||
xxxxxxxx 4e
|
||||
.xxxxxx. 4c
|
||||
..xxxx.. 4a
|
||||
---
|
||||
end
|
||||
|
||||
entity PlayerBC [Bitmap,Colormap]
|
||||
decode vcs_sprite
|
||||
---
|
||||
..xxxx.. 1a
|
||||
...xx... 1c
|
||||
...xx... 2e
|
||||
..xxxx.. 3c
|
||||
.xxxxxx. 4e
|
||||
xx.xx.xx 5e
|
||||
xxx..xxx 6e
|
||||
xx.xx.xx 7e
|
||||
xxxxxxxx 8e
|
||||
.xxxxxx. 9e
|
||||
---
|
||||
end
|
||||
|
||||
entity [BCDScore2]
|
||||
init scorecolor = $4e
|
||||
end
|
||||
/*
|
||||
entity [BCDScore2]
|
||||
init scorecolor = $ce
|
||||
end
|
||||
*/
|
||||
|
||||
// TODO
|
||||
entity [KernelSection,BGColor,Sprite,HasBitmap,HasXpos,HasColormap,HasYpos,TinyVelX]
|
||||
const lines = 30
|
||||
const bgcolor = $72
|
||||
var plyrflags = 0
|
||||
var xpos = 120
|
||||
var ypos = 22
|
||||
var bitmap = #Cool
|
||||
var colormap = #Cool
|
||||
var xvel = 11
|
||||
end
|
||||
entity [KernelSection,BGColor,Sprite,HasBitmap,HasXpos,HasColormap,HasYpos,TinyVelX]
|
||||
const lines = 35
|
||||
const bgcolor = $74
|
||||
var plyrflags = 3
|
||||
var xpos = 60
|
||||
var ypos = 10
|
||||
var bitmap = #Weird
|
||||
var colormap = #Weird
|
||||
var xvel = 5
|
||||
end
|
||||
entity [KernelSection,BGColor,Sprite,HasBitmap,HasXpos,HasColormap,HasYpos,TinyVelX]
|
||||
const lines = 40
|
||||
const bgcolor = $76
|
||||
var plyrflags = 0
|
||||
var xpos = 20
|
||||
var ypos = 15
|
||||
var bitmap = #Weird
|
||||
var colormap = #Cool
|
||||
var xvel = 9
|
||||
end
|
||||
entity Player1 [KernelSection,BGColor,Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
|
||||
const lines = 45
|
||||
const bgcolor = $78
|
||||
var plyrflags = 0
|
||||
var xpos = 70
|
||||
var ypos = 35
|
||||
var bitmap = #PlayerBC
|
||||
var colormap = #PlayerBC
|
||||
end
|
||||
entity PlayerMissile [HasXpos,HasYpos,Missile,FGColor]
|
||||
var xpos = 75
|
||||
var ypos = 100
|
||||
const fgcolor = $fe
|
||||
const index = 3
|
||||
end
|
||||
|
||||
system ShootingStuff
|
||||
// TODO
|
||||
on kernelsetup do foreach [Missile,FGColor]
|
||||
---
|
||||
lda {{<fgcolor}}
|
||||
ldy {{<index}}
|
||||
sta COLUP0-2,y
|
||||
---
|
||||
on postframe do foreach [Missile]
|
||||
---
|
||||
lda {{<ypos}}
|
||||
beq @nomissile
|
||||
dec {{<ypos}}
|
||||
@nomissile:
|
||||
---
|
||||
// TODO: nice to have constants here
|
||||
on joybutton do once
|
||||
---
|
||||
lda #138
|
||||
sta {{<PlayerMissile.ypos}}
|
||||
lda {{<Player1.xpos}}
|
||||
clc
|
||||
adc #4
|
||||
sta {{<PlayerMissile.xpos}}
|
||||
{{!playsound 0 2 5}}
|
||||
---
|
||||
// TODO: nice if we could do "with"
|
||||
on explode do select [Sprite,HasBitmap,HasColormap]
|
||||
---
|
||||
lda #{{eid Explode3}}-{{eid Blank}}
|
||||
sta {{base bitmap}},x
|
||||
sta {{base colormap}},x
|
||||
---
|
||||
// TODO: need to limit to cur player
|
||||
on explode do foreach [BCDScore2]
|
||||
---
|
||||
{{!AddBCD2 1}}
|
||||
---
|
||||
// TODO: nice if we could do "with"
|
||||
on explode do with [Missile]
|
||||
---
|
||||
lda #0
|
||||
sta {{<ypos}}
|
||||
{{!playsound 0 1 10}}
|
||||
---
|
||||
on preframeloop do once
|
||||
---
|
||||
nop
|
||||
---
|
||||
end
|
||||
|
||||
system BounceEnemies
|
||||
// TODO: event1, event2 in handler?
|
||||
on xlimit_right do with [TinyVelX]
|
||||
---
|
||||
lda {{<xvel}}
|
||||
eor #$0f
|
||||
sta {{<xvel}}
|
||||
---
|
||||
on xlimit_left do with [TinyVelX]
|
||||
---
|
||||
lda {{<xvel}}
|
||||
eor #$0f
|
||||
sta {{<xvel}}
|
||||
---
|
||||
end
|
||||
|
||||
system ExplodingAnimation
|
||||
on postframe do with [FrameCount]
|
||||
---
|
||||
lda {{<frame}}
|
||||
and #$0f
|
||||
bne @noframe16
|
||||
{{!frame16}}
|
||||
@noframe16:
|
||||
and #$07
|
||||
bne @noframe8
|
||||
{{!frame8}}
|
||||
@noframe8:
|
||||
---
|
||||
// TODO: forward jump conversion
|
||||
on frame16 do foreach [Sprite,-Player]
|
||||
//if bitmap > 0 and bitmap < #Blank then bitmap--
|
||||
---
|
||||
lda {{<bitmap}}
|
||||
beq @noinc
|
||||
cmp #{{eid Explode3}}-{{eid Blank}}+1
|
||||
bcs @noinc
|
||||
dec {{<bitmap}}
|
||||
@noinc:
|
||||
---
|
||||
end
|
||||
|
||||
using Random
|
||||
entity [Random8]
|
||||
var seed = 1
|
||||
end
|
||||
|
||||
system SpawnEnemies
|
||||
on preframeloop do foreach [Sprite,-Player]
|
||||
---
|
||||
{{!nextrand8}}
|
||||
and #15
|
||||
;sta {{<xvel}}
|
||||
---
|
||||
end
|
||||
|
||||
entity [FrameCount]
|
||||
end
|
||||
using FrameCounter, TinyMover
|
||||
|
||||
using Joystick, JoyButton, MoveJoyX with [Player]
|
||||
|
||||
using SoundEngine
|
||||
|
||||
entity SFXNull [SoundEffect]
|
||||
const duration = 0
|
||||
const sounddata = [0]
|
||||
end
|
||||
entity SFXExplode [SoundEffect]
|
||||
const duration = 10
|
||||
const sounddata = [$02,$03,$04,$08,$10,$20,$40,$20,$10,$a4]
|
||||
end
|
||||
entity SFXFire [SoundEffect]
|
||||
const duration = 10
|
||||
const sounddata = [$70,$60,$50,$40,$20,$10,$00,$50,$a4,$84]
|
||||
end
|
||||
|
||||
entity SFX1 [SoundChannel]
|
||||
end
|
||||
entity SFX2 [SoundChannel]
|
||||
end
|
||||
|
||||
end demo
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
|
||||
//#resource "vcs-ca65.h"
|
||||
|
||||
import "vcslib.ecs"
|
||||
import "sprites.ecs"
|
||||
|
||||
system Kernel1Sprite
|
||||
locals 7
|
||||
|
||||
on kernelsetup do with [Sprite]
|
||||
---
|
||||
; set player object flags
|
||||
lda {{<plyrflags}}
|
||||
sta NUSIZ0
|
||||
sta REFP0
|
||||
---
|
||||
|
||||
on kernelsetup do with
|
||||
[Sprite,HasBitmap,HasColormap,HasYpos]
|
||||
---
|
||||
; calculate screen height - ypos
|
||||
lda {{<lines}}
|
||||
clc
|
||||
adc #32
|
||||
sec
|
||||
sbc {{<ypos}}
|
||||
sta {{$5}}
|
||||
; calculate bitmap pointer
|
||||
stx {{$6}} ; save X (Sprite index)
|
||||
lda {{<bitmap}} ; deref bitmap
|
||||
tax
|
||||
lda {{<Bitmap:bitmapdata}},x
|
||||
sec
|
||||
sbc {{$5}}
|
||||
sta {{$0}} ; Y = sprite slot index
|
||||
lda {{>Bitmap:bitmapdata}},x
|
||||
sbc #0
|
||||
sta {{$1}}
|
||||
; get bitmap height
|
||||
lda {{<Bitmap:height}},x
|
||||
sta {{$4}}
|
||||
; calculate colormap pointer
|
||||
ldx {{$6}} ; restore X
|
||||
lda {{<colormap}} ; deref colormap
|
||||
tax
|
||||
lda {{<Colormap:colormapdata}},x
|
||||
sec
|
||||
sbc {{$5}}
|
||||
sta {{$2}}
|
||||
lda {{>Colormap:colormapdata}},x
|
||||
sbc #0
|
||||
sta {{$3}}
|
||||
; save ypos
|
||||
ldx {{$6}} ; restore X
|
||||
lda {{<ypos}}
|
||||
sta {{$5}}
|
||||
@nosprite:
|
||||
---
|
||||
|
||||
// TODO: what if > 1 player? or missile?
|
||||
on kernelsetup do with [Sprite,HasXpos]
|
||||
---
|
||||
ldy #0
|
||||
lda {{<xpos}}
|
||||
{{!SetHorizPos}}
|
||||
sta HMOVE
|
||||
---
|
||||
on prescanline do once
|
||||
---
|
||||
; draw player 0
|
||||
lda {{$4}} ; height
|
||||
dcp {{$5}} ; ypos
|
||||
bcs @DoDraw1
|
||||
lda #0
|
||||
.byte $2C
|
||||
@DoDraw1:
|
||||
lda ({{$0}}),y
|
||||
---
|
||||
on scanline do once
|
||||
---
|
||||
sta GRP0
|
||||
lda ({{$2}}),y
|
||||
sta COLUP0
|
||||
---
|
||||
on kerneldone do once
|
||||
---
|
||||
lda #0
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
---
|
||||
end
|
||||
|
||||
system KernelMissile
|
||||
locals 1
|
||||
// TODO: unroll loops
|
||||
on preframe do foreach [Missile,HasYpos] limit 1
|
||||
---
|
||||
lda {{<ypos}}
|
||||
sta {{$0}}
|
||||
---
|
||||
on scanline do foreach [Missile,HasYpos] limit 1
|
||||
---
|
||||
dec {{$0}}
|
||||
php
|
||||
pla
|
||||
sta ENAM0+{{const index}}-2
|
||||
---
|
||||
on kerneldone do foreach [Missile,HasYpos] limit 1
|
||||
---
|
||||
; skip 3 lines each kernel section
|
||||
lda #0
|
||||
sta ENAM0+{{const index}}-2
|
||||
dec {{$0}}
|
||||
dec {{$0}}
|
||||
dec {{$0}}
|
||||
---
|
||||
end
|
||||
|
||||
system KernelCollide
|
||||
locals 1
|
||||
on preframe do once
|
||||
---
|
||||
lda #$ff
|
||||
sta {{$0}} ; object index if collision
|
||||
---
|
||||
on kernelsetup do once
|
||||
---
|
||||
sta CXCLR ; clear collision flags
|
||||
---
|
||||
on kerneldone do with [Sprite]
|
||||
---
|
||||
lda CXM1P
|
||||
bpl @nocollide ; missile 1 <-> player 0?
|
||||
stx {{$0}} ; save object index
|
||||
@nocollide:
|
||||
---
|
||||
// TODO: somehow avoid select? pass arg to explode?
|
||||
on postframe do select [Sprite]
|
||||
---
|
||||
ldx {{$0}} ; get object index
|
||||
bmi @noexplode ; was there collision?
|
||||
{{!explode}}
|
||||
@noexplode:
|
||||
---
|
||||
end
|
|
@ -7,6 +7,7 @@ system Init
|
|||
.include "vcs-ca65.h"
|
||||
.macpack longbranch
|
||||
.define PAL 0
|
||||
.segment "STARTUP"
|
||||
__NMI:
|
||||
__Reset:
|
||||
__BRK:
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
/*
|
||||
See the "VCSLib Demo" example for more features.
|
||||
*/
|
||||
|
||||
//#resource "vcslib/vcs-ca65.inc"
|
||||
//#resource "vcslib/kernel.inc"
|
||||
|
||||
//#link "vcslib/vcslib.ca65"
|
||||
//#link "vcslib/frameloop.c"
|
||||
//#link "vcslib/mapper_3e.ca65"
|
||||
|
||||
#include <peekpoke.h>
|
||||
#include "vcslib/bcd.h"
|
||||
#include "vcslib/vcslib.h"
|
||||
|
||||
#pragma wrapped-call (push, bankselect, bank)
|
||||
#pragma code-name (push, "ROM0")
|
||||
|
||||
void init(void) {
|
||||
// init code here
|
||||
}
|
||||
|
||||
void my_preframe(void) {
|
||||
// stuff that happens before the frame is drawn
|
||||
TIA.colubk = 0x00;
|
||||
}
|
||||
|
||||
void my_kernel(void) {
|
||||
byte i;
|
||||
for (i=0; i<190; i++) {
|
||||
do_wsync();
|
||||
TIA.colubk = i;
|
||||
}
|
||||
}
|
||||
|
||||
void my_postframe(void) {
|
||||
// stuff that happens after the frame is drawn
|
||||
}
|
||||
|
||||
void kernel_loop() {
|
||||
while (1) {
|
||||
kernel_1();
|
||||
my_preframe();
|
||||
kernel_2();
|
||||
my_kernel();
|
||||
kernel_3();
|
||||
my_postframe();
|
||||
kernel_4();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma code-name (pop)
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
/*
|
||||
The main() function is called at startup.
|
||||
It resides in the shared ROM area (PERM).
|
||||
*/
|
||||
void main(void) {
|
||||
|
||||
// initialization
|
||||
init();
|
||||
|
||||
// main kernel loop
|
||||
kernel_loop();
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
#include <atari2600.h>
|
||||
#include <vcslib.h>
|
||||
#include <peekpoke.h>
|
||||
#include <mapper.h>
|
||||
|
||||
#ifdef __ATARI2600_MAPPER_3E__
|
||||
MAPPER_CART_ROM_KB(6); // 6K ROM
|
||||
#endif
|
||||
|
||||
#ifdef MAPPER_BANKED_ROM
|
||||
#define ROM_BANK(index) __attribute__((noinline, section(".rom"#index)))
|
||||
#else
|
||||
#define ROM_BANK(index)
|
||||
#endif
|
||||
|
||||
#define KERNEL_BANK 1
|
||||
|
||||
ROM_BANK(KERNEL_BANK) void my_preframe(void) {
|
||||
}
|
||||
|
||||
ROM_BANK(KERNEL_BANK) void my_doframe(void) {
|
||||
int i;
|
||||
// Set player sprite color
|
||||
TIA.colup0 = COLOR_CONV(0xfe);
|
||||
// Draw each scanline
|
||||
for (i=0; i<192; i++) {
|
||||
TIA.wsync = 0; // sync to scanline
|
||||
TIA.colubk = i; // set background color
|
||||
TIA.pf1 = i; // set playfield
|
||||
TIA.grp0 = i; // set sprite bitmap
|
||||
}
|
||||
TIA.grp0 = 0; // clear sprite
|
||||
TIA.colubk = 0; // clear background
|
||||
}
|
||||
|
||||
ROM_BANK(KERNEL_BANK) void my_postframe(void) {
|
||||
// additional post-frame processing goes here
|
||||
}
|
||||
|
||||
// Display kernel loop
|
||||
ROM_BANK(KERNEL_BANK) void do_kernel_loop() {
|
||||
// loop until reset released
|
||||
while (SW_RESET()) { }
|
||||
// loop forever
|
||||
while (1) {
|
||||
kernel_1();
|
||||
my_preframe();
|
||||
kernel_2();
|
||||
my_doframe();
|
||||
kernel_3();
|
||||
my_postframe();
|
||||
kernel_4();
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
// test banked rom call, if available
|
||||
#ifdef MAPPER_BANKED_ROM
|
||||
banked_call_rom(KERNEL_BANK, do_kernel_loop);
|
||||
#else
|
||||
do_kernel_loop();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#ifndef _BCD_H
|
||||
#define _BCD_H
|
||||
|
||||
#define BCD_ADD(a,b) { \
|
||||
int _temp = (b); \
|
||||
asm("sed"); \
|
||||
(a) += _temp; \
|
||||
asm("cld"); \
|
||||
}
|
||||
|
||||
#define BCD_SUB(a,b) { \
|
||||
int _temp = (b); \
|
||||
asm("sed"); \
|
||||
(a) -= _temp; \
|
||||
asm("cld"); \
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
.importzp tmp1, tmp2
|
||||
.import _reset_sprites
|
||||
.import Return
|
||||
|
||||
.export _bitmap48_kernel
|
||||
.export _bitmap48_setup
|
||||
.export _bitmap48_setaddress
|
||||
.export _bitmap48_setheight
|
||||
.export _bitmap48_ptr_0, _bitmap48_ptr_1, _bitmap48_ptr_2, _bitmap48_ptr_3, _bitmap48_ptr_4, _bitmap48_ptr_5
|
||||
|
||||
LoopCount = tmp1
|
||||
Temp = tmp2
|
||||
FontBuf = $1000 ;unused
|
||||
|
||||
; when the first STA GRP1 of the sequence happens
|
||||
.define B48_CYCLE 42
|
||||
|
||||
; this will get loaded into RAM
|
||||
; so we can change the offsets
|
||||
.segment "XDATA"
|
||||
|
||||
; Display the resulting 48x5 bitmap from FontBuf
|
||||
_bitmap48_kernel:
|
||||
sta WSYNC
|
||||
sta LoopCount
|
||||
dec LoopCount
|
||||
b48loop:
|
||||
ldy LoopCount ; counts backwards
|
||||
sta WSYNC ; sync to next scanline
|
||||
_bitmap48_ptr_0 = *+1
|
||||
lda FontBuf+0,y ; load B0 (1st sprite byte)
|
||||
sta GRP0 ; B0 -> [GRP0]
|
||||
_bitmap48_ptr_1 = *+1
|
||||
lda FontBuf+5,y ; load B1 -> A
|
||||
sta GRP1 ; B1 -> [GRP1], B0 -> GRP0
|
||||
_bitmap48_ptr_2 = *+1
|
||||
lda FontBuf+10,y ; load B2 -> A
|
||||
sta GRP0 ; B2 -> [GRP0], B1 -> GRP1
|
||||
_bitmap48_ptr_5 = *+1
|
||||
lda FontBuf+25,y ; load B5 -> A
|
||||
sta Temp ; B5 -> temp
|
||||
_bitmap48_ptr_4 = *+1
|
||||
ldx FontBuf+20,y ; load B4 -> X
|
||||
_bitmap48_ptr_3 = *+1
|
||||
lda FontBuf+15,y ; load B3 -> A
|
||||
ldy Temp ; load B5 -> Y
|
||||
sta GRP1 ; B3 -> [GRP1]; B2 -> GRP0
|
||||
stx GRP0 ; B4 -> [GRP0]; B3 -> GRP1
|
||||
sty GRP1 ; B5 -> [GRP1]; B4 -> GRP0
|
||||
sta GRP0 ; ?? -> [GRP0]; B5 -> GRP1
|
||||
b48dec:
|
||||
dec LoopCount ; go to next line
|
||||
bpl b48loop ; repeat until < 0
|
||||
jmp _reset_sprites
|
||||
|
||||
; only used by _bitmap48_setaddress
|
||||
_bitmap48_height: .byte 8
|
||||
|
||||
; TODO: can we write even when RAM not selected?
|
||||
.proc _bitmap48_setaddress
|
||||
sta _bitmap48_ptr_0+$400+0
|
||||
stx _bitmap48_ptr_0+$400+1
|
||||
jsr add_height_ax
|
||||
sta _bitmap48_ptr_1+$400+0
|
||||
stx _bitmap48_ptr_1+$400+1
|
||||
jsr add_height_ax
|
||||
sta _bitmap48_ptr_2+$400+0
|
||||
stx _bitmap48_ptr_2+$400+1
|
||||
jsr add_height_ax
|
||||
sta _bitmap48_ptr_3+$400+0
|
||||
stx _bitmap48_ptr_3+$400+1
|
||||
jsr add_height_ax
|
||||
sta _bitmap48_ptr_4+$400+0
|
||||
stx _bitmap48_ptr_4+$400+1
|
||||
jsr add_height_ax
|
||||
sta _bitmap48_ptr_5+$400+0
|
||||
stx _bitmap48_ptr_5+$400+1
|
||||
rts
|
||||
add_height_ax:
|
||||
clc
|
||||
adc _bitmap48_height
|
||||
bcc :+
|
||||
inx
|
||||
: rts
|
||||
.endproc
|
||||
|
||||
.proc _bitmap48_setheight
|
||||
sta _bitmap48_height+$400
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.code
|
||||
.proc _bitmap48_setup
|
||||
lda #THREE_COPIES
|
||||
sta NUSIZ0
|
||||
sta NUSIZ1
|
||||
sta WSYNC
|
||||
SLEEPR B48_CYCLE-7
|
||||
sta RESP0
|
||||
sta RESP1
|
||||
sta HMCLR
|
||||
lda #$10
|
||||
sta HMP1
|
||||
sta WSYNC
|
||||
sta HMOVE
|
||||
lda #1
|
||||
sta VDELP0
|
||||
sta VDELP1
|
||||
sta REFP0
|
||||
sta REFP1
|
||||
rts
|
||||
.endproc
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.setcpu "6502x"
|
||||
.macpack longbranch
|
||||
|
||||
.global _kernel_2pp_4pfa
|
||||
.global _kernel_2pfasync
|
||||
|
||||
.importzp _k_height
|
||||
.importzp _k_ypos
|
||||
.importzp _k_bitmap
|
||||
.importzp _k_colormap
|
||||
.importzp _k_playfield
|
||||
.importzp tmp1
|
||||
.import _k_asyncpf
|
||||
.import _reset_gfx
|
||||
|
||||
_k_pftmp = tmp1 ; no one's using this just now, right?
|
||||
|
||||
.include "kernel.inc"
|
||||
|
||||
.code
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Display Kernel
|
||||
; - two double-line players w/ colormap
|
||||
; - two missiles, variable height
|
||||
; - versatile playfield, 4 lines per change (no cross page)
|
||||
; Modifies: _k_ypos, _k_playfield
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
.proc _kernel_2pp_4pfa
|
||||
tay
|
||||
ldx #0
|
||||
@loop:
|
||||
; first two lines, fetch PF0 and PF1
|
||||
DO_PCOLOR 0
|
||||
DO_PCOLOR 1
|
||||
DO_DRAW 0,1
|
||||
DO_DRAW 1,0
|
||||
DO_MISSILE 2
|
||||
DO_MISSILE_NOP 3
|
||||
DO_VERSATILE_PF_1
|
||||
dey
|
||||
; second two lines, fetch PF2 and write PF registers
|
||||
DO_PCOLOR 0
|
||||
DO_PCOLOR 1
|
||||
DO_DRAW 0,1
|
||||
DO_DRAW 1,0
|
||||
DO_MISSILE_NOP 2
|
||||
DO_MISSILE 3
|
||||
DO_VERSATILE_PF_2
|
||||
dey
|
||||
jne @loop
|
||||
jmp _reset_gfx
|
||||
.endproc
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Display Kernel
|
||||
; - async playfield, 6 lines per change
|
||||
; - playfield data should be page-aligned
|
||||
; Modifies: _k_playfield
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
.proc _kernel_2pfasync
|
||||
tay
|
||||
loop2:
|
||||
dey
|
||||
ldx #5
|
||||
loop:
|
||||
DO_PFWRITE_2
|
||||
DO_WSYNC
|
||||
lda _k_asyncpf,y
|
||||
sta _k_pftmp,x
|
||||
DO_PFWRITE
|
||||
stx COLUPF ; fun vfx rainbow
|
||||
dex
|
||||
bmi loop2
|
||||
dey
|
||||
jne loop
|
||||
jmp _reset_gfx
|
||||
.endproc
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,435 @@
|
|||
|
||||
//#resource "vcs-ca65.inc"
|
||||
//#resource "kernel.inc"
|
||||
|
||||
//#link "demo_kernels.ca65"
|
||||
|
||||
//#link "libvcs.ca65"
|
||||
//#link "mapper_3e.ca65"
|
||||
//#link "xdata.ca65"
|
||||
//#link "frameloop.c"
|
||||
//#link "scorepf.ca65"
|
||||
//#link "rand8.ca65"
|
||||
//#link "bitmap48.ca65"
|
||||
//#link "tinyfont48.c"
|
||||
//#link "score6.ca65"
|
||||
|
||||
//#link "sound.ca65"
|
||||
//#link "music.ca65"
|
||||
//#link "demo_sounds.c"
|
||||
|
||||
#include <peekpoke.h>
|
||||
#include "bcd.h"
|
||||
#include "vcslib.h"
|
||||
|
||||
#define NSPRITES 2
|
||||
#define NOBJS 5
|
||||
|
||||
#pragma bss-name (push,"ZEROPAGE")
|
||||
|
||||
/*
|
||||
Attributes (position, etc) for all objects.
|
||||
These map directly to player0/player1/missile0/missile1/ball.
|
||||
(But they don't have to, if you write the code differently.)
|
||||
*/
|
||||
byte xpos[NOBJS];
|
||||
byte ypos[NOBJS];
|
||||
|
||||
/*
|
||||
These are variables used by the display kernels.
|
||||
Some of them are modified by the kernels, like k_ypos,
|
||||
so they must be initialized before the kernel starts.
|
||||
*/
|
||||
byte k_height[NOBJS];
|
||||
byte k_ypos[NOBJS];
|
||||
byte* k_bitmap[NSPRITES];
|
||||
byte* k_colormap[NSPRITES];
|
||||
const byte* k_playfield;
|
||||
|
||||
/*
|
||||
BCD-encoded score, used by score display routines.
|
||||
*/
|
||||
byte bcd_score[3]; // support 6-digit score (3 bytes)
|
||||
|
||||
#pragma bss-name (pop)
|
||||
|
||||
/*
|
||||
We build a number of 30x5 bitmaps with tinyfont48
|
||||
*/
|
||||
#define NCAPTIONS 4
|
||||
|
||||
// the font doesn't map exactly to ASCII
|
||||
#pragma charmap (0x20, 0x5b)
|
||||
#pragma charmap (0x21, 0x29)
|
||||
#pragma charmap (0x5f, 0x2d)
|
||||
|
||||
// use the same ROM bank as tinyfont
|
||||
#pragma bss-name(push, "XDATA")
|
||||
|
||||
// these have to be either in PERM or in XDATA
|
||||
const char* const CAPTIONS[NCAPTIONS] = {
|
||||
"HELLO WORLD!",
|
||||
" WELCOME TO ",
|
||||
"**[VCSLIB[**",
|
||||
"C FOR 2600!!",
|
||||
};
|
||||
|
||||
// used by tinyfont48 routine
|
||||
byte font_bitmap[NCAPTIONS][32]; // at least 30 bytes each
|
||||
|
||||
#pragma bss-name(pop)
|
||||
|
||||
// music data (demo_sounds.c)
|
||||
extern const byte music_1[];
|
||||
extern const byte music_2[];
|
||||
|
||||
// kernel function for player sprites + background
|
||||
extern void fastcall kernel_2pp_4pfa(byte nlines);
|
||||
|
||||
#pragma code-name (push, "ROM2")
|
||||
#pragma rodata-name (push, "ROM2")
|
||||
|
||||
// kernel function for banner
|
||||
extern void fastcall kernel_2pfasync(byte nlines);
|
||||
|
||||
// asynchronous playfield bitmap
|
||||
/*{w:48,h:8,flip:1}*/
|
||||
const byte k_asyncpf[6*8] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x80,0x0C,0xCE,0x30,0xEE,0x10,
|
||||
0x40,0x92,0x50,0x00,0x49,0x28,
|
||||
0x20,0x50,0x50,0x00,0x49,0x50,
|
||||
0x20,0x50,0x4E,0x00,0x4E,0x28,
|
||||
0x20,0x52,0x41,0x00,0x49,0x50,
|
||||
0x20,0x4C,0x4E,0x00,0xEE,0x20,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
// number of lines in the 2pp sprite kernel
|
||||
#define NLINES (192-44-48)
|
||||
|
||||
// Player sprite bitmap
|
||||
/*{w:8,h:17,flip:1}*/
|
||||
const byte Frame0[17] = {
|
||||
0b1100001,
|
||||
0b100010,
|
||||
0b100100,
|
||||
0b101100,
|
||||
0b111000,
|
||||
0b10111001,
|
||||
0b10111010,
|
||||
0b1111100,
|
||||
0b11000,
|
||||
0b111100,
|
||||
0b1100110,
|
||||
0b1011010,
|
||||
0b1111110,
|
||||
0b1111110,
|
||||
0b1010110,
|
||||
0b1111110,
|
||||
0b10111101,
|
||||
};
|
||||
|
||||
// Player sprite color map
|
||||
const byte ColorFrame0[17+1] = {
|
||||
0xF4, // bottom
|
||||
0xF6,
|
||||
0x84,
|
||||
0x86,
|
||||
0x88,
|
||||
0xC2,
|
||||
0xC4,
|
||||
0xC6,
|
||||
0xC8,
|
||||
0x18,
|
||||
0x28,
|
||||
0x18,
|
||||
0x18,
|
||||
0x18,
|
||||
0x18,
|
||||
0x16,
|
||||
0x5c, // top
|
||||
0x5c, // (duplicated)
|
||||
};
|
||||
|
||||
// move player with joystick
|
||||
void move_joy(void) {
|
||||
if (JOY_UP(0)) {
|
||||
if (ypos[1] > 0x22) ypos[1]--;
|
||||
}
|
||||
if (JOY_DOWN(0)) {
|
||||
if (ypos[1] < 0x22 + 16 + NLINES/2) ypos[1]++;
|
||||
}
|
||||
if (JOY_LEFT(0)) {
|
||||
if (xpos[1] > 0x3) xpos[1]--;
|
||||
TIA.refp1 = NO_REFLECT;
|
||||
}
|
||||
if (JOY_RIGHT(0)) {
|
||||
if (xpos[1] < 0x9c) xpos[1]++;
|
||||
TIA.refp1 = REFLECT;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup an object for the kernel routines.
|
||||
void setup_object(byte index) {
|
||||
k_ypos[index] = ypos[index] >> 1;
|
||||
set_horiz_pos((index<<8) | xpos[index]);
|
||||
}
|
||||
|
||||
// Setup a player object for the kernel routines.
|
||||
void setup_player(byte nlines, byte index) {
|
||||
byte y = ypos[index] >> 1;
|
||||
byte ofs = nlines - y + 1;
|
||||
k_bitmap[index] = (char*) Frame0 - ofs;
|
||||
ofs -= 1;
|
||||
ofs -= ypos[index] & 1;
|
||||
k_colormap[index] = (char*) ColorFrame0 - ofs;
|
||||
k_ypos[index] = y;
|
||||
set_horiz_pos((index<<8) | xpos[index]);
|
||||
}
|
||||
|
||||
/*
|
||||
This function runs after VSYNC, and before the display kernel.
|
||||
*/
|
||||
void my_preframe(void) {
|
||||
TIA.vdelp0 = ypos[0];
|
||||
TIA.vdelp1 = ypos[1];
|
||||
TIA.nusiz0 = ONE_COPY | MSBL_SIZE4;
|
||||
TIA.nusiz1 = DOUBLE_SIZE | MSBL_SIZE4;
|
||||
setup_player(NLINES/2, P0);
|
||||
setup_player(NLINES/2, P1);
|
||||
setup_object(M0);
|
||||
setup_object(M1);
|
||||
apply_hmove();
|
||||
// k_playfield = (char*) 0xf000;
|
||||
}
|
||||
|
||||
/*
|
||||
Versatile playfield data is pretty easy:
|
||||
FIrst byte contains the register, second byte has the value.
|
||||
It's in reverse order.
|
||||
*/
|
||||
const byte VersatilePlayfield_data_e0_b0[] = {
|
||||
0x00, 0x3F, 0x00, 0x3F, 0x00, 0x0E, 0xAA, 0x0E,
|
||||
0x18, 0x08, 0x02, 0x09, 0x00, 0x0F, 0x08, 0x0F,
|
||||
0x7F, 0x0F, 0x3E, 0x0F, 0x1C, 0x0F, 0x08, 0x0F,
|
||||
0xC2, 0x08, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F,
|
||||
0x00, 0x0E, 0x1E, 0x0E, 0x08, 0x08, 0x7F, 0x0E,
|
||||
0xFE, 0x0E, 0x38, 0x0E, 0x06, 0x08, 0x01, 0x0A,
|
||||
0xa0, 0x09
|
||||
};
|
||||
|
||||
/*
|
||||
This function is called to display the frame.
|
||||
*/
|
||||
void my_doframe(void) {
|
||||
byte caption_index; // which message to display? (0..NCAPTIONS-1)
|
||||
|
||||
// draw the VCSLIB title using the async playfield kernel
|
||||
TIA.ctrlpf = 0;
|
||||
do_wsync();
|
||||
TIA.colubk = COLOR_CONV(0x68);
|
||||
TIA.colupf = COLOR_CONV(0xa2);
|
||||
kernel_2pfasync(42);
|
||||
|
||||
// draw the sprites + playfield
|
||||
TIA.colubk = 0x0;
|
||||
TIA.ctrlpf = PF_REFLECT;
|
||||
kernel_2pp_4pfa(NLINES/2); // each line is doubled
|
||||
|
||||
// draw the playfield 2-digit score
|
||||
TIA.ctrlpf = PF_SCORE;
|
||||
do_wsync();
|
||||
TIA.colubk = COLOR_CONV(0xa2);
|
||||
TIA.colup0 = COLOR_CONV(0x2e);
|
||||
TIA.colup1 = COLOR_CONV(0x8e);
|
||||
scorepf_kernel();
|
||||
TIA.wsync = 0;
|
||||
TIA.colubk = 0;
|
||||
TIA.ctrlpf = PF_REFLECT;
|
||||
|
||||
// draw a 12-letter caption using bitmap48
|
||||
TIA.colubk = COLOR_CONV(0x82);
|
||||
// cycle between the messages
|
||||
// (we are low on memory, so use whatever counter is available :P)
|
||||
caption_index = ((byte)music_ptr>>3) & (NCAPTIONS-1);
|
||||
bitmap48_setheight(5); // must call before bitmap48_setaddress()
|
||||
bitmap48_setaddress(font_bitmap[caption_index]);
|
||||
bitmap48_setup();
|
||||
bitmap48_kernel(5); // 5 lines high
|
||||
|
||||
// draw the 6-digit score (again using bitmap48)
|
||||
score6_build();
|
||||
bitmap48_kernel(8); // 8 lines high
|
||||
}
|
||||
|
||||
/*
|
||||
This function is called after the frame is displayed,
|
||||
and before overscan.
|
||||
*/
|
||||
void my_postframe(void) {
|
||||
// move P1
|
||||
move_joy();
|
||||
// move P0
|
||||
if (++xpos[P0] > 150) {
|
||||
xpos[P0] = 0;
|
||||
}
|
||||
if (++ypos[P0] > 100) {
|
||||
ypos[P0] = 0;
|
||||
}
|
||||
// set missile positions
|
||||
ypos[M0] = 80;
|
||||
ypos[M1] = 82;
|
||||
xpos[M0] = 10;
|
||||
xpos[M1] = 155;
|
||||
// fire buttons
|
||||
if (JOY_FIRE(0)) {
|
||||
sound_play(7);
|
||||
score6_add(0x0199);
|
||||
}
|
||||
if (JOY_FIRE(1)) {
|
||||
BCD_ADD(bcd_score[0], 1);
|
||||
}
|
||||
// update sound
|
||||
sound_update();
|
||||
music_update();
|
||||
// update sound meter
|
||||
k_height[M0] = sndchan_timer[0]*4;
|
||||
k_height[M1] = sndchan_timer[1]*4;
|
||||
// prepare score for next frame
|
||||
scorepf_build();
|
||||
// play more music?
|
||||
if (SW_SELECT()) { music_play(music_2); }
|
||||
}
|
||||
|
||||
/*
|
||||
kernel_loop() is the main loop routine.
|
||||
It's wrapped with wrapped-call so that it
|
||||
switches to the appropriate bank (the one
|
||||
that contains the function) before running.
|
||||
|
||||
kernel_1() etc. do not have to be wrapped,
|
||||
as long as they are called from a function
|
||||
that is itself wrapped and in the same bank.
|
||||
*/
|
||||
|
||||
#pragma wrapped-call (push, bankselect, bank)
|
||||
|
||||
void kernel_loop() {
|
||||
while (1) {
|
||||
kernel_1();
|
||||
my_preframe();
|
||||
kernel_2();
|
||||
my_doframe();
|
||||
kernel_3();
|
||||
my_postframe();
|
||||
kernel_4();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
#pragma rodata-name (pop)
|
||||
#pragma code-name (pop)
|
||||
|
||||
|
||||
/*
|
||||
These are just test routines, they can be removed.
|
||||
*/
|
||||
#pragma code-name(push, "XDATA");
|
||||
#pragma data-name(push, "XDATA");
|
||||
long int var = 0xdeadbeef;
|
||||
int testfn() {
|
||||
return 0x1234;
|
||||
}
|
||||
#pragma code-name(pop);
|
||||
#pragma data-name(pop);
|
||||
|
||||
#pragma wrapped-call (push, ramselect, 0)
|
||||
void ramtest(void) {
|
||||
char x;
|
||||
POKE(0x17f0, 0xaa);
|
||||
x = PEEK(0x17f0);
|
||||
if (x != 0xaa) asm("brk");
|
||||
x = PEEK(&var); // 0xdeadbeef
|
||||
if (x != 0xef) asm("brk");
|
||||
x = PEEK((char*)testfn+4); // rts from testfn()
|
||||
if (x != 0x60) asm("brk");
|
||||
// TODO: doesn't work when ram selected
|
||||
xramset((char*)0x13e0);
|
||||
xramwrite(0x55);
|
||||
x = xramread(); // TODO: selects ROM0 here
|
||||
if (x != 0x55) asm("brk");
|
||||
}
|
||||
#pragma wrapped-call (pop)
|
||||
/* end of test routines */
|
||||
|
||||
|
||||
/*
|
||||
init() runs first, and runs out of ROM0, which is
|
||||
selected at power-up.
|
||||
*/
|
||||
|
||||
#pragma wrapped-call (push, bankselect, bank)
|
||||
#pragma code-name (push, "ROM0")
|
||||
|
||||
void init(void) {
|
||||
byte i;
|
||||
|
||||
// set up initial object positions
|
||||
xpos[P1] = 80;
|
||||
ypos[P1] = 50;
|
||||
ypos[M0] = 30;
|
||||
ypos[M1] = 40;
|
||||
ypos[BALL] = 60;
|
||||
|
||||
// set up kernel variables
|
||||
k_playfield = VersatilePlayfield_data_e0_b0-1; // kernel expects offset to be -1
|
||||
k_height[P0] = 16;
|
||||
k_height[P1] = 16;
|
||||
k_height[M0] = 0; // multiple of 4
|
||||
k_height[M1] = 4; // multiple of 4
|
||||
k_height[BALL] = 10;
|
||||
|
||||
// initial BCD scores
|
||||
bcd_score[0] = 0x12;
|
||||
bcd_score[1] = 0x34;
|
||||
|
||||
// build bitmap for caption messages
|
||||
for (i=0; i<NCAPTIONS; i++) {
|
||||
tinyfont48_build(font_bitmap[i], CAPTIONS[i]);
|
||||
}
|
||||
|
||||
// start playing music
|
||||
music_play(music_1);
|
||||
}
|
||||
|
||||
#pragma code-name (pop)
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
/*
|
||||
The main() function is called at startup.
|
||||
It resides in the shared ROM area (PERM).
|
||||
*/
|
||||
void main(void) {
|
||||
|
||||
// call functions once for "Analyze CPU Timing" button
|
||||
// (bank-switching does an indirect jump which isn't detected)
|
||||
asm("lda #4");
|
||||
asm("jsr _kernel_2pp_4pfa");
|
||||
asm("lda #4");
|
||||
asm("jsr _kernel_2pfasync");
|
||||
|
||||
// copy initialized data to XRAM
|
||||
copyxdata();
|
||||
|
||||
// test XRAM (can be removed)
|
||||
ramtest();
|
||||
|
||||
// initialization
|
||||
init();
|
||||
|
||||
// main kernel loop
|
||||
kernel_loop();
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "vcslib.h"
|
||||
|
||||
#pragma warn (const-comparison, off)
|
||||
|
||||
void kernel_1(void) {
|
||||
// Vertical Sync signal
|
||||
TIA.vsync = START_VERT_SYNC;
|
||||
TIA.wsync = 0x00;
|
||||
// Test reset switch
|
||||
if (SW_RESET()) {
|
||||
asm("brk");
|
||||
}
|
||||
TIA.wsync = 0x00;
|
||||
TIA.wsync = 0x00;
|
||||
TIA.vsync = STOP_VERT_SYNC;
|
||||
|
||||
// Vertical Blank (preframe)
|
||||
RIOT.tim64t = VBLANK_TIM64;
|
||||
}
|
||||
|
||||
void kernel_2(void) {
|
||||
while (RIOT.intim != 0) {}
|
||||
|
||||
// Turn on beam
|
||||
TIA.wsync = 0x00;
|
||||
TIA.vblank = ENABLE_TIA;
|
||||
|
||||
// Display frame (doframe)
|
||||
#ifdef PAL
|
||||
RIOT.t1024t = KERNAL_T1024;
|
||||
#else
|
||||
RIOT.tim64t = KERNAL_TIM64;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kernel_3(void) {
|
||||
while (RIOT.intim != 0) {}
|
||||
|
||||
// Turn off beam
|
||||
TIA.wsync = 0x00;
|
||||
TIA.vblank = DISABLE_TIA;
|
||||
|
||||
// Overscan (postframe)
|
||||
RIOT.tim64t = OVERSCAN_TIM64;
|
||||
}
|
||||
|
||||
void kernel_4(void) {
|
||||
while (RIOT.intim != 0) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
|
||||
.macro DO_WSYNC
|
||||
sta WSYNC
|
||||
.endmacro
|
||||
|
||||
; 16-17 cycles
|
||||
; modifies _k_ypos
|
||||
.macro DO_DRAW_A index
|
||||
lda _k_height+index
|
||||
dcp _k_ypos+index
|
||||
bcs :+
|
||||
lda #0
|
||||
.byte $2C
|
||||
:
|
||||
lda (_k_bitmap+index*2),y
|
||||
.endmacro
|
||||
|
||||
; 19-20 cycles (unless WSYNC)
|
||||
; modifies _k_ypos
|
||||
.macro DO_DRAW index,wsync
|
||||
DO_DRAW_A index
|
||||
.if wsync
|
||||
DO_WSYNC
|
||||
.endif
|
||||
sta GRP0+index
|
||||
.endmacro
|
||||
|
||||
; 8 cycles
|
||||
.macro DO_PCOLOR index
|
||||
lda (_k_colormap+index*2),y
|
||||
sta COLUP0+index
|
||||
.endmacro
|
||||
|
||||
; 13-14 cycles
|
||||
; modifies _k_playfield (can't cross page boundary)
|
||||
.macro DO_PF index
|
||||
lda (_k_playfield,x)
|
||||
sta _k_pftmp + index
|
||||
inc _k_playfield
|
||||
.endmacro
|
||||
|
||||
; 18 cycles
|
||||
.macro DO_PFWRITE
|
||||
lda _k_pftmp+0
|
||||
sta PF0
|
||||
lda _k_pftmp+1
|
||||
sta PF1
|
||||
lda _k_pftmp+2
|
||||
sta PF2
|
||||
.endmacro
|
||||
|
||||
; 18 cycles
|
||||
.macro DO_PFWRITE_2
|
||||
lda _k_pftmp+3
|
||||
sta PF0
|
||||
lda _k_pftmp+4
|
||||
sta PF1
|
||||
lda _k_pftmp+5
|
||||
sta PF2
|
||||
.endmacro
|
||||
|
||||
; 7-8 cycles
|
||||
.macro DO_VERSATILE_PF_1
|
||||
lda (_k_playfield),y
|
||||
tax
|
||||
.endmacro
|
||||
|
||||
; 9-10 cycles
|
||||
.macro DO_VERSATILE_PF_2
|
||||
lda (_k_playfield),y
|
||||
sta $40,x ; use TIA mirror
|
||||
.endmacro
|
||||
|
||||
; 13 cycles
|
||||
; modifies _k_ypos
|
||||
.macro DO_MISSILE index
|
||||
lda _k_height+index
|
||||
dcp _k_ypos+index
|
||||
sbc #$fe
|
||||
sta ENAM0-2+index
|
||||
.endmacro
|
||||
|
||||
; 5 cycles
|
||||
; modifies _k_ypos
|
||||
.macro DO_MISSILE_NOP index
|
||||
dcp _k_ypos+index
|
||||
.endmacro
|
||||
|
||||
; 13 cycles
|
||||
.macro DO_MISSILE_PIXEL index
|
||||
cpy _k_ypos+index
|
||||
php
|
||||
pla
|
||||
sta ENAM0-2+index
|
||||
.endmacro
|
||||
|
||||
.macro RESET_GFX
|
||||
lda #0
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
sta PF0
|
||||
sta PF1
|
||||
sta PF2
|
||||
.endmacro
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.global _set_horiz_pos
|
||||
.export _reset_gfx
|
||||
.export _reset_sprites
|
||||
.export Return
|
||||
|
||||
;;;
|
||||
|
||||
; SetHorizPos routine
|
||||
; A = X coordinate
|
||||
; X = player number (0 or 1)
|
||||
; must be in rodata segment because of alignment
|
||||
.rodata
|
||||
.align $10
|
||||
.proc _set_horiz_pos
|
||||
sec ; set carry flag
|
||||
sta WSYNC ; start a new line
|
||||
:
|
||||
sbc #15 ; subtract 15
|
||||
bcs :- ; branch until negative
|
||||
eor #7 ; calculate fine offset
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
sta HMP0,x ; set fine offset
|
||||
sta RESP0,x ; fix coarse position
|
||||
sta WSYNC ; won't overrun if X < 150
|
||||
rts
|
||||
.endproc
|
||||
.code
|
||||
|
||||
;;;
|
||||
|
||||
_reset_gfx:
|
||||
lda #0
|
||||
sta PF0
|
||||
sta PF1
|
||||
sta PF2
|
||||
_reset_sprites:
|
||||
lda #0
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
Return:
|
||||
rts
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
.importzp tmp4, ptr3, ptr4
|
||||
.import callax
|
||||
|
||||
.export _bankselect
|
||||
.export _ramselect
|
||||
.export _xramset
|
||||
.export _xramwrite
|
||||
.export _xramread
|
||||
|
||||
.zeropage
|
||||
|
||||
; current ROM bank index (not used for RAM)
|
||||
_currbank: .res 1
|
||||
|
||||
; must be in shared ROM bank
|
||||
.code
|
||||
|
||||
;extern void bankselect(char index);
|
||||
;#pragma wrapped-call (push, bankselect, 0)
|
||||
;#pragma code-name (push, "ROM0")
|
||||
;
|
||||
; Wrapper function for selecting a ROM bank
|
||||
;NOTE: this does not preserve Y
|
||||
_bankselect:
|
||||
tay
|
||||
; save the old bank index
|
||||
lda _currbank
|
||||
pha
|
||||
; select the new bank
|
||||
lda tmp4
|
||||
sta _currbank
|
||||
sta $3F
|
||||
tya
|
||||
; call the wrapped function
|
||||
call_wrapped_and_exit:
|
||||
jsr call_wrapped_func
|
||||
; restore the previous bank
|
||||
pla
|
||||
sta _currbank
|
||||
sta $3F
|
||||
rts
|
||||
|
||||
; Wrapper function for selecting the RAM bank
|
||||
; This must be called from a ROM bank, because it
|
||||
; will always exit into the last selected ROM bank
|
||||
;NOTE: this does not preserve Y
|
||||
_ramselect:
|
||||
tay
|
||||
; save the old bank index
|
||||
lda _currbank
|
||||
pha
|
||||
; select the RAM bank
|
||||
lda tmp4
|
||||
sta $3E
|
||||
lda #0 ; needed for Stella signature?
|
||||
tya
|
||||
jmp call_wrapped_and_exit
|
||||
|
||||
; Used to do: jsr (ptr4)
|
||||
call_wrapped_func:
|
||||
jmp (ptr4)
|
||||
|
||||
; Write a byte to address (ptr3) in RAM bank 0
|
||||
_xramwrite:
|
||||
; select the RAM bank
|
||||
ldx #0
|
||||
stx $3E
|
||||
sta (ptr3,x)
|
||||
restore_bank:
|
||||
ldx _currbank
|
||||
stx $3F
|
||||
rts
|
||||
|
||||
; Read a byte to address (ptr4) in RAM bank 0
|
||||
_xramread:
|
||||
; modify the ptr4
|
||||
; select the RAM bank
|
||||
ldx #0
|
||||
stx $3E
|
||||
lda (ptr4,x)
|
||||
jmp restore_bank
|
||||
|
||||
; Set the xram read/write address (in ptr3/ptr4)
|
||||
_xramset:
|
||||
sta ptr4+0
|
||||
sta ptr3+0
|
||||
stx ptr4+1 ; read
|
||||
txa
|
||||
ora #%00000100
|
||||
sta ptr3+1 ; write
|
||||
rts
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.export _music_update
|
||||
.exportzp _music_ptr
|
||||
|
||||
.import _sound_duration
|
||||
.import _sound_play
|
||||
|
||||
.zeropage
|
||||
|
||||
_music_ptr: .res 2
|
||||
_music_timer: .res 1
|
||||
|
||||
.importzp _sndchan_sfx
|
||||
.importzp _sndchan_timer
|
||||
|
||||
.importzp ptr3
|
||||
musicdata = ptr3
|
||||
|
||||
.segment "ROM3"
|
||||
|
||||
; 00-3f: play note
|
||||
; 40-7f: play sound effect
|
||||
; 80-fe: set duration until next note
|
||||
; ff: stop music
|
||||
|
||||
.proc _music_update
|
||||
; is music timer up?
|
||||
lda _music_timer
|
||||
bmi @Done
|
||||
beq @NextData
|
||||
dec _music_timer
|
||||
jmp @Done
|
||||
; Timer ran out, so fetch next note
|
||||
@NextData:
|
||||
ldx #0
|
||||
lda (_music_ptr,x)
|
||||
bmi @LoadDuration
|
||||
; >= $40, play sound effect
|
||||
cmp #$40
|
||||
bcs @PlaySound
|
||||
; < $80, play next note
|
||||
; but which channel to use?
|
||||
; whichever has the lower timer counter
|
||||
tay
|
||||
ldx #0
|
||||
ldy _sndchan_timer+0
|
||||
cpy _sndchan_timer+1
|
||||
bcc @Chan0Free ; timer0 < timer 1?
|
||||
inx
|
||||
@Chan0Free:
|
||||
; set the sound channels
|
||||
tay
|
||||
lda FREQZ,y
|
||||
sta AUDF0,x
|
||||
lda TONEZ,y
|
||||
sta AUDC0,x
|
||||
; set the sound channel
|
||||
lda #0
|
||||
sta _sndchan_sfx,x ; sound 0 = envelope
|
||||
lda _sound_duration+0
|
||||
sta _sndchan_timer,x ; set channel timer
|
||||
jmp @IncMusic
|
||||
@LoadDuration:
|
||||
cmp #$ff
|
||||
beq @Done ; end of sound
|
||||
and #$7f
|
||||
sta _music_timer ; set music timer
|
||||
@IncMusic:
|
||||
inc _music_ptr
|
||||
bne @Done
|
||||
inc _music_ptr+1
|
||||
@Done:
|
||||
rts
|
||||
@PlaySound:
|
||||
sec
|
||||
sbc #$40
|
||||
jsr _sound_play
|
||||
jmp @IncMusic
|
||||
.endproc
|
||||
|
||||
; Table of AUDF base values for each note
|
||||
FREQZ:
|
||||
.byte 31, 31, 31, 31, 30, 28, 27, 25, 24, 22, 21, 20, 19, 17, 17, 15, 15, 14, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 31, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15, 14, 13, 12, 12, 11, 10, 31, 29, 27, 26, 24, 23, 22, 20, 19, 18, 17, 16, 15
|
||||
|
||||
; Table of AUDC values for each note
|
||||
TONEZ:
|
||||
.byte 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.global _randseed8
|
||||
.global _initrand8
|
||||
.global _nextrand8
|
||||
.global _prevrand8
|
||||
|
||||
_randseed8: .res 1
|
||||
|
||||
.proc _initrand8
|
||||
lda INTIM
|
||||
ora #1
|
||||
sta _randseed8
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc _nextrand8
|
||||
lda _randseed8
|
||||
lsr
|
||||
bcc :+
|
||||
eor #$d4
|
||||
:
|
||||
sta _randseed8
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc _prevrand8
|
||||
lda _randseed8
|
||||
asl
|
||||
bcc :+
|
||||
eor #$a9
|
||||
:
|
||||
sta _randseed8
|
||||
rts
|
||||
.endproc
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
.export _score6_build
|
||||
.export _score6_add
|
||||
.importzp _bcd_score
|
||||
.import _bitmap48_ptr_0, _bitmap48_ptr_1, _bitmap48_ptr_2, _bitmap48_ptr_3, _bitmap48_ptr_4, _bitmap48_ptr_5
|
||||
|
||||
.proc _score6_add
|
||||
sed
|
||||
clc
|
||||
adc _bcd_score+0
|
||||
sta _bcd_score+0
|
||||
txa
|
||||
adc _bcd_score+1
|
||||
sta _bcd_score+1
|
||||
lda #0
|
||||
adc _bcd_score+2
|
||||
sta _bcd_score+2
|
||||
cld
|
||||
rts
|
||||
.endproc
|
||||
|
||||
; needs to have XRAM active
|
||||
.proc _score6_build
|
||||
lda #>FontTable09
|
||||
sta _bitmap48_ptr_0+$400+1
|
||||
sta _bitmap48_ptr_1+$400+1
|
||||
sta _bitmap48_ptr_2+$400+1
|
||||
sta _bitmap48_ptr_3+$400+1
|
||||
sta _bitmap48_ptr_4+$400+1
|
||||
sta _bitmap48_ptr_5+$400+1
|
||||
ldy #2 ; start from most-sigificant BCD value
|
||||
jsr score6_getbcd
|
||||
stx _bitmap48_ptr_0+$400
|
||||
sta _bitmap48_ptr_1+$400
|
||||
dey
|
||||
jsr score6_getbcd
|
||||
stx _bitmap48_ptr_2+$400
|
||||
sta _bitmap48_ptr_3+$400
|
||||
dey
|
||||
jsr score6_getbcd
|
||||
stx _bitmap48_ptr_4+$400
|
||||
sta _bitmap48_ptr_5+$400
|
||||
rts
|
||||
score6_getbcd:
|
||||
lda _bcd_score,y ; get BCD value
|
||||
and #$f0 ; isolate high nibble (* 16)
|
||||
lsr ; shift right 1 bit (* 8)
|
||||
ora #<FontTable09
|
||||
tax ; lo ptr 0 -> X
|
||||
lda _bcd_score,y ; get BCD value (again)
|
||||
and #$f ; isolate low nibble
|
||||
asl
|
||||
asl
|
||||
asl ; * 8
|
||||
ora #<FontTable09
|
||||
rts ; lo ptr 1 -> A
|
||||
.endproc
|
||||
|
||||
; needs to be in PERM rom
|
||||
.rodata
|
||||
.align $80
|
||||
; Font table for digits 0-9 (8x8 pixels)
|
||||
;;{w:8,h:8,count:12,brev:1,flip:1};;
|
||||
FontTable09:
|
||||
.byte $00,$3C,$66,$66,$76,$6E,$66,$3C,$00,$7E,$18,$18,$18,$38,$18,$18
|
||||
.byte $00,$7E,$60,$30,$0C,$06,$66,$3C,$00,$3C,$66,$06,$1C,$06,$66,$3C
|
||||
.byte $00,$06,$06,$7F,$66,$1E,$0E,$06,$00,$3C,$66,$06,$06,$7C,$60,$7E
|
||||
.byte $00,$3C,$66,$66,$7C,$60,$66,$3C,$00,$18,$18,$18,$18,$0C,$66,$7E
|
||||
.byte $00,$3C,$66,$66,$3C,$66,$66,$3C,$00,$3C,$66,$06,$3E,$66,$66,$3C
|
||||
.byte $00,$18,$00,$00,$00,$00,$00,$00,$00,$10,$7C,$12,$7C,$90,$7C,$10
|
||||
;;
|
|
@ -0,0 +1,121 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.global _scorepf_build
|
||||
.global _scorepf_kernel
|
||||
.importzp _bcd_score
|
||||
.importzp tmp1
|
||||
.import _reset_gfx
|
||||
.import Return
|
||||
|
||||
.zeropage
|
||||
digit_ofs: .res 4
|
||||
;pftmp: .res 2
|
||||
; no one is using this, right??
|
||||
pftmp = tmp1
|
||||
|
||||
.segment "ROM1"
|
||||
; calculate the byte offsets for each digit
|
||||
; basically (digit * 5)
|
||||
.proc _scorepf_build
|
||||
ldx #0
|
||||
lda _bcd_score+0
|
||||
jsr calc_bcd_pair
|
||||
lda _bcd_score+1
|
||||
jsr calc_bcd_pair
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc calc_bcd_pair
|
||||
pha
|
||||
and #$0f
|
||||
sta pftmp
|
||||
jsr mul5store ; (clever inlining)
|
||||
pla
|
||||
and #$f0
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
mul5store:
|
||||
sta pftmp
|
||||
asl
|
||||
asl
|
||||
adc pftmp ; mul by 5
|
||||
sta digit_ofs,x
|
||||
inx
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc _scorepf_kernel
|
||||
jsr _reset_gfx ; returns A=0
|
||||
sta pftmp+0
|
||||
sta pftmp+1
|
||||
tax
|
||||
; render the digits
|
||||
ldx #0
|
||||
@loop:
|
||||
; first digit pair
|
||||
sta WSYNC
|
||||
ldy digit_ofs+0
|
||||
inc digit_ofs+0
|
||||
lda DigitsBitmap,y
|
||||
and #$0f
|
||||
ldy pftmp+0 ; load old value digits 0/1
|
||||
sta pftmp+0
|
||||
sty PF1 ; store in PF1
|
||||
ldy digit_ofs+1
|
||||
inc digit_ofs+1
|
||||
lda DigitsBitmap,y
|
||||
and #$f0
|
||||
ora pftmp+0
|
||||
sta pftmp+0
|
||||
; second digit pair
|
||||
ldy pftmp+1 ; load old value digits 2/3
|
||||
sty PF1 ; store in PF1
|
||||
ldy digit_ofs+2
|
||||
inc digit_ofs+2
|
||||
lda DigitsBitmap,y
|
||||
and #$0f
|
||||
sta pftmp+1
|
||||
sta WSYNC
|
||||
ldy digit_ofs+3
|
||||
inc digit_ofs+3
|
||||
lda DigitsBitmap,y
|
||||
and #$f0
|
||||
ora pftmp+1
|
||||
sta pftmp+1
|
||||
; one more line
|
||||
lda pftmp+0
|
||||
sta PF1
|
||||
SLEEPR 6
|
||||
lda pftmp+1
|
||||
sta PF1
|
||||
; loop over 5 lines
|
||||
inx
|
||||
cpx #5
|
||||
bne @loop
|
||||
; one more line
|
||||
sta WSYNC
|
||||
lda pftmp+0
|
||||
sta PF1
|
||||
SLEEPR 24
|
||||
lda pftmp+1
|
||||
sta PF1
|
||||
sta WSYNC
|
||||
jmp _reset_gfx
|
||||
.endproc
|
||||
|
||||
; Bitmap pattern for digits
|
||||
DigitsBitmap: ;;{w:8,h:5,count:10,brev:1};;
|
||||
.byte $EE,$AA,$AA,$AA,$EE
|
||||
.byte $22,$22,$22,$22,$22
|
||||
.byte $EE,$22,$EE,$88,$EE
|
||||
.byte $EE,$22,$66,$22,$EE
|
||||
.byte $AA,$AA,$EE,$22,$22
|
||||
.byte $EE,$88,$EE,$22,$EE
|
||||
.byte $EE,$88,$EE,$AA,$EE
|
||||
.byte $EE,$22,$22,$22,$22
|
||||
.byte $EE,$AA,$EE,$AA,$EE
|
||||
.byte $EE,$AA,$EE,$22,$EE
|
||||
;;end
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.export _sound_update
|
||||
.export _sound_play
|
||||
|
||||
.import _sound_duration
|
||||
.import _sound_data
|
||||
|
||||
.zeropage
|
||||
|
||||
_sndchan_sfx: .res 2
|
||||
_sndchan_timer: .res 2
|
||||
|
||||
.exportzp _sndchan_sfx
|
||||
.exportzp _sndchan_timer
|
||||
|
||||
.importzp ptr3
|
||||
sounddata = ptr3
|
||||
|
||||
.segment "ROM3"
|
||||
|
||||
; 00-1F: set frequency
|
||||
; 81-9F odd: set volume
|
||||
; 80-9E even: set control register
|
||||
|
||||
.proc _sound_update
|
||||
ldx #0
|
||||
jsr _sound_update_channel
|
||||
ldx #1
|
||||
.endproc
|
||||
.proc _sound_update_channel
|
||||
; decrement timer
|
||||
lda _sndchan_timer,x
|
||||
beq @done
|
||||
dec _sndchan_timer,x
|
||||
beq @killsound
|
||||
; get sound data address
|
||||
lda _sndchan_sfx,x
|
||||
asl
|
||||
tay
|
||||
lda _sound_data+0,y
|
||||
sta sounddata+0
|
||||
lda _sound_data+1,y
|
||||
sta sounddata+1
|
||||
; get next sound data byte
|
||||
ldy _sndchan_timer,x
|
||||
lda (sounddata),y ; get sound data
|
||||
bpl @setfreq ; hi bit clear = just freq
|
||||
lsr ; right shift (/ 2)
|
||||
bcs @setvol ; lo bit set = volume
|
||||
sta AUDC0,x ; lo bit clear = control
|
||||
lsr ; also set freq (/ 2)
|
||||
@setfreq:
|
||||
sta AUDF0,x ; set frequency
|
||||
rts
|
||||
@killsound:
|
||||
lda #0
|
||||
@setvol:
|
||||
sta AUDV0,x ; set volume
|
||||
@done:
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc _sound_play
|
||||
; but which channel to use?
|
||||
; whichever has the lower timer counter
|
||||
ldx #0
|
||||
ldy _sndchan_timer+0
|
||||
cpy _sndchan_timer+1
|
||||
bcc @Chan0Free ; timer0 < timer 1?
|
||||
inx
|
||||
@Chan0Free:
|
||||
sta _sndchan_sfx,x
|
||||
tay
|
||||
lda _sound_duration,y
|
||||
sta _sndchan_timer,x
|
||||
rts
|
||||
.endproc
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
#include "vcslib.h"
|
||||
|
||||
#pragma code-name (push, "ROM1")
|
||||
#pragma rodata-name (push, "ROM1")
|
||||
|
||||
#define LoChar 41 // lowest character value
|
||||
#define HiChar 90 // highest character value
|
||||
|
||||
/*{w:8,h:5,brev:1,flip:1,count:51}*/
|
||||
const unsigned char TINYFONT[51*5] = {
|
||||
0x22, 0x00, 0x22, 0x22, 0x22, 0x55, 0x22, 0x55, 0x00, 0x00, 0x22, 0x77, 0x22, 0x00, 0x00, 0x44,
|
||||
0x22, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44,
|
||||
0x22, 0x11, 0x11, 0x66, 0x55, 0x55, 0x55, 0x33, 0x22, 0x22, 0x22, 0x66, 0x22, 0x77, 0x44, 0x22,
|
||||
0x11, 0x66, 0x66, 0x11, 0x22, 0x11, 0x66, 0x11, 0x11, 0x77, 0x55, 0x55, 0x66, 0x11, 0x66, 0x44,
|
||||
0x77, 0x77, 0x55, 0x77, 0x44, 0x33, 0x44, 0x44, 0x22, 0x11, 0x77, 0x77, 0x55, 0x77, 0x55, 0x77,
|
||||
0x66, 0x11, 0x77, 0x55, 0x77, 0x44, 0x00, 0x44, 0x00, 0x00, 0x44, 0x22, 0x00, 0x22, 0x00, 0x11,
|
||||
0x22, 0x44, 0x22, 0x11, 0x77, 0x00, 0x77, 0x00, 0x00, 0x44, 0x22, 0x11, 0x22, 0x44, 0x22, 0x00,
|
||||
0x22, 0x11, 0x77, 0x33, 0x44, 0x77, 0x55, 0x22, 0x55, 0x55, 0x77, 0x55, 0x22, 0x66, 0x55, 0x66,
|
||||
0x55, 0x66, 0x33, 0x44, 0x44, 0x44, 0x33, 0x66, 0x55, 0x55, 0x55, 0x66, 0x77, 0x44, 0x77, 0x44,
|
||||
0x77, 0x44, 0x44, 0x77, 0x44, 0x77, 0x33, 0x55, 0x77, 0x44, 0x33, 0x55, 0x55, 0x77, 0x55, 0x55,
|
||||
0x77, 0x22, 0x22, 0x22, 0x77, 0x22, 0x55, 0x11, 0x11, 0x11, 0x55, 0x55, 0x66, 0x55, 0x55, 0x77,
|
||||
0x44, 0x44, 0x44, 0x44, 0x55, 0x55, 0x77, 0x77, 0x55, 0x55, 0x77, 0x77, 0x77, 0x55, 0x22, 0x55,
|
||||
0x55, 0x55, 0x22, 0x44, 0x44, 0x66, 0x55, 0x66, 0x33, 0x77, 0x55, 0x55, 0x22, 0x55, 0x66, 0x77,
|
||||
0x55, 0x66, 0x66, 0x11, 0x22, 0x44, 0x33, 0x22, 0x22, 0x22, 0x22, 0x77, 0x33, 0x55, 0x55, 0x55,
|
||||
0x55, 0x22, 0x22, 0x55, 0x55, 0x55, 0x55, 0x77, 0x77, 0x55, 0x55, 0x55, 0x55, 0x22, 0x55, 0x55,
|
||||
0x22, 0x22, 0x22, 0x55, 0x55, 0x77, 0x44, 0x22, 0x11, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
void tinyfont48_build_char(byte* dest, char ch1, char ch2) {
|
||||
byte y;
|
||||
byte font1 = 5*(ch1-LoChar);
|
||||
byte font2 = 5*(ch2-LoChar);
|
||||
for (y=0; y<5; y++) {
|
||||
byte b1 = TINYFONT[font1++] & 0xf0;
|
||||
byte b2 = TINYFONT[font2++] & 0x0f;
|
||||
xramset(dest);
|
||||
xramwrite(b1 | b2);
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can we write when RAM is not selected?
|
||||
void tinyfont48_build(byte* dest, const char str[12]) {
|
||||
byte stri;
|
||||
for (stri=0; stri<12; stri+=2) {
|
||||
tinyfont48_build_char(dest, str[stri], str[stri+1]);
|
||||
dest += 5;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma code-name (pop)
|
||||
#pragma rodata-name (pop)
|
|
@ -0,0 +1,375 @@
|
|||
.setcpu "6502X"
|
||||
|
||||
; TIA write registers
|
||||
|
||||
VSYNC := $00 ; ---- --1- This address controls vertical sync time by writing D1 into the VSYNC latch.
|
||||
VBLANK := $01 ; 76-- --1- 1=Start VBLANK, 6=Enable INPT4, INPT5 latches, 7=Dump INPT1,2,3,6 to ground
|
||||
WSYNC := $02 ; ---- ---- This address halts microprocessor by clearing RDY latch to zero. RDY is set true again by the leading edge of horizontal blank.
|
||||
RSYNC := $03 ; ---- ---- This address resets the horizontal sync counter to define the beginning of horizontal blank time, and is used in chip testing.
|
||||
NUSIZ0 := $04 ; --54 -210 \ 0,1,2: player copys'n'size, 4,5: missile size: 2^x pixels
|
||||
NUSIZ1 := $05 ; --54 -210 /
|
||||
COLUP0 := $06 ; 7654 321- color player 0
|
||||
COLUP1 := $07 ; 7654 321- color player 1
|
||||
COLUPF := $08 ; 7654 321- color playfield
|
||||
COLUBK := $09 ; 7654 321- color background
|
||||
CTRLPF := $0A ; --54 -210 0=reflect playfield, 1=pf uses player colors, 2=playfield over sprites 4,5=ballsize:2^x
|
||||
REFP0 := $0B ; ---- 3--- reflect player 0
|
||||
REFP1 := $0C ; ---- 3--- reflect player 1
|
||||
PF0 := $0D ; DCBA ---- \ Playfield bits: ABCDEFGHIJKLMNOPQRST
|
||||
PF1 := $0E ; EFGH IJKL > normal: ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRST
|
||||
PF2 := $0F ; TSRQ PONM / reflect: ABCDEFGHIJKLMNOPQRSTTSRQPONMLKJIHGFEDCBA
|
||||
RESP0 := $10 ; ---- ---- \
|
||||
RESP1 := $11 ; ---- ---- \
|
||||
RESM0 := $12 ; ---- ---- > reset players, missiles and the ball. The object will begin its serial graphics at the time of a horizontal line at which the reset address occurs.
|
||||
RESM1 := $13 ; ---- ---- /
|
||||
RESBL := $14 ; ---- ---- /
|
||||
AUDC0 := $15 ; ---- 3210 audio control voice 0
|
||||
AUDC1 := $16 ; ---- 3210 audio control voice 1
|
||||
AUDF0 := $17 ; ---4 3210 frequency divider voice 0
|
||||
AUDF1 := $18 ; ---4 3210 frequency divider voice 1
|
||||
AUDV0 := $19 ; ---- 3210 audio volume voice 0
|
||||
AUDV1 := $1A ; ---- 3210 audio volume voice 1
|
||||
GRP0 := $1B ; 7654 3210 graphics player 0
|
||||
GRP1 := $1C ; 7654 3210 graphics player 1
|
||||
ENAM0 := $1D ; ---- --1- enable missile 0
|
||||
ENAM1 := $1E ; ---- --1- enable missile 1
|
||||
ENABL := $1F ; ---- --1- enable ball
|
||||
HMP0 := $20 ; 7654 ---- write data (horizontal motion values) into the horizontal motion registers
|
||||
HMP1 := $21 ; 7654 ---- write data (horizontal motion values) into the horizontal motion registers
|
||||
HMM0 := $22 ; 7654 ---- write data (horizontal motion values) into the horizontal motion registers
|
||||
HMM1 := $23 ; 7654 ---- write data (horizontal motion values) into the horizontal motion registers
|
||||
HMBL := $24 ; 7654 ---- write data (horizontal motion values) into the horizontal motion registers
|
||||
VDELP0 := $25 ; ---- ---0 delay player 0 by one vertical line
|
||||
VDELP1 := $26 ; ---- ---0 delay player 1 by one vertical line
|
||||
VDELBL := $27 ; ---- ---0 delay ball by one vertical line
|
||||
RESMP0 := $28 ; ---- --1- keep missile 0 aligned with player 0
|
||||
RESMP1 := $29 ; ---- --1- keep missile 1 aligned with player 1
|
||||
HMOVE := $2A ; ---- ---- This address causes the horizontal motion register values to be acted upon during the horizontal blank time in which it occurs.
|
||||
HMCLR := $2B ; ---- ---- This address clears all horizontal motion registers to zero (no motion).
|
||||
CXCLR := $2C ; ---- ---- clears all collision latches
|
||||
|
||||
; TIA read registers
|
||||
|
||||
CXM0P := $00 ; xx00 0000 Read Collision M0-P1 M0-P0
|
||||
CXM1P := $01 ; xx00 0000 M1-P0 M1-P1
|
||||
CXP0FB := $02 ; xx00 0000 P0-PF P0-BL
|
||||
CXP1FB := $03 ; xx00 0000 P1-PF P1-BL
|
||||
CXM0FB := $04 ; xx00 0000 M0-PF M0-BL
|
||||
CXM1FB := $05 ; xx00 0000 M1-PF M1-BL
|
||||
CXBLPF := $06 ; x000 0000 BL-PF -----
|
||||
CXPPMM := $07 ; xx00 0000 P0-P1 M0-M1
|
||||
INPT0 := $08 ; x000 0000 Read Pot Port 0
|
||||
INPT1 := $09 ; x000 0000 Read Pot Port 1
|
||||
INPT2 := $0A ; x000 0000 Read Pot Port 2
|
||||
INPT3 := $0B ; x000 0000 Read Pot Port 3
|
||||
INPT4 := $0C ; x000 0000 Read Input (Trigger) 0
|
||||
INPT5 := $0D ; x000 0000 Read Input (Trigger) 1
|
||||
|
||||
; RIOT
|
||||
|
||||
SWCHA := $0280
|
||||
SWACNT := $0281
|
||||
SWCHB := $0282
|
||||
SWBCNT := $0283
|
||||
INTIM := $0284 ; Timer output
|
||||
TIMINT := $0285
|
||||
|
||||
TIM1T := $0294
|
||||
TIM8T := $0295
|
||||
TIM64T := $0296
|
||||
TIM1024T := $0297
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; SLEEP duration
|
||||
; Original author: Thomas Jentzsch
|
||||
; Inserts code which takes the specified number of cycles to execute. This is
|
||||
; useful for code where precise timing is required.
|
||||
; ILLEGAL-OPCODE VERSION DOES NOT AFFECT FLAGS OR REGISTERS.
|
||||
; LEGAL OPCODE VERSION MAY AFFECT FLAGS
|
||||
; Uses illegal opcode (DASM 2.20.01 onwards).
|
||||
|
||||
.macro SLEEP cycles
|
||||
.if cycles < 0 || cycles = 1
|
||||
.error "MACRO ERROR: 'SLEEP': Duration must be >= 2"
|
||||
.endif
|
||||
.if cycles & 1
|
||||
.ifndef NO_ILLEGAL_OPCODES
|
||||
nop 0
|
||||
.else
|
||||
bit VSYNC
|
||||
.endif
|
||||
.repeat (cycles-3)/2
|
||||
nop
|
||||
.endrep
|
||||
.else
|
||||
.repeat cycles/2
|
||||
nop
|
||||
.endrep
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; VERTICAL_SYNC
|
||||
; revised version by Edwin Blink -- saves bytes!
|
||||
; Inserts the code required for a proper 3 scanline vertical sync sequence
|
||||
; Note: Alters the accumulator
|
||||
|
||||
; OUT: A = 0
|
||||
|
||||
.macro VERTICAL_SYNC
|
||||
lda #%1110 ; each '1' bits generate a VSYNC ON line (bits 1..3)
|
||||
.local VSLP1
|
||||
VSLP1: sta WSYNC ; 1st '0' bit resets Vsync, 2nd '0' bit exit loop
|
||||
sta VSYNC
|
||||
lsr
|
||||
bne VSLP1 ; branch until VYSNC has been reset
|
||||
.endmacro
|
||||
|
||||
;-------------------------------------------------------
|
||||
; Usage: TIMER_SETUP lines
|
||||
; where lines is the number of scanlines to skip (> 2).
|
||||
; The timer will be set so that it expires before this number
|
||||
; of scanlines. A WSYNC will be done first.
|
||||
|
||||
.macro TIMER_SETUP lines
|
||||
.local cycles
|
||||
cycles = ((lines * 76) - 13)
|
||||
; special case for when we have two timer events in a line
|
||||
; and our 2nd event straddles the WSYNC boundary
|
||||
.if (cycles .mod 64) < 12
|
||||
lda #(cycles / 64) - 1
|
||||
sta WSYNC
|
||||
.else
|
||||
lda #(cycles / 64)
|
||||
sta WSYNC
|
||||
.endif
|
||||
sta TIM64T
|
||||
.endmacro
|
||||
|
||||
;-------------------------------------------------------
|
||||
; Use with TIMER_SETUP to wait for timer to complete.
|
||||
; Performs a WSYNC afterwards.
|
||||
|
||||
.macro TIMER_WAIT
|
||||
.local waittimer
|
||||
waittimer:
|
||||
lda INTIM
|
||||
bne waittimer
|
||||
sta WSYNC
|
||||
.endmacro
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; CLEAN_START
|
||||
; Original author: Andrew Davie
|
||||
; Standardised start-up code, clears stack, all TIA registers and RAM to 0
|
||||
; Sets stack pointer to $FF, and all registers to 0
|
||||
; Sets decimal mode off, sets interrupt flag (kind of un-necessary)
|
||||
; Use as very first section of code on boot (ie: at reset)
|
||||
; Code written to minimise total ROM usage - uses weird 6502 knowledge :)
|
||||
|
||||
.macro CLEAN_START
|
||||
.local CLEAR_STACK
|
||||
sei
|
||||
cld
|
||||
ldx #0
|
||||
txa
|
||||
tay
|
||||
CLEAR_STACK: dex
|
||||
txs
|
||||
pha
|
||||
bne CLEAR_STACK ; SP=$FF, X = A = Y = 0
|
||||
.endmacro
|
||||
|
||||
;-------------------------------------------------------
|
||||
; SET_POINTER
|
||||
; Original author: Manuel Rotschkar
|
||||
;
|
||||
; Sets a 2 byte RAM pointer to an absolute address.
|
||||
;
|
||||
; Usage: SET_POINTER pointer, address
|
||||
; Example: SET_POINTER SpritePTR, SpriteData
|
||||
;
|
||||
; Note: Alters the accumulator, NZ flags
|
||||
; IN 1: 2 byte RAM location reserved for pointer
|
||||
; IN 2: absolute address
|
||||
.macro SET_POINTER ptr, addr
|
||||
lda #<addr
|
||||
sta ptr
|
||||
lda #>addr
|
||||
sta ptr+1
|
||||
.endmacro
|
||||
|
||||
|
||||
; assume NTSC unless PAL defined
|
||||
.ifndef PAL
|
||||
PAL = 0
|
||||
.endif
|
||||
|
||||
; 192 visible scanlines for NTSC, 228 for PAL
|
||||
.if PAL
|
||||
SCANLINES = 228
|
||||
LINESD12 = 19
|
||||
.else
|
||||
SCANLINES = 192
|
||||
LINESD12 = 16
|
||||
.endif
|
||||
|
||||
; start of frame -- vsync and set back porch timer
|
||||
.macro FRAME_START
|
||||
VERTICAL_SYNC
|
||||
.if PAL
|
||||
TIMER_SETUP 44
|
||||
.else
|
||||
TIMER_SETUP 36
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
; end of back porch -- start kernel
|
||||
.macro KERNEL_START
|
||||
TIMER_WAIT
|
||||
lda #0
|
||||
sta VBLANK
|
||||
.if !PAL
|
||||
TIMER_SETUP 194
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
; end of kernel -- start front porch timer
|
||||
.macro KERNEL_END
|
||||
.if !PAL
|
||||
TIMER_WAIT
|
||||
.endif
|
||||
lda #2
|
||||
sta VBLANK
|
||||
.if PAL
|
||||
TIMER_SETUP 36
|
||||
.else
|
||||
TIMER_SETUP 28
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
; end of frame -- jump to frame start
|
||||
.macro FRAME_END
|
||||
TIMER_WAIT
|
||||
.endmacro
|
||||
|
||||
;-----------------------------------------------------------
|
||||
; SLEEPR - sleep macro that uses JSR/RTS for 12 cycle delays
|
||||
; Requires a lone RTS instruction with the label "Return"
|
||||
; (note: may fool 8bitworkshop's Anaylze CPU Timing feature)
|
||||
|
||||
.macro SLEEPR cycles
|
||||
.if cycles >= 14 || cycles = 12
|
||||
jsr Return
|
||||
SLEEPR (cycles-12)
|
||||
.else
|
||||
SLEEP cycles
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
;-----------------------------------------------------------
|
||||
; SLEEPH - sleep macro that uses PHA/PLA for 7 cycle delays
|
||||
; (may affect flags)
|
||||
|
||||
.macro SLEEPH cycles
|
||||
.if cycles >= 9 || cycles = 7
|
||||
pha
|
||||
pla
|
||||
SLEEPH (cycles-7)
|
||||
.else
|
||||
SLEEP cycles
|
||||
.endif
|
||||
.endmacro
|
||||
|
||||
;==============================================================================
|
||||
; T I A - C O N S T A N T S
|
||||
;==============================================================================
|
||||
|
||||
HMOVE_L7 = $70
|
||||
HMOVE_L6 = $60
|
||||
HMOVE_L5 = $50
|
||||
HMOVE_L4 = $40
|
||||
HMOVE_L3 = $30
|
||||
HMOVE_L2 = $20
|
||||
HMOVE_L1 = $10
|
||||
HMOVE_0 = $00
|
||||
HMOVE_R1 = $F0
|
||||
HMOVE_R2 = $E0
|
||||
HMOVE_R3 = $D0
|
||||
HMOVE_R4 = $C0
|
||||
HMOVE_R5 = $B0
|
||||
HMOVE_R6 = $A0
|
||||
HMOVE_R7 = $90
|
||||
HMOVE_R8 = $80
|
||||
|
||||
; values for ENAMx and ENABL
|
||||
DISABLE_BM = %00
|
||||
ENABLE_BM = %10
|
||||
|
||||
; values for RESMPx
|
||||
LOCK_MISSILE = %10
|
||||
UNLOCK_MISSILE = %00
|
||||
|
||||
; values for REFPx:
|
||||
NO_REFLECT = %0000
|
||||
REFLECT = %1000
|
||||
|
||||
; values for NUSIZx:
|
||||
ONE_COPY = %000
|
||||
TWO_COPIES = %001
|
||||
TWO_MED_COPIES = %010
|
||||
THREE_COPIES = %011
|
||||
TWO_WIDE_COPIES = %100
|
||||
DOUBLE_SIZE = %101
|
||||
THREE_MED_COPIES = %110
|
||||
QUAD_SIZE = %111
|
||||
MSBL_SIZE1 = %000000
|
||||
MSBL_SIZE2 = %010000
|
||||
MSBL_SIZE4 = %100000
|
||||
MSBL_SIZE8 = %110000
|
||||
|
||||
; values for CTRLPF:
|
||||
PF_PRIORITY = %100
|
||||
PF_SCORE = %10
|
||||
PF_REFLECT = %01
|
||||
PF_NO_REFLECT = %00
|
||||
|
||||
; values for SWCHB
|
||||
P1_DIFF_MASK = %10000000
|
||||
P0_DIFF_MASK = %01000000
|
||||
BW_MASK = %00001000
|
||||
SELECT_MASK = %00000010
|
||||
RESET_MASK = %00000001
|
||||
|
||||
VERTICAL_DELAY = 1
|
||||
|
||||
; SWCHA joystick bits:
|
||||
MOVE_RIGHT = %01111111
|
||||
MOVE_LEFT = %10111111
|
||||
MOVE_DOWN = %11011111
|
||||
MOVE_UP = %11101111
|
||||
P0_JOYSTICK_MASK = %11110000
|
||||
P1_JOYSTICK_MASK = %00001111
|
||||
P0_NO_MOVE = P0_JOYSTICK_MASK
|
||||
P1_NO_MOVE = P1_JOYSTICK_MASK
|
||||
NO_MOVE = P0_NO_MOVE | P1_NO_MOVE
|
||||
P0_HORIZ_MOVE = MOVE_RIGHT & MOVE_LEFT & P0_NO_MOVE
|
||||
P0_VERT_MOVE = MOVE_UP & MOVE_DOWN & P0_NO_MOVE
|
||||
P1_HORIZ_MOVE = ((MOVE_RIGHT & MOVE_LEFT) >> 4) & P1_NO_MOVE
|
||||
P1_VERT_MOVE = ((MOVE_UP & MOVE_DOWN) >> 4) & P1_NO_MOVE
|
||||
|
||||
; SWCHA paddle bits:
|
||||
P0_TRIGGER_PRESSED = %01111111
|
||||
P1_TRIGGER_PRESSED = %10111111
|
||||
P2_TRIGGER_PRESSED = %11110111
|
||||
P3_TRIGGER_PRESSED = %11111011
|
||||
|
||||
; values for VBLANK:
|
||||
DUMP_PORTS = %10000000
|
||||
ENABLE_LATCHES = %01000000
|
||||
DISABLE_TIA = %00000010
|
||||
ENABLE_TIA = %00000000
|
||||
|
||||
;values for VSYNC:
|
||||
START_VERT_SYNC = %10
|
||||
STOP_VERT_SYNC = %00
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
.include "vcs-ca65.inc"
|
||||
|
||||
.global _set_horiz_pos
|
||||
.export _reset_gfx
|
||||
.export _reset_sprites
|
||||
.export Return
|
||||
|
||||
;;;
|
||||
|
||||
; SetHorizPos routine
|
||||
; A = X coordinate
|
||||
; X = player number (0 or 1)
|
||||
; must be in rodata segment because of alignment
|
||||
.rodata
|
||||
.align $10
|
||||
.proc _set_horiz_pos
|
||||
sec ; set carry flag
|
||||
sta WSYNC ; start a new line
|
||||
:
|
||||
sbc #15 ; subtract 15
|
||||
bcs :- ; branch until negative
|
||||
eor #7 ; calculate fine offset
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
sta HMP0,x ; set fine offset
|
||||
sta RESP0,x ; fix coarse position
|
||||
sta WSYNC ; won't overrun if X < 150
|
||||
rts
|
||||
.endproc
|
||||
.code
|
||||
|
||||
;;;
|
||||
|
||||
_reset_gfx:
|
||||
lda #0
|
||||
sta PF0
|
||||
sta PF1
|
||||
sta PF2
|
||||
_reset_sprites:
|
||||
lda #0
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
sta GRP0
|
||||
sta GRP1
|
||||
Return:
|
||||
rts
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
|
||||
#ifndef _VCSLIB_H
|
||||
#define _VCSLIB_H
|
||||
|
||||
#include <atari2600.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Define data types for different data sizes and signedness
|
||||
|
||||
typedef unsigned char byte; // 8-bit unsigned data type
|
||||
typedef signed char sbyte; // 8-bit signed data type
|
||||
typedef unsigned short word; // 16-bit unsigned data type
|
||||
typedef signed short sword; // 16-bit signed data type
|
||||
|
||||
// Bank switching functions that will be called directly when needed
|
||||
// These are for changing which section of ROM or RAM the Atari 2600 accesses
|
||||
|
||||
// Select a ROM bank by index
|
||||
extern void fastcall bankselect(byte bankindex);
|
||||
|
||||
// Select a RAM bank by index
|
||||
extern void fastcall ramselect(byte ramindex);
|
||||
|
||||
// Set address in extended RAM
|
||||
extern void fastcall xramset(void* address);
|
||||
|
||||
// Write a byte to extended RAM at set address
|
||||
extern void fastcall xramwrite(byte value);
|
||||
|
||||
// Read a byte from extended RAM at set address
|
||||
extern byte fastcall xramread(void);
|
||||
|
||||
// Copies initialized data from ROM to RAM at startup, if used
|
||||
extern void copyxdata(void);
|
||||
|
||||
// Atari 2600 kernel helpers, called in a sequence every frame
|
||||
|
||||
extern void kernel_1(void); // before preframe
|
||||
extern void kernel_2(void); // before kernel
|
||||
extern void kernel_3(void); // after kernel
|
||||
extern void kernel_4(void); // after postframe
|
||||
|
||||
// Function to set horizontal position of a game object.
|
||||
// The position and object index are packed into a single int.
|
||||
// Hi byte = object index
|
||||
// Lo byte = X coordinate
|
||||
|
||||
extern void fastcall set_horiz_pos(int hi_obj__lo_xpos);
|
||||
|
||||
// Waits for next scanline start
|
||||
#define do_wsync() asm("sta $42 ; WSYNC");
|
||||
|
||||
// Applies horizontal motion to sprite(s) after set_horiz_pos()
|
||||
#define apply_hmove() \
|
||||
asm("sta $42 ; WSYNC"); \
|
||||
asm("sta $6a ; HMOVE");
|
||||
|
||||
|
||||
/**** SCOREBOARD ROUTINES ****/
|
||||
|
||||
// Add 4-digit BCD to 6-digit BCD score
|
||||
extern void fastcall score6_add(int delta_bcd);
|
||||
|
||||
#pragma wrapped-call (push, bankselect, bank)
|
||||
|
||||
// Setup TIA for Playfield score display
|
||||
extern void scorepf_build(void);
|
||||
|
||||
// Kernel for Playfield score display
|
||||
extern void scorepf_kernel(void);
|
||||
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
|
||||
/**** SOUND AND MUSIC ROUTINES ****/
|
||||
|
||||
#pragma wrapped-call (push, bankselect, bank)
|
||||
|
||||
// Update sound playback (once per frame)
|
||||
extern void sound_update();
|
||||
|
||||
// Play a specific sound
|
||||
extern void sound_play(byte sndindex);
|
||||
|
||||
// Update music playback
|
||||
extern void music_update();
|
||||
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
extern const byte* music_ptr; // Pointer to current music data
|
||||
#pragma zpsym("music_ptr");
|
||||
|
||||
// Macro to set music data pointer and begin playback
|
||||
#define music_play(ptr) music_ptr = (ptr);
|
||||
|
||||
extern byte sndchan_timer[2]; // sound channel timers, 0 = free channel
|
||||
#pragma zpsym("sndchan_timer");
|
||||
|
||||
extern byte sndchan_sfx[2]; // sound channel sound index
|
||||
#pragma zpsym("sndchan_sfx");
|
||||
|
||||
|
||||
/**** 48-PIXEL BITMAP ROUTINES ****/
|
||||
|
||||
// Setup TIA for 48-pixel wide bitmap mode
|
||||
extern void fastcall bitmap48_setup();
|
||||
|
||||
#pragma wrapped-call (push, ramselect, 0)
|
||||
|
||||
// Draws a 48-pixel wide bitmap
|
||||
extern void fastcall bitmap48_kernel(unsigned char nlines);
|
||||
|
||||
// Sets height for bitmap48_setaddress() function
|
||||
extern void fastcall bitmap48_setheight(byte height);
|
||||
|
||||
// Sets address of 48-pixel bitmap data
|
||||
// Bitmap should be 6 bytes wide
|
||||
extern void fastcall bitmap48_setaddress(byte* bitmap);
|
||||
|
||||
// Builds a 6-digit score display in XRAM
|
||||
extern void fastcall score6_build();
|
||||
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
#pragma wrapped-call (push, bankselect, bank)
|
||||
|
||||
// Create 48-pixel font from string (requires tinyfont48.c)
|
||||
extern void tinyfont48_build(byte* dest, const char str[12]);
|
||||
|
||||
#pragma wrapped-call (pop)
|
||||
|
||||
/////
|
||||
|
||||
#define P0 0
|
||||
#define P1 1
|
||||
#define M0 2
|
||||
#define M1 3
|
||||
#define BALL 4
|
||||
|
||||
#define OBJ_PLAYER_0 0x000
|
||||
#define OBJ_PLAYER_1 0x100
|
||||
#define OBJ_MISSILE_0 0x200
|
||||
#define OBJ_MISSILE_1 0x300
|
||||
#define OBJ_BALL 0x400
|
||||
|
||||
#define SW_RESET() ((RIOT.swchb & RESET_MASK) == 0)
|
||||
#define SW_SELECT() ((RIOT.swchb & SELECT_MASK) == 0)
|
||||
#define SW_COLOR() ((RIOT.swchb & BW_MASK) != 0)
|
||||
#define SW_P0_PRO() ((RIOT.swchb & P0_DIFF_MASK) != 0)
|
||||
#define SW_P1_PRO() ((RIOT.swchb & P1_DIFF_MASK) != 0)
|
||||
|
||||
#define COLOR_CONV(color) (SW_COLOR() ? color : color & 0x0f)
|
||||
|
||||
#define _CYCLES(lines) (((lines) * 76) - 13)
|
||||
#define _TIM64(cycles) (((cycles) >> 6) - (((cycles) & 63) < 12))
|
||||
#define _T1024(cycles) ((cycles) >> 10)
|
||||
|
||||
#ifdef PAL
|
||||
#define VBLANK_TIM64 _TIM64(_CYCLES(45))
|
||||
#define KERNAL_T1024 _T1024(_CYCLES(250))
|
||||
#define OVERSCAN_TIM64 _TIM64(_CYCLES(36))
|
||||
#else
|
||||
#define VBLANK_TIM64 _TIM64(_CYCLES(37))
|
||||
#define KERNAL_TIM64 _TIM64(_CYCLES(198))
|
||||
#define OVERSCAN_TIM64 _TIM64(_CYCLES(28))
|
||||
#endif
|
||||
|
||||
#define JOY_UP(plyr) (!(RIOT.swcha & ((plyr) ? 0x1 : ~MOVE_UP)))
|
||||
#define JOY_DOWN(plyr) (!(RIOT.swcha & ((plyr) ? 0x2 : ~MOVE_DOWN)))
|
||||
#define JOY_LEFT(plyr) (!(RIOT.swcha & ((plyr) ? 0x4 : ~MOVE_LEFT)))
|
||||
#define JOY_RIGHT(plyr) (!(RIOT.swcha & ((plyr) ? 0x8 : ~MOVE_RIGHT)))
|
||||
#define JOY_FIRE(plyr) !(((plyr) ? TIA.inpt5 : TIA.inpt4) & 0x80)
|
||||
|
||||
// TIA - CONSTANTS
|
||||
|
||||
#define HMOVE_L7 (0x70)
|
||||
#define HMOVE_L6 (0x60)
|
||||
#define HMOVE_L5 (0x50)
|
||||
#define HMOVE_L4 (0x40)
|
||||
#define HMOVE_L3 (0x30)
|
||||
#define HMOVE_L2 (0x20)
|
||||
#define HMOVE_L1 (0x10)
|
||||
#define HMOVE_0 (0x00)
|
||||
#define HMOVE_R1 (0xF0)
|
||||
#define HMOVE_R2 (0xE0)
|
||||
#define HMOVE_R3 (0xD0)
|
||||
#define HMOVE_R4 (0xC0)
|
||||
#define HMOVE_R5 (0xB0)
|
||||
#define HMOVE_R6 (0xA0)
|
||||
#define HMOVE_R7 (0x90)
|
||||
#define HMOVE_R8 (0x80)
|
||||
|
||||
// Values for ENAMx and ENABL
|
||||
#define DISABLE_BM (0b00)
|
||||
#define ENABLE_BM (0b10)
|
||||
|
||||
// Values for RESMPx
|
||||
#define LOCK_MISSILE (0b10)
|
||||
#define UNLOCK_MISSILE (0b00)
|
||||
|
||||
// Values for REFPx
|
||||
#define NO_REFLECT (0b0000)
|
||||
#define REFLECT (0b1000)
|
||||
|
||||
// Values for NUSIZx
|
||||
#define ONE_COPY (0b000)
|
||||
#define TWO_COPIES (0b001)
|
||||
#define TWO_MED_COPIES (0b010)
|
||||
#define THREE_COPIES (0b011)
|
||||
#define TWO_WIDE_COPIES (0b100)
|
||||
#define DOUBLE_SIZE (0b101)
|
||||
#define THREE_MED_COPIES (0b110)
|
||||
#define QUAD_SIZE (0b111)
|
||||
#define MSBL_SIZE1 (0b000000)
|
||||
#define MSBL_SIZE2 (0b010000)
|
||||
#define MSBL_SIZE4 (0b100000)
|
||||
#define MSBL_SIZE8 (0b110000)
|
||||
|
||||
// Values for CTRLPF
|
||||
#define PF_PRIORITY (0b100)
|
||||
#define PF_SCORE (0b10)
|
||||
#define PF_REFLECT (0b01)
|
||||
#define PF_NO_REFLECT (0b00)
|
||||
|
||||
// Values for SWCHB
|
||||
#define P1_DIFF_MASK (0b10000000)
|
||||
#define P0_DIFF_MASK (0b01000000)
|
||||
#define BW_MASK (0b00001000)
|
||||
#define SELECT_MASK (0b00000010)
|
||||
#define RESET_MASK (0b00000001)
|
||||
|
||||
#define VERTICAL_DELAY (1)
|
||||
|
||||
// SWCHA joystick bits
|
||||
#define MOVE_RIGHT (0b01111111)
|
||||
#define MOVE_LEFT (0b10111111)
|
||||
#define MOVE_DOWN (0b11011111)
|
||||
#define MOVE_UP (0b11101111)
|
||||
#define P0_JOYSTICK_MASK (0b11110000)
|
||||
#define P1_JOYSTICK_MASK (0b00001111)
|
||||
#define P0_NO_MOVE (P0_JOYSTICK_MASK)
|
||||
#define P1_NO_MOVE (P1_JOYSTICK_MASK)
|
||||
#define NO_MOVE (P0_NO_MOVE | P1_NO_MOVE)
|
||||
#define P0_HORIZ_MOVE (MOVE_RIGHT & MOVE_LEFT & P0_NO_MOVE)
|
||||
#define P0_VERT_MOVE (MOVE_UP & MOVE_DOWN & P0_NO_MOVE)
|
||||
#define P1_HORIZ_MOVE (((MOVE_RIGHT & MOVE_LEFT) >> 4) & P1_NO_MOVE)
|
||||
#define P1_VERT_MOVE (((MOVE_UP & MOVE_DOWN) >> 4) & P1_NO_MOVE)
|
||||
|
||||
// SWCHA paddle bits
|
||||
#define P0_TRIGGER_PRESSED (0b01111111)
|
||||
#define P1_TRIGGER_PRESSED (0b10111111)
|
||||
#define P2_TRIGGER_PRESSED (0b11110111)
|
||||
#define P3_TRIGGER_PRESSED (0b11111011)
|
||||
|
||||
// Values for VBLANK
|
||||
#define DUMP_PORTS (0b10000000)
|
||||
#define ENABLE_LATCHES (0b01000000)
|
||||
#define DISABLE_TIA (0b00000010)
|
||||
#define ENABLE_TIA (0b00000000)
|
||||
|
||||
// Values for VSYNC
|
||||
#define START_VERT_SYNC (0b10)
|
||||
#define STOP_VERT_SYNC (0b00)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
.export _copyxdata
|
||||
.import __XDATA_LOAD__, __XDATA_RUN__, __XDATA_SIZE__
|
||||
.importzp ptr1, ptr2, tmp1
|
||||
|
||||
.code
|
||||
|
||||
_copyxdata:
|
||||
lda #<__XDATA_LOAD__ ; Source pointer
|
||||
sta ptr1
|
||||
lda #>__XDATA_LOAD__
|
||||
sta ptr1+1
|
||||
|
||||
lda #<__XDATA_RUN__ ; Target pointer
|
||||
sta ptr2
|
||||
lda #>__XDATA_RUN__
|
||||
ora #$04 ; write port
|
||||
sta ptr2+1
|
||||
|
||||
ldx #<~__XDATA_SIZE__
|
||||
lda #>~__XDATA_SIZE__ ; Use -(__DATASIZE__+1)
|
||||
sta tmp1
|
||||
ldy #$00
|
||||
|
||||
; Copy loop
|
||||
|
||||
@L1: inx
|
||||
beq @L3
|
||||
|
||||
@L2:
|
||||
lda #0
|
||||
sta $3F ; select ROM0
|
||||
lda (ptr1),y
|
||||
pha
|
||||
lda #0
|
||||
sta $3E ; select RAM0
|
||||
pla
|
||||
sta (ptr2),y
|
||||
iny
|
||||
bne @L1
|
||||
inc ptr1+1
|
||||
inc ptr2+1 ; Bump pointers
|
||||
bne @L1 ; Branch always (hopefully)
|
||||
|
||||
; Bump the high counter byte
|
||||
|
||||
@L3: inc tmp1
|
||||
bne @L2
|
||||
|
||||
; Done
|
||||
|
||||
lda #0
|
||||
sta $3F ; select ROM0
|
||||
rts
|
||||
|
|
@ -187,7 +187,7 @@ void draw_actor_rect(Actor* a) {
|
|||
}
|
||||
|
||||
word get_distance_squared(byte dx, byte dy) {
|
||||
return cc65_imul8x8r16(dx,dx) + cc65_imul8x8r16(dy,dy);
|
||||
return imul8x8r16(dx,dx) + imul8x8r16(dy,dy);
|
||||
}
|
||||
|
||||
typedef void ActorCollisionFn(struct Actor*, struct Actor*);
|
||||
|
@ -248,16 +248,16 @@ void explosion_update_fn(struct Actor* a) {
|
|||
}
|
||||
|
||||
const Actor ship_actor = {
|
||||
ship_shapes, NULL, 3, 0xb0, WHITE, 7, 0x1,
|
||||
ship_shapes, NULL, 3, 0xb0, WHITE, 7, 0x1
|
||||
};
|
||||
const Actor tetra_actor = {
|
||||
tetra_shapes, obstacle_update_fn, 3, 0x80, CYAN, 7, 0x2,
|
||||
tetra_shapes, obstacle_update_fn, 3, 0x80, CYAN, 7, 0x2
|
||||
};
|
||||
const Actor torpedo_actor = {
|
||||
torpedo_shapes, torpedo_update_fn, 4, 0xe0, YELLOW, 15, 0x4,
|
||||
torpedo_shapes, torpedo_update_fn, 4, 0xe0, YELLOW, 15, 0x4
|
||||
};
|
||||
const Actor explosion_actor = {
|
||||
explosion_shape, explosion_update_fn, 8, 0xa0, WHITE, 15, 0,
|
||||
explosion_shape, explosion_update_fn, 8, 0xa0, WHITE, 15, 0
|
||||
};
|
||||
|
||||
void create_obstacle() {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,9 +15,9 @@ void vec_mat_transform(Vector16* dest, const Vector8* v, const Matrix* m) {
|
|||
int* result = &dest->x;
|
||||
const sbyte* mval = &m->m[0][0];
|
||||
for (i=0; i<3; i++) {
|
||||
*result++ = cc65_imul8x8r16(*mval++, v->x)
|
||||
+ cc65_imul8x8r16(*mval++, v->y)
|
||||
+ cc65_imul8x8r16(*mval++, v->z);
|
||||
*result++ = imul8x8r16(*mval++, v->x)
|
||||
+ imul8x8r16(*mval++, v->y)
|
||||
+ imul8x8r16(*mval++, v->z);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "vecops.h"
|
||||
|
||||
const word* const VECFONT[];
|
||||
extern const word* const VECFONT[];
|
||||
|
||||
void draw_char(char ch);
|
||||
void draw_string(const char* str, byte spacing);
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
/*
|
||||
A bouncing ball using absolute coordinates.
|
||||
|
||||
Note: This module uses different clock domains
|
||||
and thus may be unstable on a FPGA.
|
||||
See: https://github.com/sehugg/8bitworkshop/issues/23
|
||||
*/
|
||||
|
||||
module ball_absolute_top(clk, reset, hsync, vsync, rgb);
|
||||
|
@ -18,8 +22,8 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
|
|||
reg [8:0] ball_hpos; // ball current X position
|
||||
reg [8:0] ball_vpos; // ball current Y position
|
||||
|
||||
reg [8:0] ball_horiz_move = -2; // ball current X velocity
|
||||
reg [8:0] ball_vert_move = 2; // ball current Y velocity
|
||||
reg [8:0] ball_horiz_move; // ball current X velocity
|
||||
reg [8:0] ball_vert_move; // ball current Y velocity
|
||||
|
||||
localparam ball_horiz_initial = 128; // ball initial X position
|
||||
localparam ball_vert_initial = 128; // ball initial Y position
|
||||
|
@ -52,15 +56,15 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
|
|||
end
|
||||
|
||||
// vertical bounce
|
||||
always @(posedge ball_vert_collide)
|
||||
always @(posedge ball_vert_collide or posedge reset)
|
||||
begin
|
||||
ball_vert_move <= -ball_vert_move;
|
||||
ball_vert_move <= reset ? 2 : -ball_vert_move;
|
||||
end
|
||||
|
||||
// horizontal bounce
|
||||
always @(posedge ball_horiz_collide)
|
||||
always @(posedge ball_horiz_collide or posedge reset)
|
||||
begin
|
||||
ball_horiz_move <= -ball_horiz_move;
|
||||
ball_horiz_move <= reset ? -2 : -ball_horiz_move;
|
||||
end
|
||||
|
||||
// offset of ball position from video beam
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
org $a000-2 ; so we can write the ...
|
||||
.word $a000 ; cartridge 2-byte header
|
||||
.word Start ; start vector
|
||||
.word Start ; RESTORE vector
|
||||
.byte $41, $30, $c3, $c2, $cd ; "A0CBM"
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#include "williams.h"
|
||||
//#link "williams.c"
|
||||
|
||||
int main(void) {
|
||||
byte i;
|
||||
|
||||
// write to graphics ROM
|
||||
rom_select = 1;
|
||||
// set palette
|
||||
for (i=0; i<16; i++)
|
||||
palette[i] = (byte)(i*7);
|
||||
// draw a rectangle
|
||||
blit_solid(0, 0, 152, 255, 0x1f);
|
||||
|
||||
// main loop
|
||||
while (1) {
|
||||
watchdog0x39 = 0x39;
|
||||
// code here
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
#include "stdlib.h"
|
||||
|
||||
const byte palette_data[16] = {
|
||||
0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x00, 0x00, 0x00, 0xf8, };
|
||||
const byte palette_data[16] = {/*{pal:332,n:16}*/
|
||||
0x00, 0x03, 0x19, 0x50, 0x52, 0x07, 0x1f, 0x37, 0xe0, 0xa4, 0xfd, 0xff, 0x38, 0x70, 0x7f, 0xf8, };
|
||||
|
||||
const byte sprite1[2+16*16/2] = {
|
||||
8,16,
|
||||
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
||||
0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
|
||||
0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
|
||||
0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
|
||||
|
@ -27,27 +27,28 @@ const byte sprite1[2+16*16/2] = {
|
|||
0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
|
||||
};
|
||||
|
||||
const byte sprite2[2+16*15/2] = {
|
||||
8,16,
|
||||
0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
|
||||
0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
|
||||
0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
|
||||
0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
|
||||
0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
|
||||
0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
|
||||
0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
|
||||
0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
|
||||
0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
|
||||
0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
|
||||
0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
|
||||
0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
|
||||
0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
|
||||
0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
|
||||
const byte sprite2[2+16*16/2] = {
|
||||
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
||||
0x00,0x08,0x80,0x40,0x00,0x00,0x8D,0x00,
|
||||
0x80,0x94,0x88,0x90,0x09,0x48,0x89,0x00,
|
||||
0x08,0x49,0x48,0x66,0x66,0x98,0x94,0x98,
|
||||
0x94,0x89,0x66,0x66,0x66,0x66,0x98,0x89,
|
||||
0x99,0x66,0x67,0x76,0x67,0x76,0x69,0x98,
|
||||
0x88,0x67,0x77,0x66,0x66,0x77,0x74,0x90,
|
||||
0x09,0x97,0x74,0x46,0x64,0x47,0x78,0x88,
|
||||
0x09,0x89,0x43,0x96,0x69,0x34,0x99,0x90,
|
||||
0x08,0x89,0xBB,0x39,0x93,0xBB,0x98,0x90,
|
||||
0x80,0x99,0x3B,0x33,0x33,0xB0,0x99,0x88,
|
||||
0x00,0x09,0x9C,0xC3,0x3C,0xC8,0x99,0x08,
|
||||
0x00,0x00,0x03,0xC3,0x8C,0x30,0x00,0x00,
|
||||
0x00,0x00,0x0D,0xD3,0x3D,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x00,0x0D,0xD0,0x00,0x00,
|
||||
0x00,0x00,0xDD,0x30,0x03,0xD0,0x00,0x00,
|
||||
0x00,0x00,0xD0,0x40,0x00,0xD0,0x00,0x00,
|
||||
};
|
||||
|
||||
const byte sprite3[2+16*16/2] = {
|
||||
8,16,
|
||||
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
||||
0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x11,0x11,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,
|
||||
|
@ -67,7 +68,7 @@ const byte sprite3[2+16*16/2] = {
|
|||
};
|
||||
|
||||
const byte sprite4[2+16*16/2] = {
|
||||
8,16,
|
||||
8,16,/*{w:16,h:16,bpp:4,brev:1}*/
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0xbb,0xbb,0x00,0x00,0x00,
|
||||
|
@ -106,8 +107,8 @@ const byte sprite5[2+16*16/2] = {
|
|||
0x02,0x02,0x00,0x20,0x02,0x00,0x20,0x20,
|
||||
};
|
||||
|
||||
const byte sprite6[2+16*10/2] = {
|
||||
8,10,
|
||||
const byte sprite6[2+10*16/2] = {
|
||||
8,10,/*{w:16,h:10,bpp:4,brev:1}*/
|
||||
0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00,
|
||||
0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x40,
|
||||
0x00,0x00,0x04,0x04,0x49,0x49,0x99,0x44,
|
||||
|
@ -120,8 +121,8 @@ const byte sprite6[2+16*10/2] = {
|
|||
0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
const byte sprite7[2+16*14/2] = {
|
||||
8,14,
|
||||
const byte sprite7[2+14*16/2] = {
|
||||
8,14,/*{w:16,h:14,bpp:4,brev:1}*/
|
||||
0x00,0x60,0x00,0x00,0x00,0x00,0x06,0x00,
|
||||
0x60,0x60,0x00,0x00,0x00,0x00,0x06,0x06,
|
||||
0x60,0x60,0x50,0x00,0x00,0x05,0x06,0x06,
|
||||
|
@ -138,8 +139,8 @@ const byte sprite7[2+16*14/2] = {
|
|||
0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
|
||||
};
|
||||
|
||||
const byte sprite8[2+16*15/2] = {
|
||||
8,15,
|
||||
const byte sprite8[2+15*16/2] = {
|
||||
8,15,/*{w:16,h:15,bpp:4,brev:1}*/
|
||||
0x00,0x00,0x11,0x11,0x11,0x11,0x00,0x00,
|
||||
0x00,0x01,0x61,0x11,0x21,0x12,0x10,0x00,
|
||||
0x00,0x11,0x12,0x11,0x61,0x11,0x11,0x00,
|
||||
|
@ -158,7 +159,7 @@ const byte sprite8[2+16*15/2] = {
|
|||
};
|
||||
|
||||
const byte sprite9[2+13*16/2] = {
|
||||
8,13,
|
||||
8,13,/*{w:16,h:13,bpp:4,brev:1}*/
|
||||
0x00,0x00,0xaa,0x00,0x00,0xaa,0x00,0x00,
|
||||
0x00,0x00,0xa0,0x0a,0xa0,0x0a,0x00,0x00,
|
||||
0x0a,0xaa,0xa4,0xaa,0xaa,0x3a,0xaa,0xa0,
|
||||
|
@ -174,6 +175,7 @@ const byte sprite9[2+13*16/2] = {
|
|||
0x00,0x0a,0xa0,0x00,0x00,0x0a,0xa0,0x00,
|
||||
};
|
||||
|
||||
|
||||
const byte* const all_sprites[9] = {
|
||||
sprite1,
|
||||
sprite2,
|
||||
|
@ -329,6 +331,7 @@ int main() {
|
|||
while (video_counter >= 0x80) ;
|
||||
update_grid_rows(GDIM/2,GDIM);
|
||||
watchdog0x39 = 0x39;
|
||||
//palette[0] = i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue