Compare commits

...

101 Commits

Author SHA1 Message Date
Steven Hugg d733a2cd27 arm32: fixed VCVT, VLDR/VSTR 2024-01-09 15:56:10 -05:00
Steven Hugg 098dcda93a arm32: parse dwarf info tree, convert to number 2024-01-06 11:55:59 -05:00
Steven Hugg 886e19611e arm32: crt0 update for malloc 2024-01-05 12:23:54 -05:00
Steven Hugg 02986aed38 arm32: parse dwarf 2024-01-04 22:30:53 -05:00
Steven Hugg d5b5734ef9 arm: fixed fpu, raster frame sync 2024-01-02 13:49:55 -05:00
Steven Hugg 579e58e966 close button for debug info 2024-01-01 15:27:42 -05:00
Steven Hugg 47a7aa5a83 arm: started on fpu insns 2024-01-01 15:21:52 -05:00
Steven Hugg 9142328468 arm: merged libc and libtcc1 2023-12-31 14:45:51 -05:00
Steven Hugg 70eee2bdae arm: fixing libc 2023-12-30 16:08:16 -05:00
Steven Hugg 949e216c69 make sure display + serial is updated if advanceFrame() throws 2023-12-30 15:24:57 -05:00
Steven Hugg b160fb2ef2 license: clarified multi-license 2023-12-30 15:07:29 -05:00
Steven Hugg 63ee25741b arm: libc 2023-12-30 11:53:56 -05:00
Steven Hugg 8bdbae36e3 arm: parse ELF 2023-12-29 20:41:40 -05:00
Steven Hugg c0909bef1b arm: arm-tcc 2023-12-28 17:26:44 -05:00
Steven Hugg 8023d56b88 c64: presets 2023-12-25 10:24:31 -05:00
Steven Hugg 45bc17d7ee exidy: started platform, c example 2023-12-15 19:46:06 -05:00
Steven Hugg 8452fe73a1 galaxian: update skeleton 2023-12-15 10:18:04 -05:00
Steven Hugg dff5c73d6a directive #embed for sdcc and cmoc 2023-12-13 23:38:38 -05:00
Steven Hugg f8462de014 williams: updated presets 2023-12-13 21:27:54 -05:00
Steven Hugg d08d73f422 astrocade: worked on arcade emulation 2023-12-13 20:54:42 -05:00
Steven Hugg 0ede0e514b sdcc: link errors no longer vanish if compile errors occur 2023-12-13 13:35:01 -05:00
Steven Hugg dbe73c4fb2 verilog: added example categories 2023-12-04 13:20:35 -06:00
Steven Hugg 9ecfb3cfa8 ide: refactored ui.ts a bit 2023-12-04 11:59:51 -06:00
Steven Hugg 312cb3d025 c64: removed wait_vblank macro 2023-12-01 11:14:18 -06:00
Steven Hugg bd63ef1268 dasm: started testing wasi
dasm:
2023-11-30 12:04:05 -06:00
Steven Hugg 2e0382b0a6 worker: refactor 2023-11-29 15:04:05 -06:00
Steven Hugg 611c174aed c64: set_raster_irq(), wait_vblank() 2023-11-29 12:51:42 -06:00
Steven Hugg d9001df5d4 cc7800 2023-11-28 18:08:02 -06:00
Steven Hugg e6c3dc98e1 fixed tests 2023-11-25 13:18:41 -06:00
Steven Hugg 43d844fa79 cleaned up Memory Map view
apple2: no logIOWrite for reads
2023-11-25 12:33:08 -06:00
Steven Hugg c5bcd8ad9b npm audit fix 2023-11-23 14:12:30 -06:00
Steven Hugg c189875be3 apple2: AppleSingle header for CC65 by default, try to parse 4-byte DOS headers 2023-11-22 21:43:30 -06:00
Steven Hugg 16fcf33881 c64: presets 2023-11-20 18:44:26 -06:00
Steven Hugg 8091985fde wasi: working on shim 2023-11-20 13:45:22 -06:00
Steven Hugg c9354a83ea changed #incbin to #embed (loosely based on C23 standard) 2023-11-17 10:29:35 -06:00
Steven Hugg 73c7ac5941 added category field to presets 2023-11-16 13:40:23 -06:00
Steven Hugg 19e3bbbea3 c64: updated examples 2023-11-14 15:24:49 -06:00
Steven Hugg 12957d7740 changed file selector to <optgroup> 2023-11-14 10:57:37 -06:00
Steven Hugg a252ea65bd vic20: default tiny bios 2023-11-13 22:35:49 -06:00
Steven Hugg 1c0b3e2fdd vcs: fixed test with null Context2D 2023-11-13 16:10:07 -06:00
Steven Hugg 44271fe9b8 added acme assembler
vcslib: increased # of lines in kernel
2023-11-13 12:37:38 -06:00
Steven Hugg f6452a719f c64: update presets, refactor analysis 2023-11-11 22:01:39 -06:00
Steven Hugg de6250b0cd show raster x/y crosshair when stopped (getRasterCanvasPosition) 2023-11-10 12:56:16 -06:00
Steven Hugg c6345ec728 server: updated parsing, flags 2023-11-09 10:10:45 -06:00
Steven Hugg d31a8c4efe tweaks to analysis, fixed verilog ball reset bug 2023-11-06 14:10:18 -06:00
Steven Hugg 3a08c24869 EmuHalt is squelched
nes: fixed loadState() npe
2023-11-05 21:27:27 -06:00
Steven Hugg 99370530f5 vcs: new skeleton for cc65 2023-11-05 20:07:33 -06:00
Steven Hugg fe6a8a6514 tool container setup 2023-11-05 14:43:54 -06:00
Steven Hugg a2d818c3e5 removed script platform 2023-11-05 12:16:39 -06:00
Steven Hugg fbd9089a8d updated nightwatch tests 2023-11-05 12:12:14 -06:00
Steven Hugg f18365cf9f remote: updates for multiple linked files, c64 samples 2023-11-05 06:21:31 -06:00
Steven Hugg 99f7ff41bb c64: updated music player, sid macros 2023-11-03 15:24:11 -05:00
Steven Hugg 2de919a225 hacked in "incbin" for C files, c64 lz4 example 2023-11-03 11:02:04 -05:00
Steven Hugg dd96813b76 pce: aspect ratio 2023-11-03 11:01:56 -05:00
Steven Hugg fc432a3bbf c64: .wiz 2023-11-02 12:39:11 -05:00
Steven Hugg 483675fded c64: .tap export 2023-11-01 16:48:19 -05:00
Steven Hugg 64ef7cc885 pce: hello.wiz 2023-10-31 23:09:58 -05:00
Steven Hugg 69600744df pce: optimizations, 32KB carts 2023-10-31 20:43:10 -05:00
Steven Hugg 5bc85161eb pce: pc engine started 2023-10-31 19:45:33 -05:00
Steven Hugg d11c1d1664 vcs: forgot vcslib.ca65 2023-10-31 11:35:23 -05:00
Steven Hugg 64f27879d7 multiple controllers no longer interfere 2023-10-31 11:25:45 -05:00
Steven Hugg 92fde04422 vcs: added vcslib demo 2023-10-30 23:16:36 -05:00
Steven Hugg d5460c991f ecs: C export if no system instances 2023-10-27 16:42:34 -05:00
Steven Hugg 73c74c519e vcs: changed .cfg file for TigerVision (3E) mapper
vcs: mappers 3E/3F don't correct bank offsets, so banks must not overlap
ca65: parse .proc symbols
2023-10-27 14:24:21 -05:00
Steven Hugg 2e2996bd73 ca65: fixed listing parsing 2023-10-15 10:28:48 -05:00
Steven Hugg 9e6fc9a0e3 vcs: added prelim cc65 support (using old compiler, new .lib/.h and custom .cfg) 2023-10-13 12:13:09 -05:00
Steven Hugg 0bf41a39c7 fixes for updated typescript 2023-09-12 21:57:08 -05:00
Steven Hugg ac9c14351f updated typescript 2023-08-31 14:27:57 -05:00
Steven Hugg f4d9124102 removed BaseWASIMachine, fixed wiz compile bug 2023-08-31 12:00:36 -05:00
Steven Hugg 70fdb68622 npm audit fix 2023-08-01 23:15:58 -05:00
Steven Hugg 3dba86c75d add d-pad switches to game controller
mapped some 2-button controllers to Z and X also
2023-08-01 13:53:26 -05:00
Steven Hugg cc385b7d98 atari7800: fixed write mode 2023-07-16 21:43:10 -05:00
Steven Hugg 3cea5a7d15 apple2: support shifted characters again 2023-07-13 14:26:38 -05:00
Steven Hugg b131d29663 7800: tweaks to debug info 2023-07-12 16:37:29 -05:00
Steven Hugg d4b8473b86 7800: implemented missing gfx modes, color kill, kangaroo mode 2023-07-12 16:21:39 -05:00
Steven Hugg 02834db8a1 atari7800: added 7800.h 2023-07-12 14:08:54 -05:00
Steven Hugg 37633d8875 atari8: fixed bug in debug tree 2023-07-09 23:35:02 -05:00
Steven Hugg 5a93bc8b75 a7800: pia timer, timing changes 2023-07-08 14:57:30 -05:00
Steven Hugg 47cabad5ec atari8: debug tree display list 2023-07-07 23:59:44 -05:00
Steven Hugg de12d20459 atari7800: debug tree for dlist, fixed dma hole bug 2023-07-06 21:18:00 -05:00
Steven Hugg c186d478fb removed ga 2023-07-02 10:11:04 -05:00
Steven Hugg 3bacf50409 forgot to upload tools/remote 2023-05-22 11:10:36 -05:00
Steven Hugg ac8f7c3f8b fixed audit msg by overriding node-fetch@2.6.7 2023-05-20 12:55:15 -05:00
Steven Hugg ee3ced574b more work on server, listings, platforms 2023-05-19 12:38:28 -05:00
Steven Hugg ba179160d6 started on server 2023-05-19 11:27:50 -05:00
Steven Hugg 5d11dd37df c64: decode SYS value for start addr, fix SYS xxxx kbd sticky issue 2023-05-19 11:27:50 -05:00
Steven Hugg 61443f586f modify link tags 2023-05-13 08:58:10 -05:00
Steven Hugg 0f011ee856 updated sentry.io 2023-05-11 11:28:42 -05:00
Steven Hugg 13656092c5 version bump 2023-04-25 12:44:49 -05:00
Steven Hugg f30850fdf1 atari-vector: fixed music.c
ui: fixed auto-play
2023-04-24 12:23:05 -05:00
Steven Hugg b707c5bf09 6502: fixed OPS_6502 stats as per https://github.com/TomHarte/ProcessorTests 2023-03-15 11:50:20 -05:00
Steven Hugg 232c027445 npm update 2023-02-15 17:24:09 -05:00
Steven Hugg 7bd5bffab5 fixed README for git url 2023-02-07 14:41:00 -05:00
Steven Hugg a3d7cc7dca c64: fixed presets 2023-02-07 14:26:35 -05:00
Steven Hugg 3972da4a13 c64: fixed presets 2023-02-07 14:24:42 -05:00
Steven Hugg a5a8b94991 c64: fixed presets 2023-02-07 14:16:38 -05:00
Steven Hugg 63d3b88a7a atari8: paddle inputs 2023-02-07 12:30:44 -05:00
Steven Hugg 9d39edf452 atari5200: added menu item, presets 2023-02-06 14:03:25 -05:00
Steven Hugg 2f8a5bee84 github: fixed delete repository 2023-02-06 13:50:31 -05:00
Steven Hugg e724ccb7d2 atari800: music preset; removed twitter link 2023-02-02 14:46:41 -05:00
Steven Hugg 3671054b16 vector-ataricolor: fixed examples for new cc65 2022-12-04 12:51:50 -06:00
236 changed files with 100907 additions and 10161 deletions

