├── .gitattributes ├── .gitignore ├── LICENSES.txt ├── MBMlib ├── LICENSE ├── MBMlib.rel ├── README.md └── src │ ├── MBMlib.c │ └── MBMlib.h ├── PSGlib ├── LICENSE ├── PSGlib.lib ├── PSGlib_MB.lib ├── PSGlib_NOSFX.lib ├── README.md ├── how to build this.txt └── src │ ├── PSGAttenuation.c │ ├── PSGPlayLoops.c │ ├── PSGRestoreVolumes.c │ ├── PSGResume.c │ ├── PSGlib.c │ ├── PSGlib.h │ └── PSGlib_extern.h ├── README.md ├── SGlib ├── LICENSE ├── README.md ├── SGlib.rel ├── how to build this.txt └── src │ ├── SGlib.c │ └── SGlib.h ├── SMSlib ├── LICENSE ├── README.md ├── SMSlib.lib ├── SMSlib_GG.lib └── src │ ├── Makefile │ ├── SMSlib.c │ ├── SMSlib.h │ ├── SMSlib_PSGaiden.c │ ├── SMSlib_STC0comp.c │ ├── SMSlib_STC4comp.c │ ├── SMSlib_STMcomp.c │ ├── SMSlib_UNSAFE.c │ ├── SMSlib_UNSAFE_SAT.c │ ├── SMSlib_UNSAFE_aPLib.c │ ├── SMSlib_UNSAFE_memcpy.c │ ├── SMSlib_VRAMmemcpy.c │ ├── SMSlib_VRAMmemcpy_brief.c │ ├── SMSlib_VRAMmemset.c │ ├── SMSlib_aPLib.c │ ├── SMSlib_autotext.c │ ├── SMSlib_common.c │ ├── SMSlib_debug.c │ ├── SMSlib_deprecated.c │ ├── SMSlib_foursprites.c │ ├── SMSlib_getTile.c │ ├── SMSlib_load1bppTiles.c │ ├── SMSlib_loadTileMapArea.c │ ├── SMSlib_loadTileMapColumn.c │ ├── SMSlib_metasprite.c │ ├── SMSlib_paddle.c │ ├── SMSlib_paletteAdd.c │ ├── SMSlib_paletteAdv.c │ ├── SMSlib_paletteSub.c │ ├── SMSlib_paletteZero.c │ ├── SMSlib_readVRAM.c │ ├── SMSlib_sprite.c │ ├── SMSlib_spriteAdv.c │ ├── SMSlib_spriteClip.c │ ├── SMSlib_string.c │ ├── SMSlib_textrenderer.c │ ├── SMSlib_threesprites.c │ ├── SMSlib_twosprites.c │ ├── SMSlib_zx7.c │ ├── SMSlib_zx7_VRAM.c │ ├── how to build this.txt │ └── peep-rules.txt ├── SUPPORT.md ├── assets2banks ├── README.md ├── Windows │ └── assets2banks.exe └── src │ └── assets2banks.py ├── build the library yourself.txt ├── crt0 ├── COPYING.txt ├── README.md ├── crt0_BASIC.rel ├── crt0_sg.rel ├── crt0_sms.rel └── src │ ├── Makefile │ ├── crt0_BASIC.s │ ├── crt0_sg.s │ └── crt0_sms.s ├── examples ├── .gitignore ├── first_test │ ├── Makefile │ ├── Makefile.gg │ ├── README.md │ ├── main.c │ └── screenshots │ │ └── first.png └── hello_sms │ ├── Makefile │ ├── README.md │ ├── main.c │ └── screenshots │ └── hello.png ├── folder2c ├── LICENSE ├── Linux │ └── folder2c ├── Windows │ └── folder2c.exe └── src │ └── folder2c.c ├── ihx2sms ├── LICENSE ├── Linux │ └── ihx2sms ├── README.md ├── Windows │ └── ihx2sms.exe └── src │ └── ihx2sms.c └── makesms ├── LICENSE ├── Linux └── makesms ├── README.md ├── Windows └── makesms.exe └── src ├── Makefile └── makesms.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /LICENSES.txt: -------------------------------------------------------------------------------- 1 | devkitSMS/crt0/crt0_sms.s is licensed under GPL2 with a "special exception", please read note in crt0/src/crt0_sms.s 2 | devkitSMS/crt0/crt0_sg.s is licensed under GPL2 with a "special exception", please read note in crt0/src/crt0_sg.s 3 | devkitSMS/ihx2sms is public domain. For more information, please refer to http://unlicense.org 4 | devkitSMS/assets2banks is public domain. For more information, please refer to http://unlicense.org 5 | devkitSMS/folder2c is public domain. For more information, please refer to http://unlicense.org 6 | devkitSMS/PSGlib is public domain. For more information, please refer to http://unlicense.org 7 | devkitSMS/MBMlib is public domain, as agreed with Kagesan. For more information, please refer to http://unlicense.org 8 | note:original MBM replay code by "Remco Schrijvers / MoonSoft", on WTFPL license. 9 | devkitSMS/SGlib is public domain, as agreed with na_th_an. For more information, please refer to http://unlicense.org 10 | devkitSMS/SMSlib is public domain. For more information, please refer to http://unlicense.org 11 | note:includes ZX7 decompression routines (noted as required by ZX7 license) 12 | note:includes aPLib decompression routines (in public domain, as agreed with Maxim and DWEdit) 13 | 14 | -------------------------------------------------------------------------------- /MBMlib/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /MBMlib/README.md: -------------------------------------------------------------------------------- 1 | MBMlib 2 | ====== 3 | 4 | A library to replay MoonBlaster modules on SEGA Master System / SEGA Mark III equipped with FM chip (either built in/add-on or mod board) 5 | 6 | These are the currently defined functions for module replay: 7 | 8 | ``` 9 | void MBMPlay (void *module) /* this will make your MoonBlaster module start and, if a loop has been defined in the module, loop infinitely */ 10 | void MBMCancelLoop (void) /* tell the library to stop the looping tune at next loop point */ 11 | void MBMPlayNoRepeat (void *module) /* this will make your MoonBlaster module start and stop at the end even if the module defined a loop */ 12 | 13 | void MBMStop (void) /* this will make the module stop (pause) */ 14 | void MBMResume (void) /* this will make your stopped (paused) tune resume playing */ 15 | 16 | unsigned char MBMGetStatus (void) /* get the current status of the tune. possible values are: */ 17 | 18 | MBM_STOPPED /* (zero) no module currently playing */ 19 | MBM_PLAYING /* a module is playing */ 20 | 21 | void MBMFadeOut (unsigned char fade_fraction) /* fade out the tune until the volume is zero and stop the tune */ 22 | /* parameter is a fraction denominator so: */ 23 | /* 0 is not valid, 1 will make the fade immediate and 255 is the slowest fade possible */ 24 | 25 | void MBMFrame (void) /* you should call this once per frame to replay the tune */ 26 | ``` 27 | 28 | Then, there are functions for sound effect replay: 29 | 30 | ``` 31 | void MBMSFXPlay (void *sound_effect) /* this will fire your sound effect */ 32 | void MBMSFXPlayLoop (void *sound_effect) /* this will start your sound effect in auto-retrigger mode */ 33 | void MBMSFXCancelLoop (void) /* tells the library to cancel the auto-retrigging on the currently playing sound effect */ 34 | 35 | void MBMSFXStop (void) /* this stops the playing sound effect immediately */ 36 | 37 | unsigned char MBMSFXGetStatus (void) /* get the current status of the sound effect. possible values are: */ 38 | 39 | MBMSFX_STOPPED /* (zero) no sound effect currently playing */ 40 | MBMSFX_PLAYING /* a sound effect is playing */ 41 | 42 | void MBMSFXFrame (void) /* you should call this once per frame to replay the sound effect */ 43 | 44 | ``` 45 | 46 | Finally, the library also provides a function to detect the presence of the FM chip and a function to enable/disable audio chips: 47 | 48 | ``` 49 | unsigned char SMS_GetFMAudioCapabilities (void) /* return if FM audio is available. possible values are: */ 50 | 51 | SMS_AUDIO_NO_FM /* (zero) if no FM chip is available */ 52 | SMS_AUDIO_FM_ONLY /* if FM chip is available but PSG audio won't be available when this is enabled */ 53 | SMS_AUDIO_FM_PSG /* if FM chip is available and PSG audio can be enabled at the same time */ 54 | 55 | void SMS_EnableAudio (unsigned char chips) /* use this to enable/disable audio chips. possible values are: */ 56 | 57 | SMS_ENABLE_AUDIO_FM_ONLY /* enable FM audio, disable PSG chip */ 58 | SMS_ENABLE_AUDIO_FM_PSG /* enable both audio chips, if possible */ 59 | SMS_ENABLE_AUDIO_PSG_ONLY /* disable FM chip, enable PSG audio */ 60 | SMS_ENABLE_AUDIO_NONE /* disable both audio chips, if possible */ 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /MBMlib/src/MBMlib.h: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | MBMlib - C programming library for Moonblaster modules replay 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | code: 'Remco Schrijvers / MoonSoft', Kagesan, sverx 5 | ************************************************** */ 6 | 7 | #define MBM_STOPPED 0 8 | #define MBM_PLAYING (~MBM_STOPPED) 9 | 10 | void MBMPlay (void *module) __z88dk_fastcall __naked; 11 | void MBMCancelLoop (void) __naked; 12 | void MBMPlayNoRepeat (void *module) __z88dk_fastcall __naked; 13 | 14 | void MBMStop (void) __naked; 15 | void MBMResume (void) __naked; 16 | 17 | unsigned char MBMGetStatus (void); 18 | 19 | void MBMFadeOut (unsigned char fade_fraction) __z88dk_fastcall; 20 | 21 | void MBMFrame (void) __naked; 22 | 23 | /* functions to detect and enable FM/PSG audio hardware */ 24 | 25 | #define SMS_AUDIO_NO_FM 0 26 | #define SMS_AUDIO_FM_ONLY 1 27 | #define SMS_AUDIO_FM_PSG 2 28 | 29 | unsigned char SMS_GetFMAudioCapabilities (void) __naked; 30 | 31 | #define SMS_ENABLE_AUDIO_FM_ONLY 0x01 32 | #define SMS_ENABLE_AUDIO_FM_PSG 0x03 33 | #define SMS_ENABLE_AUDIO_PSG_ONLY 0x00 34 | #define SMS_ENABLE_AUDIO_NONE 0x02 35 | 36 | void SMS_EnableAudio (unsigned char chips) __z88dk_fastcall __naked; 37 | 38 | /* SFX */ 39 | 40 | #define MBMSFX_STOPPED 0 41 | #define MBMSFX_PLAYING 1 42 | 43 | void MBMSFXPlay (void *sound_effect) __z88dk_fastcall __naked; 44 | void MBMSFXPlayLoop (void *sound_effect) __z88dk_fastcall; 45 | void MBMSFXCancelLoop (void); 46 | 47 | void MBMSFXStop (void) __naked; 48 | 49 | unsigned char MBMSFXGetStatus (void); 50 | 51 | void MBMSFXFrame (void) __naked; 52 | -------------------------------------------------------------------------------- /PSGlib/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /PSGlib/PSGlib.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/PSGlib/PSGlib.lib -------------------------------------------------------------------------------- /PSGlib/PSGlib_MB.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/PSGlib/PSGlib_MB.lib -------------------------------------------------------------------------------- /PSGlib/PSGlib_NOSFX.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/PSGlib/PSGlib_NOSFX.lib -------------------------------------------------------------------------------- /PSGlib/README.md: -------------------------------------------------------------------------------- 1 | PSGlib 2 | ====== 3 | 4 | these are the currently defined functions/macros: 5 | 6 | ``` 7 | 8 | void PSGPlay (void *song); /* this will make your PSG tune start and loop forever */ 9 | void PSGPlayLoops (void *song, unsigned char loops); /* this will make your PSG tune start and loop the requested amount of times*/ 10 | void PSGPlayNoRepeat (void *song); /* this will make your PSG tune start and stop at loop */ 11 | 12 | 13 | 14 | void PSGCancelLoop (void); /* tell the library to stop the tune at next loop */ 15 | void PSGStop (void); /* this will make your PSG tune stop (pause) */ 16 | void PSGResume (void); /* this will make your stopped (paused) PSG tune resume playing */ 17 | unsigned char PSGGetStatus (void); /* get the current status of the tune */ 18 | 19 | void PSGSetMusicVolumeAttenuation (unsigned char attenuation); /* this will set the tune attenuation (0-15) */ 20 | 21 | void PSGSFXPlay (unsigned char *sfx, unsigned char channels); /* this will make your SFX start */ 22 | void PSGSFXPlayLoop (unsigned char *sfx, unsigned char channels); /* this will make your looping SFX start */ 23 | void PSGSFXCancelLoop (void); /* tell the library to stop the SFX at next loop */ 24 | void PSGSFXStop (void); /* this will make your SFX stop */ 25 | unsigned char PSGSFXGetStatus (void); /* get the current status of the SFX */ 26 | 27 | void PSGSilenceChannels (void); /* this will silence all PSG channels */ 28 | void PSGRestoreVolumes (void); /* this will restore PSG channels volume */ 29 | 30 | void PSGFrame (void); /* you should call this at a constant pace */ 31 | void PSGSFXFrame (void); /* you should call this too at a constant pace, if you use SFXs */ 32 | ``` 33 | 34 | Multibank support 35 | ----------------- 36 | 37 | If PSGlib is compiled with PSGLIB_MULTIBANK, the PSGPlay functions 38 | also take a bank argument. This initial bank is rememberd by 39 | PSGlib and the bank will be switched automatically when calling 40 | PSGFrame(). 41 | 42 | PSGlib will automatically switch bank if the song data occupies 43 | more than 16kB, but it is assumed that the data is not segmented. 44 | (i.e. it must be consecutive in ROM) 45 | 46 | When PSGFrame() returns, the current bank in slot 2 may have 47 | been changed, so keep this in mind and take the necessary 48 | steps if necessary. (Set the bank again after the call, or 49 | use SMS_saveROMBank/restoreROMBank) 50 | 51 | When NOT compiled with PSGLIB_MULTIBANK, you must 52 | set the correct bank before calling PSGFrame manually and 53 | the song data cannot exceed 16kB. 54 | 55 | ``` 56 | /* Only if the library is compiled with PSGLIB_MULTIBANK. 57 | * Make sure to define PSGLIB_MULTIBANK before including 58 | * PSGlib.h 59 | */ 60 | 61 | void PSGPlay (void *song, unsigned char bank); /* this will make your PSG tune start and loop forever */ 62 | void PSGPlayLoops (void *song, unsigned char bank, unsigned char loops); /* this will make your PSG tune start and loop the requested amount of times*/ 63 | void PSGPlayNoRepeat (void *song, unsigned char bank); /* this will make your PSG tune start and stop at loop */ 64 | 65 | ``` 66 | -------------------------------------------------------------------------------- /PSGlib/how to build this.txt: -------------------------------------------------------------------------------- 1 | 2 | # default compile 3 | sdcc -c -mz80 --max-allocs-per-node 100000 PSGlib.c 4 | sdcc -c -mz80 --max-allocs-per-node 100000 PSGAttenuation.c 5 | sdcc -c -mz80 --max-allocs-per-node 100000 PSGPlayLoops.c 6 | sdcc -c -mz80 --max-allocs-per-node 100000 PSGRestoreVolumes.c 7 | sdcc -c -mz80 --max-allocs-per-node 100000 PSGResume.c 8 | 9 | # multibank compile 10 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_MULTIBANK -o PSGlib_MB.rel PSGlib.c 11 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_MULTIBANK -o PSGAttenuation_MB.rel PSGAttenuation.c 12 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_MULTIBANK -o PSGPlayLoops_MB.rel PSGPlayLoops.c 13 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_MULTIBANK -o PSGRestoreVolumes_MB.rel PSGRestoreVolumes.c 14 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_MULTIBANK -o PSGResume_MB.rel PSGResume.c 15 | 16 | # noSFX compile 17 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_NOSFXCODE -o PSGlib_NOSFX.rel PSGlib.c 18 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_NOSFXCODE -o PSGAttenuation_NOSFX.rel PSGAttenuation.c 19 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_NOSFXCODE -o PSGPlayLoops_NOSFX.rel PSGPlayLoops.c 20 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_NOSFXCODE -o PSGRestoreVolumes_NOSFX.rel PSGRestoreVolumes.c 21 | sdcc -c -mz80 --max-allocs-per-node 100000 -D PSGLIB_NOSFXCODE -o PSGResume_NOSFX.rel PSGResume.c 22 | 23 | # create libraries 24 | sdar r PSGlib.lib PSGlib.rel PSGAttenuation.rel PSGPlayLoops.rel PSGRestoreVolumes.rel PSGResume.rel 25 | sdar r PSGlib_MB.lib PSGlib_MB.rel PSGAttenuation_MB.rel PSGPlayLoops_MB.rel PSGRestoreVolumes_MB.rel PSGResume_MB.rel 26 | sdar r PSGlib_NOSFX.lib PSGlib_NOSFX.rel PSGAttenuation_NOSFX.rel PSGPlayLoops_NOSFX.rel PSGRestoreVolumes_NOSFX.rel PSGResume_NOSFX.rel 27 | 28 | -------------------------------------------------------------------------------- /PSGlib/src/PSGAttenuation.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | PSGlib - C programming library for the SEGA PSG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "PSGlib.h" 7 | #include "PSGlib_extern.h" 8 | 9 | void PSGSetMusicVolumeAttenuation (unsigned char attenuation) { 10 | /* ********************************************************************* 11 | sets the volume attenuation for the music (0-15) 12 | */ 13 | PSGMusicVolumeAttenuation=attenuation; 14 | if (PSGMusicStatus) { 15 | if (!PSGChannel0SFX) 16 | PSGPort=PSGLatch|PSGChannel0|PSGVolumeData|(((PSGChan0Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan0Volume&0x0F)+PSGMusicVolumeAttenuation); 17 | if (!PSGChannel1SFX) 18 | PSGPort=PSGLatch|PSGChannel1|PSGVolumeData|(((PSGChan1Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan1Volume&0x0F)+PSGMusicVolumeAttenuation); 19 | if (!PSGChannel2SFX) 20 | PSGPort=PSGLatch|PSGChannel2|PSGVolumeData|(((PSGChan2Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan2Volume&0x0F)+PSGMusicVolumeAttenuation); 21 | if (!PSGChannel3SFX) 22 | PSGPort=PSGLatch|PSGChannel3|PSGVolumeData|(((PSGChan3Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan3Volume&0x0F)+PSGMusicVolumeAttenuation); 23 | } 24 | } 25 | 26 | #ifndef PSGLIB_NOSFXCODE 27 | void PSGSetSFXVolumeAttenuation (unsigned char attenuation) { 28 | /* ********************************************************************* 29 | sets the volume attenuation for the SFXs (0-15) 30 | */ 31 | PSGSFXVolumeAttenuation=attenuation; 32 | if (PSGMusicStatus) { 33 | if (PSGChannel0SFX) 34 | PSGPort=PSGLatch|PSGChannel0|PSGVolumeData|(((PSGSFXChan0Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan0Volume&0x0F)+PSGSFXVolumeAttenuation); 35 | if (PSGChannel1SFX) 36 | PSGPort=PSGLatch|PSGChannel1|PSGVolumeData|(((PSGSFXChan1Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan1Volume&0x0F)+PSGSFXVolumeAttenuation); 37 | if (PSGChannel2SFX) 38 | PSGPort=PSGLatch|PSGChannel2|PSGVolumeData|(((PSGSFXChan2Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan2Volume&0x0F)+PSGSFXVolumeAttenuation); 39 | if (PSGChannel3SFX) 40 | PSGPort=PSGLatch|PSGChannel3|PSGVolumeData|(((PSGSFXChan3Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan3Volume&0x0F)+PSGSFXVolumeAttenuation); 41 | } 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /PSGlib/src/PSGPlayLoops.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | PSGlib - C programming library for the SEGA PSG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "PSGlib.h" 7 | #include "PSGlib_extern.h" 8 | 9 | #ifdef PSGLIB_MULTIBANK 10 | void PSGPlayLoops (void *song, unsigned char bank, unsigned char loops) { 11 | #else 12 | void PSGPlayLoops (void *song, unsigned char loops) { 13 | #endif 14 | /* ********************************************************************* 15 | receives the address of the PSG to start playing (continuously) and 16 | the number of loops (going back to loop point) requested 17 | */ 18 | #ifdef PSGLIB_MULTIBANK 19 | PSGPlay(song, bank); 20 | #else 21 | PSGPlay(song); 22 | #endif 23 | PSGLoopFlag=0; 24 | PSGLoopCounter=loops; 25 | } 26 | 27 | 28 | void PSGCancelLoop (void) { 29 | /* ********************************************************************* 30 | sets the currently looping music to no more loops after the current 31 | */ 32 | PSGLoopFlag=0; 33 | PSGLoopCounter=0; 34 | } 35 | 36 | #ifdef PSGLIB_MULTIBANK 37 | void PSGPlayNoRepeat (void *song, unsigned char bank) { 38 | #else 39 | void PSGPlayNoRepeat (void *song) { 40 | #endif 41 | /* ********************************************************************* 42 | receives the address of the PSG to start playing (once) 43 | */ 44 | #ifdef PSGLIB_MULTIBANK 45 | PSGPlay(song, bank); 46 | #else 47 | PSGPlay(song); 48 | #endif 49 | PSGLoopFlag=0; 50 | PSGLoopCounter=0; 51 | } 52 | -------------------------------------------------------------------------------- /PSGlib/src/PSGRestoreVolumes.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | PSGlib - C programming library for the SEGA PSG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "PSGlib.h" 7 | #include "PSGlib_extern.h" 8 | 9 | void PSGSilenceChannels (void) { 10 | /* ********************************************************************* 11 | silence all the PSG channels 12 | */ 13 | PSGPort=PSGLatch|PSGChannel0|PSGVolumeData|0x0F; 14 | PSGPort=PSGLatch|PSGChannel1|PSGVolumeData|0x0F; 15 | PSGPort=PSGLatch|PSGChannel2|PSGVolumeData|0x0F; 16 | PSGPort=PSGLatch|PSGChannel3|PSGVolumeData|0x0F; 17 | } 18 | 19 | void PSGRestoreVolumes (void) { 20 | /* ********************************************************************* 21 | restore the PSG channels volumes (if a tune or an SFX uses them!) 22 | */ 23 | if (PSGChannel0SFX) 24 | PSGPort=PSGLatch|PSGChannel0|PSGVolumeData|(((PSGSFXChan0Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan0Volume&0x0F)+PSGSFXVolumeAttenuation); 25 | else if (PSGMusicStatus) 26 | PSGPort=PSGLatch|PSGChannel0|PSGVolumeData|(((PSGChan0Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan0Volume&0x0F)+PSGMusicVolumeAttenuation); 27 | if (PSGChannel1SFX) 28 | PSGPort=PSGLatch|PSGChannel1|PSGVolumeData|(((PSGSFXChan1Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan1Volume&0x0F)+PSGSFXVolumeAttenuation); 29 | else if (PSGMusicStatus) 30 | PSGPort=PSGLatch|PSGChannel1|PSGVolumeData|(((PSGChan1Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan1Volume&0x0F)+PSGMusicVolumeAttenuation); 31 | if (PSGChannel2SFX) 32 | PSGPort=PSGLatch|PSGChannel2|PSGVolumeData|(((PSGSFXChan2Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan2Volume&0x0F)+PSGSFXVolumeAttenuation); 33 | else if (PSGMusicStatus) 34 | PSGPort=PSGLatch|PSGChannel2|PSGVolumeData|(((PSGChan2Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan2Volume&0x0F)+PSGMusicVolumeAttenuation); 35 | if (PSGChannel3SFX) 36 | PSGPort=PSGLatch|PSGChannel3|PSGVolumeData|(((PSGSFXChan3Volume&0x0F)+PSGSFXVolumeAttenuation>15)?15:(PSGSFXChan3Volume&0x0F)+PSGSFXVolumeAttenuation); 37 | else if (PSGMusicStatus) 38 | PSGPort=PSGLatch|PSGChannel3|PSGVolumeData|(((PSGChan3Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan3Volume&0x0F)+PSGMusicVolumeAttenuation); 39 | } 40 | -------------------------------------------------------------------------------- /PSGlib/src/PSGResume.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | PSGlib - C programming library for the SEGA PSG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "PSGlib.h" 7 | #include "PSGlib_extern.h" 8 | 9 | void PSGResume (void) { 10 | /* ********************************************************************* 11 | resume the previously playing music (also using current attenuation) 12 | */ 13 | if (!PSGMusicStatus) { 14 | if (!PSGChannel0SFX) { 15 | PSGPort=PSGLatch|PSGChannel0|(PSGChan0LowTone&0x0F); // restore channel 0 frequency 16 | PSGPort=PSGChan0HighTone&0x3F; 17 | PSGPort=PSGLatch|PSGChannel0|PSGVolumeData|(((PSGChan0Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan0Volume&0x0F)+PSGMusicVolumeAttenuation); // restore channel 0 volume 18 | } 19 | if (!PSGChannel1SFX) { 20 | PSGPort=PSGLatch|PSGChannel1|(PSGChan1LowTone&0x0F); // restore channel 1 frequency 21 | PSGPort=PSGChan1HighTone&0x3F; 22 | PSGPort=PSGLatch|PSGChannel1|PSGVolumeData|(((PSGChan1Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan1Volume&0x0F)+PSGMusicVolumeAttenuation); // restore channel 1 volume 23 | } 24 | if (!PSGChannel2SFX) { 25 | PSGPort=PSGLatch|PSGChannel2|(PSGChan2LowTone&0x0F); // restore channel 2 frequency 26 | PSGPort=PSGChan2HighTone&0x3F; 27 | PSGPort=PSGLatch|PSGChannel2|PSGVolumeData|(((PSGChan2Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan2Volume&0x0F)+PSGMusicVolumeAttenuation); // restore channel 2 volume 28 | } 29 | if (!PSGChannel3SFX) { 30 | PSGPort=PSGLatch|PSGChannel3|(PSGChan3LowTone&0x0F); // restore channel 3 frequency 31 | PSGPort=PSGLatch|PSGChannel3|PSGVolumeData|(((PSGChan3Volume&0x0F)+PSGMusicVolumeAttenuation>15)?15:(PSGChan3Volume&0x0F)+PSGMusicVolumeAttenuation); // restore channel 3 volume 32 | } 33 | PSGMusicStatus=PSG_PLAYING; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /PSGlib/src/PSGlib.h: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | PSGlib - C programming library for the SEGA PSG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #define PSG_STOPPED 0 7 | #define PSG_PLAYING 1 8 | 9 | #define SFX_CHANNEL2 #0x01 10 | #define SFX_CHANNEL3 #0x02 11 | #define SFX_CHANNELS2AND3 SFX_CHANNEL2|SFX_CHANNEL3 12 | #define SFX_CHANNEL0 #0x04 13 | #define SFX_CHANNEL1 #0x08 14 | 15 | /* About multi bank support 16 | * 17 | * If PSGlib is compiled with PSGLIB_MULTIBANK, the PSGPlayX functions 18 | * also take a bank argument. This initial bank is remembered by 19 | * PSGlib and the bank will be switched automatically when calling 20 | * PSGFrame(). 21 | * 22 | * PSGlib will automatically switch bank if the song data occupies 23 | * more than 16kB, but it is assumed that the data is not segmented. 24 | * (i.e. it must be consecutive in ROM) 25 | * 26 | * When PSGFrame() returns, the current bank in slot 2 may have 27 | * been changed, so keep this in mind and take the necessary 28 | * steps if necessary. (Set the bank again after the call, or 29 | * use SMS_saveROMBank/restoreROMBank) 30 | * 31 | * When NOT compiled with PSGLIB_MULTIBANK, you must 32 | * set the correct bank before calling PSGFrame manually and 33 | * the song data cannot exceed 16kB. 34 | */ 35 | 36 | #ifdef PSGLIB_MULTIBANK 37 | void PSGPlay (void *song, unsigned char bank); 38 | void PSGPlayLoops (void *song, unsigned char loops, unsigned char bank); 39 | void PSGPlayNoRepeat (void *song, unsigned char bank); 40 | #else 41 | void PSGPlay (void *song); 42 | void PSGPlayLoops (void *song, unsigned char loops); 43 | void PSGPlayNoRepeat (void *song); 44 | #endif 45 | 46 | void PSGCancelLoop (void); 47 | void PSGStop (void); 48 | void PSGResume (void); 49 | unsigned char PSGGetStatus (void); 50 | 51 | void PSGSetMusicVolumeAttenuation (unsigned char attenuation); 52 | void PSGSetSFXVolumeAttenuation (unsigned char attenuation); 53 | 54 | void PSGSFXPlay (void *sfx, unsigned char channels); 55 | void PSGSFXPlayLoop (void *sfx, unsigned char channels); 56 | void PSGSFXCancelLoop (void); 57 | void PSGSFXStop (void); 58 | unsigned char PSGSFXGetStatus (void); 59 | 60 | void PSGSilenceChannels (void); 61 | void PSGRestoreVolumes (void); 62 | 63 | void PSGFrame (void); 64 | void PSGSFXFrame (void); 65 | -------------------------------------------------------------------------------- /PSGlib/src/PSGlib_extern.h: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | PSGlib - C programming library for the SEGA PSG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #define PSGDataPort #0x7f 7 | 8 | #define PSGLatch #0x80 9 | #define PSGData #0x40 10 | 11 | #define PSGChannel0 #0b00000000 12 | #define PSGChannel1 #0b00100000 13 | #define PSGChannel2 #0b01000000 14 | #define PSGChannel3 #0b01100000 15 | #define PSGVolumeData #0b00010000 16 | 17 | #define PSGWait #0x38 18 | #define PSGSubString #0x08 19 | #define PSGLoop #0x01 20 | #define PSGEnd #0x00 21 | 22 | /* define PSGPort (SDCC z80 syntax) */ 23 | __sfr __at 0x7F PSGPort; 24 | 25 | // fundamental vars 26 | extern unsigned char PSGMusicStatus; // are we playing a background music? 27 | extern void *PSGMusicStart; // the pointer to the beginning of music 28 | extern void *PSGMusicPointer; // the pointer to the current 29 | extern void *PSGMusicLoopPoint; // the pointer to the loop begin 30 | #ifdef PSGLIB_MULTIBANK 31 | extern unsigned char PSGMusicStartBank; 32 | extern unsigned char PSGMusicPointerBank; 33 | extern unsigned char PSGMusicLoopPointBank; 34 | #endif 35 | extern unsigned char PSGMusicSkipFrames; // the frames we need to skip 36 | extern unsigned char PSGLoopFlag; // the tune should loop infinitely or not (flag) 37 | extern unsigned char PSGLoopCounter; // how many times the tune should loop 38 | extern unsigned char PSGMusicLastLatch; // the last PSG music latch 39 | extern unsigned char PSGMusicVolumeAttenuation; // the volume attenuation applied to the tune (0-15) 40 | 41 | // decompression vars 42 | extern unsigned char PSGMusicSubstringLen; // lenght of the substring we are playing 43 | extern void *PSGMusicSubstringRetAddr; // return to this address when substring is over 44 | #ifdef PSGLIB_MULTIBANK 45 | extern unsigned char PSGMusicSubstringRetBank; 46 | #endif 47 | 48 | // volume/frequence buffering 49 | extern unsigned char PSGChan0Volume; // the volume for channel 0 50 | extern unsigned char PSGChan1Volume; // the volume for channel 1 51 | extern unsigned char PSGChan2Volume; // the volume for channel 2 52 | extern unsigned char PSGChan3Volume; // the volume for channel 3 53 | extern unsigned char PSGChan0LowTone; // the low tone bits for channel 0 54 | extern unsigned char PSGChan0HighTone; // the high tone bits for channel 0 55 | extern unsigned char PSGChan1LowTone; // the low tone bits for channel 1 56 | extern unsigned char PSGChan1HighTone; // the high tone bits for channel 1 57 | extern unsigned char PSGChan2LowTone; // the low tone bits for channel 2 58 | extern unsigned char PSGChan2HighTone; // the high tone bits for channel 2 59 | extern unsigned char PSGChan3LowTone; // the tone bits for channel 3 60 | 61 | // flags for channels SFX access 62 | extern unsigned char PSGChannel0SFX; // !0 means channel 0 is allocated to SFX 63 | extern unsigned char PSGChannel1SFX; // !0 means channel 1 is allocated to SFX 64 | extern unsigned char PSGChannel2SFX; // !0 means channel 2 is allocated to SFX 65 | extern unsigned char PSGChannel3SFX; // !0 means channel 3 is allocated to SFX 66 | 67 | // volume buffering for SFX 68 | extern unsigned char PSGSFXChan0Volume; // the volume for SFX channel 0 69 | extern unsigned char PSGSFXChan1Volume; // the volume for SFX channel 1 70 | extern unsigned char PSGSFXChan2Volume; // the volume for SFX channel 2 71 | extern unsigned char PSGSFXChan3Volume; // the volume for SFX channel 3 72 | 73 | // fundamental vars for SFX 74 | extern unsigned char PSGSFXStatus; // are we playing a SFX? 75 | extern void *PSGSFXStart; // the pointer to the beginning of SFX 76 | extern void *PSGSFXPointer; // the pointer to the current address 77 | extern void *PSGSFXLoopPoint; // the pointer to the loop begin 78 | extern unsigned char PSGSFXSkipFrames; // the frames we need to skip 79 | extern unsigned char PSGSFXLoopFlag; // the SFX should loop or not (flag) 80 | extern unsigned char PSGSFXVolumeAttenuation; // the volume attenuation applied to the SFX (0-15) 81 | 82 | // decompression vars for SFX 83 | extern unsigned char PSGSFXSubstringLen; // lenght of the substring we are playing 84 | extern void *PSGSFXSubstringRetAddr; // return to this address when substring is over 85 | -------------------------------------------------------------------------------- /SGlib/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /SGlib/README.md: -------------------------------------------------------------------------------- 1 | SGlib 2 | ===== 3 | 4 | currently defined functions/macros: 5 | 6 | ``` 7 | /* basic VDP handling */ 8 | void SG_init (void) /* you don't even need to call this if you're using devkitSMS crt0_sg */ 9 | void SG_VDPturnOnFeature (unsigned int feature) /* check feature list in SGlib.h */ 10 | void SG_VDPturnOffFeature (unsigned int feature) 11 | SG_displayOn() /* macro - turns on screen */ 12 | SG_displayOff() /* macro - turns off screen */ 13 | void SG_setSpriteMode (unsigned char mode) /* check sprite modes in SGlib.h */ 14 | void SG_setBackdropColor (unsigned char entry) 15 | void SG_waitForVBlank (void) /* wait until next vBlank starts */ 16 | 17 | /* bankswitching */ 18 | SG_mapROMBank(n) /* macro - maps ROM bank n */ 19 | SG_getROMBank() /* macro - retrieve currently mapped ROM bank */ 20 | SG_saveROMBank() /* macro - save the currently mapped ROM bank in a local variable */ 21 | SG_restoreROMBank() /* macro - restore the previously saved ROM bank */ 22 | SG_enableSRAM() /* macro - enable cartridge SRAM */ 23 | SG_enableSRAMBank(n) /* macro - enable cartridge SRAM bank n */ 24 | SG_disableSRAM() /* macro - disable cartridge SRAM and go back to ROM mapping */ 25 | 26 | /* functions to load tiles patterns/colours into VRAM */ 27 | void SG_loadTilePatterns (void *src, unsigned int tilefrom, unsigned int size) 28 | void SG_loadTileColours (void *src, unsigned int tilefrom, unsigned int size) 29 | void SG_loadSpritePatterns (void *src, unsigned int tilefrom, unsigned int size) 30 | 31 | /* functions for tilemap loading/handling */ 32 | void SG_loadTileMap (unsigned char x, unsigned char y, void *src, unsigned int size) 33 | void SG_loadTileMapArea (unsigned char x, unsigned char y, void *src, unsigned char width, unsigned char height) 34 | void SG_setNextTileatXY (unsigned char x, unsigned char y) 35 | void SG_setTile (unsigned char tile) 36 | SG_setTileatXY(x,y,tile) 37 | void SG_getNextTileatXY (unsigned char x, unsigned char y) 38 | unsigned char SG_getTile (void) 39 | SG_getTileatXY(x,y) 40 | 41 | /* sprite handling */ 42 | void SG_initSprites (void) 43 | _Bool SG_addSprite (unsigned char x, unsigned char y, unsigned char tile, unsigned char attr) /* returns false if no more sprites are available */ 44 | void SG_setClippingWindow (unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1) 45 | _Bool SG_addSpriteClipping (int x, int y, unsigned char tile, unsigned char attr) /* returns false if no more sprites are available or sprite clipped */ 46 | void SG_finalizeSprites (void) 47 | void SG_copySpritestoSAT (void) 48 | 49 | /* joypad handling */ 50 | unsigned int SG_getKeysStatus (void) /* the current status of the keys */ 51 | unsigned int SG_getKeysPressed (void) /* the keys that were up last frame and down now */ 52 | unsigned int SG_getKeysHeld (void) /* the keys that were down last frame and still down now */ 53 | unsigned int SG_getKeysReleased (void) /* the keys that were down last frame and up now */ 54 | 55 | /* functions to read the keyboard virtual joypad(s) */ 56 | unsigned int SG_getKeyboardJoypadStatus (void) 57 | unsigned int SG_getKeyboardJoypadPressed (void) 58 | unsigned int SG_getKeyboardJoypadHeld (void) 59 | unsigned int SG_getKeyboardJoypadReleased (void) 60 | 61 | /* read from keyboard max keys and return the keycodes and amount */ 62 | unsigned char SG_getKeycodes (unsigned int *keys, unsigned char max_keys) 63 | 64 | /* pause handling */ 65 | _Bool SG_queryPauseRequested (void) /* the pause key has been pressed since previous check */ 66 | void SG_resetPauseRequest (void) /* reset/acknowledge pause requests */ 67 | 68 | /* decompress data to RAM */ 69 | void SG_decompressZX7 (const void *src, void *dst) /* function that does the decompression to RAM */ 70 | 71 | /* functions and macros to decompress data to VRAM */ 72 | void SG_decompressZX7toVRAM (const void *src, unsigned int dst) /* function that does the decompression directly to VRAM */ 73 | SG_loadZX7compressedBGTiles(src,tilefrom) /* handy macro to decompress tiles to background tiles */ 74 | SG_loadZX7compressedBGColors(src,tilefrom) /* handy macro to decompress tiles to background attributes */ 75 | SG_loadZX7compressedSpritesTiles(src,tilefrom) /* handy macro to decompress tiles to sprites */ 76 | SG_loadZX7compressedTilesatAddr(src,dst) /* handy macro to decompress tiles to any location in VRAM */ 77 | 78 | /* low level functions */ 79 | void SG_VRAMmemcpy (unsigned int dst, void *src, unsigned int size) /* memcpy to VRAM */ 80 | void SG_VRAMmemcpy_brief (unsigned int dst, void *src, unsigned char size) /* memcpy to VRAM (256 bytes max) */ 81 | void SG_VRAMmemset (unsigned int dst, unsigned char value, unsigned int size) /* memset to VRAM */ 82 | ``` 83 | 84 | -------------------------------------------------------------------------------- /SGlib/how to build this.txt: -------------------------------------------------------------------------------- 1 | sdcc -o SGlib.rel -c -mz80 --max-allocs-per-node 100000 SGlib.c 2 | 3 | -------------------------------------------------------------------------------- /SGlib/src/SGlib.h: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SGlib - C programming library for the SEGA SG-1000 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | code: na_th_an, sverx 5 | ************************************************** */ 6 | 7 | /* library initialization. you don't need to call this if you use devkitSMS crt0_sg.rel */ 8 | void SG_init (void); 9 | 10 | /* VDP operative mode handling functions */ 11 | void SG_VDPturnOnFeature (unsigned int feature); 12 | void SG_VDPturnOffFeature (unsigned int feature); 13 | /* turns on/off a VDP feature */ 14 | /* feature can be one of the following: */ 15 | #define SG_VDPFEATURE_SHOWDISPLAY 0x0140 16 | #define SG_VDPFEATURE_FRAMEIRQ 0x0120 17 | #define SG_VDPFEATURE_USELARGESPRITES 0x0102 18 | #define SG_VDPFEATURE_ZOOMSPRITES 0x0101 19 | /* (it's possible to combine (OR) them if they belong to the same group) */ 20 | 21 | /* handy macros :) */ 22 | #define SG_displayOn() SG_VDPturnOnFeature(SG_VDPFEATURE_SHOWDISPLAY) /* turns on display */ 23 | #define SG_displayOff() SG_VDPturnOffFeature(SG_VDPFEATURE_SHOWDISPLAY) /* turns off display */ 24 | 25 | void SG_setSpriteMode (unsigned char mode); 26 | #define SG_SPRITEMODE_NORMAL 0x00 27 | #define SG_SPRITEMODE_LARGE 0x01 28 | #define SG_SPRITEMODE_ZOOMED 0x02 29 | #define SG_SPRITEMODE_LARGE_ZOOMED 0x03 30 | 31 | void SG_setBackdropColor (unsigned char entry); 32 | #define SG_COLOR_TRANSPARENT 0x00 33 | #define SG_COLOR_BLACK 0x01 34 | #define SG_COLOR_MEDIUM_GREEN 0x02 35 | #define SG_COLOR_LIGHT_GREEN 0x03 36 | #define SG_COLOR_DARK_BLUE 0x04 37 | #define SG_COLOR_LIGHT_BLUE 0x05 38 | #define SG_COLOR_DARK_RED 0x06 39 | #define SG_COLOR_CYAN 0x07 40 | #define SG_COLOR_MEDIUM_RED 0x08 41 | #define SG_COLOR_LIGHT_RED 0x09 42 | #define SG_COLOR_DARK_YELLOW 0x0A 43 | #define SG_COLOR_LIGHT_YELLOW 0x0B 44 | #define SG_COLOR_DARK_GREEN 0x0C 45 | #define SG_COLOR_MAGENTA 0x0D 46 | #define SG_COLOR_GRAY 0x0E 47 | #define SG_COLOR_WHITE 0x0F 48 | 49 | /* wait until next VBlank starts */ 50 | void SG_waitForVBlank (void); 51 | 52 | /* macro for ROM bankswitching */ 53 | volatile __at (0xffff) unsigned char ROM_bank_to_be_mapped_on_slot2; 54 | #define SG_mapROMBank(n) ROM_bank_to_be_mapped_on_slot2=(n) 55 | 56 | /* macro to retrieve the currently mapped ROM bank */ 57 | #define SG_getROMBank() (ROM_bank_to_be_mapped_on_slot2) 58 | 59 | /* macros to preserve and restore the currently mapped ROM bank */ 60 | /* NOTE: they need to be used within the same scope (they use local variables) */ 61 | /* Typical use: In functions using SG_mapROMBank(), to make sure the mapped bank */ 62 | /* when entering the function is unchanged upon return. */ 63 | /* Use only one SG_saveROMBank() before the first SG_mapROMBank() in the function, */ 64 | /* and at least one SG_restoreROMBank() per following return statement. */ 65 | /* SG_restoreROMBank() may be used several times, for instance to access data in the original bank. */ 66 | #define SG_saveROMBank() unsigned char _saved_slot2_ROM_bank = ROM_bank_to_be_mapped_on_slot2 67 | #define SG_restoreROMBank() SG_mapROMBank(_saved_slot2_ROM_bank) 68 | 69 | /* additional symbols to control other mapper slots - use with care! */ 70 | volatile __at (0xfffe) unsigned char ROM_bank_to_be_mapped_on_slot1; 71 | volatile __at (0xfffd) unsigned char ROM_bank_to_be_mapped_on_slot0; 72 | 73 | /* macro for SRAM access */ 74 | volatile __at (0xfffc) unsigned char SRAM_bank_to_be_mapped_on_slot2; 75 | #define SG_enableSRAM() SRAM_bank_to_be_mapped_on_slot2=0x08 76 | #define SG_enableSRAMBank(n) SRAM_bank_to_be_mapped_on_slot2=((((n)<<2)|0x08)&0x0C) 77 | #define SG_disableSRAM() SRAM_bank_to_be_mapped_on_slot2=0x00 78 | 79 | /* SRAM access is as easy as accessing an array of char */ 80 | __at (0x8000) unsigned char SG_SRAM[]; 81 | 82 | /* functions to load tiles into VRAM */ 83 | void SG_loadTilePatterns (void *src, unsigned int tilefrom, unsigned int size); 84 | void SG_loadTileColours (void *src, unsigned int tilefrom, unsigned int size); 85 | void SG_loadSpritePatterns (void *src, unsigned int tilefrom, unsigned int size); 86 | 87 | /* functions for the tilemap */ 88 | void SG_loadTileMap (unsigned char x, unsigned char y, void *src, unsigned int size); 89 | void SG_loadTileMapArea (unsigned char x, unsigned char y, void *src, unsigned char width, unsigned char height); 90 | void SG_setNextTileatXY (unsigned char x, unsigned char y); 91 | void SG_setTile (unsigned char tile); 92 | void SG_getNextTileatXY (unsigned char x, unsigned char y); 93 | unsigned char SG_getTile (void); 94 | #define SG_setTileatXY(x,y,tile) do{SG_setNextTileatXY((x),(y));SG_setTile(tile);}while(0) 95 | #define SG_getTileatXY(x,y) (SG_getNextTileatXY((x),(y)),SG_getTile()) 96 | 97 | /* functions for sprites handling */ 98 | void SG_initSprites (void); 99 | _Bool SG_addSprite (unsigned char x, unsigned char y, unsigned char tile, unsigned char attr); /* returns false if no more sprites are available */ 100 | void SG_setClippingWindow (unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1); 101 | _Bool SG_addSpriteClipping (int x, int y, unsigned char tile, unsigned char attr); /* returns false if no more sprites are available or sprite clipped */ 102 | void SG_finalizeSprites (void); 103 | void SG_copySpritestoSAT (void); 104 | 105 | /* functions to read joypad(s) */ 106 | unsigned int SG_getKeysStatus (void); 107 | unsigned int SG_getKeysPressed (void); 108 | unsigned int SG_getKeysHeld (void); 109 | unsigned int SG_getKeysReleased (void); 110 | 111 | /* handy defines for joypad(s) handling */ 112 | #ifndef CONTROLLER_PORTS 113 | #define CONTROLLER_PORTS 114 | #define PORT_A_KEY_UP 0x0001 115 | #define PORT_A_KEY_DOWN 0x0002 116 | #define PORT_A_KEY_LEFT 0x0004 117 | #define PORT_A_KEY_RIGHT 0x0008 118 | #define PORT_A_KEY_1 0x0010 119 | #define PORT_A_KEY_2 0x0020 120 | #define PORT_A_KEY_START PORT_A_KEY_1 /* handy alias */ 121 | 122 | #define PORT_B_KEY_UP 0x0040 123 | #define PORT_B_KEY_DOWN 0x0080 124 | #define PORT_B_KEY_LEFT 0x0100 125 | #define PORT_B_KEY_RIGHT 0x0200 126 | #define PORT_B_KEY_1 0x0400 127 | #define PORT_B_KEY_2 0x0800 128 | #define PORT_B_KEY_START PORT_B_KEY_1 /* handy alias */ 129 | 130 | #define RESET_KEY 0x1000 131 | #define CARTRIDGE_SLOT 0x2000 /* ??? */ 132 | #define PORT_A_TH 0x4000 /* for light gun */ 133 | #define PORT_B_TH 0x8000 /* for light gun */ 134 | #endif 135 | 136 | _Bool SG_queryPauseRequested (void); /* true if the pause key has been pressed */ 137 | void SG_resetPauseRequest (void); /* reset/acknowledge pause requests */ 138 | 139 | _Bool SG_detectKeyboard (void); /* true if an attached keyboard is detected */ 140 | void SG_scanKeyboardJoypad (void); /* this scans the keyboard keys (emulating a joypad) */ 141 | 142 | /* functions to read the keyboard virtual joypad(s) */ 143 | unsigned int SG_getKeyboardJoypadStatus (void); 144 | unsigned int SG_getKeyboardJoypadPressed (void); 145 | unsigned int SG_getKeyboardJoypadHeld (void); 146 | unsigned int SG_getKeyboardJoypadReleased (void); 147 | 148 | /* read from keyboard max keys and return the keycodes and amount */ 149 | unsigned char SG_getKeycodes (unsigned int *keys, unsigned char max_keys); 150 | 151 | /* decompress data to RAM */ 152 | void SG_decompressZX7 (const void *src, void *dst) __naked; 153 | 154 | /* functions to decompress data to VRAM */ 155 | #define SG_loadZX7compressedBGTiles(src,tilefrom) SG_decompressZX7toVRAM((src),0x4000+((tilefrom)<<3)) 156 | #define SG_loadZX7compressedBGColors(src,tilefrom) SG_decompressZX7toVRAM((src),0x6000+((tilefrom)<<3)) 157 | #define SG_loadZX7compressedSpritesTiles(src,tilefrom) SG_decompressZX7toVRAM((src),0x7800+((tilefrom)<<3)) 158 | #define SG_loadZX7compressedTilesatAddr(src,dst) SG_decompressZX7toVRAM((src),(dst)) 159 | void SG_decompressZX7toVRAM (const void *src, unsigned int dst) __naked; 160 | 161 | /* low level functions */ 162 | void SG_VRAMmemcpy (unsigned int dst, void *src, unsigned int size); 163 | void SG_VRAMmemcpy_brief (unsigned int dst, void *src, unsigned char size); 164 | void SG_VRAMmemset (unsigned int dst, unsigned char value, unsigned int size); 165 | void SG_VRAMmemsetW (unsigned int dst, unsigned int value, unsigned int size); 166 | 167 | /* vertical interrupt hook */ 168 | #ifndef NO_FRAME_INT_HOOK 169 | /* If non-NULL, the specified function will be called by SG_isr after acknowledging */ 170 | /* the interrupt and reading controller status. */ 171 | void SG_setFrameInterruptHandler (void (*theHandlerFunction)(void)) __z88dk_fastcall; 172 | #endif 173 | 174 | /* the Interrupt Service Routines (do not modify) */ 175 | void SG_isr (void) __critical __interrupt(0); 176 | void SG_nmi_isr (void) __critical __interrupt; 177 | -------------------------------------------------------------------------------- /SMSlib/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /SMSlib/SMSlib.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/SMSlib/SMSlib.lib -------------------------------------------------------------------------------- /SMSlib/SMSlib_GG.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/SMSlib/SMSlib_GG.lib -------------------------------------------------------------------------------- /SMSlib/src/Makefile: -------------------------------------------------------------------------------- 1 | CC=sdcc 2 | AR=sdar 3 | 4 | ########### BUILD CONFIGURATION ############## 5 | 6 | # Enables a faster version of SMS_addSprite (and SMS_add*AdjoiningSprites) 7 | # which does not return a handle and does not check for sprite terminator 8 | # and sprite availability 9 | #CONFIG+=-DNO_SPRITE_CHECKS 10 | 11 | # Enables a faster version of SMS_add*AdjoiningSprites through disabling 12 | # support for zoomed sprites 13 | #CONFIG+=-DNO_SPRITE_ZOOM 14 | 15 | # Enable support for Megadrive controllers 16 | #CONFIG+=-DMD_PAD_SUPPORT 17 | 18 | # Enable support for VDP type detection 19 | #CONFIG+=-DVDPTYPE_DETECTION 20 | 21 | # Build a lib supporting less sprites to save memory. Max is 64 (all). 22 | #CONFIG+=-DMAXSPRITES=64 23 | 24 | # Omit support for a frame interrupt hook to save a few bytes 25 | # and cycles. 26 | #CONFIG+=-DNO_FRAME_INT_HOOK 27 | 28 | ############# END OF BUILD CONFIG OPTIONS ############# 29 | 30 | OPT=--max-allocs-per-node 100000 31 | CFLAGS=-mz80 $(OPT) $(CONFIG) 32 | PEEP_OPTIONS=--peep-file peep-rules.txt 33 | 34 | OUTPUT_LIBS=SMSlib.lib SMSlib_GG.lib 35 | 36 | # Files that are compiled once and used for SMS and GG 37 | SRCS=SMSlib_aPLib.c SMSlib_autotext.c SMSlib_deprecated.c SMSlib_load1bppTiles.c SMSlib_loadTileMapArea.c SMSlib_loadTileMapColumn.c SMSlib_paddle.c SMSlib_paletteAdv.c SMSlib_paletteAdd.c SMSlib_paletteSub.c SMSlib_paletteZero.c SMSlib_STC0comp.c SMSlib_STC4comp.c SMSlib_PSGaiden.c SMSlib_spriteAdv.c SMSlib_sprite.c SMSlib_STMcomp.c SMSlib_textrenderer.c SMSlib_twosprites.c SMSlib_threesprites.c SMSlib_foursprites.c SMSlib_metasprite.rel SMSlib_UNSAFE.c SMSlib_UNSAFE_SAT.c SMSlib_UNSAFE_memcpy.c SMSlib_UNSAFE_aPLib.c SMSlib_VRAMmemcpy_brief.c SMSlib_VRAMmemcpy.c SMSlib_VRAMmemset.c SMSlib_zx7.c SMSlib_zx7_VRAM.c SMSlib_string.c SMSlib_getTile.c SMSlib_readVRAM.c SMSlib_debug.c 38 | 39 | # One .rel per common source file. Add target specific .rel dependencies here. 40 | OBJS_SMS=$(patsubst %.c,%.rel,$(SRCS)) SMSlib.rel SMSlib_autotext.rel SMSlib_spriteClip.rel 41 | OBJS_GG=$(patsubst %.c,%.rel,$(SRCS)) SMSlib_GG.rel SMSlib_autotext_GG.rel SMSlib_spriteClip_GG.rel 42 | 43 | ALL: $(OUTPUT_LIBS) 44 | 45 | # Library outputs 46 | SMSlib.lib: $(OBJS_SMS) 47 | sdar r $@ $^ 48 | 49 | SMSlib_GG.lib: $(OBJS_GG) 50 | sdar r $@ $^ 51 | 52 | 53 | # Specific rules for some files with particular compilation options or specific 54 | # to a target. 55 | 56 | SMSlib.rel: SMSlib.c SMSlib.h peep-rules.txt 57 | #$(CC) $(CFLAGS) $(PEEP_OPTIONS) --reserve-regs-iy -c -o $@ $< 58 | $(CC) $(CFLAGS) $(PEEP_OPTIONS) -c -o $@ $< 59 | 60 | SMSlib_GG.rel: SMSlib.c SMSlib.h peep-rules.txt 61 | #$(CC) $(CFLAGS) $(PEEP_OPTIONS) --reserve-regs-iy -c -o $@ $< -DTARGET_GG 62 | $(CC) $(CFLAGS) $(PEEP_OPTIONS) -c -o $@ $< -DTARGET_GG 63 | 64 | SMSlib_autotext_GG.rel: SMSlib_autotext.c SMSlib.h peep-rules.txt 65 | $(CC) $(CFLAGS) $(PEEP_OPTIONS) -c -o $@ $< -DTARGET_GG 66 | 67 | SMSlib_spriteClip_GG.rel: SMSlib_spriteClip.c SMSlib.h peep-rules.txt 68 | $(CC) $(CFLAGS) $(PEEP_OPTIONS) -c -o $@ $< -DTARGET_GG 69 | 70 | # The following are compiled without --peep-rules 71 | SMSlib_zx7.rel: SMSlib_zx7.c 72 | $(CC) $(CFLAGS) -c -o $@ $< 73 | 74 | SMSlib_UNSAFE_zx7.rel: SMSlib_UNSAFE_zx7.c 75 | $(CC) $(CFLAGS) -c -o $@ $< 76 | 77 | SMSlib_aPLib.rel: SMSlib_aPLib.c 78 | $(CC) $(CFLAGS) -c -o $@ $< 79 | 80 | SMSlib_paddle.rel: SMSlib_paddle.c 81 | $(CC) $(CFLAGS) -c -o $@ $< 82 | 83 | # Default rules 84 | %.rel: %.c SMSlib.h peep-rules.txt 85 | $(CC) $(CFLAGS) $(PEEP_OPTIONS) -c -o $@ $< 86 | 87 | clean: 88 | rm -f $(OUTPUT_LIBS) $(OBJS_SMS) $(OBJS_GG) *.lst *.sym *.asm 89 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_PSGaiden.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | unsigned char decompBuffer[32]; /* decompression buffer */ 10 | 11 | #pragma save 12 | #pragma disable_warning 85 13 | void SMS_loadPSGaidencompressedTilesatAddr (const void *src, unsigned int dst) __naked __sdcccall(1) { 14 | /* *********************************************************************************** 15 | Phantasy Star Gaiden Tile Decoder 16 | taken from http://www.smspower.org/Development/PhantasyStarGaidenTileDecoder 17 | (slightly modified and wrapped into a C function - and it MUST preserve ix register ) 18 | ************************************************************************************** */ 19 | // src in HL 20 | // dst in DE 21 | __asm 22 | push ix ; preserve ix 23 | 24 | ld c, #0xbf ; Set VRAM address 25 | di 26 | out (c),e 27 | out (c),d 28 | ei 29 | 30 | ld c,(hl) ; bc = number of tiles 31 | inc hl 32 | ld b,(hl) 33 | inc hl 34 | 35 | push hl ; ld ix,hl 36 | pop ix 37 | 38 | _DecompressTile: 39 | push bc ; save number of tiles 40 | ld b,#4 ; count 4 bitplanes 41 | ld de,#_decompBuffer ; write to de 42 | ld c,(ix) ; c = encoding information for 4 bitplanes 43 | inc ix 44 | 45 | _DecompressBitplane: 46 | rlc c ; %0x = all bits either 0 or 1 47 | jr nc,_AllTheSame 48 | rlc c ; %11 = raw data 49 | jr c,_RawData 50 | 51 | _Compressed: 52 | ld a,(ix) ; get method byte 53 | inc ix 54 | 55 | ex de,hl ; get bitplane, if it is referring to one 56 | ld d,a 57 | and #0x03 58 | add a,a ; calculate address of that bitplane 59 | add a,a ; = buffer + bitplane * 8 60 | add a,a 61 | ld e,a 62 | ld a,d ; get method byte back 63 | ld d,#0x00 64 | ld iy,#_decompBuffer 65 | add iy,de ; now iy points to the referred to bitplane 66 | ex de,hl 67 | 68 | ; now check the method byte 69 | cp #0x03 ; %000000pp 70 | jr c,_DuplicateBitplane 71 | cp #0x10 72 | jr c,_CommonValue 73 | cp #0x13 ; %000100pp 74 | jr c,_DuplicateBitplaneInvert 75 | cp #0x20 76 | jr c,_CommonValue 77 | cp #0x23 ; %001000pp 78 | jr c,_DuplicateBitplanePartial 79 | cp #0x40 80 | jr c,_CommonValue 81 | cp #0x43 ; %010000pp 82 | jr c,_DuplicateBitplanePartialInvert 83 | ; fall through 84 | 85 | _CommonValue: 86 | ld h,a ; h = bitmask 87 | ld l,(ix) ; l = common value 88 | inc ix 89 | jr _OutputCommonValue 90 | 91 | _RawData: 92 | ld h,#0x00 ; empty bitmask; no common value 93 | jr _OutputCommonValue 94 | 95 | _AllTheSame: 96 | rlc c ; get next bit into carry 97 | sbc a,a ; will make $00 if carry = 0, $ff if it is 1 98 | ld l,a ; that is the common value 99 | ld h,#0xff ; full bitmask 100 | ; fall through 101 | 102 | _OutputCommonValue: 103 | push bc 104 | ld b,#8 ; loop counter 105 | _loop1: 106 | ld a,l ; get common value 107 | rlc h ; get bit out of bitmask 108 | jr c,_skip1 ; if 1, use the common value 109 | ld a,(ix) ; else get it from (ix++) 110 | inc ix 111 | _skip1: 112 | ld (de),a ; write to dest 113 | inc de 114 | djnz _loop1 ; loop over 8 bytes 115 | pop bc 116 | jr _BitplaneDone 117 | 118 | _DuplicateBitplane: 119 | ld hl,#0xff00 ; full copy bitmask, empty inversion bitmask 120 | jr _OutputDuplicate 121 | 122 | _DuplicateBitplaneInvert: 123 | ld hl,#0xffff ; full copy bitmask, full inversion bitmask 124 | jr _OutputDuplicate 125 | 126 | _DuplicateBitplanePartial: 127 | ld h,(ix) ; get copy bitmask 128 | ld l,#0x00 ; empty inversion bitmask 129 | inc ix 130 | jr _OutputDuplicate 131 | 132 | _DuplicateBitplanePartialInvert: 133 | ld h,(ix) ; get copy bitmask 134 | ld l,#0xff ; full inversion bitmask 135 | inc ix 136 | ; fall through 137 | 138 | _OutputDuplicate: 139 | push bc 140 | ld b,#8 ; loop counter 141 | _loop2: 142 | ld a,(iy) ; read byte to copy 143 | inc iy 144 | xor l ; apply inversion mask 145 | rlc h ; get bit out of bitmask 146 | jr c,_skip2 ; if 1, use the copied value 147 | ld a,(ix) ; else get it from (ix++) 148 | inc ix 149 | _skip2: 150 | ld (de),a ; write to dest 151 | inc de 152 | djnz _loop2 ; loop over 8 bytes 153 | pop bc 154 | ; fall through 155 | 156 | _BitplaneDone: 157 | dec b ; decrement bitplane counter 158 | jp nz,_DecompressBitplane ; loop if not zero 159 | 160 | _OutputTileToVRAM: 161 | ld de,#8 ; we are interleaving every 8th byte 162 | ld c,e ; counter for the interleaving run 163 | ld hl,#_decompBuffer ; point at data to write 164 | 165 | _outLoop: 166 | ld b,#4 ; there are 4 bytes to interleave 167 | push hl 168 | _inLoop: 169 | ld a,(hl) ; read byte 170 | out (#0xbe),a ; write to vram 171 | add hl,de ; skip 8 bytes 172 | djnz _inLoop 173 | pop hl 174 | inc hl ; next interleaving run 175 | dec c 176 | jr nz,_outLoop 177 | 178 | pop bc 179 | dec bc ; next tile 180 | ld a,b 181 | or c 182 | jp nz,_DecompressTile 183 | pop ix ; restore preserved ix 184 | ret ; because this function is naked 185 | __endasm; 186 | } 187 | #pragma restore 188 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_STC0comp.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | #pragma save 9 | #pragma disable_warning 85 10 | void SMS_loadSTC0compressedTilesatAddr (const void *src, unsigned int dst) __naked __sdcccall(1) { 11 | __asm 12 | ld c,#0xbf ; VDP_CTRL_PORT 13 | di 14 | out (c),e 15 | out (c),d 16 | ei 17 | dec c ; same as ld c,VDP_DATA_PORT_ADDRESS 18 | ld de,#0x00FF ; D = 0x00, E = 0xFF 19 | 20 | _stc0_decompress_outer_loop: 21 | ld b,#4 22 | ld a,(hl) 23 | inc hl 24 | 25 | _stc0_decompress_inner_loop: 26 | rla 27 | jr c,_compressed_byte ; if 1X found, write 0x00 or 0xFF 28 | rla 29 | jr nc,_same_byte_or_leave 30 | outi ; write raw byte 31 | jr nz,_stc0_decompress_inner_loop 32 | jp _stc0_decompress_outer_loop 33 | 34 | _same_byte_or_leave: 35 | bit 2,b 36 | ret nz ; 00 found in first 2 bits -> end of data, leave 37 | dec hl 38 | outi ; write same raw byte again 39 | jr nz,_stc0_decompress_inner_loop 40 | jp _stc0_decompress_outer_loop 41 | 42 | _compressed_byte: 43 | rla 44 | jr c,_compressed_FF 45 | out (c),d ; write 0x00 46 | djnz _stc0_decompress_inner_loop 47 | jp _stc0_decompress_outer_loop 48 | 49 | _compressed_FF: 50 | out (c),e ; write 0xFF 51 | djnz _stc0_decompress_inner_loop 52 | jp _stc0_decompress_outer_loop 53 | __endasm; 54 | } 55 | #pragma restore 56 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_STC4comp.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | unsigned char stc4_buffer[4]; 9 | 10 | #pragma save 11 | #pragma disable_warning 85 12 | void SMS_loadSTC4compressedTilesatAddr (const void *src, unsigned int dst) __naked __sdcccall(1) { 13 | __asm 14 | ld c,#0xbf ; VDP_CTRL_PORT 15 | di 16 | out (c),e ; set VRAM destination address 17 | out (c),d 18 | ei 19 | 20 | _stc4_decompress_outer_loop: 21 | ld a,(hl) 22 | cp #0x20 ; if value less than 0x20 it is a rerun or an end-of-data marker 23 | jr c,_reruns_or_leave 24 | 25 | ld b,#4 26 | ld de,#_stc4_buffer 27 | 28 | _stc4_decompress_inner_loop: 29 | rla 30 | jr c,_compressed_00_or_FF ; if 1X found, write $00 or $FF 31 | 32 | rla 33 | jr nc,_same_or_diff ; if 0b00 found it is same or diff 34 | 35 | ld c,a ; preserve A 36 | inc hl 37 | ld a,(hl) ; load uncompressed byte 38 | 39 | _stc4_write_byte: 40 | out (#0xbe),a ; write byte to VRAM 41 | ld (de),a ; and to buffer too 42 | inc de ; advance buffer pointer 43 | ld a,c ; restore A 44 | djnz _stc4_decompress_inner_loop ; we have got more to process in this byte 45 | 46 | inc hl ; move to next byte 47 | jp _stc4_decompress_outer_loop 48 | 49 | _compressed_00_or_FF: 50 | rla 51 | ld c,a ; preserve A 52 | sbc a ; this turns the CF into $00 or $FF 53 | jp _stc4_write_byte 54 | 55 | _same_or_diff: 56 | bit 2,b 57 | jr nz,_diff ; if byte is $00nnnnnn then it means it is a diff, not a same byte in the group 58 | 59 | _same_byte: 60 | ld c,a ; preserve A 61 | ld a,(hl) ; we won't [inc hl] here because we're loading the same value as before so we are already on that 62 | jp _stc4_write_byte 63 | 64 | ; ************************************ 65 | _diff: 66 | rla ; skip D5 67 | ld c,a ; save D4 in C MSB 68 | rla ; skip D4 69 | 70 | _diff_loop: 71 | rla 72 | .db 0xFD ; --- SDCC issues workaround 73 | ld l,a ; ld iyl,a (preserve A) 74 | jr c,_raw_value_follows ; when 1 a data byte will follow 75 | 76 | ld a,(de) 77 | bit 7,c 78 | jr z,_write_diff_byte 79 | 80 | cpl ; invert data if D4 was set 81 | ld (de),a ; and save it back into the buffer 82 | 83 | _write_diff_byte: 84 | out (#0xbe),a ; write byte from buffer to VRAM 85 | .db 0xFD ; --- SDCC issues workaround 86 | ld a,l ; ld a,iyl (restore A) 87 | inc de ; advance buffer pointer 88 | djnz _diff_loop ; until we are done with the 4 bits 89 | 90 | inc hl ; move to next byte 91 | jp _stc4_decompress_outer_loop ; loop over 92 | 93 | _raw_value_follows: 94 | inc hl 95 | ld a,(hl) 96 | ld (de),a ; save it into the buffer 97 | jp _write_diff_byte 98 | 99 | ; ************************************ 100 | _reruns_or_leave: 101 | and #0x1F ; keep the lowest 5 bits only 102 | ret z ; if value is zero, the EOD marker has been found, so leave 103 | 104 | ld b,a ; save reruns counter in B 105 | 106 | _transfer_whole_buffer_B_times: 107 | ld de,#_stc4_buffer 108 | ld a,(de) ; 7 109 | out (#0xbe),a ; 11 110 | nop ; 4 111 | inc de ; 6 = 28 112 | 113 | ld a,(de) ; 7 114 | out (#0xbe),a ; 11 115 | nop ; 4 116 | inc de ; 6 = 28 117 | 118 | ld a,(de) ; 7 119 | out (#0xbe),a ; 11 120 | nop ; 4 121 | inc de ; 6 = 28 122 | 123 | ld a,(de) ; 7 124 | out (#0xbe),a ; 11 125 | djnz _transfer_whole_buffer_B_times ; 13 = 31 126 | 127 | inc hl ; move to next byte 128 | jp _stc4_decompress_outer_loop ; loop over 129 | 130 | __endasm; 131 | } 132 | #pragma restore 133 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_STMcomp.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | #include 9 | 10 | unsigned char *STM_src; 11 | unsigned int STM_dest; 12 | unsigned char STM_HH; 13 | unsigned char STM_oldHH; 14 | unsigned char STM_needRestore; 15 | unsigned char STM_ttw; 16 | unsigned char STM_width; 17 | 18 | void SMS_loadSTMcompressedTileMapatAddr (unsigned int dst, const void *src) { 19 | STM_dest=dst; 20 | STM_src=(unsigned char *)(src); 21 | STM_width=*STM_src++; 22 | STM_ttw=STM_width; 23 | STM_HH=0; 24 | STM_oldHH=0; 25 | STM_needRestore=0; 26 | __asm 27 | ld hl,(#_STM_dest) 28 | call _SMS_crt0_RST08 29 | 30 | _STM_loop: 31 | ld hl,(#_STM_src) 32 | ld a,(hl) 33 | inc hl 34 | ld (#_STM_src),hl 35 | rra 36 | jr nc,_STM_noRLE 37 | rra 38 | jr nc,_STM_RLE 39 | ; ***************** RLE of successive words 40 | and #0x3F ; keep only last 6 bits (counter) 41 | add a,#2 42 | ld b,a ; b = cnt 43 | ld a,(#_STM_HH) 44 | ld d,a ; d = high part of tile 45 | ld e,(hl) ; e = low part of tile 46 | inc hl 47 | ld (#_STM_src),hl ; src++ 48 | ld hl,#_STM_ttw 49 | ld c,(hl) ; c = ttw 50 | 51 | _STM_inc_RLE_loop: 52 | ld a,e ; write tile to VRAM respecting access time costraints 53 | out (#0xBE),a ; 11 54 | ld a,d ; 4 55 | nop ; *delay* 4 56 | nop ; *delay* 4 57 | dec c ; ttw-- 4 = 27 (VRAM SAFE ON GG TOO) 58 | out (#0xBE),a 59 | 60 | call z,_STM_setAddr ; ttw==0? 61 | 62 | dec b 63 | jr z,_STM_inc_RLE_done ; cnt==0? 64 | inc de ; tile++ 65 | jr _STM_inc_RLE_loop 66 | 67 | _STM_inc_RLE_done: 68 | ld hl,#_STM_HH ; save high part of tile 69 | ld (hl),d 70 | ld hl,#_STM_ttw ; save ttw 71 | ld (hl),c 72 | 73 | _STM_check_restore: 74 | ld a,(#_STM_needRestore) 75 | or a 76 | jr z,_STM_loop 77 | xor a 78 | ld (#_STM_needRestore),a 79 | ld a,(#_STM_oldHH) 80 | ld (#_STM_HH),a 81 | jr _STM_loop 82 | 83 | _STM_noRLE: 84 | rra 85 | jr nc,_STM_RAW 86 | ; ***************** special 87 | rra 88 | jr nc,_STM_no_temp_HH 89 | ld b,a 90 | ld a,(#_STM_HH) 91 | ld (#_STM_oldHH),a 92 | ld a,#1 93 | ld (#_STM_needRestore),a 94 | ld a,b 95 | _STM_no_temp_HH: 96 | and #0x1F ; keep only last 5 bits 97 | ld (#_STM_HH),a 98 | jr _STM_loop 99 | 100 | _STM_RLE: ; ***************** RLE 101 | and #0x3F ; keep only last 6 bits (counter) 102 | add a,#2 103 | ld b,a ; b = cnt 104 | ld a,(#_STM_HH) 105 | ld d,a ; d = high part of tile 106 | ld e,(hl) ; e = low part of tile 107 | inc hl 108 | ld (#_STM_src),hl ; src++ 109 | ld hl,#_STM_ttw 110 | ld c,(hl) ; c = ttw 111 | 112 | _STM_RLE_loop: 113 | ld a,e ; write tile to VRAM respecting access time costraints 114 | out (#0xBE),a ; 11 115 | ld a,d ; 4 116 | nop ; *delay* 4 117 | nop ; *delay* 4 118 | dec c ; ttw-- 4 = 27 (VRAM SAFE ON GG TOO) 119 | out (#0xBE),a 120 | 121 | call z,_STM_setAddr ; ttw==0? 122 | 123 | dec b 124 | jr nz,_STM_RLE_loop ; cnt==0? 125 | 126 | ld hl,#_STM_ttw ; save ttw 127 | ld (hl),c 128 | 129 | jr _STM_check_restore 130 | 131 | _STM_RAW: ; ***************** RAW 132 | and #0x3F ; keep only last 6 bits (counter) 133 | or a 134 | jr z,_STM_leave ; if cnt is 0 - end of STM 135 | ld b,a ; b = cnt 136 | ld hl,#_STM_ttw 137 | ld c,(hl) ; c = ttw 138 | _STM_RAW_loop: 139 | ld hl,(#_STM_src) 140 | ld a,(hl) 141 | out (#0xBE),a ; 11 low part of tile 142 | inc hl ; 6 143 | ld (#_STM_src),hl ; 16 src++ 144 | ld a,(#_STM_HH) ; 13 high part of tile 145 | out (#0xBE),a ; xx = VRAM safe 146 | 147 | dec c 148 | call z,_STM_setAddr 149 | 150 | dec b 151 | jr nz,_STM_RAW_loop 152 | 153 | ld hl,#_STM_ttw 154 | ld (hl),c 155 | 156 | jr _STM_check_restore 157 | 158 | 159 | _STM_setAddr: 160 | ld hl,(#_STM_dest) 161 | ld a,b ; preserve b 162 | ld bc,#64 163 | add hl,bc 164 | ld b,a ; restore b 165 | ld (#_STM_dest),hl 166 | ld c,#0xBF ; set VDP Control Port 167 | di ; make it interrupt SAFE 168 | out (c),l 169 | out (c),h 170 | ei 171 | ld a,(#_STM_width) 172 | ld (#_STM_ttw),a 173 | ld c,a 174 | ret 175 | 176 | _STM_leave: 177 | __endasm; 178 | } 179 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_UNSAFE.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | // VRAM unsafe functions. Fast, but dangerous! 9 | /* UNSAFE_SMS_load[1-4]Tile(s) are macros that call these functions */ 10 | 11 | #pragma save 12 | #pragma disable_warning 85 13 | void * UNSAFE_SMS_VRAMmemcpy32 (unsigned int dst, const void *src) __naked __preserves_regs(a,iyh,iyl) __sdcccall(1) { 14 | // dst in HL 15 | // src in DE 16 | // returns a void pointer to src+32 in HL 17 | __asm 18 | set 6, h ; set VRAM address write flag 19 | rst #0x08 20 | 21 | ex de,hl ; move src in hl 22 | dec c ; because c value is already #_VDPControlPort and this faster than using ld c,#_VDPDataPort 23 | jp _OUTI32 ; tail call optimization 24 | __endasm; 25 | } 26 | 27 | void * UNSAFE_SMS_VRAMmemcpy64 (unsigned int dst, const void *src) __naked __preserves_regs(a,iyh,iyl) __sdcccall(1) { 28 | // dst in HL 29 | // src in DE 30 | // returns a void pointer to src+64 in HL 31 | __asm 32 | set 6, h ; set VRAM address write flag 33 | rst #0x08 34 | 35 | ex de,hl ; move src in hl 36 | dec c ; because c value is already #_VDPControlPort and this faster than using ld c,#_VDPDataPort 37 | jp _OUTI64 ; tail call optimization 38 | __endasm; 39 | } 40 | 41 | void * UNSAFE_SMS_VRAMmemcpy96 (unsigned int dst, const void *src) __naked __preserves_regs(a,iyh,iyl) __sdcccall(1) { 42 | // dst in HL 43 | // src in DE 44 | // returns a void pointer to src+96 in HL 45 | __asm 46 | set 6, h ; set VRAM address write flag 47 | rst #0x08 48 | 49 | ex de,hl ; move src in hl 50 | dec c ; because c value is already #_VDPControlPort and this faster than using ld c,#_VDPDataPort 51 | jp _OUTI96 ; tail call optimization 52 | __endasm; 53 | } 54 | 55 | void * UNSAFE_SMS_VRAMmemcpy128 (unsigned int dst, const void *src) __naked __preserves_regs(a,iyh,iyl) __sdcccall(1) { 56 | // dst in HL 57 | // src in DE 58 | // returns a void pointer to src+128 in HL 59 | __asm 60 | set 6, h ; set VRAM address write flag 61 | rst #0x08 62 | 63 | ex de,hl ; move src in hl 64 | dec c ; because c value is already #_VDPControlPort and this faster than using ld c,#_VDPDataPort 65 | jp _OUTI128 ; tail call optimization 66 | __endasm; 67 | } 68 | #pragma restore 69 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_UNSAFE_SAT.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | extern unsigned char SpriteTableY[MAXSPRITES]; 10 | extern unsigned char SpriteTableXN[MAXSPRITES*2]; 11 | extern unsigned char SpriteNextFree; 12 | 13 | // VRAM unsafe functions. Fast, but dangerous! 14 | void UNSAFE_SMS_copySpritestoSAT (void) { 15 | SMS_setAddr(SMS_SATAddress); 16 | __asm 17 | ld a,(#_SpriteNextFree) 18 | or a 19 | jr z,_no_sprites 20 | add a,a ; SpriteNextFree*=2 (and reset carry) 21 | ld c,a 22 | ld b,#0 23 | ld hl,#_outi_block 24 | sbc hl,bc 25 | ex de,hl 26 | ld hl,#_SpriteTableY 27 | call _do_copy_Y 28 | ld a,(#_SpriteNextFree) 29 | cp #64 30 | jr z,_no_sprite_term 31 | ld a,#0xD0 32 | out (c),a 33 | _no_sprite_term: 34 | __endasm; 35 | SMS_setAddr(SMS_SATAddress+128); 36 | __asm 37 | ld a,(#_SpriteNextFree) 38 | dec a ; there is surely at least one sprite used 39 | add a,a 40 | add a,a ; a=(SpriteNextFree-1)*4 (and reset carry) 41 | ld c,a 42 | ld b,#0 43 | ld hl,#_outi_block-4 44 | sbc hl,bc 45 | push hl ; push jump address into stack 46 | ld hl,#_SpriteTableXN 47 | ld c,#_VDPDataPort 48 | ret ; get jump address from stack 49 | _do_copy_Y: 50 | ld c,#_VDPDataPort 51 | push de 52 | ret ; get jump address from stack 53 | _no_sprites: 54 | ld a,#0xD0 55 | out (#_VDPDataPort),a 56 | __endasm; 57 | } 58 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_UNSAFE_memcpy.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | // VRAM unsafe functions. Fast, but dangerous! 9 | /* UNSAFE_SMS_loadNTiles() and UNSAFE_SMS_loadTiles() are macros that call UNSAFE_SMS_VRAMmemcpy() */ 10 | 11 | #pragma save 12 | #pragma disable_warning 85 13 | void * UNSAFE_SMS_VRAMmemcpy (unsigned int dst, const void *src, unsigned int size) __naked __z88dk_callee __preserves_regs(iyh,iyl) __sdcccall(1) { 14 | // dst in HL 15 | // src in DE 16 | // size onto the stack 17 | // returns a void pointer to src+size in HL 18 | __asm 19 | set 6, h ; set VRAM address write flag 20 | rst #0x08 21 | 22 | ex de,hl ; move src in hl 23 | 24 | pop bc ; pop ret address 25 | pop de ; pop size in DE 26 | push bc ; push ret address back into stack 27 | 28 | 1$: 29 | ld a,e 30 | and #0x80 ; keep only msb 31 | or d 32 | jr z,2$ ; jump when there are less than 128 bytes to transfer left 33 | 34 | ld c,#_VDPDataPort 35 | call _OUTI128 ; quickly transfer 128 bytes 36 | 37 | ex de,hl ; preserve HL,DE 38 | ld bc,#128 39 | xor a ; reset carry 40 | sbc hl,bc 41 | ex de,hl ; restore HL,DE 42 | jp 1$ 43 | 44 | 2$: 45 | ld a,e ; size left is <128 46 | add a,a ; calculate jump address (and reset carry) 47 | ret z ; end here when size equals zero 48 | 49 | ld c,a 50 | ld b,#0 ; size * 2 in BC 51 | ex de,hl ; preserve HL 52 | ld hl,#_outi_block 53 | sbc hl,bc 54 | ex de,hl ; restore HL, jump address in DE 55 | 56 | ld c,#_VDPDataPort 57 | push de ; push jump address onto stack 58 | ret ; jump to address 59 | __endasm; 60 | } 61 | #pragma restore 62 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_VRAMmemcpy.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | /* SMS_loadTiles() and SMS_loadTileMap() are just calls to SMS_VRAMmemcpy() */ 10 | 11 | #pragma save 12 | #pragma disable_warning 85 13 | void SMS_VRAMmemcpy (unsigned int dst, const void *src, unsigned int size) __naked __z88dk_callee __preserves_regs(iyh,iyl) __sdcccall(1) { 14 | // dst in hl 15 | // src in de 16 | // size onto the stack 17 | __asm 18 | set 6, h ; Set VRAM address 19 | rst #0x08 20 | 21 | ex de,hl ; move src in hl 22 | 23 | pop de ; pop ret address 24 | pop bc ; pop size 25 | push de ; push ret address 26 | 27 | dec bc 28 | inc b 29 | inc c ; increment B if C is not zero 30 | 31 | ld a,b ; HI(size) 32 | ld b,c ; LO(size) 33 | 34 | ld c,#_VDPDataPort 35 | 36 | 1$: 37 | outi ; 16 38 | jr nz,1$ ; 12 = 28 (VRAM safe on GG too) 39 | dec a 40 | jp nz,1$ 41 | ret ; because this function is naked 42 | __endasm; 43 | } 44 | #pragma restore 45 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_VRAMmemcpy_brief.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | void SMS_VRAMmemcpy_brief (unsigned int dst, const void *src, unsigned char size) __naked __z88dk_callee __preserves_regs(iyh,iyl) __sdcccall(1) { 12 | // dst in hl 13 | // src in de 14 | // size onto the stack 15 | __asm 16 | set 6, h ; Set VRAM address 17 | rst #0x08 18 | 19 | ex de,hl ; move src in hl 20 | 21 | pop de ; pop ret address 22 | dec sp 23 | pop bc ; size (in b) 24 | push de ; push ret address 25 | 26 | ld c,#_VDPDataPort 27 | 28 | 1$: 29 | outi ; 16 30 | jr nz,1$ ; 12 = 28 (VRAM safe on GG too) 31 | ret ; because this function is naked 32 | __endasm; 33 | } 34 | #pragma restore 35 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_VRAMmemset.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | /* low level functions, just to be used for dirty tricks ;) */ 10 | /* 11 | void SMS_VRAMmemset (unsigned int dst, unsigned char value, unsigned int size) { 12 | // SMS_set_address_VRAM(dst); 13 | SMS_setAddr(0x4000|dst); 14 | while (size>0) { 15 | SMS_byte_to_VDP_data(value); 16 | size--; 17 | } 18 | } 19 | */ 20 | 21 | #pragma save 22 | #pragma disable_warning 85 23 | void SMS_VRAMmemset_f (unsigned char value, unsigned int dst, unsigned int size) __naked __z88dk_callee __preserves_regs(a,h,l,iyh,iyl) __sdcccall(1) { 24 | // value in a 25 | // dst in de 26 | // size onto the stack 27 | __asm 28 | set 6, d ; Set VRAM address 29 | ld c, #_VDPControlPort 30 | di 31 | out (c),e 32 | out (c),d 33 | ei 34 | 35 | pop de ; pop ret address 36 | pop bc ; pop size 37 | push de ; push ret address 38 | 39 | dec bc 40 | inc b 41 | inc c ; increment B if C is not zero 42 | 43 | ld e,b ; HI(size) 44 | ld b,c ; LO(size) 45 | 46 | 1$: 47 | out(#_VDPDataPort),a ; 11 48 | nop ; 4 49 | djnz 1$ ; 13 = 28 (VRAM safe on GG too) 50 | dec e 51 | jp nz,1$ 52 | ret ; because this function is naked 53 | __endasm; 54 | } 55 | 56 | void SMS_VRAMmemsetW (unsigned int dst, unsigned int value, unsigned int size) __naked __z88dk_callee __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 57 | /* 58 | SMS_setAddr(0x4000|dst); 59 | while (size>0) { 60 | SMS_byte_to_VDP_data(LO(value)); 61 | WAIT_VRAM; 62 | SMS_byte_to_VDP_data(HI(value)); 63 | size-=2; 64 | } 65 | */ 66 | // dst in hl 67 | // value in de 68 | // size onto the stack 69 | __asm 70 | set 6, h ; Set VRAM address 71 | rst #0x08 72 | 73 | pop bc ; pop ret address 74 | pop hl ; pop size 75 | push bc ; push ret address 76 | 77 | ld c,#_VDPDataPort 78 | 79 | 1$: 80 | out(c),e ; 12 81 | dec hl ; 6 82 | dec hl ; 6 83 | ld a,h ; 4 = 28 (VRAM safe on GG too) 84 | out(c),d ; 12 85 | or a,l ; 4 86 | jr nz,1$ ; 12 = 28 (VRAM safe on GG too) 87 | ret ; because this function is naked 88 | __endasm; 89 | } 90 | #pragma restore 91 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_aPLib.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | /* 7 | * Z80/SMS aPLib decompression library 8 | * version 1.2 9 | * 1/12/2008 10 | * Maxim (http://www.smspower.org/maxim) 11 | * based on code by Dan Weiss (Dwedit) - see readme.txt 12 | * C wrapper by sverx 13 | */ 14 | 15 | #include "SMSlib.h" 16 | 17 | unsigned char aPLib_bits[2]; 18 | unsigned char aPLib_LWM; 19 | unsigned int aPLib_R0; 20 | 21 | #pragma save 22 | #pragma disable_warning 85 23 | void SMS_decompressaPLib (const void *src, void *dst) __naked __sdcccall(1) { 24 | __asm 25 | ;hl = source 26 | ;de = dest 27 | ldi 28 | xor a 29 | ld (_aPLib_LWM),a 30 | inc a 31 | ld (_aPLib_bits),a 32 | 33 | _aploop: 34 | call ap_getbit 35 | jp z, _apbranch1 36 | call ap_getbit 37 | jr z, _apbranch2 38 | call ap_getbit 39 | jr z, _apbranch3 40 | ;LWM = 0 41 | xor a 42 | ld (_aPLib_LWM),a 43 | ;get an offset 44 | ld bc,#0 45 | call ap_getbitbc 46 | call ap_getbitbc 47 | call ap_getbitbc 48 | call ap_getbitbc 49 | ld a,b 50 | or c 51 | jr nz,_apbranch4 52 | ; xor a ;write a 0 ; Maxim: a is zero already (just failed nz test), optimise this line away 53 | ld (de),a 54 | inc de 55 | jr _aploop 56 | _apbranch4: 57 | ex de,hl ;write a previous bit (1-15 away from dest) 58 | push hl 59 | sbc hl,bc 60 | ld a,(hl) 61 | pop hl 62 | ld (hl),a 63 | inc hl 64 | ex de,hl 65 | jr _aploop 66 | _apbranch3: 67 | ;use 7 bit offset, length = 2 or 3 68 | ;if a zero is encountered here, it is EOF 69 | ld c,(hl) 70 | inc hl 71 | rr c 72 | ret z 73 | ld b,#2 74 | jr nc,_plus4 75 | inc b 76 | _plus4: 77 | ;LWM = 1 78 | ld a,#1 79 | ld (_aPLib_LWM),a 80 | push hl 81 | ld a,b 82 | ld b,#0 83 | ;R0 = c 84 | ld (_aPLib_R0),bc 85 | ld h,d 86 | ld l,e 87 | or a 88 | sbc hl,bc 89 | ld c,a 90 | ldir 91 | pop hl 92 | jr _aploop 93 | 94 | _apbranch2: 95 | ;use a gamma code * 256 for offset, another gamma code for length 96 | call ap_getgamma 97 | dec bc 98 | dec bc 99 | ld a,(_aPLib_LWM) 100 | or a 101 | jr nz,_ap_not_LWM 102 | ;bc = 2? ; Maxim: I think he means 0 103 | ld a,b 104 | or c 105 | jr nz,_ap_not_zero_gamma 106 | ;if gamma code is 2, use old R0 offset, and a new gamma code for length 107 | call ap_getgamma 108 | push hl 109 | ld h,d 110 | ld l,e 111 | push bc 112 | ld bc,(_aPLib_R0) 113 | sbc hl,bc 114 | pop bc 115 | ldir 116 | pop hl 117 | jr _ap_finishup 118 | 119 | _ap_not_zero_gamma: 120 | dec bc 121 | _ap_not_LWM: 122 | ;do I even need this code? ; Maxim: seems so, it is broken without it 123 | ;bc=bc*256+(hl), lazy 16bit way 124 | ld b,c 125 | ld c,(hl) 126 | inc hl 127 | ld (_aPLib_R0),bc 128 | push bc 129 | call ap_getgamma 130 | ex (sp),hl 131 | ;bc = len, hl=offs 132 | push de 133 | ex de,hl 134 | ;some comparison junk for some reason 135 | ; Maxim: optimised to use add instead of sbc 136 | ld hl,#-32000 137 | add hl,de 138 | jr nc,_plus1 139 | inc bc 140 | _plus1: 141 | ld hl,#-1280 142 | add hl,de 143 | jr nc,_plus2 144 | inc bc 145 | _plus2: 146 | ld hl,#-128 147 | add hl,de 148 | jr c,_plus3 149 | inc bc 150 | inc bc 151 | _plus3: 152 | ;bc = len, de = offs, hl=junk 153 | pop hl 154 | push hl 155 | or a 156 | sbc hl,de 157 | pop de 158 | ;hl=dest-offs, bc=len, de = dest 159 | ldir 160 | pop hl 161 | _ap_finishup: 162 | ld a,#1 163 | ld (_aPLib_LWM),a 164 | jp _aploop 165 | _apbranch1: 166 | ldi 167 | xor a 168 | ld (_aPLib_LWM),a 169 | jp _aploop 170 | 171 | ap_getbit: 172 | push bc 173 | ld bc,(_aPLib_bits) 174 | rrc c 175 | jr nc,_plus9 176 | ld b,(hl) 177 | inc hl 178 | _plus9: 179 | ld a,c 180 | and b 181 | ld (_aPLib_bits),bc 182 | pop bc 183 | ret 184 | 185 | ap_getbitbc: ;doubles BC and adds the read bit 186 | sla c 187 | rl b 188 | call ap_getbit 189 | ret z 190 | inc bc 191 | ret 192 | 193 | ap_getgamma: 194 | ld bc,#1 195 | _minus3: 196 | call ap_getbitbc 197 | call ap_getbit 198 | jr nz,_minus3 199 | ret 200 | __endasm; 201 | } 202 | #pragma restore 203 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_autotext.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | const unsigned char devkitSMS_font__tiles__1bpp[768]={ 10 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x00, 11 | 0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00, 12 | 0x0c,0x3f,0x68,0x3e,0x0b,0x7e,0x18,0x00,0x60,0x66,0x0c,0x18,0x30,0x66,0x06,0x00, 13 | 0x38,0x6c,0x6c,0x38,0x6d,0x66,0x3b,0x00,0x0c,0x18,0x30,0x00,0x00,0x00,0x00,0x00, 14 | 0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00, 15 | 0x00,0x18,0x7e,0x3c,0x7e,0x18,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00, 16 | 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00, 17 | 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x00,0x00, 18 | 0x3c,0x66,0x6e,0x7e,0x76,0x66,0x3c,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00, 19 | 0x3c,0x66,0x06,0x0c,0x18,0x30,0x7e,0x00,0x3c,0x66,0x06,0x1c,0x06,0x66,0x3c,0x00, 20 | 0x0c,0x1c,0x3c,0x6c,0x7e,0x0c,0x0c,0x00,0x7e,0x60,0x7c,0x06,0x06,0x66,0x3c,0x00, 21 | 0x1c,0x30,0x60,0x7c,0x66,0x66,0x3c,0x00,0x7e,0x06,0x0c,0x18,0x30,0x30,0x30,0x00, 22 | 0x3c,0x66,0x66,0x3c,0x66,0x66,0x3c,0x00,0x3c,0x66,0x66,0x3e,0x06,0x0c,0x38,0x00, 23 | 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x30, 24 | 0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00, 25 | 0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x3c,0x66,0x0c,0x18,0x18,0x00,0x18,0x00, 26 | 0x3c,0x66,0x6e,0x6a,0x6e,0x60,0x3c,0x00,0x3c,0x66,0x66,0x7e,0x66,0x66,0x66,0x00, 27 | 0x7c,0x66,0x66,0x7c,0x66,0x66,0x7c,0x00,0x3c,0x66,0x60,0x60,0x60,0x66,0x3c,0x00, 28 | 0x78,0x6c,0x66,0x66,0x66,0x6c,0x78,0x00,0x7e,0x60,0x60,0x7c,0x60,0x60,0x7e,0x00, 29 | 0x7e,0x60,0x60,0x7c,0x60,0x60,0x60,0x00,0x3c,0x66,0x60,0x6e,0x66,0x66,0x3c,0x00, 30 | 0x66,0x66,0x66,0x7e,0x66,0x66,0x66,0x00,0x7e,0x18,0x18,0x18,0x18,0x18,0x7e,0x00, 31 | 0x3e,0x0c,0x0c,0x0c,0x0c,0x6c,0x38,0x00,0x66,0x6c,0x78,0x70,0x78,0x6c,0x66,0x00, 32 | 0x60,0x60,0x60,0x60,0x60,0x60,0x7e,0x00,0x63,0x77,0x7f,0x6b,0x6b,0x63,0x63,0x00, 33 | 0x66,0x66,0x76,0x7e,0x6e,0x66,0x66,0x00,0x3c,0x66,0x66,0x66,0x66,0x66,0x3c,0x00, 34 | 0x7c,0x66,0x66,0x7c,0x60,0x60,0x60,0x00,0x3c,0x66,0x66,0x66,0x6a,0x6c,0x36,0x00, 35 | 0x7c,0x66,0x66,0x7c,0x6c,0x66,0x66,0x00,0x3c,0x66,0x60,0x3c,0x06,0x66,0x3c,0x00, 36 | 0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3c,0x00, 37 | 0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00,0x63,0x63,0x6b,0x6b,0x7f,0x77,0x63,0x00, 38 | 0x66,0x66,0x3c,0x18,0x3c,0x66,0x66,0x00,0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00, 39 | 0x7e,0x06,0x0c,0x18,0x30,0x60,0x7e,0x00,0x7c,0x60,0x60,0x60,0x60,0x60,0x7c,0x00, 40 | 0x00,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e,0x00, 41 | 0x18,0x3c,0x66,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, 42 | 0x00,0xc0,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x06,0x3e,0x66,0x3e,0x00, 43 | 0x60,0x60,0x7c,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x3c,0x66,0x60,0x66,0x3c,0x00, 44 | 0x06,0x06,0x3e,0x66,0x66,0x66,0x3e,0x00,0x00,0x00,0x3c,0x66,0x7e,0x60,0x3c,0x00, 45 | 0x1c,0x30,0x30,0x7c,0x30,0x30,0x30,0x00,0x00,0x00,0x3e,0x66,0x66,0x3e,0x06,0x3c, 46 | 0x60,0x60,0x7c,0x66,0x66,0x66,0x66,0x00,0x18,0x00,0x38,0x18,0x18,0x18,0x3c,0x00, 47 | 0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x70,0x60,0x60,0x66,0x6c,0x78,0x6c,0x66,0x00, 48 | 0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x36,0x7f,0x6b,0x6b,0x63,0x00, 49 | 0x00,0x00,0x7c,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x3c,0x66,0x66,0x66,0x3c,0x00, 50 | 0x00,0x00,0x7c,0x66,0x66,0x7c,0x60,0x60,0x00,0x00,0x3e,0x66,0x66,0x3e,0x06,0x07, 51 | 0x00,0x00,0x6c,0x76,0x60,0x60,0x60,0x00,0x00,0x00,0x3e,0x60,0x3c,0x06,0x7c,0x00, 52 | 0x30,0x30,0x7c,0x30,0x30,0x30,0x1c,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x00, 53 | 0x00,0x00,0x66,0x66,0x66,0x3c,0x18,0x00,0x00,0x00,0x63,0x6b,0x6b,0x7f,0x36,0x00, 54 | 0x00,0x00,0x66,0x3c,0x18,0x3c,0x66,0x00,0x00,0x00,0x66,0x66,0x66,0x3e,0x06,0x3c, 55 | 0x00,0x00,0x7e,0x0c,0x18,0x30,0x7e,0x00,0x0c,0x18,0x18,0x70,0x18,0x18,0x0c,0x00, 56 | 0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x30,0x18,0x18,0x0e,0x18,0x18,0x30,0x00, 57 | 0x00,0x60,0xf2,0x9e,0x0c,0x00,0x00,0x00,0x00,0x18,0x18,0x34,0x34,0x62,0x7e,0x00}; 58 | 59 | void SMS_autoSetUpTextRenderer (void) { 60 | SMS_load1bppTiles(devkitSMS_font__tiles__1bpp,0,sizeof(devkitSMS_font__tiles__1bpp),0,1); 61 | #ifdef TARGET_GG 62 | GG_setBGPaletteColor (0, RGB(0,0,0)); 63 | GG_setBGPaletteColor (1, RGB(15,15,15)); 64 | #else 65 | SMS_setBGPaletteColor (0, RGB(0,0,0)); 66 | SMS_setBGPaletteColor (1, RGB(3,3,3)); 67 | #endif 68 | SMS_configureTextRenderer(-32); 69 | SMS_displayOn(); 70 | SMS_setNextTileatXY(0,0); 71 | } 72 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_common.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #define HI(x) (((x)>>8)) 7 | #define LO(x) ((unsigned char)(x)) 8 | 9 | #define DISABLE_INTERRUPTS __asm di __endasm 10 | #define ENABLE_INTERRUPTS __asm ei __endasm 11 | 12 | /* 13 | #define WAIT_VRAM __asm nop \ 14 | nop \ 15 | nop __endasm 16 | */ 17 | 18 | #define SMS_SATAddress ((unsigned int)0x7F00) 19 | 20 | #ifndef MAXSPRITES 21 | #define MAXSPRITES 64 22 | #endif 23 | 24 | /* declare various I/O ports in SDCC z80 syntax */ 25 | /* define VDPControlPort */ 26 | __sfr __at 0xBF VDPControlPort; 27 | /* define VDPStatusPort */ 28 | __sfr __at 0xBF VDPStatusPort; 29 | /* define VDPDataPort */ 30 | __sfr __at 0xBE VDPDataPort; 31 | /* define VDPVcounter */ 32 | __sfr __at 0x7E VDPVCounterPort; 33 | /* define VDPHcounter */ 34 | __sfr __at 0x7F VDPHCounterPort; 35 | 36 | inline void SMS_write_to_VDPRegister (unsigned char VDPReg, unsigned char value) { 37 | // INTERNAL FUNCTION 38 | unsigned char v=value; 39 | DISABLE_INTERRUPTS; 40 | VDPControlPort=v; 41 | VDPControlPort=VDPReg|0x80; 42 | ENABLE_INTERRUPTS; 43 | } 44 | 45 | inline void SMS_byte_to_VDP_data (unsigned char data) { 46 | // INTERNAL FUNCTION 47 | VDPDataPort=data; 48 | } 49 | 50 | inline void SMS_byte_array_to_VDP_data (const unsigned char *data, unsigned int size) { 51 | // INTERNAL FUNCTION 52 | do { 53 | VDPDataPort=*(data++); 54 | } while (--size); 55 | } 56 | 57 | inline void SMS_byte_brief_array_to_VDP_data (const unsigned char *data, unsigned char size) { 58 | // INTERNAL FUNCTION 59 | do { 60 | VDPDataPort=*(data++); 61 | } while (--size); 62 | } 63 | 64 | #define ASM_DE_TO_VDP_CONTROL \ 65 | __asm \ 66 | ld c,#_VDPControlPort \ 67 | di \ 68 | out (c),e \ 69 | out (c),d \ 70 | ei \ 71 | __endasm 72 | // writes a control word to VDP 73 | // it's INTerrupt safe (DI/EI around control port writes) 74 | // controlword in DE 75 | 76 | #define ASM_L_TO_VDP_DATA \ 77 | __asm \ 78 | ld a,l \ 79 | out (_VDPDataPort),a ; 11 \ 80 | __endasm 81 | // writes one byte to VDP 82 | // it's VRAM safe since it's used by SMS_setColor which adds enough overhead (call/ret) 83 | // byte will be passed in L 84 | 85 | #define ASM_SHORT_XFER_TO_VDP_DATA \ 86 | __asm \ 87 | ld c,#_VDPDataPort \ 88 | 1$: outi ; 16 \ 89 | jr nz,1$ ; 12 = 28 *VRAM SAFE ON GG TOO* \ 90 | __endasm 91 | // writes B bytes from (HL) on to VDP 92 | // it's VRAM safe on GG too (at least 27 cycles between writes) 93 | 94 | #define ASM_LD_DE_IMM(imm) \ 95 | __asm \ 96 | ld de,imm \ 97 | __endasm 98 | 99 | #define ASM_LD_B_IMM(imm) \ 100 | __asm \ 101 | ld b,imm \ 102 | __endasm 103 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_debug.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | void SMS_debugPrintf(const unsigned char *format, ...) __naked __preserves_regs(a,b,c,iyh,iyl) { 12 | // basic debug_printf code kindly provided by toxa - thank you! 13 | __asm 14 | ld hl,#2 15 | add hl,sp 16 | ld e,(hl) 17 | inc hl 18 | ld d,(hl) 19 | inc hl 20 | ex de,hl ; format string needs to be in HL 21 | ld d,d 22 | ret 23 | nop ; (needs to skip an additional byte here, so nop) 24 | .dw 0x6464 ; emulator debug function request 25 | .dw 0x0200 ; debug_printf function selected 26 | __endasm; 27 | } 28 | #pragma restore 29 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_deprecated.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | 5 | NOTE: 6 | this is the source file containing deprecated functions 7 | I suggest you stop using them, as they'll be dropped 8 | ************************************************** */ 9 | 10 | #include "SMSlib.h" 11 | #include "SMSlib_common.c" 12 | 13 | extern unsigned char SpriteTableY[MAXSPRITES]; 14 | extern unsigned char SpriteTableXN[MAXSPRITES*2]; 15 | extern unsigned char SpriteNextFree; 16 | 17 | void SMS_finalizeSprites (void) { 18 | // *DEPRECATED* - will be dropped at some point in 2018 19 | } 20 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_foursprites.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | 12 | #ifdef NO_SPRITE_CHECKS 13 | void SMS_addFourAdjoiningSprites_f (unsigned char y, unsigned int x_tile) __naked __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 14 | // Y passed in A 15 | // X passed in D 16 | // tile passed in E 17 | __asm 18 | ld hl,#_SpriteNextFree ; load current SpriteNextFree value 19 | ld c,(hl) ; (in C) 20 | inc (hl) ; increment SpriteNextFree 21 | 22 | ld b,#0x00 23 | ld hl,#_SpriteTableY 24 | add hl,bc ; hl+=SpriteNextFree 25 | dec a 26 | ld (hl),a ; write Y (as Y-1) 27 | inc hl 28 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 29 | inc hl 30 | ld (hl),a ; write Y again for the third sprite (always as Y-1) 31 | inc hl 32 | ld (hl),a ; write Y again for the fourth sprite (always as Y-1) 33 | 34 | ld hl,#_SpriteTableXN 35 | sla c 36 | ld (hl),d ; write X 37 | inc hl 38 | ld (hl),e ; write tile number 39 | 40 | #ifdef NO_SPRITE_ZOOM 41 | ld a,#8 42 | #else 43 | ld a,(#_spritesWidth) ; load current sprite width 44 | ld b,a ; save it in B 45 | #endif 46 | add a,d ; add to X 47 | ret c ; if new X is overflowing, do not place second sprite and leave 48 | 49 | inc hl 50 | ld (hl),a ; write X + spritesWidth 51 | 52 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 53 | ld c,a ; save it in C 54 | add a,e 55 | inc hl 56 | ld (hl),a ; write tile number + spritesTileOffset 57 | 58 | ld hl,#_SpriteNextFree 59 | inc (hl) ; increment SpriteNextFree again 60 | 61 | #ifdef NO_SPRITE_ZOOM 62 | ld a,#16 63 | #else 64 | ld a,b ; load current sprite width from B 65 | add a,a ; double it 66 | #endif 67 | add a,d ; add to X 68 | ret c ; if new X is overflowing, do not place third sprite and leave 69 | 70 | inc hl 71 | ld (hl),a ; write X + spritesWidth*2 72 | 73 | ld a,c ; load current sprite tile offset from C 74 | add a,a ; double it 75 | add a,e ; add to tile number 76 | inc hl 77 | ld (hl),a ; write tile number + spritesTileOffset*2 78 | 79 | ld hl,#_SpriteNextFree 80 | inc (hl) ; increment SpriteNextFree again 81 | 82 | #ifdef NO_SPRITE_ZOOM 83 | ld a,#24 84 | #else 85 | ld a,b ; load current sprite width from B 86 | add a,a ; make it twice 87 | add a,b ; make it three times 88 | #endif 89 | add a,d ; add to X 90 | ret c ; if new X is overflowing, do not place fourth sprite and leave 91 | 92 | inc hl 93 | ld (hl),a ; write X + spritesWidth*3 94 | 95 | ld a,c ; load current sprite tile offset from C 96 | add a,a ; double it 97 | add a,c ; make it three times 98 | add a,e ; add to tile number 99 | inc hl 100 | ld (hl),a ; write tile number + spritesTileOffset*3 101 | 102 | ld hl,#_SpriteNextFree 103 | inc (hl) ; increment SpriteNextFree again 104 | ret 105 | __endasm; 106 | } 107 | #else 108 | void SMS_addFourAdjoiningSprites_f (unsigned int y, unsigned int x_tile) __naked __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 109 | // Y passed in L 110 | // X passed in D 111 | // tile passed in E 112 | __asm 113 | ld a,(#_SpriteNextFree) 114 | cp a,#MAXSPRITES-3 115 | ret nc ; we do not have 4 sprites left, leave! 116 | ld c,a ; save SpriteNextFree value in c 117 | 118 | ld a,l 119 | cp a,#0xd1 120 | ret z ; invalid Y, leave! 121 | 122 | ld b,#0x00 123 | ld hl,#_SpriteTableY 124 | add hl,bc 125 | dec a 126 | ld (hl),a ; write Y (as Y-1) 127 | inc hl 128 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 129 | inc hl 130 | ld (hl),a ; write Y also for the third sprite (always as Y-1) 131 | inc hl 132 | ld (hl),a ; write Y once more for the fourth sprite (always as Y-1) 133 | 134 | ld hl,#_SpriteTableXN 135 | add hl,bc 136 | add hl,bc 137 | ld (hl),d ; write X 138 | inc hl 139 | ld (hl),e ; write tile number 140 | 141 | #ifdef NO_SPRITE_ZOOM 142 | ld a,#8 ; each sprite is 8 pixels wide 143 | #else 144 | ld a,(#_spritesWidth) ; load current sprite width 145 | ld b,a ; save it in B 146 | #endif 147 | add a,d ; add to X 148 | jr c,_secondSpriteClipped ; if new X is overflowing, do not place second sprite 149 | inc hl 150 | ld (hl),a ; write X + spritesWidth 151 | 152 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 153 | ld c,a ; save it in C 154 | add a,e 155 | inc hl 156 | ld (hl),a ; write tile number + spritesTileOffset 157 | 158 | #ifdef NO_SPRITE_ZOOM 159 | ld a,#16 ; each sprite is 8 pixels wide 160 | #else 161 | ld a,b ; load current sprite width 162 | add a,a ; double that 163 | #endif 164 | add a,d ; add to X 165 | jr c,_thirdSpriteClipped ; if new X is overflowing, do not place third sprite 166 | inc hl 167 | ld (hl),a ; write X + spritesWidth*2 168 | 169 | ld a,c ; load current sprite tile offset 170 | add a,a ; double that 171 | add a,e 172 | inc hl 173 | ld (hl),a ; write tile number + spritesTileOffset*2 174 | 175 | #ifdef NO_SPRITE_ZOOM 176 | ld a,#24 ; each sprite is 8 pixels wide 177 | #else 178 | ld a,b ; load current sprite width 179 | add a,a ; double that 180 | add a,b ; three times that 181 | #endif 182 | add a,d ; add to X 183 | jr c,_fourthSpriteClipped ; if new X is overflowing, do not place fourth sprite 184 | inc hl 185 | ld (hl),a ; write X + spritesWidth*3 186 | 187 | ld a,c ; load current sprite tile offset 188 | add a,a ; double that 189 | add a,c ; three times that 190 | add a,e 191 | inc hl 192 | ld (hl),a ; write tile number + spritesTileOffset*3 193 | 194 | ld a,(#_SpriteNextFree) ; four sprites have been placed, then SpriteNextFree+=4 195 | add a,#4 196 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 197 | ret 198 | 199 | _secondSpriteClipped: 200 | ld a,(#_SpriteNextFree) ; second sprite has been clipped, so just inc SpriteNextFree 201 | inc a 202 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 203 | ret 204 | 205 | _thirdSpriteClipped: 206 | ld a,(#_SpriteNextFree) ; third sprite has been clipped, so just SpriteNextFree+=2 207 | add a,#2 208 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 209 | ret 210 | 211 | _fourthSpriteClipped: 212 | ld a,(#_SpriteNextFree) ; fourth sprite has been clipped, so just SpriteNextFree+=3 213 | add a,#3 214 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 215 | ret 216 | __endasm; 217 | } 218 | #endif 219 | #pragma restore 220 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_getTile.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | #include "SMSlib.h" 6 | #include "SMSlib_common.c" 7 | 8 | #pragma save 9 | #pragma disable_warning 85 10 | unsigned int SMS_getTile(void) __naked __z88dk_fastcall __preserves_regs(b,c,d,e,iyh,iyl) { 11 | __asm 12 | in a,(#_VDPDataPort) ; 11 13 | ld l,a ; 4 14 | inc hl ; 6 15 | dec hl ; 6 = 27 (safe on every Game Gear too) 16 | in a,(#_VDPDataPort) 17 | ld h,a 18 | ret 19 | __endasm; 20 | } 21 | #pragma restore 22 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_load1bppTiles.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | void SMS_load1bppTiles (const void *src, unsigned int tilefrom, unsigned int size, unsigned char color0, unsigned char color1) { 10 | unsigned char *s=(unsigned char *)src; 11 | unsigned char mask; 12 | SMS_setAddr(0x4000|(tilefrom*32)); 13 | do { 14 | for (mask=0x01;mask<0x10;mask<<=1) { 15 | if ((color0^color1)&mask) 16 | if (color1&mask) 17 | SMS_byte_to_VDP_data(*s); 18 | else 19 | SMS_byte_to_VDP_data(~*s); 20 | else 21 | if (color1&mask) 22 | SMS_byte_to_VDP_data(0xff); 23 | else 24 | SMS_byte_to_VDP_data(0x00); 25 | } 26 | s++; 27 | } while (--size); 28 | } 29 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_loadTileMapArea.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | // now even faster! 12 | void SMS_loadTileMapAreaatAddr (unsigned int dst, const void *src, unsigned char width, unsigned char height) __naked __z88dk_callee __sdcccall(1) { 13 | // dst in hl 14 | // src in de 15 | // height and width onto the stack 16 | __asm 17 | pop bc ; pop ret address 18 | pop iy ; pop height (iyh) and width (iyl) 19 | push bc ; push ret address 20 | 21 | set 6,h ; set VRAM address for write 22 | .db 0xFD ; --- SDCC issues workaround 23 | ld a,l ; ld a,iyl ; load width into A 24 | 25 | 1$: 26 | ld c,#_VDPControlPort 27 | di ; make it interrupt SAFE 28 | out (c),l 29 | out (c),h 30 | ei 31 | 32 | dec c ; faster than ld c,#_VDPDataPort 33 | ex de,hl 34 | ld b,a ; B=width 35 | 36 | 2$: 37 | outi ; 16 38 | inc b ; 4 39 | sub #0 ; 7 = 27 : SAFE on every SMS and GG 40 | outi ; 16 41 | jr nz,2$ ; 12 = 28 : SAFE on every SMS and GG 42 | 43 | .db 0xFD ; --- SDCC issues workaround 44 | dec h ; dec iyh ; decrement the height counter 45 | ret z ; leave if zero 46 | 47 | ex de,hl 48 | ld c,#64 49 | add hl,bc ; add offset to dest address (B is zero, C is 64) 50 | jp 1$ 51 | __endasm; 52 | } 53 | #pragma restore 54 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_loadTileMapColumn.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | void SMS_loadTileMapColumnatAddr (unsigned int dst, const void *src, unsigned int height) __naked __z88dk_callee __sdcccall(1) { 12 | // dst in hl 13 | // src in de 14 | // height onto the stack 15 | __asm 16 | pop bc ; pop ret address 17 | pop iy ; pop height 18 | push bc ; push ret address 19 | 20 | set 6,h ; set VRAM address for write 21 | ld bc,#64 ; preload VRAM offset between lines 22 | 23 | 1$: 24 | ld a,l 25 | di ; make it interrupt SAFE 26 | out (#_VDPControlPort),a 27 | ld a,h 28 | out (#_VDPControlPort),a 29 | ei 30 | 31 | ld a,(de) 32 | out (#_VDPDataPort),a 33 | inc de ; 6 34 | ld a,(de) ; 7 35 | inc de ; 6 36 | out (#_VDPDataPort),a ; 11 37 | 38 | .db 0xFD ; --- SDCC issues workaround 39 | dec l ; dec iyl ; decrement the counter 40 | ret z ; return if zero 41 | 42 | add hl,bc 43 | jp 1$ 44 | __endasm; 45 | } 46 | #pragma restore 47 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_metasprite.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | /* metasprites definition are a sequence of n*3 char values: 10 | * (signed) delta_x, (signed) delta_y, (unsigned) tile number 11 | * terminated by a METASPRITE_END terminator value (-128) 12 | * if METASPRITE_DELTA_TILES is defined, also tile number is 13 | * signed and is relative to MetaSpriteBaseTile variable */ 14 | 15 | /* pseudo: 16 | * 17 | * preserve metasprite's origin point 18 | * prepare destination addresses for sprites data 19 | * read metasprite's delta X 20 | * leave if METASPRITE_END 21 | * calculate sprite's final X 22 | * write final X 23 | * read metasprite's delta Y 24 | * calculate sprite's final Y 25 | * write final Y 26 | * read metasprite's tile # 27 | * write sprite's tile # 28 | * loop 29 | */ 30 | 31 | #ifdef METASPRITE_DELTA_TILES 32 | unsigned char MetaSpriteBaseTile; 33 | #endif 34 | 35 | #pragma save 36 | #pragma disable_warning 85 37 | void SMS_addMetaSprite_f (unsigned int origin_yx, void *metasprite) __naked __sdcccall(1) { 38 | // origin_Y passed in H 39 | // origin_X passed in L 40 | // *metasprite passed in DE 41 | __asm 42 | dec h ; origin_Y = origin_Y-1 43 | push hl 44 | pop iy ; origin X in iyl, origin Y in iyh 45 | 46 | ld a,(#_SpriteNextFree) 47 | 48 | #ifndef NO_SPRITE_CHECKS 49 | cp #MAXSPRITES ; ensure that we are not using too many sprites 50 | ret nc 51 | #endif 52 | 53 | ld c,a 54 | ld b,#0 55 | ld hl,#_SpriteTableY 56 | add hl,bc 57 | 58 | push hl 59 | add a,a 60 | ld c,a 61 | ld hl,#_SpriteTableXN 62 | add hl,bc 63 | pop bc ; BC = &SpriteTableY[SpriteNextFree] 64 | ex de,hl ; DE = &SpriteTableXN[SpriteNextFree] 65 | ; HL = *metasprite 66 | 67 | metasprite_loop: 68 | ld a,(hl) ; read delta_X 69 | cp #METASPRITE_END 70 | ret z ; leave when metasprite completed 71 | 72 | inc hl 73 | 74 | or a ; test delta_X sign 75 | jp m, negative_delta_X 76 | 77 | .db 0xFD ; --- SDCC issues workaround 78 | add a,l ; add a,iyl ; delta_X + origin_X 79 | jr c, h_clipped ; skip this sprite when clipped 80 | 81 | not_h_clipped: 82 | ld (de),a ; write X 83 | 84 | ld a,(hl) ; get delta_Y 85 | inc hl 86 | 87 | .db 0xFD ; --- SDCC issues workaround 88 | add a,h ; add a,iyh ; delta_Y + origin_Y 89 | cp #191 ; should this be clipped? 90 | jr nc, check_v_clipped ; surely not when 0<=y<=190 (that is row 1 to row 191 on screen) 91 | 92 | not_v_clipped: 93 | ld (bc),a ; write Y 94 | inc bc 95 | 96 | #ifdef METASPRITE_DELTA_TILES 97 | ld a,(#_MetaSpriteBaseTile) ; get tile # base 98 | add a,(hl) ; add tile # delta 99 | #else 100 | ld a,(hl) ; get tile# 101 | #endif 102 | 103 | inc hl 104 | inc de 105 | ld (de),a ; write tile# 106 | inc de 107 | 108 | ld a,(#_SpriteNextFree) 109 | inc a 110 | ld (#_SpriteNextFree),a 111 | 112 | #ifndef NO_SPRITE_CHECKS 113 | cp #MAXSPRITES ; ensure that we are not using too many sprites 114 | ret nc 115 | #endif 116 | 117 | jp metasprite_loop 118 | 119 | check_v_clipped: 120 | #ifdef NO_SPRITE_ZOOM 121 | cp #241 ; should this be clipped? yes when y<=240 (above row 240 on screen) 122 | #else 123 | cp #225 ; should this be clipped? yes when y<=224 (above row 224 on screen) 124 | #endif 125 | jr c, v_clipped ; this works both with 8 and 16 pixels tall sprites (and zoomed ones) 126 | ; and makes sure that $D0 does not get into the Y table 127 | jp not_v_clipped 128 | 129 | negative_delta_X: 130 | .db 0xFD ; --- SDCC issues workaround 131 | add a,l ; add a,iyl ; delta_X + origin_X 132 | jp c, not_h_clipped ; draw this sprite when not clipped 133 | 134 | h_clipped: 135 | inc hl ; skip delta_Y 136 | v_clipped: 137 | inc hl ; skip tile# 138 | jp metasprite_loop 139 | __endasm; 140 | } 141 | #pragma restore 142 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_paddle.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | // (original asm code from SMS Test Suite) 9 | // (improved by Raphaël Assenat [raphnet]) 10 | // references: 11 | // https://www.smspower.org/Development/Paddle 12 | // https://www.smspower.org/Development/PeripheralPorts 13 | 14 | #define DETECT_MIN 0x60 15 | #define DETECT_MAX 0xA0 16 | 17 | #pragma save 18 | #pragma disable_warning 85 19 | 20 | _Bool SMS_detectPaddle (unsigned char port) __z88dk_fastcall __naked { 21 | __asm 22 | ld a,l 23 | or a 24 | ld bc,#0 25 | jr nz, detect_second_pad 26 | 27 | read: 28 | in a,(#0xDC) 29 | and #0x20 30 | jr nz, skip_inc 31 | inc c 32 | 33 | skip_inc: 34 | djnz read 35 | jr discriminate 36 | 37 | detect_second_pad: 38 | in a,(#0xDD) 39 | and #08 40 | jr nz, skip_inc_2 41 | inc c 42 | 43 | skip_inc_2: 44 | djnz detect_second_pad 45 | 46 | discriminate: 47 | ld a,c 48 | ld l,#0 ; set false 49 | sub #DETECT_MIN 50 | ret c 51 | cp #(DETECT_MAX-DETECT_MIN) 52 | ret nc 53 | inc l ; set true 54 | ret 55 | __endasm; 56 | } 57 | 58 | unsigned char SMS_readPaddle (unsigned char port) __z88dk_fastcall __naked { 59 | __asm 60 | ld a,l 61 | or a 62 | jr nz, read_second_pad 63 | 64 | ; First, synchronize by waiting until port A key 2 is high. 65 | ; 66 | ; Without this, the values occasionally glitches on real hardware, 67 | ; because the bits may be in the middle of changing and are therefore 68 | ; not reliable. (Remember the real world is analog) 69 | ; 70 | 71 | ld d, #255 72 | wait_5_set_sync: 73 | dec d 74 | jp Z, paddle_timeout 75 | in a,(#0xDC) 76 | bit 5,a 77 | jr z, wait_5_set_sync ; wait until bit 5 is 1 78 | 79 | ld d, #255 80 | wait_5_reset: 81 | dec d 82 | jp Z, paddle_timeout 83 | in a,(#0xDC) 84 | bit 5,a 85 | jr nz, wait_5_reset ; wait until bit 5 is 0 86 | and #0x0F 87 | ld l,a ; save lower 4 bits into l 88 | 89 | ld d, #255 90 | wait_5_set: 91 | dec d 92 | jp Z, paddle_timeout 93 | in a,(#0xDC) 94 | bit 5,a 95 | jr z, wait_5_set ; wait until bit 5 is 1 96 | and #0x0F ; save lower 4 bits 97 | add a,a 98 | add a,a 99 | add a,a 100 | add a,a 101 | or l ; move to high nibble 102 | ld l,a ; together with lower part 103 | ret 104 | 105 | read_second_pad: 106 | ld c,#0xDC 107 | 108 | ; First, synchronize by waiting until port B key 2 is high. 109 | ; 110 | ; Without this, the values occasionally glitches on real hardware, 111 | ; because the bits may be in the middle of changing and are therefore 112 | ; not reliable. (Remember the real world is analog) 113 | 114 | ld d, #255 115 | wait_3_set_sync: 116 | dec d 117 | jp Z, paddle_timeout 118 | in a,(#0xDD) 119 | bit 3,a 120 | jr z, wait_3_set_sync ; wait until bit 3 is 1 121 | 122 | ld d, #255 123 | wait_3_reset: 124 | dec d 125 | jp Z, paddle_timeout 126 | in a,(#0xDD) ; ensure we are reading both ports same moment 127 | ld e,a 128 | in b,(c) 129 | in a,(#0xDD) 130 | or e 131 | bit 3,a 132 | jr nz, wait_3_reset ; wait until bit 5 is 0 133 | ld a,b 134 | and #0xC0 ; save upper 2 bits 135 | rlca 136 | rlca 137 | ld l,a ; into l (bits 0,1) 138 | ld a,e 139 | and #0x03 ; save lower 2 bits 140 | rlca 141 | rlca 142 | or l ; together with l 143 | ld l,a ; into l (bits 2,3) 144 | 145 | ld d, #255 146 | wait_3_set: 147 | dec d 148 | jp Z, paddle_timeout 149 | in a,(#0xDD) ; ensure we are reading both ports same moment 150 | ld e,a 151 | in b,(c) 152 | in a,(#0xDD) 153 | and e 154 | bit 3,a 155 | jr z, wait_3_set ; wait until bit 5 is 1 156 | ld a,b 157 | and #0xC0 ; save upper 2 bits 158 | rrca 159 | rrca 160 | ld h,a ; into h (bits 4,5) 161 | ld a,e 162 | and #0x03 ; save lower 2 bits 163 | rrca 164 | rrca 165 | or h ; together with h (bits 6,7) 166 | or l ; together with lower part 167 | ld l,a 168 | ret 169 | 170 | paddle_timeout: 171 | ld l,#128 172 | ret 173 | 174 | __endasm; 175 | } 176 | #pragma restore 177 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_paletteAdd.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #ifdef TARGET_GG 10 | #define COLOR_ADD(c,r) ((((c)&0x00f)+((r)&0x00f)>=0x00f?0x00f:((c)&0x00f)+((r)&0x00f))|(((c)&0x0f0)+((r)&0x0f0)>=0x0f0?0x0f0:((c)&0x0f0)+((r)&0x0f0))|(((c)&0xf00)+((r)&0xf00)>=0xf00?0xf00:((c)&0xf00)+((r)&0xf00))) 11 | void GG_loadBGPaletteafterColorAddition(const void *palette, const unsigned int addition_color) { 12 | unsigned char i; 13 | GG_setNextBGColoratIndex(0); 14 | for (i=0;i<16;i++) 15 | GG_setColor(COLOR_ADD(((unsigned int *)(palette))[i], addition_color)); 16 | } 17 | 18 | void GG_loadSpritePaletteafterColorAddition(const void *palette, const unsigned int addition_color) { 19 | unsigned char i; 20 | GG_setNextSpriteColoratIndex(0); 21 | for (i=0;i<16;i++) 22 | GG_setColor(COLOR_ADD(((unsigned int *)(palette))[i], addition_color)); 23 | } 24 | #else 25 | #define COLOR_ADD(c,r) ((((c)&0x03)+((r)&0x03)>=0x03?0x03:((c)&0x03)+((r)&0x03))|(((c)&0x0c)+((r)&0x0c)>=0x0c?0x0c:((c)&0x0c)+((r)&0x0c))|(((c)&0x30)+((r)&0x30)>=0x30?0x30:((c)&0x30)+((r)&0x30))) 26 | void SMS_loadBGPaletteafterColorAddition(const void *palette, const unsigned char addition_color) { 27 | unsigned char i; 28 | SMS_setNextBGColoratIndex(0); 29 | for (i=0;i<16;i++) 30 | SMS_setColor(COLOR_ADD(((unsigned char *)(palette))[i], addition_color)); 31 | } 32 | 33 | void SMS_loadSpritePaletteafterColorAddition(const void *palette, const unsigned char addition_color) { 34 | unsigned char i; 35 | SMS_setNextSpriteColoratIndex(0); 36 | for (i=0;i<16;i++) 37 | SMS_setColor(COLOR_ADD(((unsigned char *)(palette))[i], addition_color)); 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_paletteAdv.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | #ifndef TARGET_GG 12 | void SMS_loadBGPaletteHalfBrightness (const void *palette) __z88dk_fastcall { 13 | // *palette will be in HL 14 | ASM_LD_DE_IMM(#SMS_CRAMAddress); 15 | ASM_DE_TO_VDP_CONTROL; 16 | ASM_LD_B_IMM(#16); 17 | __asm 18 | 1$: ld a,(hl) ; 7 19 | rrca ; 4 20 | and #0x15 ; 7 21 | out (_VDPDataPort),a ; 11 22 | inc hl ; 6 23 | djnz 1$ ; 13 = *VRAM SAFE* 24 | __endasm; 25 | } 26 | 27 | void SMS_loadSpritePaletteHalfBrightness (const void *palette) __z88dk_fastcall { 28 | // *palette will be in HL 29 | ASM_LD_DE_IMM(#SMS_CRAMAddress+0x10); 30 | ASM_DE_TO_VDP_CONTROL; 31 | ASM_LD_B_IMM(#16); 32 | __asm 33 | 1$: ld a,(hl) ; 7 34 | rrca ; 4 35 | and #0x15 ; 7 36 | out (_VDPDataPort),a ; 11 37 | inc hl ; 6 38 | djnz 1$ ; 13 *VRAM SAFE* 39 | __endasm; 40 | } 41 | #endif 42 | #pragma restore 43 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_paletteSub.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #ifdef TARGET_GG 10 | #define COLOR_SUBTRACT(c,r) (((((r)&0xF)>=((c)&0xF))?0:(((c)&0xF)-((r)&0xF)))|((((r)&0xF0)>=((c)&0xF0))?0:(((c)&0xF0)-((r)&0xF0)))|((((r)&0xF00)>=((c)&0xF00))?0:(((c)&0xF00)-((r)&0xF00)))) 11 | void GG_loadBGPaletteafterColorSubtraction (const void *palette, const unsigned int subtraction_color) { 12 | unsigned char i; 13 | GG_setNextBGColoratIndex(0); 14 | for (i=0;i<16;i++) 15 | GG_setColor(COLOR_SUBTRACT(((unsigned int *)(palette))[i],subtraction_color)); 16 | } 17 | 18 | void GG_loadSpritePaletteafterColorSubtraction (const void *palette, const unsigned int subtraction_color) { 19 | unsigned char i; 20 | GG_setNextSpriteColoratIndex(0); 21 | for (i=0;i<16;i++) 22 | GG_setColor(COLOR_SUBTRACT(((unsigned int *)(palette))[i],subtraction_color)); 23 | } 24 | #else 25 | #define COLOR_SUBTRACT(c,r) (((((r)&0x3)>=((c)&0x3))?0:(((c)&0x3)-((r)&0x3)))|((((r)&0xC)>=((c)&0xC))?0:(((c)&0xC)-((r)&0xC)))|((((r)&0x30)>=((c)&0x30))?0:(((c)&0x30)-((r)&0x30)))) 26 | void SMS_loadBGPaletteafterColorSubtraction (const void *palette, const unsigned char subtraction_color) { 27 | unsigned char i; 28 | SMS_setNextBGColoratIndex(0); 29 | for (i=0;i<16;i++) 30 | SMS_setColor(COLOR_SUBTRACT(((unsigned char *)(palette))[i],subtraction_color)); 31 | } 32 | 33 | void SMS_loadSpritePaletteafterColorSubtraction (const void *palette, const unsigned char subtraction_color) { 34 | unsigned char i; 35 | SMS_setNextSpriteColoratIndex(0); 36 | for (i=0;i<16;i++) 37 | SMS_setColor(COLOR_SUBTRACT(((unsigned char *)(palette))[i],subtraction_color)); 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_paletteZero.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | #ifndef TARGET_GG 12 | void SMS_zeroBGPalette (void) { 13 | ASM_LD_DE_IMM(#SMS_CRAMAddress); 14 | ASM_DE_TO_VDP_CONTROL; 15 | ASM_LD_B_IMM(#16); 16 | __asm 17 | xor a 18 | 1$: out (_VDPDataPort),a ; 11 19 | nop ; 4 20 | djnz 1$ ; 13 = 28 *VRAM SAFE ON GG TOO* 21 | __endasm; 22 | } 23 | 24 | void SMS_zeroSpritePalette (void) { 25 | ASM_LD_DE_IMM(#SMS_CRAMAddress+0x10); 26 | ASM_DE_TO_VDP_CONTROL; 27 | ASM_LD_B_IMM(#16); 28 | __asm 29 | xor a 30 | 1$: out (_VDPDataPort),a ; 11 31 | nop ; 4 32 | djnz 1$ ; 13 = 28 *VRAM SAFE ON GG TOO* 33 | __endasm; 34 | } 35 | #endif 36 | #pragma restore 37 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_readVRAM.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | #include "SMSlib.h" 6 | #include "SMSlib_common.c" 7 | 8 | void SMS_saveTileMapArea(unsigned char x, unsigned char y, void *dst, unsigned char width, unsigned char height) { 9 | unsigned char i; 10 | unsigned int *d = dst; 11 | unsigned int src = (SMS_PNTAddress & ~0x4000) + y * 64 + x * 2; 12 | 13 | for (i=0; i VRAM safe 194 | out (c),a 195 | _no_sprite_term: 196 | __endasm; 197 | SMS_setAddr(SMS_SATAddress+128); 198 | __asm 199 | ld c,#_VDPDataPort 200 | ld a,(#_SpriteNextFree) 201 | add a,a 202 | ld b,a 203 | ld hl,#_SpriteTableXN 204 | _next_spriteXN: 205 | outi ; 16 cycles 206 | jr nz,_next_spriteXN ; 12 cycles = 28 (VRAM safe on GG too) 207 | ret 208 | 209 | _no_sprites: 210 | ld a,#0xD0 211 | out (#_VDPDataPort),a 212 | __endasm; 213 | } 214 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_spriteAdv.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | extern unsigned char SpriteTableY[MAXSPRITES]; 10 | extern unsigned char SpriteTableXN[MAXSPRITES*2]; 11 | extern unsigned char SpriteNextFree; 12 | 13 | signed char SMS_reserveSprite (void) { 14 | if (SpriteNextFree=MAXSPRITES) || // no sprite left? 30 | (x>clipWin_x1) || (x<((int)(clipWin_x0)-(int)(spritesWidth))) || // clipped by x? 31 | (x<0) || // x negative? 32 | (y>clipWin_y1) || (y<((int)(clipWin_y0)-(int)(spritesHeight))) || // clipped by y? 33 | ((y-1)==0xD0) ) // y-1 is 0xD1? 34 | return (-1); // sprite clipped! 35 | SpriteTableY[SpriteNextFree]=y-1; 36 | stXN=&SpriteTableXN[SpriteNextFree*2]; 37 | *stXN++=x; 38 | *stXN=tile; 39 | return(SpriteNextFree++); 40 | } 41 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_string.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | #include 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | extern signed int SMS_TextRenderer_offset; 10 | 11 | void SMS_putchar (unsigned char c) { 12 | SMS_setTile(c+SMS_TextRenderer_offset); 13 | } 14 | 15 | void SMS_print (const unsigned char *str) { 16 | // If using SMS_TextRenderer_offset directly, SDCC 17 | // ends up loading it from memory inside the loop. 18 | // 19 | // The register keyword does not make a difference, but 20 | // it does capture the intention... 21 | register int off = SMS_TextRenderer_offset; 22 | 23 | while (*str) { 24 | SMS_setTile(*str + off); 25 | str++; 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_textrenderer.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | #include 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | signed int SMS_TextRenderer_offset; 10 | 11 | void SMS_configureTextRenderer (signed int ascii_to_tile_offset) __z88dk_fastcall { 12 | SMS_TextRenderer_offset=ascii_to_tile_offset; 13 | } 14 | 15 | #pragma save 16 | #pragma disable_warning 59 17 | 18 | int putchar (int c) { 19 | SMS_setTile(c+SMS_TextRenderer_offset); 20 | } 21 | 22 | #pragma restore 23 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_threesprites.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | 12 | #ifdef NO_SPRITE_CHECKS 13 | void SMS_addThreeAdjoiningSprites_f (unsigned char y, unsigned int x_tile) __naked __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 14 | // Y passed in A 15 | // X passed in D 16 | // tile passed in E 17 | __asm 18 | ld hl,#_SpriteNextFree ; load current SpriteNextFree value 19 | ld c,(hl) ; (in C) 20 | inc (hl) ; increment SpriteNextFree 21 | 22 | ld b,#0x00 23 | ld hl,#_SpriteTableY 24 | add hl,bc ; hl+=SpriteNextFree 25 | dec a 26 | ld (hl),a ; write Y (as Y-1) 27 | inc hl 28 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 29 | inc hl 30 | ld (hl),a ; write Y again for the third sprite (always as Y-1) 31 | 32 | ld hl,#_SpriteTableXN 33 | sla c 34 | ld (hl),d ; write X 35 | inc hl 36 | ld (hl),e ; write tile number 37 | 38 | #ifdef NO_SPRITE_ZOOM 39 | ld a,#8 40 | #else 41 | ld a,(#_spritesWidth) ; load current sprite width 42 | #endif 43 | add a,d ; add to X 44 | ret c ; if new X is overflowing, do not place second sprite and leave 45 | 46 | inc hl 47 | ld (hl),a ; write X + spritesWidth 48 | 49 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 50 | add a,e ; add to tile number 51 | inc hl 52 | ld (hl),a ; write tile number + spritesTileOffset 53 | 54 | ld hl,#_SpriteNextFree 55 | inc (hl) ; increment SpriteNextFree again 56 | 57 | #ifdef NO_SPRITE_ZOOM 58 | ld a,#16 59 | #else 60 | ld a,(#_spritesWidth) ; load current sprite width 61 | add a,a ; double it 62 | #endif 63 | add a,d ; add to X 64 | ret c ; if new X is overflowing, do not place third sprite and leave 65 | 66 | inc hl 67 | ld (hl),a ; write X + spritesWidth 68 | 69 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 70 | add a,a ; double it 71 | add a,e ; add to tile number 72 | inc hl 73 | ld (hl),a ; write tile number + spritesTileOffset*2 74 | 75 | ld hl,#_SpriteNextFree 76 | inc (hl) ; increment SpriteNextFree again 77 | ret 78 | __endasm; 79 | } 80 | #else 81 | void SMS_addThreeAdjoiningSprites_f (unsigned int y, unsigned int x_tile) __naked __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 82 | // Y passed in L 83 | // X passed in D 84 | // tile passed in E 85 | __asm 86 | ld a,(#_SpriteNextFree) 87 | cp a,#MAXSPRITES-2 88 | ret nc ; we do not have 3 sprites left, leave! 89 | ld c,a ; save SpriteNextFree value in c 90 | 91 | ld a,l 92 | cp a,#0xd1 93 | ret z ; invalid Y, leave! 94 | 95 | ld b,#0x00 96 | ld hl,#_SpriteTableY 97 | add hl,bc 98 | dec a 99 | ld (hl),a ; write Y (as Y-1) 100 | inc hl 101 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 102 | inc hl 103 | ld (hl),a ; write Y once more for the third sprite (always as Y-1) 104 | 105 | ld hl,#_SpriteTableXN 106 | add hl,bc 107 | add hl,bc 108 | ld (hl),d ; write X 109 | inc hl 110 | ld (hl),e ; write tile number 111 | 112 | 113 | #ifdef NO_SPRITE_ZOOM 114 | ld a,#8 ; each sprite is 8 pixels wide 115 | #else 116 | ld a,(#_spritesWidth) ; load current sprite width 117 | #endif 118 | add a,d ; add to X 119 | jr c,_secondSpriteClipped ; if new X is overflowing, do not place second sprite 120 | inc hl 121 | ld (hl),a ; write X + spritesWidth 122 | 123 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 124 | add a,e 125 | inc hl 126 | ld (hl),a ; write tile number + spritesTileOffset 127 | 128 | #ifdef NO_SPRITE_ZOOM 129 | ld a,#16 ; each sprite is 8 pixels wide 130 | #else 131 | ld a,(#_spritesWidth) ; load current sprite width 132 | add a,a ; double that 133 | #endif 134 | add a,d ; add to X 135 | jr c,_thirdSpriteClipped ; if new X is overflowing, do not place third sprite 136 | inc hl 137 | ld (hl),a ; write X + spritesWidth*2 138 | 139 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 140 | add a,a ; double that 141 | add a,e 142 | inc hl 143 | ld (hl),a ; write tile number + spritesTileOffset*2 144 | 145 | ld a,c ; three sprite has been placed, then SpriteNextFree+=3 146 | add a,#3 147 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 148 | ret 149 | 150 | _secondSpriteClipped: 151 | ld a,c ; second sprite has been clipped, so just inc SpriteNextFree 152 | inc a 153 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 154 | ret 155 | 156 | _thirdSpriteClipped: 157 | ld a,c ; third sprite has been clipped, so just SpriteNextFree+=2 158 | add a,#2 159 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 160 | ret 161 | __endasm; 162 | } 163 | #endif 164 | #pragma restore 165 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_twosprites.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | #include "SMSlib_common.c" 8 | 9 | #pragma save 10 | #pragma disable_warning 85 11 | 12 | // 2nd ASM version: 290 CPU cycles 13 | /* 14 | void SMS_addTwoAdjoiningSprites (unsigned char x, unsigned char y, unsigned char tile) __naked __preserves_regs(iyh,iyl) __sdcccall(0) { 15 | __asm 16 | ld a,(#_SpriteNextFree) 17 | cp a,#MAXSPRITES-1 18 | ret nc ; we do not have 2 sprites left, leave! 19 | ld c,a ; save SpriteNextFree value in c 20 | ld b,#0x00 21 | 22 | ld hl,#2 23 | add hl,sp 24 | ld e,(hl) ; read X 25 | inc hl 26 | ld a,(hl) ; read Y 27 | cp a,#0xd1 28 | ret z ; invalid Y, leave! 29 | inc hl 30 | ld d,(hl) ; read tile number 31 | 32 | ld hl,#_SpriteTableY 33 | add hl,bc 34 | dec a 35 | ld (hl),a ; write Y (as Y-1) 36 | inc hl 37 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 38 | 39 | ld hl,#_SpriteTableXN 40 | add hl,bc 41 | add hl,bc 42 | ld (hl),e ; write X 43 | inc hl 44 | ld (hl),d ; write tile number 45 | 46 | ld a,(#_spritesWidth) ; load current sprite width 47 | add a,e 48 | jr c,_secondSpriteClipped ; if new X is overflowing, do not place second sprite 49 | inc hl 50 | ld (hl),a ; write X + spritesWidth 51 | 52 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 53 | add a,d 54 | inc hl 55 | ld (hl),a ; write tile number + spritesTileOffset 56 | 57 | ld a,c 58 | add a,#2 59 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 60 | ret 61 | 62 | _secondSpriteClipped: 63 | ld hl,#_SpriteNextFree ; second sprite has been clipped, so just inc SpriteNextFree 64 | inc (hl) 65 | ret 66 | __endasm; 67 | } 68 | */ 69 | 70 | #ifdef NO_SPRITE_CHECKS 71 | // 1st sdcccall(1) ASM version: 204 CPU cycles 72 | void SMS_addTwoAdjoiningSprites_f (unsigned char y, unsigned int x_tile) __naked __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 73 | // Y passed in A 74 | // X passed in D 75 | // tile passed in E 76 | __asm 77 | ld hl,#_SpriteNextFree ; load current SpriteNextFree value 78 | ld c,(hl) ; (in C) 79 | inc (hl) ; increment SpriteNextFree 80 | 81 | ld b,#0x00 82 | ld hl,#_SpriteTableY 83 | add hl,bc ; hl+=SpriteNextFree 84 | dec a 85 | ld (hl),a ; write Y (as Y-1) 86 | inc hl 87 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 88 | 89 | ld hl,#_SpriteTableXN 90 | sla c 91 | ld (hl),d ; write X 92 | inc hl 93 | ld (hl),e ; write tile number 94 | 95 | #ifdef NO_SPRITE_ZOOM 96 | ld a,#8 97 | #else 98 | ld a,(#_spritesWidth) ; load current sprite width 99 | #endif 100 | add a,d ; add to X 101 | ret c ; if new X is overflowing, do not place second sprite 102 | inc hl 103 | ld (hl),a ; write X + spritesWidth 104 | 105 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 106 | add a,e 107 | inc hl 108 | ld (hl),a ; write tile number + spritesTileOffset 109 | 110 | ld hl,#_SpriteNextFree 111 | inc (hl) ; increment SpriteNextFree again 112 | ret 113 | __endasm; 114 | } 115 | #else 116 | // 1st sdcccall(1) ASM version: 240 CPU cycles 117 | void SMS_addTwoAdjoiningSprites_f (unsigned int y, unsigned int x_tile) __naked __preserves_regs(d,e,iyh,iyl) __sdcccall(1) { 118 | // Y passed in L 119 | // X passed in D 120 | // tile passed in E 121 | __asm 122 | ld a,(#_SpriteNextFree) 123 | cp a,#MAXSPRITES-1 124 | ret nc ; we do not have 2 sprites left, leave! 125 | ld c,a ; save SpriteNextFree value in c 126 | 127 | ld a,l 128 | cp a,#0xd1 129 | ret z ; invalid Y, leave! 130 | 131 | ld hl,#_SpriteTableY 132 | ld b,#0x00 133 | add hl,bc 134 | dec a 135 | ld (hl),a ; write Y (as Y-1) 136 | inc hl 137 | ld (hl),a ; write Y again for the second sprite (always as Y-1) 138 | 139 | ld hl,#_SpriteTableXN 140 | add hl,bc 141 | add hl,bc 142 | ld (hl),d ; write X 143 | inc hl 144 | ld (hl),e ; write tile number 145 | 146 | #ifdef NO_SPRITE_ZOOM 147 | ld a,#8 ; each sprite is 8 pixels wide 148 | #else 149 | ld a,(#_spritesWidth) ; load current sprite width 150 | #endif 151 | add a,d ; add to X 152 | jr c,_secondSpriteClipped ; if new X is overflowing, do not place second sprite 153 | inc hl 154 | ld (hl),a ; write X + spritesWidth 155 | 156 | ld a,(#_spritesTileOffset) ; load current sprite tile offset 157 | add a,e 158 | inc hl 159 | ld (hl),a ; write tile number + spritesTileOffset 160 | 161 | ld a,c 162 | add a,#2 163 | ld (#_SpriteNextFree),a ; save SpriteNextFree new value 164 | ret 165 | 166 | _secondSpriteClipped: 167 | ld hl,#_SpriteNextFree ; second sprite has been clipped, so just inc SpriteNextFree 168 | inc (hl) 169 | ret 170 | __endasm; 171 | } 172 | #endif 173 | #pragma restore 174 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_zx7.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | #pragma save 9 | #pragma disable_warning 85 10 | void SMS_decompressZX7 (const void *src, void *dst) __naked __sdcccall(1) { 11 | /* ************************************************** 12 | ZX7 decoder by Einar Saukas & Urusergi ("Turbo" version) 13 | C wrapper by sverx 14 | ***************************************************** */ 15 | __asm 16 | ld a, #0x80 17 | dzx7t_copy_byte_loop: 18 | ldi ; copy literal byte 19 | dzx7t_main_loop: 20 | add a, a ; check next bit 21 | call z, dzx7t_load_bits ; no more bits left? 22 | jr nc, dzx7t_copy_byte_loop ; next bit indicates either literal or sequence 23 | 24 | ; determine number of bits used for length (Elias gamma coding) 25 | push de 26 | ld bc, #1 27 | ld d, b 28 | dzx7t_len_size_loop: 29 | inc d 30 | add a, a ; check next bit 31 | call z, dzx7t_load_bits ; no more bits left? 32 | jr nc, dzx7t_len_size_loop 33 | jp dzx7t_len_value_start 34 | 35 | ; determine length 36 | dzx7t_len_value_loop: 37 | add a, a ; check next bit 38 | call z, dzx7t_load_bits ; no more bits left? 39 | rl c 40 | rl b 41 | jr c, dzx7t_exit ; check end marker 42 | dzx7t_len_value_start: 43 | dec d 44 | jr nz, dzx7t_len_value_loop 45 | inc bc ; adjust length 46 | 47 | ; determine offset 48 | ld e, (hl) ; load offset flag (1 bit) + offset value (7 bits) 49 | inc hl 50 | .db 0xcb, 0x33 ; opcode for undocumented instruction "SLL E" aka "SLS E" 51 | jr nc, dzx7t_offset_end ; if offset flag is set, load 4 extra bits 52 | add a, a ; check next bit 53 | call z, dzx7t_load_bits ; no more bits left? 54 | rl d ; insert first bit into D 55 | add a, a ; check next bit 56 | call z, dzx7t_load_bits ; no more bits left? 57 | rl d ; insert second bit into D 58 | add a, a ; check next bit 59 | call z, dzx7t_load_bits ; no more bits left? 60 | rl d ; insert third bit into D 61 | add a, a ; check next bit 62 | call z, dzx7t_load_bits ; no more bits left? 63 | ccf 64 | jr c, dzx7t_offset_end 65 | inc d ; equivalent to adding 128 to DE 66 | dzx7t_offset_end: 67 | rr e ; insert inverted fourth bit into E 68 | 69 | ; copy previous sequence 70 | ex (sp), hl ; store source, restore destination 71 | push hl ; store destination 72 | sbc hl, de ; HL = destination - offset - 1 73 | pop de ; DE = destination 74 | ldir 75 | dzx7t_exit: 76 | pop hl ; restore source address (compressed data) 77 | jp nc, dzx7t_main_loop 78 | 79 | dzx7t_load_bits: 80 | ld a, (hl) ; load another group of 8 bits 81 | inc hl 82 | rla 83 | ret ; because this function is naked 84 | __endasm; 85 | } 86 | #pragma restore 87 | -------------------------------------------------------------------------------- /SMSlib/src/SMSlib_zx7_VRAM.c: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | SMSlib - C programming library for the SMS/GG 3 | ( part of devkitSMS - github.com/sverx/devkitSMS ) 4 | ************************************************** */ 5 | 6 | #include "SMSlib.h" 7 | 8 | #pragma save 9 | #pragma disable_warning 85 10 | void SMS_decompressZX7toVRAM (const void *src, unsigned int dst) __naked __sdcccall(1) { 11 | /* ===================================================================== 12 | * by Einar Saukas, Antonio Villena & Metalbrain 13 | * modified for sms vram by aralbrec 14 | * modified for asm by Maxim 15 | * C wrapper/made interrupt safe/VDP timing safe by sverx 16 | ===================================================================== */ 17 | __asm 18 | ld c,#0xbf ; VDP control port 19 | set 6,d ; set VRAM write bit 20 | di ; set VRAM address 21 | out (c),e 22 | out (c),d 23 | ei 24 | res 6,d ; remove VRAM write bit 25 | dec c ; data port 26 | 27 | ld a,#0x80 ; Signal bit for flags byte (1<<7) 28 | 29 | dzx7s_copy_byte_loop: 30 | outi ; copy literal byte 31 | inc de 32 | 33 | dzx7s_main_loop: 34 | 35 | call dzx7s_next_bit 36 | jr nc,dzx7s_copy_byte_loop ; next bit indicates either literal or sequence 37 | 38 | ; determine number of bits used for length (Elias gamma coding) 39 | push de 40 | ld bc,#0 41 | ld d,b 42 | 43 | dzx7s_len_size_loop: 44 | inc d 45 | call dzx7s_next_bit 46 | jr nc,dzx7s_len_size_loop 47 | 48 | ; determine length 49 | dzx7s_len_value_loop: 50 | call nc,dzx7s_next_bit 51 | rl c 52 | rl b 53 | 54 | jp c,l_ret 55 | dec d 56 | jr nz,dzx7s_len_value_loop 57 | inc bc ; adjust length 58 | 59 | ; determine offset 60 | ld e, (hl) ; load offset flag (1 bit) + offset value (7 bits) 61 | inc hl 62 | sla e 63 | inc e 64 | jr nc,dzx7s_offset_end ; if offset flag is set, load 4 extra bits 65 | ld d, #0x10 ; bit marker to load 4 bits 66 | 67 | dzx7s_rld_next_bit: 68 | call dzx7s_next_bit 69 | rl d ; insert next bit into D 70 | jr nc,dzx7s_rld_next_bit ; repeat 4 times, until bit marker is out 71 | inc d ; add 128 to DE 72 | srl d ; retrieve fourth bit from D 73 | 74 | dzx7s_offset_end: 75 | rr e ; insert fourth bit into E 76 | 77 | ; copy previous sequence 78 | ex (sp),hl ; store source, restore destination 79 | push hl ; store destination 80 | sbc hl,de ; HL = destination - offset - 1 81 | pop de ; DE = destination 82 | push af 83 | 84 | ; *********************** 85 | set 6,d 86 | dec bc 87 | inc b 88 | inc c 89 | ld a,c 90 | ld c,#0xbf 91 | 92 | dzx7s_outer_loop: 93 | push bc 94 | ld b,a 95 | 96 | dzx7s_inner_loop: 97 | nop ; 4 98 | di ; 4 = 27 (safe on every Master System or Game Gear) 99 | out (c),l 100 | out (c),h 101 | ei ; 4 102 | inc hl ; 6 103 | xor a ; 4 104 | ret nz ; 5 (this ret will never happen, it is just to wait 5 cycles) 105 | nop ; 4 106 | nop ; 4 = 27 (safe on every Master System or Game Gear) 107 | in a,(#0xbe) 108 | 109 | nop ; 4 110 | nop ; 4 111 | nop ; 4 112 | nop ; 4 113 | nop ; 4 114 | nop ; 4 115 | di ; 4 = 28 (safe on every Master System or Game Gear) 116 | out (c),e 117 | out (c),d 118 | ei 119 | out (#0xbe),a 120 | inc de ; 6 121 | djnz dzx7s_inner_loop ; 13 122 | ld a,b 123 | pop bc 124 | djnz dzx7s_outer_loop 125 | ld c,b 126 | res 6,d 127 | ; *********************** 128 | 129 | pop af 130 | ld c,#0xbe 131 | pop hl ; restore source address (compressed data) 132 | jr nc, dzx7s_main_loop 133 | 134 | dzx7s_next_bit: 135 | add a,a ; check next bit 136 | ret nz ; no more bits left? 137 | ld a,(hl) ; load another group of 8 bits 138 | inc hl 139 | rla 140 | ret 141 | 142 | l_ret: 143 | pop hl 144 | ret 145 | __endasm; 146 | } 147 | #pragma restore 148 | -------------------------------------------------------------------------------- /SMSlib/src/how to build this.txt: -------------------------------------------------------------------------------- 1 | set OPT=--max-allocs-per-node 100000 2 | 3 | sdcc -o SMSlib.rel -c -mz80 %OPT% --peep-file peep-rules.txt --reserve-regs-iy SMSlib.c 4 | @if %errorlevel% NEQ 0 goto :EOF 5 | 6 | sdcc -o SMSlib_GG.rel -c -mz80 %OPT% -DTARGET_GG --peep-file peep-rules.txt --reserve-regs-iy SMSlib.c 7 | @if %errorlevel% NEQ 0 goto :EOF 8 | 9 | sdcc -o SMSlib_sprite.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_sprite.c 10 | @if %errorlevel% NEQ 0 goto :EOF 11 | 12 | sdcc -o SMSlib_twosprites.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_twosprites.c 13 | @if %errorlevel% NEQ 0 goto :EOF 14 | 15 | sdcc -o SMSlib_threesprites.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_threesprites.c 16 | @if %errorlevel% NEQ 0 goto :EOF 17 | 18 | sdcc -o SMSlib_foursprites.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_foursprites.c 19 | @if %errorlevel% NEQ 0 goto :EOF 20 | 21 | sdcc -o SMSlib_metasprite.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_metasprite.c 22 | @if %errorlevel% NEQ 0 goto :EOF 23 | 24 | sdcc -o SMSlib_paletteAdv.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_paletteAdv.c 25 | @if %errorlevel% NEQ 0 goto :EOF 26 | 27 | sdcc -o SMSlib_paletteAdd.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_paletteAdd.c 28 | @if %errorlevel% NEQ 0 goto :EOF 29 | 30 | sdcc -o SMSlib_paletteAdd_GG.rel -c -mz80 %OPT% -DTARGET_GG --peep-file peep-rules.txt SMSlib_paletteAdd.c 31 | @if %errorlevel% NEQ 0 goto :EOF 32 | 33 | sdcc -o SMSlib_paletteSub.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_paletteSub.c 34 | @if %errorlevel% NEQ 0 goto :EOF 35 | 36 | sdcc -o SMSlib_paletteZero.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_paletteZero.c 37 | @if %errorlevel% NEQ 0 goto :EOF 38 | 39 | sdcc -o SMSlib_paletteSub_GG.rel -c -mz80 %OPT% -DTARGET_GG --peep-file peep-rules.txt SMSlib_paletteSub.c 40 | @if %errorlevel% NEQ 0 goto :EOF 41 | 42 | sdcc -o SMSlib_spriteAdv.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_spriteAdv.c 43 | @if %errorlevel% NEQ 0 goto :EOF 44 | 45 | sdcc -o SMSlib_spriteClip.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_spriteClip.c 46 | @if %errorlevel% NEQ 0 goto :EOF 47 | 48 | sdcc -o SMSlib_spriteClip_GG.rel -c -mz80 %OPT% -DTARGET_GG --peep-file peep-rules.txt SMSlib_spriteClip.c 49 | @if %errorlevel% NEQ 0 goto :EOF 50 | 51 | sdcc -o SMSlib_loadTileMapArea.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_loadTileMapArea.c 52 | @if %errorlevel% NEQ 0 goto :EOF 53 | 54 | sdcc -o SMSlib_loadTileMapColumn.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_loadTileMapColumn.c 55 | @if %errorlevel% NEQ 0 goto :EOF 56 | 57 | sdcc -o SMSlib_load1bppTiles.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_load1bppTiles.c 58 | @if %errorlevel% NEQ 0 goto :EOF 59 | 60 | sdcc -o SMSlib_STMcomp.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_STMcomp.c 61 | @if %errorlevel% NEQ 0 goto :EOF 62 | 63 | sdcc -o SMSlib_VRAMmemcpy.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_VRAMmemcpy.c 64 | @if %errorlevel% NEQ 0 goto :EOF 65 | 66 | sdcc -o SMSlib_VRAMmemcpy_brief.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_VRAMmemcpy_brief.c 67 | @if %errorlevel% NEQ 0 goto :EOF 68 | 69 | sdcc -o SMSlib_VRAMmemset.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_VRAMmemset.c 70 | @if %errorlevel% NEQ 0 goto :EOF 71 | 72 | sdcc -o SMSlib_UNSAFE.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_UNSAFE.c 73 | @if %errorlevel% NEQ 0 goto :EOF 74 | 75 | sdcc -o SMSlib_UNSAFE_SAT.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_UNSAFE_SAT.c 76 | @if %errorlevel% NEQ 0 goto :EOF 77 | 78 | sdcc -o SMSlib_UNSAFE_memcpy.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_UNSAFE_memcpy.c 79 | @if %errorlevel% NEQ 0 goto :EOF 80 | 81 | sdcc -o SMSlib_STC0comp.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_STC0comp.c 82 | @if %errorlevel% NEQ 0 goto :EOF 83 | 84 | sdcc -o SMSlib_STC4comp.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_STC4comp.c 85 | @if %errorlevel% NEQ 0 goto :EOF 86 | 87 | sdcc -o SMSlib_PSGaiden.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_PSGaiden.c 88 | @if %errorlevel% NEQ 0 goto :EOF 89 | 90 | sdcc -o SMSlib_textrenderer.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_textrenderer.c 91 | @if %errorlevel% NEQ 0 goto :EOF 92 | 93 | sdcc -o SMSlib_string.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_string.c 94 | @if %errorlevel% NEQ 0 goto :EOF 95 | 96 | sdcc -o SMSlib_getTile.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_getTile.c 97 | @if %errorlevel% NEQ 0 goto :EOF 98 | 99 | sdcc -o SMSlib_readVRAM.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_readVRAM.c 100 | @if %errorlevel% NEQ 0 goto :EOF 101 | 102 | sdcc -o SMSlib_autotext.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_autotext.c 103 | @if %errorlevel% NEQ 0 goto :EOF 104 | 105 | sdcc -o SMSlib_autotext_GG.rel -c -mz80 %OPT% -DTARGET_GG --peep-file peep-rules.txt SMSlib_autotext.c 106 | @if %errorlevel% NEQ 0 goto :EOF 107 | 108 | sdcc -o SMSlib_zx7.rel -c -mz80 %OPT% SMSlib_zx7.c 109 | @if %errorlevel% NEQ 0 goto :EOF 110 | 111 | sdcc -o SMSlib_zx7_VRAM.rel -c -mz80 %OPT% SMSlib_zx7_VRAM.c 112 | @if %errorlevel% NEQ 0 goto :EOF 113 | 114 | sdcc -o SMSlib_aPLib.rel -c -mz80 %OPT% SMSlib_aPLib.c 115 | @if %errorlevel% NEQ 0 goto :EOF 116 | 117 | sdcc -o SMSlib_UNSAFE_aPLib.rel -c -mz80 %OPT% SMSlib_UNSAFE_aPLib.c 118 | @if %errorlevel% NEQ 0 goto :EOF 119 | 120 | sdcc -o SMSlib_paddle.rel -c -mz80 %OPT% SMSlib_paddle.c 121 | @if %errorlevel% NEQ 0 goto :EOF 122 | 123 | sdcc -o SMSlib_debug.rel -c -mz80 %OPT% SMSlib_debug.c 124 | @if %errorlevel% NEQ 0 goto :EOF 125 | 126 | sdcc -o SMSlib_deprecated.rel -c -mz80 %OPT% --peep-file peep-rules.txt SMSlib_deprecated.c 127 | @if %errorlevel% NEQ 0 goto :EOF 128 | 129 | 130 | sdar r SMSlib.lib SMSlib.rel SMSlib_sprite.rel SMSlib_twosprites.rel SMSlib_threesprites.rel SMSlib_foursprites.rel SMSlib_metasprite.rel SMSlib_paletteAdv.rel SMSlib_paletteAdd.rel SMSlib_paletteSub.rel SMSlib_paletteZero.rel SMSlib_spriteAdv.rel SMSlib_spriteClip.rel SMSlib_STC0comp.rel SMSlib_STC4comp.rel SMSlib_PSGaiden.rel SMSlib_STMcomp.rel SMSlib_loadTileMapArea.rel SMSlib_loadTileMapColumn.rel SMSlib_load1bppTiles.rel SMSlib_VRAMmemcpy.rel SMSlib_VRAMmemcpy_brief.rel SMSlib_VRAMmemset.rel SMSlib_UNSAFE.rel SMSlib_UNSAFE_SAT.rel SMSlib_UNSAFE_memcpy.rel SMSlib_textrenderer.rel SMSlib_string.rel SMSlib_getTile.rel SMSlib_readVRAM.rel SMSlib_autotext.rel SMSlib_zx7.rel SMSlib_zx7_VRAM.rel SMSlib_aPLib.rel SMSlib_UNSAFE_aPLib.rel SMSlib_paddle.rel SMSlib_debug.rel SMSlib_deprecated.rel 131 | @if %errorlevel% NEQ 0 goto :EOF 132 | 133 | sdar r SMSlib_GG.lib SMSlib_GG.rel SMSlib_sprite.rel SMSlib_twosprites.rel SMSlib_threesprites.rel SMSlib_foursprites.rel SMSlib_metasprite.rel SMSlib_paletteAdv.rel SMSlib_paletteAdd_GG.rel SMSlib_paletteSub_GG.rel SMSlib_paletteZero.rel SMSlib_spriteAdv.rel SMSlib_spriteClip_GG.rel SMSlib_STC0comp.rel SMSlib_STC4comp.rel SMSlib_PSGaiden.rel SMSlib_STMcomp.rel SMSlib_loadTileMapArea.rel SMSlib_loadTileMapColumn.rel SMSlib_load1bppTiles.rel SMSlib_VRAMmemcpy.rel SMSlib_VRAMmemcpy_brief.rel SMSlib_VRAMmemset.rel SMSlib_UNSAFE.rel SMSlib_UNSAFE_SAT.rel SMSlib_UNSAFE_memcpy.rel SMSlib_textrenderer.rel SMSlib_string.rel SMSlib_getTile.rel SMSlib_readVRAM.rel SMSlib_autotext_GG.rel SMSlib_zx7.rel SMSlib_zx7_VRAM.rel SMSlib_aPLib.rel SMSlib_UNSAFE_aPLib.rel SMSlib_debug.rel SMSlib_deprecated.rel 134 | @if %errorlevel% NEQ 0 goto :EOF 135 | 136 | -------------------------------------------------------------------------------- /SMSlib/src/peep-rules.txt: -------------------------------------------------------------------------------- 1 | replace restart { 2 | ld a,%1 3 | add a,#0xFF 4 | ld %1,a 5 | or a, a 6 | } by { 7 | dec %1 8 | } if notUsed('a') 9 | 10 | replace restart { 11 | ld %1, %2 12 | di 13 | ld %2, %1 14 | } by { 15 | ; peephole rule 1-with_DI removed dead load from %2 into %1. 16 | di 17 | } if notVolatile(%1), notUsed(%1), notVolatile(%2) 18 | 19 | replace restart { 20 | ld %1, %2 21 | di 22 | ld %3, %1 23 | } by { 24 | ; peephole rule 1b-with_DI loaded %2 into %3 directly instead of going through %1. 25 | ld %3, %2 26 | di 27 | } if canAssign(%3 %2), notVolatile(%1), notUsed(%1) 28 | 29 | replace restart { 30 | ld %1, %2 (%3) 31 | di 32 | ld %4, %1 33 | } by { 34 | ; peephole rule 11-with_DI loaded %2 (%3) into %4 directly instead of going through %1. 35 | ld %4, %2 (%3) 36 | di 37 | } if canAssign(%4 %2 %3), notVolatile(%1), notUsed(%1) 38 | 39 | replace { 40 | call _SMS_crt0_RST08 41 | } by { 42 | ; devkitSMS peephole rule #1 replaced 'call_SMS_crt0_RST08' with 'rst #0x08' 43 | rst #0x08 44 | } 45 | 46 | replace { 47 | call _SMS_crt0_RST18 48 | } by { 49 | ; devkitSMS peephole rule #2 replaced 'call_SMS_crt0_RST18' with 'rst #0x18' 50 | rst #0x18 51 | } 52 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | ### How to support devkitSMS 2 | 3 | I sometimes get asked if there's a way to support this devkit/libraries. 4 | 5 | First of all, you don't need to. Second, for fiscal reasons, I won't currently accept any money. 6 | 7 | Providing feedback, suggest improvements, open issues on GitHub or help with development is gladly received instead! 8 | 9 | If you're past this point you might be interested to know that I might accept gifts 😉 10 | I love music, the CD audio being my format of choice, and I love retro stuff in general. 11 | Get in contact with me at sverx@yahoo.com if you're in the EU and you want to send me something. 12 | You totally don't have to, and you can ignore this note. Enjoy programming! ❤️ 13 | 14 | P.S. If you use promo code WINTER45 on Hedvig.com we both get a small discount on our insurance 😛 15 | 16 | -------------------------------------------------------------------------------- /assets2banks/Windows/assets2banks.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/assets2banks/Windows/assets2banks.exe -------------------------------------------------------------------------------- /build the library yourself.txt: -------------------------------------------------------------------------------- 1 | in SMSlib/src folder there's a note about building SMSlib yourself 2 | -------------------------------------------------------------------------------- /crt0/README.md: -------------------------------------------------------------------------------- 1 | how to build crt0 yourself 2 | 3 | for SMS/GG: 4 | ``` 5 | sdasz80 -g -o crt0_sms.s 6 | ``` 7 | 8 | for SG-1000: 9 | ``` 10 | sdasz80 -g -o crt0_sg.s 11 | ``` 12 | 13 | -------------------------------------------------------------------------------- /crt0/crt0_BASIC.rel: -------------------------------------------------------------------------------- 1 | XL3 2 | H D areas 8 global symbols 3 | M crt0 4 | S _main Ref000000 5 | S _SG_init Ref000000 6 | S .__.ABS. Def000000 7 | S _SG_isr Ref000000 8 | S s__INITIALIZED Ref000000 9 | S l__INITIALIZER Ref000000 10 | S s__INITIALIZER Ref000000 11 | A _CODE size 0 flags 0 addr 0 12 | A _HEADER size 0 flags 8 addr 0 13 | A _HEADER0 size 3A flags 8 addr 9800 14 | A _HEADER1 size 3 flags 8 addr 9898 15 | A _HOME size 0 flags 0 addr 0 16 | A _INITIALIZER size 0 flags 0 addr 0 17 | A _GSINIT size F flags 0 addr 0 18 | S gsinit Def000000 19 | A _GSFINAL size 1 flags 0 addr 0 20 | A _DATA size 0 flags 0 addr 0 21 | A _INITIALIZED size 0 flags 0 addr 0 22 | A _BSEG size 0 flags 0 addr 0 23 | A _BSS size 0 flags 0 addr 0 24 | A _HEAP size 0 flags 0 addr 0 25 | T 00 98 00 26 | R 00 00 02 00 27 | T 00 98 00 28 | R 00 00 02 00 29 | T 00 98 00 F3 ED 5E 31 F0 95 AF 21 00 80 77 11 30 | R 00 00 02 00 31 | T 0C 98 00 01 80 01 EF 15 ED B0 3E 92 D3 DF 3E 07 32 | R 00 00 02 00 33 | T 19 98 00 D3 DE 3E 96 ED 47 3E 98 21 00 96 77 11 34 | R 00 00 02 00 35 | T 26 98 00 01 96 01 00 01 ED B0 CD 00 00 CD 00 00 36 | R 00 00 02 00 00 0B 06 00 02 0E 01 00 37 | T 33 98 00 FB CD 00 00 38 | R 00 00 02 00 02 05 00 00 39 | T 37 98 00 40 | R 00 00 02 00 41 | T 37 98 00 76 18 FD 42 | R 00 00 02 00 43 | T 98 98 00 44 | R 00 00 03 00 45 | T 98 98 00 C3 00 00 46 | R 00 00 03 00 02 04 03 00 47 | T 00 00 00 48 | R 00 00 06 00 49 | T 00 00 00 01 00 00 78 B1 28 08 11 00 00 21 00 00 50 | R 00 00 06 00 02 04 05 00 02 0B 04 00 02 0E 06 00 51 | T 0D 00 00 ED B0 52 | R 00 00 06 00 53 | T 0F 00 00 54 | R 00 00 06 00 55 | T 00 00 00 C9 56 | R 00 00 07 00 57 | -------------------------------------------------------------------------------- /crt0/crt0_sg.rel: -------------------------------------------------------------------------------- 1 | XL3 2 | H F areas C global symbols 3 | M crt0 4 | S _main Ref000000 5 | S _SG_nmi_isr Ref000000 6 | S _SG_init Ref000000 7 | S .__.ABS. Def000000 8 | S _SG_isr Ref000000 9 | S s__INITIALIZED Ref000000 10 | S l__INITIALIZER Ref000000 11 | S s__INITIALIZER Ref000000 12 | A _CODE size A flags 0 addr 0 13 | S __clock Def000000 14 | S _exit Def000004 15 | A _HEADER size 0 flags 8 addr 0 16 | A _HEADER0 size 6 flags 8 addr 0 17 | A _HEADER1 size 3 flags 8 addr 38 18 | A _HEADER2 size 3 flags 8 addr 66 19 | A _HEADER3 size 126 flags 8 addr 70 20 | S _outi_block Def000195 21 | A _HOME size 0 flags 0 addr 0 22 | A _INITIALIZER size 0 flags 0 addr 0 23 | A _GSINIT size F flags 0 addr 0 24 | S gsinit Def000000 25 | A _GSFINAL size 1 flags 0 addr 0 26 | A _DATA size 0 flags 0 addr 0 27 | A _INITIALIZED size 0 flags 0 addr 0 28 | A _BSEG size 0 flags 0 addr 0 29 | A _BSS size 0 flags 0 addr 0 30 | A _HEAP size 0 flags 0 addr 0 31 | T 00 00 00 32 | R 00 00 02 00 33 | T 00 00 00 F3 ED 56 C3 70 00 34 | R 00 00 02 00 00 07 05 00 35 | T 38 00 00 36 | R 00 00 03 00 37 | T 38 00 00 C3 00 00 38 | R 00 00 03 00 02 04 04 00 39 | T 66 00 00 40 | R 00 00 04 00 41 | T 66 00 00 C3 00 00 42 | R 00 00 04 00 02 04 01 00 43 | T 70 00 00 44 | R 00 00 05 00 45 | T 70 00 00 46 | R 00 00 05 00 47 | T 70 00 00 31 F0 C3 AF 21 00 C0 77 11 01 C0 01 48 | R 00 00 05 00 49 | T 7C 00 00 EF 03 ED B0 3E 92 D3 DF 3E 07 D3 DE CD 50 | R 00 00 05 00 51 | T 89 00 00 00 00 CD 00 00 FB CD 00 00 C3 52 | R 00 00 05 00 00 03 08 00 02 06 02 00 02 0A 00 00 53 | T 93 00 00 04 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED 54 | R 00 00 05 00 00 03 00 00 55 | T A0 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 56 | R 00 00 05 00 57 | T AD 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 58 | R 00 00 05 00 59 | T BA 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 60 | R 00 00 05 00 61 | T C7 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 62 | R 00 00 05 00 63 | T D4 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 64 | R 00 00 05 00 65 | T E1 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 66 | R 00 00 05 00 67 | T EE 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 68 | R 00 00 05 00 69 | T FB 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 70 | R 00 00 05 00 71 | T 08 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 72 | R 00 00 05 00 73 | T 15 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 74 | R 00 00 05 00 75 | T 22 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 76 | R 00 00 05 00 77 | T 2F 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 78 | R 00 00 05 00 79 | T 3C 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 80 | R 00 00 05 00 81 | T 49 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 82 | R 00 00 05 00 83 | T 56 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 84 | R 00 00 05 00 85 | T 63 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 86 | R 00 00 05 00 87 | T 70 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 88 | R 00 00 05 00 89 | T 7D 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 90 | R 00 00 05 00 91 | T 8A 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 92 | R 00 00 05 00 93 | T 95 01 00 94 | R 00 00 05 00 95 | T 95 01 00 C9 96 | R 00 00 05 00 97 | T 00 00 00 98 | R 00 00 00 00 99 | T 00 00 00 3E 02 CF C9 100 | R 00 00 00 00 101 | T 04 00 00 102 | R 00 00 00 00 103 | T 04 00 00 3E 00 CF 104 | R 00 00 00 00 105 | T 07 00 00 106 | R 00 00 00 00 107 | T 07 00 00 76 18 FD 108 | R 00 00 00 00 109 | T 00 00 00 110 | R 00 00 08 00 111 | T 00 00 00 01 00 00 78 B1 28 08 11 00 00 21 00 00 112 | R 00 00 08 00 02 04 06 00 02 0B 05 00 02 0E 07 00 113 | T 0D 00 00 ED B0 114 | R 00 00 08 00 115 | T 0F 00 00 116 | R 00 00 08 00 117 | T 00 00 00 C9 118 | R 00 00 09 00 119 | -------------------------------------------------------------------------------- /crt0/crt0_sms.rel: -------------------------------------------------------------------------------- 1 | XL3 2 | H 10 areas 13 global symbols 3 | M crt0 4 | S _main Ref000000 5 | S _SMS_Port3EBIOSvalue Ref000000 6 | S .__.ABS. Def000000 7 | S _SMS_nmi_isr Ref000000 8 | S _SMS_init Ref000000 9 | S s__INITIALIZED Ref000000 10 | S l__INITIALIZER Ref000000 11 | S s__INITIALIZER Ref000000 12 | S _SMS_isr Ref000000 13 | A _CODE size 0 flags 0 addr 0 14 | A _HEADER size 0 flags 8 addr 0 15 | A _HEADER0 size 8 flags 8 addr 0 16 | A _HEADER1 size 9 flags 8 addr 8 17 | S _SMS_crt0_RST08 Def000008 18 | A _HEADER2 size 1F flags 8 addr 18 19 | S set_bank Def000033 20 | S _SMS_crt0_RST18 Def000018 21 | S get_bank Def00002F 22 | A _HEADER3 size 2B flags 8 addr 38 23 | A _HEADER4 size 104 flags 8 addr 66 24 | S _OUTI32 Def000129 25 | S _outi_block Def000169 26 | S _OUTI64 Def0000E9 27 | S _OUTI96 Def0000A9 28 | S _OUTI128 Def000069 29 | A _HOME size 0 flags 0 addr 0 30 | A _INITIALIZER size 0 flags 0 addr 0 31 | A _GSINIT size F flags 0 addr 0 32 | S gsinit Def000000 33 | A _GSFINAL size 1 flags 0 addr 0 34 | A _DATA size 0 flags 0 addr 0 35 | A _INITIALIZED size 0 flags 0 addr 0 36 | A _BSEG size 0 flags 0 addr 0 37 | A _BSS size 0 flags 0 addr 0 38 | A _HEAP size 0 flags 0 addr 0 39 | T 00 00 00 40 | R 00 00 02 00 41 | T 00 00 00 F3 ED 56 31 F0 DF 18 21 00 00 42 | R 00 00 02 00 0D 0A 04 00 43 | T 08 00 00 44 | R 00 00 03 00 45 | T 08 00 00 46 | R 00 00 03 00 47 | T 08 00 00 0E BF F3 ED 69 ED 61 FB C9 48 | R 00 00 03 00 49 | T 18 00 00 50 | R 00 00 04 00 51 | T 18 00 00 52 | R 00 00 04 00 53 | T 18 00 00 7D D3 BE 7C 23 2B D3 BE C9 54 | R 00 00 04 00 55 | T 21 00 00 56 | R 00 00 04 00 57 | T 21 00 00 21 00 00 22 FC FF 21 01 02 22 FE FF 18 58 | R 00 00 04 00 59 | T 2E 00 00 3B 00 00 60 | R 00 00 04 00 0D 03 05 00 61 | T 2F 00 00 62 | R 00 00 04 00 63 | T 2F 00 00 3A FE FF C9 64 | R 00 00 04 00 65 | T 33 00 00 66 | R 00 00 04 00 67 | T 33 00 00 32 FE FF C9 68 | R 00 00 04 00 69 | T 38 00 00 70 | R 00 00 05 00 71 | T 38 00 00 C3 00 00 72 | R 00 00 05 00 02 04 08 00 73 | T 3B 00 00 74 | R 00 00 05 00 75 | T 3B 00 00 21 00 C0 7E 06 00 70 11 01 C0 01 EF 1F 76 | R 00 00 05 00 77 | T 48 00 00 ED B0 32 00 00 CD 00 00 CD 00 00 FB CD 78 | R 00 00 05 00 02 06 01 00 00 09 09 00 02 0C 04 00 79 | T 55 00 00 00 00 80 | R 00 00 05 00 02 03 00 00 81 | T 57 00 00 82 | R 00 00 05 00 83 | T 57 00 00 76 18 FD 64 65 76 6B 69 74 53 4D 53 84 | R 00 00 05 00 85 | T 66 00 00 86 | R 00 00 06 00 87 | T 66 00 00 C3 00 00 88 | R 00 00 06 00 02 04 03 00 89 | T 69 00 00 90 | R 00 00 06 00 91 | T 69 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 92 | R 00 00 06 00 93 | T 76 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 94 | R 00 00 06 00 95 | T 83 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 96 | R 00 00 06 00 97 | T 90 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 98 | R 00 00 06 00 99 | T 9D 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 100 | R 00 00 06 00 101 | T A9 00 00 102 | R 00 00 06 00 103 | T A9 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 104 | R 00 00 06 00 105 | T B6 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 106 | R 00 00 06 00 107 | T C3 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 108 | R 00 00 06 00 109 | T D0 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 110 | R 00 00 06 00 111 | T DD 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 112 | R 00 00 06 00 113 | T E9 00 00 114 | R 00 00 06 00 115 | T E9 00 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 116 | R 00 00 06 00 117 | T F6 00 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 118 | R 00 00 06 00 119 | T 03 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 120 | R 00 00 06 00 121 | T 10 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 122 | R 00 00 06 00 123 | T 1D 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 124 | R 00 00 06 00 125 | T 29 01 00 126 | R 00 00 06 00 127 | T 29 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 128 | R 00 00 06 00 129 | T 36 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 130 | R 00 00 06 00 131 | T 43 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED 132 | R 00 00 06 00 133 | T 50 01 00 A3 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 134 | R 00 00 06 00 135 | T 5D 01 00 ED A3 ED A3 ED A3 ED A3 ED A3 ED A3 136 | R 00 00 06 00 137 | T 69 01 00 138 | R 00 00 06 00 139 | T 69 01 00 C9 140 | R 00 00 06 00 141 | T 00 00 00 142 | R 00 00 09 00 143 | T 00 00 00 01 00 00 78 B1 28 08 11 00 00 21 00 00 144 | R 00 00 09 00 02 04 06 00 02 0B 05 00 02 0E 07 00 145 | T 0D 00 00 ED B0 146 | R 00 00 09 00 147 | T 0F 00 00 148 | R 00 00 09 00 149 | T 00 00 00 C9 150 | R 00 00 0A 00 151 | -------------------------------------------------------------------------------- /crt0/src/Makefile: -------------------------------------------------------------------------------- 1 | AS=sdasz80 2 | OUTPUTS=crt0_sg.rel crt0_sms.rel crt0_BASIC.rel 3 | 4 | all: $(OUTPUTS) 5 | 6 | %.rel: %.s 7 | $(AS) -g -o $< 8 | 9 | clean: 10 | rm -f $(OUTPUTS) 11 | -------------------------------------------------------------------------------- /crt0/src/crt0_BASIC.s: -------------------------------------------------------------------------------- 1 | ;-------------------------------------------------------------------------- 2 | ; *** this is a modified version aimed to SG-1000 homebrew - sverx\2015 *** 3 | ; *** additional changes targeting BASIC on the SC-3000 - JoppyFurr\2024 *** 4 | ;-------------------------------------------------------------------------- 5 | ;-------------------------------------------------------------------------- 6 | ; crt0.s - Generic crt0.s for a Z80 7 | ; 8 | ; Copyright (C) 2000, Michael Hope 9 | ; 10 | ; This library is free software; you can redistribute it and/or modify it 11 | ; under the terms of the GNU General Public License as published by the 12 | ; Free Software Foundation; either version 2, or (at your option) any 13 | ; later version. 14 | ; 15 | ; This library is distributed in the hope that it will be useful, 16 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | ; GNU General Public License for more details. 19 | ; 20 | ; You should have received a copy of the GNU General Public License 21 | ; along with this library; see the file COPYING. If not, write to the 22 | ; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 23 | ; MA 02110-1301, USA. 24 | ; 25 | ; As a special exception, if you link this library with other files, 26 | ; some of which are compiled with SDCC, to produce an executable, 27 | ; this library does not by itself cause the resulting executable to 28 | ; be covered by the GNU General Public License. This exception does 29 | ; not however invalidate any other reasons why the executable file 30 | ; might be covered by the GNU General Public License. 31 | ;-------------------------------------------------------------------------- 32 | 33 | ; Memory layout: 34 | ; 0x8000: RAM at addresses lower than the load-address: 35 | ; -> Use 0x8000--0x95ff, 5.5 KiB, as work-ram 36 | ; -> Use 0x9600--0x9700, 257 bytes, as the interrupt vector table. 37 | ; 0x9800: Destination address where BASIC loads our code to. 38 | ; -> Continues to 0xc7ff for BASIC IIIa (12 KiB) 39 | ; -> Continues to 0xffff for BASIC IIIb (26 KiB) 40 | ; 0x9898: The interrupt handler, pointed to by the interrupt vector table. 41 | ; 42 | ; Note: The NMI (reset button) is not available to the user application. 43 | 44 | .module crt0 45 | .globl _main 46 | 47 | .area _HEADER (ABS) 48 | ;; Destination address used by the BASIC `LOAD` command 49 | .org 0x9800 50 | init: 51 | di ; disable interrupt 52 | im 2 ; interrupt mode 2 (this will not change) 53 | 54 | ld sp,#0x95f0 ; set stack pointer at end of our 5.5k block of RAM 55 | xor a ; clear RAM (to value 0x00) 56 | ld hl,#0x8000 ; by setting value 0 57 | ld (hl),a ; to $c000 and 58 | ld de,#0x8001 ; copying (LDIR) it to next byte 59 | ld bc,#0x1600-17 ; for 5.5 KB minus 17 bytes 60 | ldir ; do that 61 | 62 | ;; ensure this runs fine on SC-3000 too 63 | ld a,#0x92 64 | out (0xDF),a ; Config PPI (no effect on SG-1000) 65 | ld a,#7 66 | out (0xDE),a ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000) 67 | 68 | ;; Set up for interrupt-mode 2 69 | ;; Register I controls the vector MSB. The vector LSB is whatever happens to be on the bus. 70 | ;; So, a 257-entry table with a single repeated byte (0x98) will give us a reliable 0x9898 call. 71 | ld a,#0x96 ; Vector table at 0x9600, between work-ram and user code. 72 | ld i,a 73 | 74 | ld a,#0x98 75 | ld hl,#0x9600 76 | ld (hl),a ; Initialize first byte of vector table at 0x9600 to value 0x98 77 | ld de,#0x9601 ; Prepare copy to the next byte 78 | ld bc,#0x0100 ; Copy for 256 bytes, giving 257 bytes total. 79 | ldir 80 | 81 | ;; Initialise global variables 82 | call gsinit 83 | call _SG_init 84 | ei ; re-enable interrupts before going to main() 85 | call _main 86 | 1$: 87 | halt 88 | jr 1$ 89 | 90 | .org 0x9898 ; handle IRQ 91 | jp _SG_isr 92 | 93 | ;; Ordering of segments for the linker. 94 | .area _HOME 95 | .area _CODE 96 | .area _INITIALIZER 97 | .area _GSINIT 98 | .area _GSFINAL 99 | 100 | .area _DATA 101 | .area _INITIALIZED 102 | .area _BSEG 103 | .area _BSS 104 | .area _HEAP 105 | .area _CODE 106 | .area _GSINIT 107 | 108 | gsinit:: 109 | ld bc, #l__INITIALIZER 110 | ld a, b 111 | or a, c 112 | jr Z, gsinit_next 113 | ld de, #s__INITIALIZED 114 | ld hl, #s__INITIALIZER 115 | ldir 116 | gsinit_next: 117 | 118 | .area _GSFINAL 119 | ret 120 | 121 | -------------------------------------------------------------------------------- /crt0/src/crt0_sg.s: -------------------------------------------------------------------------------- 1 | ;-------------------------------------------------------------------------- 2 | ; *** this is a modified version aimed to SG-1000 homebrew - sverx\2015 *** 3 | ;-------------------------------------------------------------------------- 4 | ;-------------------------------------------------------------------------- 5 | ; crt0.s - Generic crt0.s for a Z80 6 | ; 7 | ; Copyright (C) 2000, Michael Hope 8 | ; 9 | ; This library is free software; you can redistribute it and/or modify it 10 | ; under the terms of the GNU General Public License as published by the 11 | ; Free Software Foundation; either version 2, or (at your option) any 12 | ; later version. 13 | ; 14 | ; This library is distributed in the hope that it will be useful, 15 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ; GNU General Public License for more details. 18 | ; 19 | ; You should have received a copy of the GNU General Public License 20 | ; along with this library; see the file COPYING. If not, write to the 21 | ; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 22 | ; MA 02110-1301, USA. 23 | ; 24 | ; As a special exception, if you link this library with other files, 25 | ; some of which are compiled with SDCC, to produce an executable, 26 | ; this library does not by itself cause the resulting executable to 27 | ; be covered by the GNU General Public License. This exception does 28 | ; not however invalidate any other reasons why the executable file 29 | ; might be covered by the GNU General Public License. 30 | ;-------------------------------------------------------------------------- 31 | 32 | .module crt0 33 | .globl _main 34 | 35 | .area _HEADER (ABS) 36 | ;; Reset vector 37 | .org 0 38 | di ; disable interrupt 39 | im 1 ; interrupt mode 1 (this will not change) 40 | jp init 41 | 42 | .org 0x38 ; handle IRQ 43 | jp _SG_isr 44 | 45 | .org 0x66 ; handle NMI 46 | jp _SG_nmi_isr 47 | 48 | .org 0x70 49 | init: 50 | ld sp,#0xc3f0 ; set stack pointer at end of RAM 51 | xor a ; clear RAM (to value 0x00) 52 | ld hl,#0xc000 ; by setting value 0 53 | ld (hl),a ; to $c000 and 54 | ld de,#0xc001 ; copying (LDIR) it to next byte 55 | ld bc,#0x0400-17 ; for 1 KB minus 17 bytes 56 | ldir ; do that 57 | 58 | ;; ensure this runs fine on SC-3000 too 59 | ld a,#0x92 60 | out (0xDF),a ; Config PPI (no effect on SG-1000) 61 | ld a,#7 62 | out (0xDE),a ; Select ROW 7 (row 7 of PPI is joypad = default - no effect on SG-1000) 63 | 64 | ;; Initialise global variables 65 | call gsinit 66 | call _SG_init 67 | ei ; re-enable interrupts before going to main() 68 | call _main 69 | jp _exit 70 | 71 | .rept 128 ; this is a block of 128 OUTI 72 | outi ; made for enabling UNSAFE but FAST 73 | .endm ; short data transfers to VRAM 74 | _outi_block:: ; _outi_block label points to END of block 75 | ret 76 | 77 | ;; Ordering of segments for the linker. 78 | .area _HOME 79 | .area _CODE 80 | .area _INITIALIZER 81 | .area _GSINIT 82 | .area _GSFINAL 83 | 84 | .area _DATA 85 | .area _INITIALIZED 86 | .area _BSEG 87 | .area _BSS 88 | .area _HEAP 89 | 90 | .area _CODE 91 | __clock:: 92 | ld a,#2 93 | rst 0x08 94 | ret 95 | 96 | _exit:: 97 | ;; Exit - special code to the emulator 98 | ld a,#0 99 | rst 0x08 100 | 1$: 101 | halt 102 | jr 1$ 103 | 104 | .area _GSINIT 105 | gsinit:: 106 | ld bc, #l__INITIALIZER 107 | ld a, b 108 | or a, c 109 | jr Z, gsinit_next 110 | ld de, #s__INITIALIZED 111 | ld hl, #s__INITIALIZER 112 | ldir 113 | gsinit_next: 114 | 115 | .area _GSFINAL 116 | ret 117 | 118 | -------------------------------------------------------------------------------- /crt0/src/crt0_sms.s: -------------------------------------------------------------------------------- 1 | ;-------------------------------------------------------------------------- 2 | ; ***** this is a modified version aimed to SMS homebrew - sverx\2022 ***** 3 | ;-------------------------------------------------------------------------- 4 | ;-------------------------------------------------------------------------- 5 | ; crt0.s - Generic crt0.s for a Z80 6 | ; 7 | ; Copyright (C) 2000, Michael Hope 8 | ; 9 | ; This library is free software; you can redistribute it and/or modify it 10 | ; under the terms of the GNU General Public License as published by the 11 | ; Free Software Foundation; either version 2, or (at your option) any 12 | ; later version. 13 | ; 14 | ; This library is distributed in the hope that it will be useful, 15 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ; GNU General Public License for more details. 18 | ; 19 | ; You should have received a copy of the GNU General Public License 20 | ; along with this library; see the file COPYING. If not, write to the 21 | ; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 22 | ; MA 02110-1301, USA. 23 | ; 24 | ; As a special exception, if you link this library with other files, 25 | ; some of which are compiled with SDCC, to produce an executable, 26 | ; this library does not by itself cause the resulting executable to 27 | ; be covered by the GNU General Public License. This exception does 28 | ; not however invalidate any other reasons why the executable file 29 | ; might be covered by the GNU General Public License. 30 | ;-------------------------------------------------------------------------- 31 | 32 | .module crt0 33 | .globl _main 34 | 35 | .area _HEADER (ABS) 36 | .org 0 ; Reset 00h 37 | di ; disable interrupt 38 | im 1 ; interrupt mode 1 (this will never change) 39 | ld sp, #0xdff0 ; set stack pointer at end of RAM 40 | jr init 41 | ;-------------------------------------------------------------------------- 42 | .org 0x08 ; Reset 08h - write HL to VDP Control Port 43 | _SMS_crt0_RST08:: 44 | ld c, #0xBF ; set VDP Control Port 45 | di ; make it interrupt SAFE 46 | out (c),l 47 | out (c),h 48 | ei 49 | ret 50 | ;-------------------------------------------------------------------------- 51 | .org 0x18 ; Reset 18h - write HL to VDP Data Port 52 | _SMS_crt0_RST18:: 53 | ld a,l ; (respecting VRAM time costraints) 54 | out (#0xBE),a ; 11 55 | ld a,h ; 4 56 | inc hl ; 6 57 | dec hl ; 6 = 27 (VRAM SAFE on every GameGear) 58 | out (#0xBE),a 59 | ret 60 | ;-------------------------------------------------------------------------- 61 | init: 62 | ld hl,#0x0000 ; initialize mappers 63 | ld (#0xfffc),hl ; [0xfffc]=$00, [0xfffd]=$00 64 | ld hl,#0x0201 65 | ld (#0xfffe),hl ; [0xfffe]=$01, [0xffff]=$02 66 | jr clear_ram 67 | ;-------------------------------------------------------------------------- 68 | get_bank:: ; get current code bank num into A 69 | ld a,(#0xfffe) ; (read current page from mapper) 70 | ret 71 | set_bank:: ; set current code bank num to A 72 | ld (#0xfffe),a ; (restore caller page) 73 | ret 74 | ;-------------------------------------------------------------------------- 75 | .org 0x38 ; handle IRQ 76 | jp _SMS_isr 77 | ;-------------------------------------------------------------------------- 78 | clear_ram: 79 | ld hl,#0xc000 ; save contents of $c000 80 | ld a,(hl) ; before clearing RAM 81 | ld b,#0x00 ; clear RAM (to value 0x00) by setting 82 | ld (hl),b ; value 0 to $c000 and 83 | ld de,#0xc001 ; copying (LDIR) it to next byte 84 | ld bc,#0x2000-17 ; for 8 KB (minus 17 bytes) 85 | ldir ; do that 86 | ld (_SMS_Port3EBIOSvalue),a ; restore contents of $c000 to SMS_Port3EBIOSvalue var 87 | 88 | ;; Initialise global variables 89 | call gsinit 90 | call _SMS_init 91 | ei ; re-enable interrupts before going to main() 92 | call _main 93 | 1$: 94 | halt 95 | jr 1$ 96 | ;-------------------------------------------------------------------------- 97 | .ascii 'devkitSMS' ; this is shameless 98 | ;-------------------------------------------------------------------------- 99 | .org 0x66 ; handle NMI 100 | jp _SMS_nmi_isr 101 | ;-------------------------------------------------------------------------- 102 | ; here is a block of 128 OUTI instructions, made for enabling 103 | ; UNSAFE but FAST short data transfers to VRAM 104 | ;-------------------------------------------------------------------------- 105 | _OUTI128:: ; _OUTI128 label points to a block of 128 OUTI and a RET 106 | .rept 32 107 | outi 108 | .endm 109 | _OUTI96:: ; _OUTI96 label points to a block of 96 OUTI and a RET 110 | .rept 32 111 | outi 112 | .endm 113 | _OUTI64:: ; _OUTI64 label points to a block of 64 OUTI and a RET 114 | .rept 32 115 | outi 116 | .endm 117 | _OUTI32:: ; _OUTI32 label points to a block of 32 OUTI and a RET 118 | .rept 32 119 | outi 120 | .endm 121 | _outi_block:: ; _outi_block label points to END of OUTI block 122 | ret 123 | ;-------------------------------------------------------------------------- 124 | ;; Ordering of segments for the linker. 125 | .area _HOME 126 | .area _CODE 127 | .area _INITIALIZER 128 | .area _GSINIT 129 | .area _GSFINAL 130 | 131 | .area _DATA 132 | .area _INITIALIZED 133 | .area _BSEG 134 | .area _BSS 135 | .area _HEAP 136 | 137 | .area _CODE 138 | .area _GSINIT 139 | gsinit:: 140 | ld bc, #l__INITIALIZER 141 | ld a, b 142 | or a, c 143 | jr Z, gsinit_next 144 | ld de, #s__INITIALIZED 145 | ld hl, #s__INITIALIZER 146 | ldir 147 | gsinit_next: 148 | .area _GSFINAL 149 | ret 150 | 151 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | *.ram 2 | *.swp 3 | *.map 4 | *.asm 5 | *.lst 6 | *.ihx 7 | *.lk 8 | *.noi 9 | *.rel 10 | *.sym 11 | -------------------------------------------------------------------------------- /examples/first_test/Makefile: -------------------------------------------------------------------------------- 1 | CC=sdcc 2 | IHX2SMS=ihx2sms 3 | DEVKITSMS_BASE=../../ 4 | SMSLIB_BASE=$(DEVKITSMS_BASE)/SMSlib 5 | SMSLIB_INCDIR=$(SMSLIB_BASE)/src 6 | PEEP_RULES=$(SMSLIB_BASE)/src/peep-rules.txt 7 | CRT0=$(DEVKITSMS_BASE)/crt0/crt0_sms.rel 8 | SMSLIB_LIB=$(SMSLIB_BASE)/SMSlib.lib # Use distributed lib 9 | #SMSLIB_LIB=$(SMSLIB_BASE)/src/SMSlib.lib # Use locally compiled lib 10 | 11 | CFLAGS=-mz80 -I$(SMSLIB_INCDIR) --peep-file $(PEEP_RULES) 12 | LDFLAGS=-mz80 --no-std-crt0 --data-loc 0xC000 13 | 14 | PROGNAME=first 15 | 16 | OBJS=main.rel 17 | 18 | all: $(PROGNAME).sms 19 | 20 | %.rel: %.c 21 | $(CC) $(CFLAGS) -c $< 22 | 23 | %.rel: %.c %.h 24 | $(CC) $(CFLAGS) -c $< 25 | 26 | $(PROGNAME).ihx: $(OBJS) 27 | $(CC) -o $@ $(LDFLAGS) $(CRT0) $(SMSLIB_LIB) $^ 28 | 29 | $(PROGNAME).sms: $(PROGNAME).ihx 30 | $(IHX2SMS) $< $@ 31 | 32 | clean: 33 | rm -f *.rel *.ihx *.asm *.sym *.lst *.noi *.lk *.map *.sms *.gg 34 | 35 | # When a linking error occurs, sdcc returns an error and make fails. However 36 | # a .ihx output file still gets created. This leads to make thinking that the .ihx 37 | # file is up to date the next time it runs... This forces linking to take place 38 | # every time make is called. 39 | .PHONY: $(PROGNAME).ihx 40 | -------------------------------------------------------------------------------- /examples/first_test/Makefile.gg: -------------------------------------------------------------------------------- 1 | CC=sdcc 2 | IHX2SMS=ihx2sms 3 | DEVKITSMS_BASE=../../ 4 | SMSLIB_BASE=$(DEVKITSMS_BASE)/SMSlib 5 | SMSLIB_INCDIR=$(SMSLIB_BASE)/src 6 | PEEP_RULES=$(SMSLIB_BASE)/src/peep-rules.txt 7 | CRT0=$(DEVKITSMS_BASE)/crt0/crt0_sms.rel 8 | #SMSLIB_LIB=$(SMSLIB_BASE)/SMSlib_GG.lib # Use distributed lib 9 | SMSLIB_LIB=$(SMSLIB_BASE)/src/SMSlib_GG.lib # Use locally compiled lib 10 | 11 | CFLAGS=-mz80 -I$(SMSLIB_INCDIR) --peep-file $(PEEP_RULES) -DTARGET_GG 12 | LDFLAGS=-mz80 --no-std-crt0 --data-loc 0xC000 13 | 14 | PROGNAME=first 15 | 16 | OBJS=main_GG.rel 17 | 18 | all: $(PROGNAME).gg 19 | 20 | %_GG.rel: %.c 21 | $(CC) $(CFLAGS) -c $< -o $@ 22 | 23 | %_GG.rel: %.c %.h 24 | $(CC) $(CFLAGS) -c $< -o $@ 25 | 26 | $(PROGNAME).ihx: $(OBJS) 27 | $(CC) -o $@ $(LDFLAGS) $(CRT0) $(SMSLIB_LIB) $^ 28 | 29 | $(PROGNAME).sms: $(PROGNAME).ihx 30 | $(IHX2SMS) $< $@ 31 | 32 | $(PROGNAME).gg: $(PROGNAME).ihx 33 | $(IHX2SMS) $< $@ 34 | 35 | clean: 36 | rm -f *.rel *.ihx *.asm *.sym *.lst *.noi *.lk *.map *.sms *.gg 37 | 38 | # When a linking error occurs, sdcc returns an error and make fails. However 39 | # a .ihx output file still gets created. This leads to make thinking that the .ihx 40 | # file is up to date the next time it runs... This forces linking to take place 41 | # every time make is called. 42 | .PHONY: $(PROGNAME).ihx 43 | -------------------------------------------------------------------------------- /examples/first_test/README.md: -------------------------------------------------------------------------------- 1 | # SMSlib first test example. 2 | 3 | For platform(s): SMS and GameGear 4 | 5 | ## Purpose 6 | 7 | Show how to: 8 | - Compile and link code with SMSlib 9 | - Clear VRAM 10 | - Set the background color to blue 11 | 12 | If you can compile this and it runs, you're good to go. 13 | 14 | ## Screenshots 15 | 16 | This example is not-interactive and the screen should look exactly like 17 | this when run: 18 | 19 | ![Expected result](./screenshots/first.png) 20 | 21 | ## Compilation 22 | 23 | The included Makefile will build the example using the pre-compilied SMSlib found in 24 | this repository. If you compiled SMSlib yourself, you can edit the Makefile to use 25 | that library instead. 26 | 27 | It is assumed that sdcc and tools such as ihx2sms are in your path. 28 | 29 | Here is a break down of what the Makefile does: 30 | 31 | Step 1: Individual source files are compiled to .rel objects using the -c option: 32 | 33 | `sdcc -mz80 -I../../SMSlib/src --peep-file ../../SMSlib/src/peep-rules.txt -c main.c` 34 | 35 | Step 2: .rel files are linked together. Here, crt0_sms.rel should come first, then the libraries, and finally 36 | the individual .rel files. The result is a .ihx file (first.ihx in this example) 37 | 38 | `sdcc -o first.ihx --no-std-crt0 --data-loc 0xC000 ../../crt0/crt0_sms.rel ../../SMSlib/src/SMSlib.lib main.rel` 39 | 40 | Step 3: The .ihx is converted to a .sms file using ihx2sms: 41 | 42 | `ihx2sms first.ihx first.sms` 43 | 44 | ### Game Gear 45 | 46 | Makefile.gg compiles for the Game Gear. There are two main differences: 47 | 48 | - TARGET_GG is defined when compiling (add -DTARGET_GG to the sdcc command-line) 49 | - SMSlib_GG.lib is used instead of SMSlib.lib 50 | 51 | -------------------------------------------------------------------------------- /examples/first_test/main.c: -------------------------------------------------------------------------------- 1 | #include "SMSlib.h" 2 | 3 | void main(void) 4 | { 5 | /* Clear VRAM */ 6 | SMS_VRAMmemsetW(0, 0x0000, 16384); 7 | 8 | /* Set background color to blue */ 9 | #ifdef TARGET_GG 10 | GG_setBGPaletteColor(0, RGBHTML(0x0000FF)); 11 | #else 12 | SMS_setBGPaletteColor(0, RGBHTML(0x0000FF)); 13 | #endif 14 | 15 | /* Turn on the display */ 16 | SMS_displayOn(); 17 | 18 | /* Do nothing */ 19 | for(;;) { } 20 | } 21 | 22 | SMS_EMBED_SEGA_ROM_HEADER(9999,0); 23 | SMS_EMBED_SDSC_HEADER_AUTO_DATE(1,0,"raphnet","first test","A first test. If you can compile this, you're good to go"); 24 | -------------------------------------------------------------------------------- /examples/first_test/screenshots/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/examples/first_test/screenshots/first.png -------------------------------------------------------------------------------- /examples/hello_sms/Makefile: -------------------------------------------------------------------------------- 1 | CC=sdcc 2 | IHX2SMS=ihx2sms 3 | DEVKITSMS_BASE=../../ 4 | SMSLIB_BASE=$(DEVKITSMS_BASE)/SMSlib 5 | SMSLIB_INCDIR=$(SMSLIB_BASE)/src 6 | PEEP_RULES=$(SMSLIB_BASE)/src/peep-rules.txt 7 | CRT0=$(DEVKITSMS_BASE)/crt0/crt0_sms.rel 8 | SMSLIB_LIB=$(SMSLIB_BASE)/SMSlib.lib # Use distributed lib 9 | #SMSLIB_LIB=$(SMSLIB_BASE)/src/SMSlib.lib # Use locally compiled lib 10 | 11 | CFLAGS=-mz80 -I$(SMSLIB_INCDIR) --peep-file $(PEEP_RULES) 12 | LDFLAGS=-mz80 --no-std-crt0 --data-loc 0xC000 13 | 14 | PROGNAME=hello 15 | 16 | OBJS=main.rel 17 | 18 | all: $(PROGNAME).sms 19 | 20 | %.rel: %.c 21 | $(CC) $(CFLAGS) -c $< 22 | 23 | %.rel: %.c %.h 24 | $(CC) $(CFLAGS) -c $< 25 | 26 | $(PROGNAME).ihx: $(OBJS) 27 | $(CC) -o $@ $(LDFLAGS) $(CRT0) $(SMSLIB_LIB) $^ 28 | 29 | $(PROGNAME).sms: $(PROGNAME).ihx 30 | $(IHX2SMS) $< $@ 31 | 32 | clean: 33 | rm -f *.rel *.ihx *.asm *.sym *.lst *.noi *.lk *.map *.sms *.gg 34 | 35 | # When a linking error occurs, sdcc returns an error and make fails. However 36 | # a .ihx output file still gets created. This leads to make thinking that the .ihx 37 | # file is up to date the next time it runs... This forces linking to take place 38 | # every time make is called. 39 | .PHONY: $(PROGNAME).ihx 40 | -------------------------------------------------------------------------------- /examples/hello_sms/README.md: -------------------------------------------------------------------------------- 1 | # SMSlib example "Hello, World!" 2 | 3 | For platform(s): SMS 4 | 5 | ## Purpose 6 | 7 | Show how to: 8 | - Compile and link code with SMSlib 9 | - Clear VRAM 10 | - Setup the automatic text renderer 11 | - Write to a location on the screen 12 | 13 | ## Screenshots 14 | 15 | This example is not-interactive and the screen should look exactly like 16 | this when run: 17 | 18 | ![Expected result](screenshots/hello.png) 19 | 20 | ## Compilation 21 | 22 | The included Makefile will build the example using the pre-compilied SMSlib found in 23 | this repository. If you compiled SMSlib yourself, you can edit the Makefile to use 24 | that library instead. 25 | 26 | It is assumed that sdcc and tools such as ihx2sms are in your path. 27 | 28 | Here is a break down of what the Makefile does: 29 | 30 | Step 1: Individual source files are compiled to .rel objects using the -c option: 31 | 32 | `sdcc -mz80 -I../../SMSlib/src --peep-file ../../SMSlib/src/peep-rules.txt -c main.c` 33 | 34 | Step 2: .rel files are linked together. Here, crt0_sms.rel should come first, then the libraries, and finally 35 | the individual .rel files. The result is a .ihx file (hello.ihx in this example) 36 | 37 | `sdcc -o hello.ihx --no-std-crt0 --data-loc 0xC000 ../../crt0/crt0_sms.rel ../../SMSlib/src/SMSlib.lib main.rel` 38 | 39 | Step 3: The .ihx is converted to a .sms file using ihx2sms: 40 | 41 | `ihx2sms hello.ihx hello.sms` 42 | 43 | -------------------------------------------------------------------------------- /examples/hello_sms/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SMSlib.h" 3 | 4 | void main(void) 5 | { 6 | /* Clear VRAM */ 7 | SMS_VRAMmemsetW(0, 0x0000, 16384); 8 | 9 | /* load a standard font character set into tiles 0-95, 10 | * set BG palette to B/W and turn on the screen */ 11 | SMS_autoSetUpTextRenderer(); 12 | 13 | /* Set the target of the next background write */ 14 | SMS_setNextTileatXY(4,10); 15 | 16 | /* printf() is available */ 17 | printf("Hello, World! [1/3]"); 18 | 19 | /* When formatting is not needed, SMS_print is faster */ 20 | SMS_setNextTileatXY(4,11); 21 | SMS_print("Hello, World! [2/3]"); 22 | 23 | /* The above (setting XY and then printing is common, so 24 | * the SMS_printatXY macro is there for convenience */ 25 | SMS_printatXY(4,12,"Hello, World! [3/3]"); 26 | 27 | /* Do nothing */ 28 | for(;;) { } 29 | } 30 | 31 | SMS_EMBED_SEGA_ROM_HEADER(9999,0); 32 | SMS_EMBED_SDSC_HEADER_AUTO_DATE(1,0,"raphnet","basic example","A simple example"); 33 | -------------------------------------------------------------------------------- /examples/hello_sms/screenshots/hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/examples/hello_sms/screenshots/hello.png -------------------------------------------------------------------------------- /folder2c/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /folder2c/Linux/folder2c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/folder2c/Linux/folder2c -------------------------------------------------------------------------------- /folder2c/Windows/folder2c.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/folder2c/Windows/folder2c.exe -------------------------------------------------------------------------------- /folder2c/src/folder2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | folder2c - creates a .c and a .h file with the contents of 3 | every binary file in a folder 4 | 5 | sverx\2015 6 | 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | FILE *fIN; 16 | FILE *fc; 17 | FILE *fh; 18 | DIR *dp; 19 | struct dirent *entry; 20 | 21 | #define BUFSIZE 16 22 | unsigned char buf[BUFSIZE]; 23 | #define SUBST_NUM 4 24 | char *subst[SUBST_NUM]={" ",".","(",")"}; 25 | 26 | char paramshift=0; 27 | bool verbose=false; 28 | 29 | void cleanstr(char *str) { 30 | int i; 31 | for (i=0;i5) { 47 | printf("Usage: folder2c [-v] folder outfilename [bank number]\n"); 48 | printf("creates outfilename.c and outfilename.h with contents of every\nfile found in folder.\n"); 49 | printf("-v : verbose\n"); 50 | return(1); 51 | } 52 | 53 | if (strcmp("-v",argv[1])==0) { 54 | verbose=true; 55 | paramshift=1; 56 | printf("Info: verbose mode; will print file names while converting.\n"); 57 | } 58 | 59 | 60 | if ((argc+paramshift)==4) { 61 | bank_num=atoi(argv[3+paramshift]); 62 | if (bank_num<=0) { 63 | printf("Fatal: invalid bank number\n"); 64 | return(1); 65 | } 66 | } 67 | 68 | dp = opendir(argv[1+paramshift]); 69 | if (dp == NULL) { 70 | printf("Fatal: can't open %s folder\n",argv[1+paramshift]); 71 | return (1); 72 | } 73 | 74 | cname=malloc(strlen(argv[2+paramshift])+3); 75 | hname=malloc(strlen(argv[2+paramshift])+3); 76 | 77 | sprintf(cname,"%s.c",argv[2+paramshift]); 78 | sprintf(hname,"%s.h",argv[2+paramshift]); 79 | 80 | fc=fopen(cname,"w"); 81 | if (!fc) { 82 | printf("Fatal: can't open output %s.c file\n",argv[2+paramshift]); 83 | return(1); 84 | } 85 | 86 | fh=fopen(hname,"w"); 87 | if (!fh) { 88 | printf("Fatal: can't open output %s.h file\n",argv[2+paramshift]); 89 | return(1); 90 | } 91 | 92 | while ((entry=readdir(dp))) { 93 | if (entry->d_type==DT_REG) { 94 | 95 | clean=malloc(strlen(entry->d_name)+1); 96 | strcpy(clean,entry->d_name); 97 | cleanstr(clean); 98 | 99 | iname=malloc(strlen(argv[1+paramshift])+strlen(entry->d_name)+2); 100 | sprintf(iname,"%s/%s",argv[1+paramshift],entry->d_name); 101 | 102 | if (verbose) 103 | printf("Info: converting %s ...\n",entry->d_name); 104 | 105 | fIN=fopen(iname,"rb"); 106 | if (!fc) { 107 | printf("Fatal: can't open %s\n",entry->d_name); 108 | return(1); 109 | } 110 | 111 | fprintf (fc,"const unsigned char %s[] = {\n",clean); 112 | 113 | size=0; 114 | while (!feof(fIN)) { 115 | cnt=fread (buf, 1, BUFSIZE, fIN); 116 | if ((size!=0) && (cnt!=0)) 117 | fprintf (fc,",\n"); 118 | size+=cnt; 119 | for (i=0;i 25 | 26 | -------------------------------------------------------------------------------- /ihx2sms/Linux/ihx2sms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/ihx2sms/Linux/ihx2sms -------------------------------------------------------------------------------- /ihx2sms/README.md: -------------------------------------------------------------------------------- 1 | ihx2sms 2 | ======= 3 | 4 | 'broken' ihx converter for multibank SEGA Master System / SEGA Game Gear ROMs 5 | 6 | 'broken' means that the program it's actually assuming that each new declaration of data at address 0x8000 informs that we have to allocate a new ROM bank in the final binary file 7 | 8 | ``` 9 | ihx2sms [-m file.map] [-pm|-pp] infile.ihx outfile.sms 10 | ``` 11 | 12 | First parameter is the input IHX ([Intel Hex](https://en.wikipedia.org/wiki/Intel_HEX)) file, that is SDCC output. Second parameter is generated output ROM file. 13 | 14 | The size of the ROM will be a multiple of 16KB. The utility also calculates the ROM checksum for the output file if the SEGA header has been included in your program. 15 | 16 | Optional parameters: 17 | 18 | ```-m file.map``` : you can specify a map file where the order of segment is listed. You shouldn't need this, unless you're totally sure of what you're doing. 19 | 20 | ```-pm ``` : output ROM file will be padded to size that is a multiple of 64KB. So output file size would be either 64KB or 128KB or 192KB or 256KB or 320KB... and so on. 21 | 22 | ```-pp ``` : output ROM file will be padded to size that is an exact power of 2. So output file size would be either 16KB or 32KB or 64KB or 128KB or 256KB... and so on. 23 | 24 | 25 | -------------------------------------------------------------------------------- /ihx2sms/Windows/ihx2sms.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/ihx2sms/Windows/ihx2sms.exe -------------------------------------------------------------------------------- /makesms/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /makesms/Linux/makesms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/makesms/Linux/makesms -------------------------------------------------------------------------------- /makesms/README.md: -------------------------------------------------------------------------------- 1 | makesms 2 | ======= 3 | 4 | IHX converter to BINary Master System / SEGA Game Gear ROMs 5 | 6 | ``` 7 | makesms [options] infile.ihx outfile.sms 8 | ``` 9 | 10 | First parameter is the input IHX ([Intel Hex](https://en.wikipedia.org/wiki/Intel_HEX)) file, that is SDCC output. Second parameter is generated output ROM file. 11 | 12 | The size of the ROM will be a multiple of 16 KiB. The utility also calculates the ROM checksum for the output file if the SEGA header has been included in your program. 13 | 14 | Optional parameters: 15 | 16 | ```-pm ``` : output ROM file will be padded to size that is a multiple of 64 KiB. So output file size would be either 64 KiB or 128 KiB or 192 KiB or 256 KiB or 320 KiB... and so on. 17 | 18 | ```-pp ``` : output ROM file will be padded to size that is an exact power of 2. So output file size would be either 16 KiB or 32 KiB or 64 KiB or 128 KiB or 256 KiB... and so on. 19 | 20 | ```-emptyfill value``` : Specify the byte value to be used for filling unused areas of the ROM. Default: 0x00 21 | 22 | ```-mbin file:src:len:dst``` : Merge contents of binary file into ROM before updating header and checksum. Offsets and length expressed in bytes. 23 | 24 | ```-mbank file:src:banks:dst``` : Merge contents of binary file into ROM before updating header and checksum. Offsets and length expressed in banks. (blocks of 16kB) 25 | 26 | -------------------------------------------------------------------------------- /makesms/Windows/makesms.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sverx/devkitSMS/1d65541a11800aa688d8649c4a393282717e2e5f/makesms/Windows/makesms.exe -------------------------------------------------------------------------------- /makesms/src/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | LD=$(CC) 3 | CFLAGS=-Wall -O1 4 | LDFLAGS= 5 | 6 | all: makesms 7 | 8 | makesms: makesms.o 9 | $(LD) $(LDFLAGS) -o $@ $^ 10 | --------------------------------------------------------------------------------