{"id":13297779,"url":"https://github.com/wiz21b/badapple","last_synced_at":"2025-03-10T09:33:21.119Z","repository":{"id":111245699,"uuid":"181200523","full_name":"wiz21b/badapple","owner":"wiz21b","description":"Bad Apple classic demo on a regular Apple ][+ with  floppy drive","archived":false,"fork":false,"pushed_at":"2021-08-08T11:08:10.000Z","size":488,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-07-29T17:52:40.735Z","etag":null,"topics":["apple2","appleii","demos","demoscene"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wiz21b.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-13T16:42:12.000Z","updated_at":"2024-05-29T18:54:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"f76250fd-1e53-48c0-b0f5-9887ff15ace1","html_url":"https://github.com/wiz21b/badapple","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wiz21b%2Fbadapple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wiz21b%2Fbadapple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wiz21b%2Fbadapple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wiz21b%2Fbadapple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wiz21b","download_url":"https://codeload.github.com/wiz21b/badapple/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242823809,"owners_count":20191065,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple2","appleii","demos","demoscene"],"created_at":"2024-07-29T17:27:23.563Z","updated_at":"2025-03-10T09:33:21.102Z","avatar_url":"https://github.com/wiz21b.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Bad Apple Demo\r\n--------------\r\n\r\nThis demo is the classic Bad Apple demo or \"how to fit a 3min video on a CPU absolutely not made for that\". Watch it on [YouTube](https://www.youtube.com/watch?v=IiSFeqedcho)\r\n\r\nHow to run\r\n----------\r\n\r\nDownload the [release](https://github.com/wiz21b/badapple/releases/download/1.0/BadApple.zip).\r\n\r\nOpen `BAD_DATA.DSK` file in your favourite emulator (I tested Mame and AppleWin).\r\nIt will run automatically. When requested to flip the disk, insert `BAD_APPLE_DATA.DSK` in the same drive.\r\nHit enter, and enjoy !\r\n\r\nBackground information\r\n----------------------\r\n\r\nI decided to do it after watching the demo from Onslaught on C64. It\r\nsounded sad to me that the Apple didn't run the Bad Apple :-)\r\n\r\nIt was made specifically for the Apple ][+ with floppy disk because\r\nthat's the computer I had when I was a kid. I also chose that machine\r\nbecause of its hardware limitations.\r\n\r\nFor those interested, my code is here, \"as is\".\r\n\r\nCompression\r\n-----------\r\n\r\nIf you're really interested, look at the kmean.py file.  That's the\r\ncompressor. This is what it does:\r\n\r\n1. drop some frames in the original video (chosen wisely)\r\n2. compute the delta between each frame, let's call that d-frames\r\n3. cut each d-frame in tiles of 8x8 pixels\r\n4. reduce the set of all tiles of all d-frames using k-means approach (basic Lloyd algorithm + euclidean distance; now that I think about it, euclidean distance may be replaced with IoU distance, could be better)\r\n5. use a form of RLE encoding to compress each run of tiles in d-frame (this gives \"stripes\")\r\n6. use a Huffman style dictionary to compress each stripe. Huffman is not practical on \r\n   low performance machines, so I had to make an \"approximation\" to reach a better\r\n   speed/compression balance.\r\n7. store the data on the disk (regular Prodos sectors, not a file)\r\n\r\nSteps 4 and 6 are clearly the more sophisticated ones.\r\n\r\nThe code is not super optimized and neither is the compressor.  Giving\r\nit more time, I think I could improve some more the screen size of the\r\nvideo. For example, I have the impression that using 16x16 tiles might\r\nbe more efficient, but in that case, the k-means approach must be tuned \r\nsome more.\r\n\r\nDecompression\r\n-------------\r\n\r\nThe decompressor is, of course written in assembler (6502 is 1MHz).\r\n\r\nIt has several gotcha's:\r\n* The Apple 2 has no timer. So if one wants to play a video at constant\r\n  speed, one has to figure out a time base. For that I use the rotation\r\n  speed of the disk drive. How clever :-)\r\n* The Apple 2 has no graphics CPU, no tricks whatsoever to accelerate drawing\r\n  so one has to move memory a lot, which affect performance a lot.\r\n* Reading disk sectors is CPU blocking, so I have to read sectors out of order\r\n  and mix reading and drawing on the screen in a way that the animation\r\n  has no hiccup's.\r\n* Huffman decompression is quite tricky, I've spent a lot of time to get it\r\n  to work and fast enough.\r\n* I need most of the memory to store Huffman's table and 8x8 tiles. So I have\r\n  to remove Prodos (fortunately, I could find RWTS routines source code)\r\n\r\n~~If you ever have the opportunity to run it on real Apple, please send\r\nme a video. That would be a very much apprciated gift.~~ It works on real hardware !\r\n\r\nFor those old enough and in the specific niche, I used to be called\r\nThe Wizard of the Imphobia group. By that time it was customary\r\nto send some greetings, so greetings to Scorpio, PL, Darkness,\r\nthe Overseas team, my family,...\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwiz21b%2Fbadapple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwiz21b%2Fbadapple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwiz21b%2Fbadapple/lists"}