View File

@ -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'

View File

@ -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.

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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"/>
&nbsp;&nbsp;<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"/>
&nbsp;&nbsp;<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"/>
&nbsp;&nbsp;<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"/>
&nbsp;&nbsp;<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">&#x2190;&#x2191;&#x2193;&#x2192;</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">&#x2190;&#x2191;&#x2193;&#x2192;</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">&times;</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">&times;</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

View File

@ -3,7 +3,7 @@
test_settings: {
default: {
launch_url: 'https://8bitworkshop.com',
launch_url: 'https://sehugg.github.io/8bitworkshop/'
},
safari: {

13283
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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"
}

55
presets/apple2/lz4test.c Normal file
View File

@ -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.

View File

@ -0,0 +1,7 @@
#define SERIAL_OUT ((int*)0x4000048)
void putchar_(char c) {
*SERIAL_OUT = c;
}

35
presets/arm32/sieve.c Normal file
View File

@ -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;
}

View File

@ -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;
}

25
presets/arm32/vidfill.c Normal file
View File

@ -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;
}

141
presets/atari7800/7800.h Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

152
presets/atari7800/gfx.h Normal file
View File

@ -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
};

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -0,0 +1,7 @@
* = $0801
!word Start
!byte $00,$00,$9e
!text "2066"
!byte $00,$00,$00
* = $0812

