Last active
October 29, 2025 08:59
-
-
Save samneggs/1e5ae813fa86de75f0c380c3c5f40444 to your computer and use it in GitHub Desktop.
Space Invaders game on Pi Pico in MicroPython
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from time import sleep, ticks_us, ticks_diff, ticks_ms, sleep_ms | |
| import gc | |
| import _thread, array | |
| from machine import Timer, Pin, PWM | |
| from sys import exit | |
| class Game_Sound: | |
| def __init__(self): | |
| # index,start,dur,pause,number, volume | |
| self.SPIDER_TUNE = array.array('I',(5,0, 31,71,10,12,500,550,800,10000,500,550,800,10000,800,500,550)) # 24,60 | |
| self.EXPLODE2_TUNE= array.array('I',(5,0,100, 0, 5,7,100,90,80,70,60,60)) | |
| self.EXPLODE_TUNE = array.array('I',(5,0,41, 0, 5, 10,1400,1300,1400,1300,1400,1450)) | |
| self.BACK_TUNE = array.array('I',(5,0,120,800, 3,10,147,131,117,110)) # 5,0, 21, 21,8,10 | |
| self.FIRE_TUNE = array.array('I',(5,0,11,21, 4,10,1000,2300,1000,2300,1000)) | |
| self.SOUND = 0 | |
| self.OFF = 0 | |
| self.pwm = PWM(Pin(17)) | |
| Pin(16,Pin.OUT).high() | |
| self.pwm.duty_u16(1<<12) | |
| def reset_fire(self): | |
| self.BACK_TUNE[0] = 6 | |
| @micropython.viper | |
| def callback1(self): | |
| if self.OFF: return | |
| sound = int(self.SOUND) | |
| if sound & 1<<1: | |
| tune = ptr32(self.EXPLODE2_TUNE) | |
| elif sound & 1<<3: | |
| tune = ptr32(self.FIRE_TUNE) | |
| elif sound & 1<<2: | |
| tune = ptr32(self.EXPLODE_TUNE) | |
| elif sound & 1<<0: | |
| tune = ptr32(self.BACK_TUNE) | |
| else: | |
| self.pwm.duty_u16(0) | |
| return | |
| index = tune[0] | |
| start_ms = tune[1] | |
| dur = tune[2] | |
| pause = tune[3] | |
| number = tune[4] | |
| volume = tune[5] | |
| now_ms = int(ticks_ms()) | |
| if now_ms - start_ms < dur: # or start_ms == 0: | |
| self.pwm.duty_u16(1<<volume) | |
| if tune[index] >=50: # not too low freq | |
| self.pwm.freq(tune[index]) | |
| else: | |
| self.pwm.duty_u16(0) | |
| elif now_ms - start_ms < pause: | |
| self.pwm.duty_u16(0) | |
| else: | |
| tune[0] += 1 | |
| if tune[0] > number+6: | |
| tune[0] = 5 | |
| if not(sound & 1<<0) or 1: | |
| self.SOUND = 1<<0 | |
| else: | |
| tune[1] = int(ticks_ms()) # reset time | |
| def deinit(self): | |
| self.pwm.duty_u16(0) | |
| self.SOUND = 0 | |
| #self.timer1.deinit() | |
| @micropython.viper | |
| def core1(): | |
| global EXIT, GAME_SOUND | |
| GAME_SOUND = Game_Sound() | |
| GAME_SOUND.OFF = 0 | |
| while not EXIT: | |
| GAME_SOUND.callback1() | |
| sleep_ms(10) | |
| print('Core1 Stop') | |
| if __name__=='__main__': | |
| EXIT = False | |
| _thread.start_new_thread(core1, ()) | |
| sleep_ms(500) | |
| GAME_SOUND.SOUND = 0 | |
| for loop in range(3): | |
| GAME_SOUND.SOUND = 1<<1 | |
| sleep_ms(1000) | |
| #sleep(2) | |
| GAME_SOUND.deinit() | |
| exit() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Convert Program | |
| # Generated bytearray from: Space Invaders.bin | |
| # Total size: 3588 bytes | |
| binary_data = bytearray([ | |
| 0x04, 0x40, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
| 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, | |
| 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 0x00, 0x00, 0x00, 0x00 | |
| ]) | |
| with open ('Space Invaders.bin', "w") as file: | |
| file.write(binary_data) | |
| file.close() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| b = bytearray([ | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0x00, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0x00, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0xff, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0xff, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0xff, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0xff, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0xff, 0x00, | |
| 0x00, 0xff, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0xff, 0xff, 0x00, | |
| 0x00, 0xff, 0xff, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0xff, | |
| 0xff, 0xff, 0x00, | |
| 0x00, 0xff, 0x00, | |
| 0x00, 0xff, 0x00]) | |
| with open ('s_inv_miss.bin', "w") as file: | |
| file.write(b) | |
| file.close() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Space Invaders | |
| from lcd_1_8 import LCD_1inch8 | |
| import machine | |
| from machine import Pin, PWM | |
| from uctypes import addressof | |
| from time import sleep, ticks_us, ticks_diff, ticks_ms, sleep_ms | |
| import gc, _thread, array | |
| from sys import exit | |
| from micropython import const | |
| from random import randint | |
| from math import sin,cos,tan,radians,sqrt | |
| #from rp2 import bootsel_button as RESET_PB | |
| from invaders_sound import Game_Sound | |
| with open ('Space Invaders.bin', "rb") as file: | |
| SPRITES = file.read() | |
| file.close() | |
| with open ('s_inv_miss.bin', "rb") as file: | |
| MISS_SPR = file.read() | |
| file.close() | |
| MAXSCREEN_X = const(160) | |
| MAXSCREEN_Y = const(128) | |
| SCALE = const(13) | |
| COLUMNS = const(10) | |
| S_WIDTH = const(16) | |
| S_HEIGHT = const(8) | |
| NUM_BUNKERS = const(4) | |
| NUM_MISSILES = const(3) | |
| BUNKER_Y = const(100) | |
| PLAYER_Y = const(119) | |
| START_SPEED = const(200) | |
| SPEEDUP =const(4) | |
| BUNKER_HEIGHT = const(16) | |
| PLAYER_PARAMS = const(10) | |
| # X,Y | |
| FIRE = const(2) | |
| HIT = const(3) | |
| INVADER_PARAMS = const(10) | |
| X = const(0) | |
| Y = const(1) | |
| DIR = const(2) | |
| LEFT = const(3) | |
| RIGHT = const(4) | |
| BOTTOM = const(5) | |
| COUNT = const(6) | |
| MISSILE_PARAMS = const(10) | |
| #X,Y,DIR | |
| M_SPRITE = const(3) | |
| M_SPRITE2 = const(4) | |
| GAME_PARAMS = const(10) | |
| FPS = const(0) | |
| LIVES = const(1) | |
| SPEED = const(2) | |
| TOGGLE = const(3) | |
| TIME = const(4) | |
| BUNKERS= const(5) | |
| SCORE = const(6) | |
| SCORE_MAP = bytearray([30,20,20,10,10]) | |
| EXP_MAP=array.array('b',( | |
| 0,0,1,0,0,0, | |
| 1,0,0,0,1,0, | |
| 0,0,1,1,0,1, | |
| 0,1,1,1,1,0, | |
| 1,0,1,1,1,0, | |
| 0,1,1,1,1,1, | |
| 1,0,1,1,1,0, | |
| 0,1,0,1,0,1)) | |
| char_map=array.array('b',( | |
| 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00, # U+0030 (0) | |
| 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00, # U+0031 (1) | |
| 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00, # U+0032 (2) | |
| 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00, # U+0033 (3) | |
| 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00, # U+0034 (4) | |
| 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00, # U+0035 (5) | |
| 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00, # U+0036 (6) | |
| 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00, # U+0037 (7) | |
| 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00, # U+0038 (8) | |
| 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00)) # U+0039 (9) | |
| @micropython.viper | |
| def show_num_viper(num:int,x_offset:int,y_offset:int,color:int): | |
| char_ptr = ptr8(char_map) | |
| screen_ptr = ptr16(LCD.buffer) | |
| size = 1 # 1,2,3 | |
| char = 0 | |
| offset = MAXSCREEN_X*y_offset+x_offset | |
| while num > 0: | |
| total = num//10 | |
| digit = num - (total * 10) | |
| num = total | |
| for y in range(8): | |
| row_data = char_ptr[digit*8+y] | |
| for x in range(8): | |
| if row_data & (1<<x) > 0: | |
| addr = size*y*MAXSCREEN_X+x-(char*8)+offset | |
| screen_ptr[addr] = color | |
| if size>1: | |
| screen_ptr[MAXSCREEN_X+addr] = color | |
| if size>2: | |
| screen_ptr[2*MAXSCREEN_X+addr] = color | |
| char += 1 | |
| def init_pot(): | |
| global POT_X,POT_Y,POT_X_ZERO,POT_Y_ZERO | |
| POT_X = machine.ADC(27) | |
| POT_Y = machine.ADC(26) | |
| POT_X_ZERO = 0 | |
| POT_Y_ZERO = 0 | |
| for i in range(1000): | |
| POT_X_ZERO += POT_X.read_u16() | |
| POT_Y_ZERO += POT_Y.read_u16() | |
| POT_X_ZERO = POT_X_ZERO//1000 | |
| POT_Y_ZERO = POT_Y_ZERO//1000 | |
| pot_scale = 12 | |
| @micropython.viper | |
| def read_pot(): | |
| player = ptr32(PLAYER) | |
| missile = ptr32(MISSILE) | |
| pot_scale = 12 | |
| x_inc = int(POT_X.read_u16() - POT_X_ZERO)>>pot_scale | |
| y_inc = int(POT_Y.read_u16() - POT_Y_ZERO)>>pot_scale | |
| x_inc += 2 | |
| if x_inc < 2 and x_inc > -2: | |
| x_inc=0 | |
| if not FIRE_BUTTON.value(): | |
| player[FIRE] = 1 | |
| if missile[Y] == 0: | |
| if int(GAME_SOUND.SOUND) & 1<<3 == 0: | |
| GAME_SOUND.SOUND = int(GAME_SOUND.SOUND) | 1<<3 | |
| missile[Y] = PLAYER_Y-1 | |
| missile[X] = player[X] + 8 | |
| x = player[X] - x_inc//4 | |
| if x > 0 and x < 145: | |
| player[X] = x | |
| def init_invaders(): | |
| global INVADERS, ALIVE, FIRE_INV | |
| INVADERS = array.array('i',0 for _ in range(INVADER_PARAMS)) | |
| ALIVE = bytearray(5 * COLUMNS) # 3 = alive, 2 and 1 = exploding | |
| FIRE_INV = bytearray(11) # bottom invaders that can fire | |
| def init_player(): | |
| global PLAYER, MISSILE | |
| PLAYER = array.array('i',0 for _ in range(PLAYER_PARAMS)) | |
| MISSILE = array.array('i',0 for _ in range(MISSILE_PARAMS*3)) | |
| MISSILE[DIR] = -2 # player missile direction and speed | |
| MISSILE[DIR+MISSILE_PARAMS] = 1 # invader missile #1 dir and speed | |
| MISSILE[DIR+MISSILE_PARAMS*2] = 1 # invader missile #2 | |
| PLAYER[HIT] = 0 # 0=alive, 2,1 = exploding | |
| def init_game(): | |
| global GAME, FPS_ARRY | |
| GAME = array.array('i',0 for _ in range(GAME_PARAMS)) | |
| FPS_ARRY = bytearray(35) | |
| GAME[FPS] = 0 | |
| GAME[LIVES] = 3 | |
| def init_bunker(): | |
| global BUNKER | |
| BUNKER = bytearray(160*20) # 16 | |
| def reset_bunker(): | |
| for b in range(NUM_BUNKERS): | |
| for y in range(0,5): | |
| for x in range(5-y,17+y): | |
| BUNKER[y*MAXSCREEN_X+x+b*40+10] = 1 | |
| for y in range(5,16): | |
| for x in range(22): | |
| BUNKER[y*MAXSCREEN_X+x+b*40+10] = 1 | |
| for y in range(11,16): | |
| for x in range(19-y,3+y): | |
| BUNKER[y*MAXSCREEN_X+x+b*40+10] = 0 | |
| def reset_invaders(): | |
| for i in range(5 * COLUMNS): | |
| ALIVE[i] = 3 | |
| INVADERS[X] = 2 | |
| INVADERS[Y] = 0 | |
| INVADERS[DIR] = 1 | |
| INVADERS[COUNT] = 5 * COLUMNS | |
| GAME[TIME] = START_SPEED | |
| GAME[BUNKERS] = 1 | |
| @micropython.viper | |
| def move(): | |
| player = ptr32(PLAYER) | |
| game = ptr32(GAME) | |
| invaders = ptr32(INVADERS) | |
| alive = ptr8(ALIVE) | |
| if player[HIT] == 0: | |
| game[TOGGLE] ^= 1 | |
| invaders[X] += invaders[DIR] | |
| right_most = (COLUMNS * 14) - (invaders[RIGHT] * 14) | |
| left_most = invaders[LEFT] * 14 | |
| bottom_most = (3+invaders[BOTTOM]) * 10 + invaders[Y]//MAXSCREEN_X | |
| if invaders[X] > right_most or invaders[X]+left_most < 1 : # edge of screen, move down | |
| invaders[DIR] *= -1 | |
| invaders[Y] += 4*MAXSCREEN_X | |
| if bottom_most > BUNKER_Y+8: | |
| game[BUNKERS] = 0 | |
| if bottom_most > 130: | |
| game[LIVES] -= 1 | |
| reset_invaders() | |
| for i in range(5 * COLUMNS): # invader explosions | |
| if alive[i] < 3 and alive[i] > 0: | |
| alive[i] -= 1 | |
| if player[HIT] > 0: # player explosion | |
| player[HIT] -= 1 | |
| if player[HIT] == 0: | |
| game[LIVES] -= 1 | |
| if game[LIVES] == 0: | |
| game_over() | |
| @micropython.viper | |
| def move_missiles(): | |
| missile = ptr32(MISSILE) | |
| player = ptr32(PLAYER) | |
| for index in range(NUM_MISSILES): | |
| i = index * MISSILE_PARAMS | |
| if missile[Y + i] > 0 and missile[Y + i] < MAXSCREEN_Y-7: | |
| missile[Y + i] += missile[DIR + i] # move missile up or down | |
| miss_collision() | |
| missile[M_SPRITE + i] += 1 | |
| if missile[M_SPRITE + i] > 3*4: | |
| missile[M_SPRITE + i] = 0 | |
| elif i==0: | |
| player[FIRE] = 1 | |
| else: | |
| missile[Y + i] = 0 # clear missile from bottom | |
| @micropython.viper | |
| def miss_collision(): | |
| player = ptr32(PLAYER) | |
| missile = ptr32(MISSILE) | |
| invaders = ptr32(INVADERS) | |
| alive = ptr8(ALIVE) | |
| game = ptr32(GAME) | |
| bunker = ptr8(BUNKER) | |
| m_x = missile[X] | |
| m_y = missile[Y] | |
| inv_x = invaders[X] | |
| inv_y = invaders[Y] // MAXSCREEN_X | |
| for i in range(5 * COLUMNS): # check missile vs invaders | |
| if alive[i] == 3: | |
| i_x = (i % COLUMNS)*14 + inv_x | |
| i_y = (i // COLUMNS)*10 + inv_y + 10 | |
| if m_x > i_x and m_x < i_x + 14 and m_y > i_y and m_y < i_y + 14: | |
| GAME_SOUND.SOUND = int(GAME_SOUND.SOUND) | 1<<2 | |
| game[SCORE] += int(SCORE_MAP[i // COLUMNS]) | |
| player[FIRE] = 0 | |
| missile[Y] = 0 | |
| alive[i] -= 1 | |
| get_edges() | |
| game[TIME] -= SPEEDUP | |
| GAME_SOUND.BACK_TUNE[3] = 200 + game[TIME]*3 # 800 max | |
| invaders[COUNT] -= 1 | |
| if invaders[COUNT] == 0: | |
| reset_invaders() | |
| reset_bunker() | |
| p_x = player[X] | |
| p_y = PLAYER_Y | |
| pm_x = missile[X] # player missile | |
| pm_y = missile[Y] | |
| for index in range(1,NUM_MISSILES-1): | |
| i = index * MISSILE_PARAMS | |
| m_x = missile[X + i] | |
| m_y = missile[Y + i] | |
| if m_y > 0 and m_x > p_x and m_x < p_x + 16 and m_y > p_y and m_y < p_y + 8: # invader missile vs player | |
| missile[Y + i] = 0 | |
| player[HIT] = 10 #2 | |
| GAME_SOUND.SOUND = 1<<1 | |
| break | |
| if game[BUNKERS] == 1 and m_y >= BUNKER_Y and m_y < BUNKER_Y + 22: # invader missile vs bunker | |
| b_y = m_y-BUNKER_Y | |
| if bunker[b_y * MAXSCREEN_X + m_x] == 1: | |
| missile[Y + i] = 0 | |
| bunker_exp(m_x,b_y+2) | |
| if m_y > 0 and pm_y > 0 and m_x > pm_x and m_x < pm_x + 3 and m_y > pm_y and m_y < pm_y + 7: # invader missile vs player missile | |
| missile[Y + i] = 0 | |
| missile[Y] = 0 | |
| if game[BUNKERS] == 1 and pm_y >= BUNKER_Y and pm_y < BUNKER_Y + 22 and pm_x > 9: # player missile vs bunker | |
| b_y = pm_y-BUNKER_Y | |
| if bunker[b_y * MAXSCREEN_X + pm_x] == 1 or bunker[(b_y+1) * MAXSCREEN_X + pm_x] == 1 : | |
| missile[Y] = 0 | |
| bunker_exp(pm_x,b_y+2) | |
| @micropython.viper | |
| def bunker_exp(e_x:int,e_y:int): | |
| bunker = ptr8(BUNKER) | |
| exp_map= ptr8(EXP_MAP) | |
| for y in range(-4,4): | |
| for x in range(-3,3): | |
| bunk_addr = (e_y + y) * MAXSCREEN_X + e_x + x | |
| exp = exp_map[(y+4)*8 + x + 3] | |
| if exp == 1 and bunk_addr > 0 and bunk_addr < MAXSCREEN_X * 16: | |
| bunker[bunk_addr] = 0 | |
| @micropython.viper | |
| def get_edges(): | |
| game = ptr32(GAME) | |
| invaders = ptr32(INVADERS) | |
| alive = ptr8(ALIVE) | |
| fire_inv = ptr8(FIRE_INV) | |
| invaders[RIGHT] = 0 | |
| invaders[LEFT] = 10 | |
| invaders[BOTTOM] = 0 | |
| for i in range(5 * COLUMNS): | |
| if alive[i] == 3: | |
| x = i % COLUMNS | |
| y = i // COLUMNS | |
| if x > invaders[RIGHT]: invaders[RIGHT] = x | |
| if x < invaders[LEFT]: invaders[LEFT] = x | |
| if y > invaders[BOTTOM]: invaders[BOTTOM] = y | |
| for x in range(COLUMNS): # find the bottom invaders that can fire | |
| fire_inv[x] = 0 | |
| for y in range(5): | |
| if alive[y * COLUMNS + x] == 3: | |
| fire_inv[x] = y + 1 | |
| @micropython.viper | |
| def invaders_fire(): | |
| invaders = ptr32(INVADERS) | |
| missile = ptr32(MISSILE) | |
| fire_inv = ptr8(FIRE_INV) | |
| for index in range(1,NUM_MISSILES): | |
| i = index * MISSILE_PARAMS | |
| if missile[Y + i] > 0 and missile[Y + i] < MAXSCREEN_Y: continue | |
| firing_invader = int(randint(0,COLUMNS)) | |
| while fire_inv[firing_invader] == 0: # find random bottom invader | |
| firing_invader += 1 | |
| if firing_invader > COLUMNS: firing_invader = 0 # loop around | |
| missile[Y + i] = invaders[Y]//MAXSCREEN_X + fire_inv[firing_invader] * 8 + 10 | |
| missile[X + i] = invaders[X] + firing_invader * 14 + 7 | |
| missile[M_SPRITE2 + i] = int(randint(0,2))*4 # start sprite 0,4,8 | |
| missile[M_SPRITE + i] = 0 | |
| return | |
| @micropython.viper | |
| def draw_invaders(): | |
| sprites = ptr16(SPRITES) | |
| screen = ptr16(LCD.buffer) | |
| invaders = ptr32(INVADERS) | |
| game = ptr32(GAME) | |
| alive = ptr8(ALIVE) | |
| sprite_offset = 2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| screen_offset = invaders[Y]+10*MAXSCREEN_X + invaders[X] | |
| for x1 in range(COLUMNS): | |
| test_alive = alive[x1] | |
| if test_alive > 0: | |
| if test_alive < 3: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*5 + (test_alive)*8*S_WIDTH | |
| else: | |
| sprite_offset = 2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y*MAXSCREEN_X + x+x1*14+screen_offset] = color | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| screen_offset = invaders[Y]+20*MAXSCREEN_X + invaders[X] | |
| for y1 in range(2): | |
| for x1 in range(COLUMNS): | |
| test_alive = alive[(y1+1)*COLUMNS + x1] | |
| if test_alive > 0: | |
| if test_alive < 3: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*5 + (test_alive)*8*S_WIDTH | |
| else: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y1*10*MAXSCREEN_X+y*MAXSCREEN_X + x+x1*14+screen_offset] = color | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*4 + game[TOGGLE]*8*S_WIDTH | |
| screen_offset = invaders[Y]+40*MAXSCREEN_X + invaders[X] | |
| for y1 in range(2): | |
| for x1 in range(COLUMNS): | |
| test_alive = alive[(y1+3)*COLUMNS + x1] | |
| if test_alive > 0: | |
| if test_alive < 3: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*5 + (test_alive)*8*S_WIDTH | |
| else: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*4 + game[TOGGLE]*8*S_WIDTH | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y1*10*MAXSCREEN_X+y*MAXSCREEN_X + x+x1*14+screen_offset] = color | |
| @micropython.viper | |
| def draw_player(): | |
| sprites = ptr16(SPRITES) | |
| screen = ptr16(LCD.buffer) | |
| invaders = ptr32(INVADERS) | |
| player = ptr32(PLAYER) | |
| game = ptr32(GAME) | |
| if player[HIT] > 0: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*(11+(player[HIT]%2)) | |
| else: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*11 | |
| screen_offset = MAXSCREEN_X * PLAYER_Y + player[X] | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y*MAXSCREEN_X + x+screen_offset] = color | |
| @micropython.viper | |
| def draw_bunker(): | |
| game = ptr32(GAME) | |
| bunker = ptr8(BUNKER) | |
| screen = ptr16(LCD.buffer) | |
| if not game[BUNKERS]: return | |
| screen_offset = MAXSCREEN_X*BUNKER_Y | |
| for y in range(BUNKER_HEIGHT): | |
| for x in range(MAXSCREEN_X): | |
| color = bunker[y*MAXSCREEN_X+x] | |
| if color > 0: | |
| screen[screen_offset + y * MAXSCREEN_X + x] = 0xe007 | |
| @micropython.viper | |
| def draw_missile(): | |
| missile = ptr32(MISSILE) | |
| screen = ptr16(LCD.buffer) | |
| miss_spr = ptr8(MISS_SPR) | |
| for index in range(1,NUM_MISSILES): # invader missiles | |
| i = index * MISSILE_PARAMS | |
| if missile[Y + i] > 0 and missile[Y + i] < MAXSCREEN_Y: | |
| x = missile[X + i] | |
| y = missile[Y + i] | |
| offset = missile[M_SPRITE2 + i] + (missile[M_SPRITE + i] // 4) | |
| for y1 in range(7): | |
| for x1 in range(3): | |
| miss_addr = y1 * 3 + x1 + (offset * 3 * 7) | |
| if miss_spr[miss_addr] == 0xff: | |
| screen[(y+y1) * 160 + x + x1] = 0xffff | |
| if missile[Y] > 0: # player missile | |
| x = missile[X] | |
| y = missile[Y] | |
| LCD.line(x,y,x,y+7,0xffff) | |
| def game_over(): | |
| GAME_SOUND.SOUND = 0 | |
| LCD.text('GAME OVER',40,50,0xff) | |
| LCD.show() | |
| exit() | |
| @micropython.viper | |
| def draw(): | |
| draw_invaders() | |
| draw_player() | |
| draw_bunker() | |
| draw_missile() | |
| game = ptr32(GAME) | |
| if game[SCORE] == 0: | |
| LCD.text('FPS',0,80,0xff) | |
| show_num_viper(game[FPS],40,80,0xff) | |
| if game[SCORE] == 10 : | |
| LCD.text('FREE MEM',0,90,0xff) | |
| show_num_viper(gc.mem_free(),120,90,0xff) | |
| LCD.text('SCORE',0,0,0xff) | |
| show_num_viper(game[SCORE],70,0,0xff) | |
| LCD.text('LIVES',100,0,0xff) | |
| show_num_viper(game[LIVES],145,0,0xff) | |
| LCD.show() | |
| LCD.rect(0,0,MAXSCREEN_X,MAXSCREEN_Y,0,1) | |
| @micropython.asm_thumb | |
| def avg_fps_asm(r0,r1): # r0 = fps[] , r1 = current_fps | |
| ldrb(r2,[r0,0]) # r2 = fps[0] | |
| add(r2,r2,1) # fps[0] += 1 | |
| cmp(r2,33) | |
| blt(LT_32) # if fps[0] > 32: | |
| mov(r2,1) | |
| label(LT_32) | |
| strb(r2,[r0,0]) # fps[0] = new index | |
| add(r2,r2,r0) | |
| strb(r1,[r2,0]) # fps[fps[0]] = current_fps | |
| mov(r2,1) # r2 = i | |
| mov(r3,0) # r3 = tot | |
| label(LOOP) | |
| add(r0,r0,1) | |
| ldrb(r4,[r0,0]) # r4 = fps[i] | |
| add(r3,r3,r4) # tot += fps[i] | |
| add(r2,r2,1) | |
| cmp(r2,33) #33 | |
| blt(LOOP) | |
| asr(r0,r3,5) | |
| @micropython.viper | |
| def core1(): | |
| global EXIT, GAME_SOUND | |
| GAME_SOUND = Game_Sound() | |
| GAME_SOUND.OFF = 0 | |
| while not EXIT: | |
| GAME_SOUND.callback1() | |
| sleep_ms(10) | |
| @micropython.viper | |
| def main(): | |
| init_pot() | |
| init_game() | |
| init_player() | |
| init_invaders() | |
| init_bunker() | |
| reset_bunker() | |
| reset_invaders() | |
| get_edges() | |
| game = ptr32(GAME) | |
| pot_ticks = 0 | |
| move_ticks = 0 | |
| inv_fire_ticks = 0 | |
| GAME_SOUND.SOUND = 1<<0 | |
| while not EXIT: # and not RESET_PB(): | |
| gticks = int(ticks_ms()) | |
| sleep(0.001) | |
| if gticks > pot_ticks + 10: | |
| pot_ticks = gticks | |
| read_pot() | |
| if gticks > move_ticks + game[TIME] and 1: | |
| move_ticks = gticks | |
| move() | |
| if gticks > inv_fire_ticks + game[TIME]*10: | |
| inv_fire_ticks = gticks | |
| invaders_fire() | |
| move_missiles() | |
| draw() | |
| game[FPS] = int(avg_fps_asm(FPS_ARRY,1_000//int(ticks_diff(ticks_ms(),gticks)))) | |
| def shutdown(): | |
| global EXIT | |
| EXIT = True | |
| Pin(16,Pin.OUT).low() # buzzer off | |
| pwm.deinit() | |
| Pin(13,Pin.OUT).low() # screen off | |
| gc.collect() | |
| print(gc.mem_free()) | |
| print('Core0 Stop') | |
| exit() | |
| if __name__=='__main__': | |
| FIRE_BUTTON = Pin(22, Pin.IN, Pin.PULL_UP) | |
| #machine.freq(200_000_000) | |
| #machine.mem32[0x40008048] = 1<<11 # enable peri_ctrl clock | |
| machine.freq(220_000_000) #220 | |
| machine.mem32[0x40010048] = 1<<11 # enable peri_ctrl clock | |
| pwm = PWM(Pin(13)) | |
| pwm.freq(1000) | |
| pwm.duty_u16(0x8fff)#max 0xffff | |
| LCD = LCD_1inch8() | |
| LCD.fill(0) | |
| LCD.show() | |
| EXIT = False | |
| _thread.start_new_thread(core1, ()) | |
| #main() | |
| try: | |
| main() | |
| shutdown() | |
| except KeyboardInterrupt : | |
| shutdown() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Space Invaders | |
| from lcd_1_8 import LCD_1inch8 | |
| import machine | |
| from machine import Pin, PWM | |
| from uctypes import addressof | |
| from time import sleep, ticks_us, ticks_diff, ticks_ms, sleep_ms | |
| import gc, _thread, array | |
| from sys import exit | |
| from micropython import const | |
| from random import randint | |
| from math import sin,cos,tan,radians,sqrt | |
| from rp2 import bootsel_button as RESET_PB | |
| from invaders_sound import Game_Sound | |
| with open ('Space Invaders.bin', "rb") as file: | |
| SPRITES = file.read() | |
| file.close() | |
| with open ('s_inv_miss.bin', "rb") as file: | |
| MISS_SPR = file.read() | |
| file.close() | |
| MAXSCREEN_X = const(160) | |
| MAXSCREEN_Y = const(128) | |
| SCALE = const(13) | |
| COLUMNS = const(10) | |
| S_WIDTH = const(16) | |
| S_HEIGHT = const(8) | |
| NUM_BUNKERS = const(4) | |
| NUM_MISSILES = const(3) | |
| BUNKER_Y = const(100) | |
| PLAYER_Y = const(119) | |
| START_SPEED = const(200) | |
| SPEEDUP =const(4) | |
| BUNKER_HEIGHT = const(16) | |
| PLAYER_PARAMS = const(10) | |
| # X,Y | |
| FIRE = const(2) | |
| HIT = const(3) | |
| INVADER_PARAMS = const(10) | |
| X = const(0) | |
| Y = const(1) | |
| DIR = const(2) | |
| LEFT = const(3) | |
| RIGHT = const(4) | |
| BOTTOM = const(5) | |
| COUNT = const(6) | |
| MISSILE_PARAMS = const(10) | |
| #X,Y,DIR | |
| M_SPRITE = const(3) | |
| M_SPRITE2 = const(4) | |
| GAME_PARAMS = const(10) | |
| FPS = const(0) | |
| LIVES = const(1) | |
| SPEED = const(2) | |
| TOGGLE = const(3) | |
| TIME = const(4) | |
| BUNKERS= const(5) | |
| SCORE = const(6) | |
| SCORE_MAP = bytearray([30,20,20,10,10]) | |
| EXP_MAP=array.array('b',( | |
| 0,0,1,0,0,0, | |
| 1,0,0,0,1,0, | |
| 0,0,1,1,0,1, | |
| 0,1,1,1,1,0, | |
| 1,0,1,1,1,0, | |
| 0,1,1,1,1,1, | |
| 1,0,1,1,1,0, | |
| 0,1,0,1,0,1)) | |
| char_map=array.array('b',( | |
| 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00, # U+0030 (0) | |
| 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00, # U+0031 (1) | |
| 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00, # U+0032 (2) | |
| 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00, # U+0033 (3) | |
| 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00, # U+0034 (4) | |
| 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00, # U+0035 (5) | |
| 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00, # U+0036 (6) | |
| 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00, # U+0037 (7) | |
| 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00, # U+0038 (8) | |
| 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00)) # U+0039 (9) | |
| @micropython.viper | |
| def show_num_viper(num:int,x_offset:int,y_offset:int,color:int): | |
| char_ptr = ptr8(char_map) | |
| screen_ptr = ptr16(LCD.buffer) | |
| size = 1 # 1,2,3 | |
| char = 0 | |
| offset = MAXSCREEN_X*y_offset+x_offset | |
| while num > 0: | |
| total = num//10 | |
| digit = num - (total * 10) | |
| num = total | |
| for y in range(8): | |
| row_data = char_ptr[digit*8+y] | |
| for x in range(8): | |
| if row_data & (1<<x) > 0: | |
| addr = size*y*MAXSCREEN_X+x-(char*8)+offset | |
| screen_ptr[addr] = color | |
| if size>1: | |
| screen_ptr[MAXSCREEN_X+addr] = color | |
| if size>2: | |
| screen_ptr[2*MAXSCREEN_X+addr] = color | |
| char += 1 | |
| def init_pot(): | |
| global POT_X,POT_Y,POT_X_ZERO,POT_Y_ZERO | |
| POT_X = machine.ADC(27) | |
| POT_Y = machine.ADC(26) | |
| POT_X_ZERO = 0 | |
| POT_Y_ZERO = 0 | |
| for i in range(1000): | |
| POT_X_ZERO += POT_X.read_u16() | |
| POT_Y_ZERO += POT_Y.read_u16() | |
| POT_X_ZERO = POT_X_ZERO//1000 | |
| POT_Y_ZERO = POT_Y_ZERO//1000 | |
| pot_scale = 12 | |
| @micropython.viper | |
| def read_pot(): | |
| player = ptr32(PLAYER) | |
| missile = ptr32(MISSILE) | |
| pot_scale = 12 | |
| x_inc = int(POT_X.read_u16() - POT_X_ZERO)>>pot_scale | |
| y_inc = int(POT_Y.read_u16() - POT_Y_ZERO)>>pot_scale | |
| x_inc += 2 | |
| if x_inc < 2 and x_inc > -2: | |
| x_inc=0 | |
| if not FIRE_BUTTON.value(): | |
| player[FIRE] = 1 | |
| if missile[Y] == 0: | |
| if int(GAME_SOUND.SOUND) & 1<<3 == 0: | |
| GAME_SOUND.SOUND = int(GAME_SOUND.SOUND) | 1<<3 | |
| missile[Y] = PLAYER_Y-1 | |
| missile[X] = player[X] + 8 | |
| x = player[X] - x_inc//4 | |
| if x > 0 and x < 145: | |
| player[X] = x | |
| def init_invaders(): | |
| global INVADERS, ALIVE, FIRE_INV | |
| INVADERS = array.array('i',0 for _ in range(INVADER_PARAMS)) | |
| ALIVE = bytearray(5 * COLUMNS) # 3 = alive, 2 and 1 = exploding | |
| FIRE_INV = bytearray(11) # bottom invaders that can fire | |
| def init_player(): | |
| global PLAYER, MISSILE | |
| PLAYER = array.array('i',0 for _ in range(PLAYER_PARAMS)) | |
| MISSILE = array.array('i',0 for _ in range(MISSILE_PARAMS*3)) | |
| MISSILE[DIR] = -2 # player missile direction and speed | |
| MISSILE[DIR+MISSILE_PARAMS] = 1 # invader missile #1 dir and speed | |
| MISSILE[DIR+MISSILE_PARAMS*2] = 1 # invader missile #2 | |
| PLAYER[HIT] = 0 # 0=alive, 2,1 = exploding | |
| def init_game(): | |
| global GAME, FPS_ARRY | |
| GAME = array.array('i',0 for _ in range(GAME_PARAMS)) | |
| FPS_ARRY = bytearray(35) | |
| GAME[FPS] = 0 | |
| GAME[LIVES] = 3 | |
| def init_bunker(): | |
| global BUNKER | |
| BUNKER = bytearray(160*20) # 16 | |
| def reset_bunker(): | |
| for b in range(NUM_BUNKERS): | |
| for y in range(0,5): | |
| for x in range(5-y,17+y): | |
| BUNKER[y*MAXSCREEN_X+x+b*40+10] = 1 | |
| for y in range(5,16): | |
| for x in range(22): | |
| BUNKER[y*MAXSCREEN_X+x+b*40+10] = 1 | |
| for y in range(11,16): | |
| for x in range(19-y,3+y): | |
| BUNKER[y*MAXSCREEN_X+x+b*40+10] = 0 | |
| def reset_invaders(): | |
| for i in range(5 * COLUMNS): | |
| ALIVE[i] = 3 | |
| INVADERS[X] = 2 | |
| INVADERS[Y] = 0 | |
| INVADERS[DIR] = 1 | |
| INVADERS[COUNT] = 5 * COLUMNS | |
| GAME[TIME] = START_SPEED | |
| GAME[BUNKERS] = 1 | |
| @micropython.viper | |
| def move(): | |
| player = ptr32(PLAYER) | |
| game = ptr32(GAME) | |
| invaders = ptr32(INVADERS) | |
| alive = ptr8(ALIVE) | |
| if player[HIT] == 0: | |
| game[TOGGLE] ^= 1 | |
| invaders[X] += invaders[DIR] | |
| right_most = (COLUMNS * 14) - (invaders[RIGHT] * 14) | |
| left_most = invaders[LEFT] * 14 | |
| bottom_most = (3+invaders[BOTTOM]) * 10 + invaders[Y]//MAXSCREEN_X | |
| if invaders[X] > right_most or invaders[X]+left_most < 1 : # edge of screen, move down | |
| invaders[DIR] *= -1 | |
| invaders[Y] += 4*MAXSCREEN_X | |
| if bottom_most > BUNKER_Y+8: | |
| game[BUNKERS] = 0 | |
| if bottom_most > 130: | |
| game[LIVES] -= 1 | |
| reset_invaders() | |
| for i in range(5 * COLUMNS): # invader explosions | |
| if alive[i] < 3 and alive[i] > 0: | |
| alive[i] -= 1 | |
| if player[HIT] > 0: # player explosion | |
| player[HIT] -= 1 | |
| if player[HIT] == 0: | |
| game[LIVES] -= 1 | |
| if game[LIVES] == 0: | |
| game_over() | |
| @micropython.viper | |
| def move_missiles(): | |
| missile = ptr32(MISSILE) | |
| player = ptr32(PLAYER) | |
| for index in range(NUM_MISSILES): | |
| i = index * MISSILE_PARAMS | |
| if missile[Y + i] > 0 and missile[Y + i] < MAXSCREEN_Y-7: | |
| missile[Y + i] += missile[DIR + i] # move missile up or down | |
| miss_collision() | |
| missile[M_SPRITE + i] += 1 | |
| if missile[M_SPRITE + i] > 3*4: | |
| missile[M_SPRITE + i] = 0 | |
| elif i==0: | |
| player[FIRE] = 1 | |
| else: | |
| missile[Y + i] = 0 # clear missile from bottom | |
| @micropython.viper | |
| def miss_collision(): | |
| player = ptr32(PLAYER) | |
| missile = ptr32(MISSILE) | |
| invaders = ptr32(INVADERS) | |
| alive = ptr8(ALIVE) | |
| game = ptr32(GAME) | |
| bunker = ptr8(BUNKER) | |
| m_x = missile[X] | |
| m_y = missile[Y] | |
| inv_x = invaders[X] | |
| inv_y = invaders[Y] // MAXSCREEN_X | |
| for i in range(5 * COLUMNS): # check missile vs invaders | |
| if alive[i] == 3: | |
| i_x = (i % COLUMNS)*14 + inv_x | |
| i_y = (i // COLUMNS)*10 + inv_y + 10 | |
| if m_x > i_x and m_x < i_x + 14 and m_y > i_y and m_y < i_y + 14: | |
| GAME_SOUND.SOUND = int(GAME_SOUND.SOUND) | 1<<2 | |
| game[SCORE] += int(SCORE_MAP[i // COLUMNS]) | |
| player[FIRE] = 0 | |
| missile[Y] = 0 | |
| alive[i] -= 1 | |
| get_edges() | |
| game[TIME] -= SPEEDUP | |
| GAME_SOUND.BACK_TUNE[3] = 200 + game[TIME]*3 # 800 max | |
| invaders[COUNT] -= 1 | |
| if invaders[COUNT] == 0: | |
| reset_invaders() | |
| reset_bunker() | |
| p_x = player[X] | |
| p_y = PLAYER_Y | |
| pm_x = missile[X] # player missile | |
| pm_y = missile[Y] | |
| for index in range(1,NUM_MISSILES-1): | |
| i = index * MISSILE_PARAMS | |
| m_x = missile[X + i] | |
| m_y = missile[Y + i] | |
| if m_y > 0 and m_x > p_x and m_x < p_x + 16 and m_y > p_y and m_y < p_y + 8: # invader missile vs player | |
| missile[Y + i] = 0 | |
| player[HIT] = 10 #2 | |
| GAME_SOUND.SOUND = 1<<1 | |
| break | |
| if game[BUNKERS] == 1 and m_y >= BUNKER_Y and m_y < BUNKER_Y + 22: # invader missile vs bunker | |
| b_y = m_y-BUNKER_Y | |
| if bunker[b_y * MAXSCREEN_X + m_x] == 1: | |
| missile[Y + i] = 0 | |
| bunker_exp(m_x,b_y+2) | |
| if m_y > 0 and pm_y > 0 and m_x > pm_x and m_x < pm_x + 3 and m_y > pm_y and m_y < pm_y + 7: # invader missile vs player missile | |
| missile[Y + i] = 0 | |
| missile[Y] = 0 | |
| if game[BUNKERS] == 1 and pm_y >= BUNKER_Y and pm_y < BUNKER_Y + 22 and pm_x > 9: # player missile vs bunker | |
| b_y = pm_y-BUNKER_Y | |
| if bunker[b_y * MAXSCREEN_X + pm_x] == 1 or bunker[(b_y+1) * MAXSCREEN_X + pm_x] == 1 : | |
| missile[Y] = 0 | |
| bunker_exp(pm_x,b_y+2) | |
| @micropython.viper | |
| def bunker_exp(e_x:int,e_y:int): | |
| bunker = ptr8(BUNKER) | |
| exp_map= ptr8(EXP_MAP) | |
| for y in range(-4,4): | |
| for x in range(-3,3): | |
| bunk_addr = (e_y + y) * MAXSCREEN_X + e_x + x | |
| exp = exp_map[(y+4)*8 + x + 3] | |
| if exp == 1 and bunk_addr > 0 and bunk_addr < MAXSCREEN_X * 16: | |
| bunker[bunk_addr] = 0 | |
| @micropython.viper | |
| def get_edges(): | |
| game = ptr32(GAME) | |
| invaders = ptr32(INVADERS) | |
| alive = ptr8(ALIVE) | |
| fire_inv = ptr8(FIRE_INV) | |
| invaders[RIGHT] = 0 | |
| invaders[LEFT] = 10 | |
| invaders[BOTTOM] = 0 | |
| for i in range(5 * COLUMNS): | |
| if alive[i] == 3: | |
| x = i % COLUMNS | |
| y = i // COLUMNS | |
| if x > invaders[RIGHT]: invaders[RIGHT] = x | |
| if x < invaders[LEFT]: invaders[LEFT] = x | |
| if y > invaders[BOTTOM]: invaders[BOTTOM] = y | |
| for x in range(COLUMNS): # find the bottom invaders that can fire | |
| fire_inv[x] = 0 | |
| for y in range(5): | |
| if alive[y * COLUMNS + x] == 3: | |
| fire_inv[x] = y + 1 | |
| @micropython.viper | |
| def invaders_fire(): | |
| invaders = ptr32(INVADERS) | |
| missile = ptr32(MISSILE) | |
| fire_inv = ptr8(FIRE_INV) | |
| for index in range(1,NUM_MISSILES): | |
| i = index * MISSILE_PARAMS | |
| if missile[Y + i] > 0 and missile[Y + i] < MAXSCREEN_Y: continue | |
| firing_invader = int(randint(0,COLUMNS)) | |
| while fire_inv[firing_invader] == 0: # find random bottom invader | |
| firing_invader += 1 | |
| if firing_invader > COLUMNS: firing_invader = 0 # loop around | |
| missile[Y + i] = invaders[Y]//MAXSCREEN_X + fire_inv[firing_invader] * 8 + 10 | |
| missile[X + i] = invaders[X] + firing_invader * 14 + 7 | |
| missile[M_SPRITE2 + i] = int(randint(0,2))*4 # start sprite 0,4,8 | |
| missile[M_SPRITE + i] = 0 | |
| return | |
| @micropython.viper | |
| def draw_invaders(): | |
| sprites = ptr16(SPRITES) | |
| screen = ptr16(LCD.buffer) | |
| invaders = ptr32(INVADERS) | |
| game = ptr32(GAME) | |
| alive = ptr8(ALIVE) | |
| sprite_offset = 2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| screen_offset = invaders[Y]+10*MAXSCREEN_X + invaders[X] | |
| for x1 in range(COLUMNS): | |
| test_alive = alive[x1] | |
| if test_alive > 0: | |
| if test_alive < 3: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*5 + (test_alive)*8*S_WIDTH | |
| else: | |
| sprite_offset = 2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y*MAXSCREEN_X + x+x1*14+screen_offset] = color | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| screen_offset = invaders[Y]+20*MAXSCREEN_X + invaders[X] | |
| for y1 in range(2): | |
| for x1 in range(COLUMNS): | |
| test_alive = alive[(y1+1)*COLUMNS + x1] | |
| if test_alive > 0: | |
| if test_alive < 3: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*5 + (test_alive)*8*S_WIDTH | |
| else: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*2 + game[TOGGLE]*S_HEIGHT*S_WIDTH | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y1*10*MAXSCREEN_X+y*MAXSCREEN_X + x+x1*14+screen_offset] = color | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*4 + game[TOGGLE]*8*S_WIDTH | |
| screen_offset = invaders[Y]+40*MAXSCREEN_X + invaders[X] | |
| for y1 in range(2): | |
| for x1 in range(COLUMNS): | |
| test_alive = alive[(y1+3)*COLUMNS + x1] | |
| if test_alive > 0: | |
| if test_alive < 3: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*5 + (test_alive)*8*S_WIDTH | |
| else: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*4 + game[TOGGLE]*8*S_WIDTH | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y1*10*MAXSCREEN_X+y*MAXSCREEN_X + x+x1*14+screen_offset] = color | |
| @micropython.viper | |
| def draw_player(): | |
| sprites = ptr16(SPRITES) | |
| screen = ptr16(LCD.buffer) | |
| invaders = ptr32(INVADERS) | |
| player = ptr32(PLAYER) | |
| game = ptr32(GAME) | |
| if player[HIT] > 0: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*(11+(player[HIT]%2)) | |
| else: | |
| sprite_offset = 2 + S_WIDTH*S_HEIGHT*11 | |
| screen_offset = MAXSCREEN_X * PLAYER_Y + player[X] | |
| for y in range(S_HEIGHT): | |
| for x in range(S_WIDTH): | |
| color = sprites[sprite_offset + y*S_WIDTH + x] | |
| screen[y*MAXSCREEN_X + x+screen_offset] = color | |
| @micropython.viper | |
| def draw_bunker(): | |
| game = ptr32(GAME) | |
| bunker = ptr8(BUNKER) | |
| screen = ptr16(LCD.buffer) | |
| if not game[BUNKERS]: return | |
| screen_offset = MAXSCREEN_X*BUNKER_Y | |
| for y in range(BUNKER_HEIGHT): | |
| for x in range(MAXSCREEN_X): | |
| color = bunker[y*MAXSCREEN_X+x] | |
| if color > 0: | |
| screen[screen_offset + y * MAXSCREEN_X + x] = 0xe007 | |
| @micropython.viper | |
| def draw_missile(): | |
| missile = ptr32(MISSILE) | |
| screen = ptr16(LCD.buffer) | |
| miss_spr = ptr8(MISS_SPR) | |
| for index in range(1,NUM_MISSILES): # invader missiles | |
| i = index * MISSILE_PARAMS | |
| if missile[Y + i] > 0 and missile[Y + i] < MAXSCREEN_Y: | |
| x = missile[X + i] | |
| y = missile[Y + i] | |
| offset = missile[M_SPRITE2 + i] + (missile[M_SPRITE + i] // 4) | |
| for y1 in range(7): | |
| for x1 in range(3): | |
| miss_addr = y1 * 3 + x1 + (offset * 3 * 7) | |
| if miss_spr[miss_addr] == 0xff: | |
| screen[(y+y1) * 160 + x + x1] = 0xffff | |
| if missile[Y] > 0: # player missile | |
| x = missile[X] | |
| y = missile[Y] | |
| LCD.line(x,y,x,y+7,0xffff) | |
| def game_over(): | |
| GAME_SOUND.SOUND = 0 | |
| LCD.text('GAME OVER',40,50,0xff) | |
| LCD.show() | |
| exit() | |
| @micropython.viper | |
| def draw(): | |
| draw_invaders() | |
| draw_player() | |
| draw_bunker() | |
| draw_missile() | |
| game = ptr32(GAME) | |
| if game[SCORE] == 0: | |
| LCD.text('FPS',0,80,0xff) | |
| show_num_viper(game[FPS],40,80,0xff) | |
| if game[SCORE] == 10 : | |
| LCD.text('FREE MEM',0,90,0xff) | |
| show_num_viper(gc.mem_free(),120,90,0xff) | |
| LCD.text('SCORE',0,0,0xff) | |
| show_num_viper(game[SCORE],70,0,0xff) | |
| LCD.text('LIVES',100,0,0xff) | |
| show_num_viper(game[LIVES],145,0,0xff) | |
| LCD.show() | |
| LCD.rect(0,0,MAXSCREEN_X,MAXSCREEN_Y,0,1) | |
| @micropython.asm_thumb | |
| def avg_fps_asm(r0,r1): # r0 = fps[] , r1 = current_fps | |
| ldrb(r2,[r0,0]) # r2 = fps[0] | |
| add(r2,r2,1) # fps[0] += 1 | |
| cmp(r2,33) | |
| blt(LT_32) # if fps[0] > 32: | |
| mov(r2,1) | |
| label(LT_32) | |
| strb(r2,[r0,0]) # fps[0] = new index | |
| add(r2,r2,r0) | |
| strb(r1,[r2,0]) # fps[fps[0]] = current_fps | |
| mov(r2,1) # r2 = i | |
| mov(r3,0) # r3 = tot | |
| label(LOOP) | |
| add(r0,r0,1) | |
| ldrb(r4,[r0,0]) # r4 = fps[i] | |
| add(r3,r3,r4) # tot += fps[i] | |
| add(r2,r2,1) | |
| cmp(r2,33) #33 | |
| blt(LOOP) | |
| asr(r0,r3,5) | |
| @micropython.viper | |
| def core1(): | |
| global EXIT, GAME_SOUND | |
| GAME_SOUND = Game_Sound() | |
| GAME_SOUND.OFF = 0 | |
| while not EXIT: | |
| GAME_SOUND.callback1() | |
| sleep_ms(10) | |
| @micropython.viper | |
| def main(): | |
| init_pot() | |
| init_game() | |
| init_player() | |
| init_invaders() | |
| init_bunker() | |
| reset_bunker() | |
| reset_invaders() | |
| get_edges() | |
| game = ptr32(GAME) | |
| pot_ticks = 0 | |
| move_ticks = 0 | |
| inv_fire_ticks = 0 | |
| GAME_SOUND.SOUND = 1<<0 | |
| while not EXIT and not RESET_PB(): | |
| gticks = int(ticks_ms()) | |
| sleep(0.001) | |
| if gticks > pot_ticks + 10: | |
| pot_ticks = gticks | |
| read_pot() | |
| if gticks > move_ticks + game[TIME] and 1: | |
| move_ticks = gticks | |
| move() | |
| if gticks > inv_fire_ticks + game[TIME]*10: | |
| inv_fire_ticks = gticks | |
| invaders_fire() | |
| move_missiles() | |
| draw() | |
| game[FPS] = int(avg_fps_asm(FPS_ARRY,1_000//int(ticks_diff(ticks_ms(),gticks)))) | |
| def shutdown(): | |
| global EXIT | |
| EXIT = True | |
| Pin(16,Pin.OUT).low() # buzzer off | |
| pwm.deinit() | |
| Pin(13,Pin.OUT).low() # screen off | |
| gc.collect() | |
| print(gc.mem_free()) | |
| print('Core0 Stop') | |
| exit() | |
| if __name__=='__main__': | |
| FIRE_BUTTON = Pin(22, Pin.IN, Pin.PULL_UP) | |
| machine.freq(200_000_000) | |
| machine.mem32[0x40008048] = 1<<11 # enable peri_ctrl clock | |
| pwm = PWM(Pin(13)) | |
| pwm.freq(1000) | |
| pwm.duty_u16(0x8fff)#max 0xffff | |
| LCD = LCD_1inch8() | |
| LCD.fill(0) | |
| LCD.show() | |
| EXIT = False | |
| _thread.start_new_thread(core1, ()) | |
| try: | |
| main() | |
| shutdown() | |
| except KeyboardInterrupt : | |
| shutdown() | |
Author
@samneggs , Thanks for adding the missing elements 😉 I’m now able to run the program successfully. While exploring your repository filled with these great programs and strong educational value (especially the low-level optimizations using Viper, ASM, and PIO), I noticed that many of the programs have the same issue as this one — they’re missing key components (e.g., Centipede, Tetris, Hill Climb, Race Bots → sprite, texture, sound library, gfx library) that would allow them to run properly. It would be fantastic if you could also add the missing elements for those programs. A brief reference to the hardware and libraries used (e.g., GT911, GC9A01, etc.) would also be very helpful. Thanks again for sharing such interesting work!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Zorglupy
On the Pico run make_sprites.py and s_inv_miss-py to create the binaries needed.
I also added a modified version for the Pico2 that removes the problematic RESET_PB() and changes the overclocking address.