127
presets/c64/c64.wiz Normal file
View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

42
presets/c64/hello.acme Normal file
View File

@ -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

181
presets/c64/hello.wiz Normal file
View File

@ -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;
}
}

16
presets/c64/helloc.c Normal file
View File

@ -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.

294
presets/c64/level2.ca65 Normal file
View File

@ -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

View File

@ -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

24
presets/c64/multisprite.h Normal file
View File

@ -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

300
presets/c64/plasma.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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

29
presets/c64/screen_ram.c Normal file
View File

@ -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);
}

View File

@ -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();

View File

@ -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

View File

@ -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);
}

View File

@ -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();

View File

@ -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

281
presets/c64/scrolling2.c Normal file
View File

@ -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;
}

179
presets/c64/scrollingmap1.c Normal file
View File

@ -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();
}
}

View File

@ -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();

View File

@ -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));

View File

@ -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) \

18
presets/c64/skeleton.acme Normal file
View File

@ -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

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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();
}
}

50
presets/c64/test_setirq.c Normal file
View File

@ -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);
}
}

50
presets/c64/testlz4.c Normal file
View File

@ -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();
}

View File

@ -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;
}

71
presets/exidy/minimal.c Normal file

File diff suppressed because one or more lines are too long

View File

@ -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;
}
///

130
presets/pce/hello.wiz Normal file
View File

@ -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";
}

241
presets/pce/siegegame.c Normal file
View File

@ -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();
}

14
presets/pce/skeleton.cc65 Normal file
View File

@ -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;
}

14
presets/pce/test_conio.c Normal file
View File

@ -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;
}

308
presets/vcs/ecs/airsea.ecs Normal file
View File

@ -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

147
presets/vcs/ecs/kernel1.ecs Normal file
View File

@ -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

View File

@ -7,6 +7,7 @@ system Init
.include "vcs-ca65.h"
.macpack longbranch
.define PAL 0
.segment "STARTUP"
__NMI:
__Reset:
__BRK:

68
presets/vcs/skeleton.cc65 Normal file
View File

@ -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();
}

View File

@ -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;
}

19
presets/vcs/vcslib/bcd.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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) {}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
;;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

265
presets/vcs/vcslib/vcslib.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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"

View File

@ -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;
}

View File

@ -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