From 0e3d9b9315997e547e8805163ec47802d437fa79 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira Date: Mon, 14 Oct 2024 21:09:56 +0200 Subject: [PATCH] Finish surl_stream_av asm, allow 'C' to mention people in Mastodon --- doc/mastodon-user-guide.odt | Bin 1401515 -> 1401564 bytes src/image-viewer/Makefile | 3 +- src/lib/asm/hgr.s | 85 ++++++++++++ src/lib/c/hgr.c | 16 +++ src/lib/hgr.c | 74 ----------- src/lib/hgr.h | 27 ++-- src/lib/surl.h | 3 +- src/lib/surl/surl_stream_av/6502.s | 18 ++- src/lib/surl/surl_stream_av/65c02.s | 17 ++- src/lib/surl/surl_stream_av/constants.inc | 3 + src/lib/surl/surl_stream_av/imports.inc | 25 +++- src/lib/surl/surl_stream_av/stream_url.c | 124 ------------------ src/lib/surl/surl_stream_av/stream_url.h | 6 - src/lib/surl/surl_stream_av/strings-a.inc | 14 ++ src/lib/surl/surl_stream_av/strings-b.inc | 11 ++ .../surl_stream_av/surl_start_stream_av.s | 32 +++++ src/lib/surl/surl_stream_av/surl_stream_av.s | 66 ++++++---- .../surl_stream_av/surl_stream_av_get_art.s | 10 ++ .../surl_stream_av_handle_preload.s | 16 +++ .../surl_stream_av_prepare_start.s | 44 +++++++ .../surl_stream_av_send_request.s | 51 +++++++ .../surl_stream_av/surl_stream_av_setup_ui.s | 31 +++++ .../surl_stream_av/update_load_progress.s | 45 +++++++ src/mastodon/Makefile | 12 +- src/mastodon/api/account.c | 2 - src/mastodon/api/media.c | 16 +-- src/mastodon/api/oauth.c | 15 ++- src/mastodon/cli/compose.c | 17 ++- src/mastodon/cli/img.c | 15 +-- src/mastodon/cli/login.c | 2 - src/mastodon/cli/tl.c | 13 +- src/quicktake/Makefile | 3 +- src/quicktake/qt-edit-image.c | 2 +- src/surl-server/surl_protocol.h | 2 +- src/wozamp/Makefile | 10 +- src/wozamp/videoplay.c | 3 +- src/woztubes/Makefile | 8 +- src/woztubes/main.c | 3 +- 38 files changed, 534 insertions(+), 310 deletions(-) create mode 100644 src/lib/asm/hgr.s create mode 100644 src/lib/c/hgr.c delete mode 100644 src/lib/hgr.c delete mode 100644 src/lib/surl/surl_stream_av/stream_url.c delete mode 100644 src/lib/surl/surl_stream_av/stream_url.h create mode 100644 src/lib/surl/surl_stream_av/strings-a.inc create mode 100644 src/lib/surl/surl_stream_av/strings-b.inc create mode 100644 src/lib/surl/surl_stream_av/surl_start_stream_av.s create mode 100644 src/lib/surl/surl_stream_av/surl_stream_av_get_art.s create mode 100644 src/lib/surl/surl_stream_av/surl_stream_av_handle_preload.s create mode 100644 src/lib/surl/surl_stream_av/surl_stream_av_prepare_start.s create mode 100644 src/lib/surl/surl_stream_av/surl_stream_av_send_request.s create mode 100644 src/lib/surl/surl_stream_av/surl_stream_av_setup_ui.s create mode 100644 src/lib/surl/surl_stream_av/update_load_progress.s diff --git a/doc/mastodon-user-guide.odt b/doc/mastodon-user-guide.odt index a45dadfc2f91acd30f02ba66282acd1a5e8f0e3a..edb2c5610633f2fc4530142e432387285727bfe9 100644 GIT binary patch delta 25288 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 diff --git a/src/image-viewer/Makefile b/src/image-viewer/Makefile index 3f0c96d8..b57b261a 100644 --- a/src/image-viewer/Makefile +++ b/src/image-viewer/Makefile @@ -25,7 +25,6 @@ imgview_SOURCES := \ imageview.c \ ../lib/file_select.c \ ../lib/progress_bar.c \ - ../lib/hgr.c \ ../lib/hgr_addrs.c \ ../lib/realloc_safe.c \ @@ -38,6 +37,7 @@ imgview_CC65SOURCES := \ ../lib/asm/path_helper.s \ ../lib/asm/clrzone.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/dputc.s \ ../lib/scroll.s \ ../lib/FVTABZ.s \ @@ -53,6 +53,7 @@ imgview_GCCSOURCES := \ ../lib/c/path_helper.c \ ../lib/c/clrzone.c \ ../lib/c/malloc0.c \ + ../lib/c/hgr.c \ ../lib/tgi_sdl.c \ ../lib/tgi_fastline.c \ ../lib/strtrim.c diff --git a/src/lib/asm/hgr.s b/src/lib/asm/hgr.s new file mode 100644 index 00000000..e68dd43c --- /dev/null +++ b/src/lib/asm/hgr.s @@ -0,0 +1,85 @@ +; +; Copyright (C) 2022-2024 Colin Leroy-Mira +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3 of the License, or +; (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . +; + .export _init_hgr + .export _init_text + .export _hgr_mixon + .export _hgr_mixoff + .export _hgr_init_done + .export _hgr_mix_is_on + + .data + +_hgr_init_done: .byte 0 +_hgr_mix_is_on: .byte 0 + + .segment "LOWCODE" + +_init_hgr: + .ifdef IIGS + cmp #$00 + bne @color_set + + lda #$80 + sta $C021 ; MONOCOLOR + lda $C029 ; NEWVIDEO + ora #$20 ; set bit 5 + sta $C029 + bne @color_set + + lda #$00 + sta $C021 ; MONOCOLOR + lda $C029 ; NEWVIDEO + and #$DF ; clear bit 5 + sta $C029 + .endif +@color_set: + + lda #$20 + sta $E6 ; HGRPAGE + + ; Set HGR mode + bit $C000 ; 80STORE + bit $C050 ; TXTCLR + bit $C052 ; MIXCLR + bit $C057 ; HIRES + bit $C054 ; LOWSCR + + ldx #1 + stx _hgr_init_done + dex + stx _hgr_mix_is_on + rts + +_init_text: + bit $C054 ; LOWSCR + bit $C051 ; TXTSET + bit $C056 ; LORES + lda #0 + sta _hgr_init_done + rts + +_hgr_mixon: + bit $C053 + lda #1 + sta _hgr_mix_is_on + rts + +_hgr_mixoff: + bit $C052 + lda #0 + sta _hgr_mix_is_on + rts diff --git a/src/lib/c/hgr.c b/src/lib/c/hgr.c new file mode 100644 index 00000000..084bbc2a --- /dev/null +++ b/src/lib/c/hgr.c @@ -0,0 +1,16 @@ +#include "hgr.h" + +char hgr_init_done = 0; +char hgr_mix_is_on = 0; + +#ifndef __CC65__ +#include "tgi_compat.h" + +void init_hgr(uint8 mono) { + tgi_init(); +} +void init_text(void) { + tgi_done(); +} + +#endif diff --git a/src/lib/hgr.c b/src/lib/hgr.c deleted file mode 100644 index 80a15863..00000000 --- a/src/lib/hgr.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "hgr.h" - -char hgr_init_done = 0; -char hgr_mix_is_on = 0; - -#pragma code-name(push, "LOWCODE") - -#ifndef __CC65__ -#include "tgi_compat.h" - -void init_hgr(uint8 mono) { - tgi_init(); -} -void init_text(void) { - tgi_done(); -} - -#else - -void init_hgr(uint8 mono) { -#ifdef __APPLE2__ - -#ifdef IIGS - if (mono) { - __asm__("lda #$80"); - __asm__("sta $C021"); /* MONOCOLOR */ - - __asm__("lda $C029"); /* NEWVIDEO */ - __asm__("ora #$20"); /* Set bit 5 */ - __asm__("sta $C029"); - - } else { - __asm__("lda #$00"); - __asm__("sta $C021"); /* MONOCOLOR */ - - __asm__("lda $C029"); /* NEWVIDEO */ - __asm__("and #$DF"); /* Clear bit 5 */ - __asm__("sta $C029"); - } -#endif - - #ifdef USE_HGR2 - __asm__("lda #$40"); - #else - __asm__("lda #$20"); - #endif - /* Set draw page */ - __asm__("sta $E6"); /* HGRPAGE */ - - /* Set graphics mode */ - __asm__("bit $C000"); /* 80STORE */ - __asm__("bit $C050"); /* TXTCLR */ - __asm__("bit $C052"); /* MIXCLR */ - __asm__("bit $C057"); /* HIRES */ - - /* Set view page */ - #ifdef USE_HGR2 - __asm__("bit $C055"); /* HISCR */ - #else - __asm__("bit $C054"); /* LOWSCR */ - #endif -#endif - hgr_init_done = 1; -} - -void init_text(void) { -#ifdef __APPLE2__ - switch_text(); -#endif - hgr_init_done = 0; -} -#endif - -#pragma code-name(pop) diff --git a/src/lib/hgr.h b/src/lib/hgr.h index 7f1b547d..7932e61c 100644 --- a/src/lib/hgr.h +++ b/src/lib/hgr.h @@ -7,30 +7,21 @@ #define HGR_WIDTH 280U #define HGR_HEIGHT 192U +void __fastcall__ init_hgr(uint8 mono); +void __fastcall__ init_text(void); +extern char hgr_mix_is_on; +extern char hgr_init_done; + #ifdef __CC65__ #define HGR_PAGE 0x2000 #define HGR_PAGE2 0x4000 -#else -extern char HGR_PAGE[HGR_LEN]; -#endif -extern char hgr_init_done; -extern char hgr_mix_is_on; -void init_hgr(uint8 mono); -void init_text(void); - -#ifdef __CC65__ -#define hgr_mixon() do { __asm__("bit $C053"); hgr_mix_is_on = 1; } while (0) -#define hgr_mixoff() do { __asm__("bit $C052"); hgr_mix_is_on = 0; } while (0) -#define switch_text() do { \ - __asm__("bit $C054"); /* LOWSCR */ \ - __asm__("bit $C051"); /* TXTSET */ \ - __asm__("bit $C056"); /* LORES */ \ -} while (0) -#define hgr_mix_is_on() hgr_mix_is_on +void __fastcall__ hgr_mixon(void); +void __fastcall__ hgr_mixoff(void); #else +extern char HGR_PAGE[HGR_LEN]; #define hgr_mixon() #define hgr_mixoff() -#define hgr_mix_is_on() 0 #endif + #endif diff --git a/src/lib/surl.h b/src/lib/surl.h index bb9db209..cddb406e 100644 --- a/src/lib/surl.h +++ b/src/lib/surl.h @@ -61,7 +61,8 @@ int __fastcall__ surl_get_json(char *buffer, const char *selector, const char *t int surl_wait_for_stream(void); int __fastcall__ surl_stream_video(void); int __fastcall__ surl_stream_audio(char numcols, char title_y, char vu_x, char vu_y); -int __fastcall__ surl_stream_av(void); +int __fastcall__ surl_stream_av(char *subtitles_url, char *url); + void __fastcall__ simple_serial_dump(char id, char *ptr, int nmemb); #else #define surl_stream_video() diff --git a/src/lib/surl/surl_stream_av/6502.s b/src/lib/surl/surl_stream_av/6502.s index e6bf7af4..eb464bf5 100644 --- a/src/lib/surl/surl_stream_av/6502.s +++ b/src/lib/surl/surl_stream_av/6502.s @@ -125,6 +125,9 @@ next = _zp10 ; word - next cycle JUMP_NEXT_DUTY ; 9 jump to next duty cycle .endmacro + .bss +got_art: .res 1 + .segment "CODE" ; Align each duty cycle function @@ -139,18 +142,31 @@ SAMPLE_MULT = 1 .align $100 .assert * = _SAMPLES_BASE + $100, error .include "duty-cycles/1.s" +; Add some setup function to fill in the gaps +.include "update_load_progress.s" +.include "surl_stream_av_send_request.s" +.include "surl_stream_av_setup_ui.s" +.include "surl_stream_av_get_art.s" .align $100 .assert * = _SAMPLES_BASE + $200, error .include "duty-cycles/2.s" +; Add some setup function to fill in the gaps +.include "surl_stream_av_prepare_start.s" +.include "surl_stream_av_handle_preload.s" +.include "surl_stream_av.s" .align $100 .assert * = _SAMPLES_BASE + $300, error .include "duty-cycles/3.s" +; Add some strings to fill in the gaps +.include "strings-a.inc" .align $100 .assert * = _SAMPLES_BASE + $400, error .include "duty-cycles/4.s" +; Add some strings to fill in the gaps +.include "strings-b.inc" .align $100 .assert * = _SAMPLES_BASE + $500, error @@ -258,7 +274,7 @@ SAMPLE_MULT = 1 .include "duty-cycles/26.s" ; Stuff code between duty cycles to optimize size -.include "surl_stream_av.s" +.include "surl_start_stream_av.s" .include "calc_bases.s" .include "calc_text_bases.s" .include "../surl_stream_common/patch_addresses.s" diff --git a/src/lib/surl/surl_stream_av/65c02.s b/src/lib/surl/surl_stream_av/65c02.s index 11298eb3..27dcb9b8 100644 --- a/src/lib/surl/surl_stream_av/65c02.s +++ b/src/lib/surl/surl_stream_av/65c02.s @@ -81,7 +81,6 @@ .include "constants.inc" .include "zp-variables.inc" .include "cycle-wasters.inc" - ; ----------------------------------------------------------------------------- ; CPU-specific constant and macros @@ -112,6 +111,10 @@ SAMPLE_MULT = 2 JUMP_NEXT_DUTY ; 9 jump to next duty cycle .endmacro + .bss + +got_art: .res 1 + .segment "CODE" ; The AVCODE segment location is non-important (apart of course it must not be @@ -190,7 +193,7 @@ _SAMPLES_BASE = * ; The rest of the functions don't need to be aligned. -.include "surl_stream_av.s" +.include "surl_start_stream_av.s" .include "../surl_stream_common/patch_addresses.s" .include "../surl_stream_common/patch_audio_registers.s" .include "patch_video_registers.s" @@ -199,7 +202,17 @@ _SAMPLES_BASE = * .include "video-data-data.inc" .include "audio-data.inc" +; Setup functions .include "setup.s" +.include "strings-a.inc" +.include "strings-b.inc" +.include "update_load_progress.s" +.include "surl_stream_av_send_request.s" +.include "surl_stream_av_setup_ui.s" +.include "surl_stream_av_get_art.s" +.include "surl_stream_av_prepare_start.s" +.include "surl_stream_av_handle_preload.s" +.include "surl_stream_av.s" ; ----------------------------------------------------------------------------- ; CPU-specific data (duty cycles handlers table) diff --git a/src/lib/surl/surl_stream_av/constants.inc b/src/lib/surl/surl_stream_av/constants.inc index 46e86ba4..2a4fdd88 100644 --- a/src/lib/surl/surl_stream_av/constants.inc +++ b/src/lib/surl/surl_stream_av/constants.inc @@ -20,3 +20,6 @@ PAGE1_HB = PAGE0_HB .endif SPKR := $C030 + +VIDEOMODE_40COL = $11 +VIDEOMODE_80COL = $12 diff --git a/src/lib/surl/surl_stream_av/imports.inc b/src/lib/surl/surl_stream_av/imports.inc index ca33f156..bcad5302 100644 --- a/src/lib/surl/surl_stream_av/imports.inc +++ b/src/lib/surl/surl_stream_av/imports.inc @@ -1,3 +1,4 @@ + .export _surl_start_stream_av .export _surl_stream_av .export _SAMPLES_BASE @@ -8,14 +9,36 @@ .import _simple_serial_get_cmd_reg .import _simple_serial_get_ctrl_reg + .import _enable_subtitles + .import _video_size + .import _translit_charset + .import _scrh + .import _hgr_mixon, _hgr_mixoff + .import _hgr_mix_is_on + .import _serial_putc_direct + .import _simple_serial_getc + .import _simple_serial_puts_nl .import _serial_read_byte_no_irq .import _simple_serial_set_irq .import _simple_serial_flush - .import _sleep, _init_text, _clrscr + + .import _surl_start_request + .import _surl_read_with_barrier + .import _ser_params .import acia_status_reg_r, acia_data_reg_r + .import _init_text, _init_hgr, _set_scrollwindow + .import _gotoxy, _cprintf, _videomode, _clrscr + .import _bzero, _memset, _sleep, _cputs + .import pusha, pusha0, push0, pushax, shlax3, popptr1 + + .importzp ptr1 + .include "apple2.inc" .include "../../simple_serial.inc" + .include "../../../surl-server/surl_protocol.inc" + .include "../../surl.inc" + .include "stdio.inc" diff --git a/src/lib/surl/surl_stream_av/stream_url.c b/src/lib/surl/surl_stream_av/stream_url.c deleted file mode 100644 index 6d3c2c14..00000000 --- a/src/lib/surl/surl_stream_av/stream_url.c +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "hgr.h" -#include "simple_serial.h" -#include "path_helper.h" -#include "surl.h" -#include "scrollwindow.h" - -#pragma code-name (push, STREAM_URL_SEGMENT) - -extern char enable_subtitles; -extern char video_size; -extern char *translit_charset; -extern unsigned char scrh; - -static void update_progress(void) { - unsigned char eta; - - simple_serial_putc(SURL_CLIENT_READY); - eta = simple_serial_getc(); - hgr_mixon(); - gotoxy(11, 0); /* strlen("Loading...") + 1 */ - if (eta == 255) - cputs("(Opening stream...)"); - else if (eta == 254) - cputs("(More than 30m remaining)"); - else - cprintf("(About %ds remaining) ", eta*8); -} - -int stream_url(char *url, char *subtitles_url) { - char r, got_art = 0; - - surl_start_request(NULL, 0, url, SURL_METHOD_STREAM_AV); - - simple_serial_puts_nl(translit_charset); - simple_serial_putc(1); /* Monochrome */ - if (enable_subtitles) { - simple_serial_putc(subtitles_url != NULL ? SUBTITLES_URL : SUBTITLES_AUTO); /* Enable subtitles */ - if (subtitles_url != NULL) { - simple_serial_puts(subtitles_url); - simple_serial_putc('\n'); - } - } else { - simple_serial_putc(SUBTITLES_NO); - } - - /* Do all of the slow things before finishing to send STREAM_AV parameters, - * otherwise proxy's going to start sending _STREAM_LOAD ETAs before we can - * answer. - */ - clrscr(); - set_scrollwindow(20, scrh); - init_hgr(1); - hgr_mixon(); - gotoxy(0, 0); - - /* clear text page 2 */ - memset((char*)0x800, ' '|0x80, 0x400); - -#ifdef __APPLE2ENH__ - cputs("Loading...\r\n" - "Controls: Space: Play/Pause, Esc: Quit player,\r\n" - " Left/Right: Rewind/Forward 10s, Up/Down: Rewind/Forward 1m\r\n" - " -/=/+: Volume up/default/down S: Toggle speed/quality"); -#else - cputs("Loading...\r\n" - "Space: play/pause, Esc: Quit player,\r\n" - "Left/right: Rew/Fwd 10s, U/J: 60s\r\n" - "-/=/+: Vol up/def/down, S: spd/quality "); -#endif - - /* Ready, send last parameter */ - simple_serial_putc(video_size); - -wait_load: - r = simple_serial_getc(); - if (r == SURL_ANSWER_STREAM_LOAD) { - update_progress(); - if (kbhit() && cgetc() == CH_ESC) - simple_serial_putc(SURL_METHOD_ABORT); - else - simple_serial_putc(SURL_CLIENT_READY); - goto wait_load; - } else if (r == SURL_ANSWER_STREAM_ART) { - surl_read_with_barrier((char *)HGR_PAGE, HGR_LEN); - got_art = 1; - simple_serial_putc(SURL_CLIENT_READY); - goto wait_load; - } else if (r == SURL_ANSWER_STREAM_START) { - simple_serial_putc(SURL_CLIENT_READY); - if (simple_serial_getc() == SURL_VIDEO_PORT_NOK) { - clrscr(); - cputs("Warning: proxy couldn't open video aux_tty.\r\nNo video available."); - sleep(5); - } - if (!got_art) { - bzero((char *)HGR_PAGE, HGR_LEN); - } -#ifdef __APPLE2ENH__ - videomode(VIDEOMODE_40COL); -#endif - hgr_mixoff(); - set_scrollwindow(0, scrh); - clrscr(); - surl_stream_av(); -#ifdef __APPLE2ENH__ - videomode(VIDEOMODE_80COL); -#endif - } else { - clrscr(); - cputs("Playback error"); - sleep(1); - } - set_scrollwindow(0, scrh); - return 0; -} -#pragma code-name (pop) diff --git a/src/lib/surl/surl_stream_av/stream_url.h b/src/lib/surl/surl_stream_av/stream_url.h deleted file mode 100644 index cd17f9da..00000000 --- a/src/lib/surl/surl_stream_av/stream_url.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __stream_url__h -#define __stream_url__h - -int stream_url(char *url, char *subtitles_url); - -#endif diff --git a/src/lib/surl/surl_stream_av/strings-a.inc b/src/lib/surl/surl_stream_av/strings-a.inc new file mode 100644 index 00000000..028f9bbf --- /dev/null +++ b/src/lib/surl/surl_stream_av/strings-a.inc @@ -0,0 +1,14 @@ + +eta_open_str: .asciiz "(Opening stream...)" +eta_long_str: .asciiz "(More than 30m remaining)" +eta_secs_str: .asciiz "(About %ds remaining) " +playback_err_str: .asciiz "Playback error" + +.ifdef __APPLE2ENH__ +no_video_str: .byte "Warning: proxy couldn't open video aux_tty.",$0D,$0A + .byte "No video available.", $00 + +.else +no_video_str: .byte "Warning: proxy can't open video aux_tty",$0D,$0A + .byte "No video available.", $00 +.endif diff --git a/src/lib/surl/surl_stream_av/strings-b.inc b/src/lib/surl/surl_stream_av/strings-b.inc new file mode 100644 index 00000000..9523de96 --- /dev/null +++ b/src/lib/surl/surl_stream_av/strings-b.inc @@ -0,0 +1,11 @@ +.ifdef __APPLE2ENH__ +controls_str: .byte "Loading...",$0D,$0A + .byte "Controls: Space: Play/Pause, Esc: Quit player,",$0D,$0A + .byte " Left/Right: Rewind/Forward 10s, Up/Down: Rewind/Forward 1m",$0D,$0A + .byte " -/=/+: Volume up/default/down S: Toggle speed/quality",$00 +.else +controls_str: .byte "Loading...",$0D,$0A + .byte "Space: play/pause, Esc: Quit player,",$0D,$0A + .byte "Left/right: Rew/Fwd 10s, U/J: 60s",$0D,$0A + .byte "-/=/+: Vol up/def/down, S: spd/quality",$00 +.endif diff --git a/src/lib/surl/surl_stream_av/surl_start_stream_av.s b/src/lib/surl/surl_stream_av/surl_start_stream_av.s new file mode 100644 index 00000000..36bfe7b7 --- /dev/null +++ b/src/lib/surl/surl_stream_av/surl_start_stream_av.s @@ -0,0 +1,32 @@ +_surl_start_stream_av: ; Entry point + php + sei ; Disable all interrupts + + pha + + lda #$00 ; Disable serial interrupts + jsr _simple_serial_set_irq + + pla + ; Setup pointers + jsr setup + + .ifdef DOUBLE_BUFFER + ; Clear HGR page 2 (page 1 must be done by caller) + bit $C082 + lda #$40 + sta $E6 + jsr $F3F2 + bit $C080 + .endif + + lda #$2F ; Surl client ready + jsr _serial_putc_direct + + clv ; clear offset-received flag + +ass: lda $A9FF ; Wait for an audio byte + and #HAS_BYTE + beq ass +ads: ldx $A8FF + JUMP_NEXT_9 diff --git a/src/lib/surl/surl_stream_av/surl_stream_av.s b/src/lib/surl/surl_stream_av/surl_stream_av.s index 97d63405..00687928 100644 --- a/src/lib/surl/surl_stream_av/surl_stream_av.s +++ b/src/lib/surl/surl_stream_av/surl_stream_av.s @@ -1,32 +1,48 @@ -_surl_stream_av: ; Entry point - php - sei ; Disable all interrupts +.proc _surl_stream_av + jsr surl_stream_av_send_request + jsr surl_stream_av_setup_ui - pha + ; Ready, send last parameter + lda _video_size + jsr _serial_putc_direct - lda #$00 ; Disable serial interrupts - jsr _simple_serial_set_irq + ; Now wait +@wait_load: + jsr _simple_serial_getc + cmp #SURL_ANSWER_STREAM_LOAD + beq @handle_stream_load + cmp #SURL_ANSWER_STREAM_ART + beq @handle_stream_art + cmp #SURL_ANSWER_STREAM_START + bne @handle_error - pla - ; Setup pointers - jsr setup +@handle_stream_start: + jsr surl_stream_av_prepare_start + jmp @stream_url_done - .ifdef DOUBLE_BUFFER - ; Clear HGR page 2 (page 1 must be done by caller) - bit $C082 - lda #$40 - sta $E6 - jsr $F3F2 - bit $C080 - .endif +@handle_stream_load: + jsr surl_stream_av_handle_preload + jmp @wait_load - lda #$2F ; Surl client ready - jsr _serial_putc_direct +@handle_stream_art: + jsr surl_stream_av_get_art + jmp @wait_load - clv ; clear offset-received flag +@handle_error: + jsr _clrscr + lda #playback_err_str + jsr _cputs + lda #1 + jsr _sleep + jmp @stream_url_done -ass: lda $A9FF ; Wait for an audio byte - and #HAS_BYTE - beq ass -ads: ldx $A8FF - JUMP_NEXT_9 +@stream_url_done: + lda #$00 + jsr pusha + lda _scrh + jsr _set_scrollwindow + lda #$00 + tax + rts +.endproc diff --git a/src/lib/surl/surl_stream_av/surl_stream_av_get_art.s b/src/lib/surl/surl_stream_av/surl_stream_av_get_art.s new file mode 100644 index 00000000..c6fdc3a4 --- /dev/null +++ b/src/lib/surl/surl_stream_av/surl_stream_av_get_art.s @@ -0,0 +1,10 @@ +.proc surl_stream_av_get_art + lda #<$2000 ; Read to HGR page + ldx #>$2000 + jsr pushax + ; AX already the correct length + jsr _surl_read_with_barrier + lda #SURL_CLIENT_READY + sta got_art + jmp _serial_putc_direct +.endproc diff --git a/src/lib/surl/surl_stream_av/surl_stream_av_handle_preload.s b/src/lib/surl/surl_stream_av/surl_stream_av_handle_preload.s new file mode 100644 index 00000000..3b41c5a0 --- /dev/null +++ b/src/lib/surl/surl_stream_av/surl_stream_av_handle_preload.s @@ -0,0 +1,16 @@ +.proc surl_stream_av_handle_preload + jsr update_load_progress + lda KBD + bmi @no_escape + + sta KBDSTRB + and #$7F + cmp #$1B ; Escape? + bne @no_escape + lda #SURL_METHOD_ABORT + bne @send_pong_char +@no_escape: + lda #SURL_CLIENT_READY +@send_pong_char: + jmp _serial_putc_direct +.endproc diff --git a/src/lib/surl/surl_stream_av/surl_stream_av_prepare_start.s b/src/lib/surl/surl_stream_av/surl_stream_av_prepare_start.s new file mode 100644 index 00000000..59336f51 --- /dev/null +++ b/src/lib/surl/surl_stream_av/surl_stream_av_prepare_start.s @@ -0,0 +1,44 @@ +.proc surl_stream_av_prepare_start + lda #SURL_CLIENT_READY + jsr _serial_putc_direct + + ; Check video port on proxy + jsr _simple_serial_getc + cmp #SURL_VIDEO_PORT_NOK + bne @video_ok + ; Inform there's no video available + jsr _clrscr + lda #no_video_str + jsr _cputs + lda #5 + jsr _sleep +@video_ok: + lda got_art + bne @hgr_is_set + + ; If we didn't get art, clear page + lda #<$2000 + ldx #>$2000 + jsr pushax + jsr _bzero + +@hgr_is_set: + .ifdef __APPLE2ENH__ + lda #VIDEOMODE_40COL + jsr _videomode + .endif + jsr _hgr_mixoff + lda #$00 + jsr pusha + lda _scrh + jsr _set_scrollwindow + jsr _clrscr + .ifdef __APPLE2ENH__ + jsr _surl_start_stream_av + lda #VIDEOMODE_80COL + jmp _videomode + .else + jmp _surl_start_stream_av + .endif +.endproc diff --git a/src/lib/surl/surl_stream_av/surl_stream_av_send_request.s b/src/lib/surl/surl_stream_av/surl_stream_av_send_request.s new file mode 100644 index 00000000..dd81588f --- /dev/null +++ b/src/lib/surl/surl_stream_av/surl_stream_av_send_request.s @@ -0,0 +1,51 @@ +.proc surl_stream_av_send_request + ; Backup url + pha + txa + pha + + ; setup surl request headers + jsr push0 ; Push AX 00 + jsr pusha ; Push A 0 + + sta got_art ; init got_art while we got a 0 + + ; URL + pla + tax + pla + jsr pushax + + ; Method + lda #SURL_METHOD_STREAM_AV + + ; Send request + jsr _surl_start_request + + lda _translit_charset + ldx _translit_charset+1 + jsr _simple_serial_puts_nl + + lda #1 ; Monochrome + jsr _serial_putc_direct + + jsr popptr1 ; Pop sub url to ptr1 + lda _enable_subtitles + .assert SUBTITLES_NO = 0, error + beq @no_subs + + ; Do we have a subtitles URL? + ldx ptr1+1 + beq @subs_no_url + + lda #SUBTITLES_URL + jsr _serial_putc_direct + lda ptr1 + jsr _simple_serial_puts_nl + rts +@subs_no_url: + lda #SUBTITLES_AUTO +@no_subs: + jmp _serial_putc_direct ; A=0 if coming from _enable_subtitles=0, + ; AUTO if no URL +.endproc diff --git a/src/lib/surl/surl_stream_av/surl_stream_av_setup_ui.s b/src/lib/surl/surl_stream_av/surl_stream_av_setup_ui.s new file mode 100644 index 00000000..a09d7c58 --- /dev/null +++ b/src/lib/surl/surl_stream_av/surl_stream_av_setup_ui.s @@ -0,0 +1,31 @@ +.proc surl_stream_av_setup_ui + ; Clear screen, setup HGR mix with scrollwindow + jsr _clrscr + lda #20 + jsr pusha + lda _scrh + jsr _set_scrollwindow + + lda #1 + jsr _init_hgr + jsr _hgr_mixon + jsr _clrscr + + ; Clear text page 2 + lda #<$0800 + ldx #>$0800 + jsr pushax + + lda #($20|$80) ; with non-inverse spaces + jsr pusha0 + + ; 1kB + lda #<$400 + ldx #>$400 + jsr _memset + + ; Show controls + lda #controls_str + jmp _cputs +.endproc diff --git a/src/lib/surl/surl_stream_av/update_load_progress.s b/src/lib/surl/surl_stream_av/update_load_progress.s new file mode 100644 index 00000000..6fed28bb --- /dev/null +++ b/src/lib/surl/surl_stream_av/update_load_progress.s @@ -0,0 +1,45 @@ +.proc update_load_progress + ; Go to correct place + lda #11 + jsr pusha + lda #0 + jsr _gotoxy + + ; Send ready + lda #SURL_CLIENT_READY + jsr _serial_putc_direct + + ; Get ETA + jsr _simple_serial_getc + cmp #$FF + beq @opening + cmp #$FE + beq @long +@secs: + ; < 254 means the estimate is about A<<3 seconds + pha + lda #eta_secs_str + jsr pushax + pla + ldx #$00 + jsr shlax3 + jsr pushax + ldy #$04 + bne @print +@long: + ; 254 means more than 30 minutes estimated + lda #eta_long_str + bne @print2 +@opening: + ; 255 means proxy is still opening the stream + lda #eta_open_str +@print2: + jsr pushax + ldy #$02 + +@print: + jmp _cprintf +.endproc diff --git a/src/mastodon/Makefile b/src/mastodon/Makefile index bd7a4c95..8cfecf1e 100644 --- a/src/mastodon/Makefile +++ b/src/mastodon/Makefile @@ -71,7 +71,6 @@ mastoimg_SOURCES := \ ../lib/file_select.c \ ../lib/strsplit.c \ ../lib/realloc_safe.c \ - ../lib/hgr.c \ ../lib/dgets.c ifdef IIGS @@ -82,8 +81,7 @@ mastoimg_CC65SOURCES := \ else mastoimg_CC65SOURCES := \ - ../lib/surl/surl_stream_av/$(CPU).s \ - ../lib/surl/surl_stream_av/stream_url.c + ../lib/surl/surl_stream_av/$(CPU).s endif @@ -99,6 +97,7 @@ mastoimg_CC65SOURCES := \ ../lib/asm/path_helper.s \ ../lib/asm/clrzone.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/FVTABZ.s \ ../lib/extrazp.s \ ../lib/surl/surl_wait_for_stream.c \ @@ -153,6 +152,7 @@ GCCSOURCES := \ ../lib/c/clrzone.c \ ../lib/c/path_helper.c \ ../lib/c/malloc0.c \ + ../lib/c/hgr.c \ ../lib/c/atoc.c \ ../lib/extended_conio.c \ ../lib/strtrim.c \ @@ -171,13 +171,11 @@ mastodon_CLCFLAGS = $(CLCFLAGS) -C ../../config/apple2enh-rtonce.cfg mastocli_CLCFLAGS = $(CLCFLAGS) -C ../../config/apple2enh-rtonce.cfg ifdef OLDII mastoimg_CLCFLAGS = $(CLCFLAGS) -C ../../config/apple2enh-mastoimg-6502.cfg \ - -DSTART_ADDR=0x3DA0 --start-addr 0x3DA0 \ - -DSTREAM_URL_SEGMENT='"LC"' + -DSTART_ADDR=0x3EA0 --start-addr 0x3EA0 else mastoimg_CLCFLAGS = $(CLCFLAGS) -C ../../config/apple2enh-mastoimg-65c02.cfg \ -DDOUBLE_BUFFER --asm-define DOUBLE_BUFFER \ - -DSTART_ADDR=0x5DA0 --start-addr 0x5DA0 \ - -DSTREAM_URL_SEGMENT='"LC"' + -DSTART_ADDR=0x5EA0 --start-addr 0x5EA0 endif mastowrite_CLCFLAGS = $(CLCFLAGS) -C ../../config/apple2enh-rtonce.cfg -DDGETS_MULTILINE diff --git a/src/mastodon/api/account.c b/src/mastodon/api/account.c index 7029650d..2c317c62 100644 --- a/src/mastodon/api/account.c +++ b/src/mastodon/api/account.c @@ -8,8 +8,6 @@ #include "strsplit.h" #include "api.h" -#define BUF_SIZE 255 - #ifdef __CC65__ #ifdef SURL_TO_LANGCARD #pragma code-name (push, "LC") diff --git a/src/mastodon/api/media.c b/src/mastodon/api/media.c index 64fe0c79..22cae698 100644 --- a/src/mastodon/api/media.c +++ b/src/mastodon/api/media.c @@ -10,16 +10,16 @@ #include "api.h" #ifdef __CC65__ -#pragma code-name (push, "LOWCODE") +#pragma code-name (push, "LC") #endif #define IMG_BUF_SIZE 2048 static char img_buf[IMG_BUF_SIZE]; -#ifdef USE_HGR2 - #define NUMCOLS 40 +#ifdef __APPLE2ENH__ +#define NUMCOLS 80 #else - #define NUMCOLS 80 +#define NUMCOLS 40 #endif static media *media_new_from_json(char *base_selector, char *description_selector) { @@ -117,11 +117,11 @@ media *api_get_status_media(char *id) { id); } +#ifdef __CC65__ +#pragma code-name (pop) +#endif + media *api_get_account_media(char *id) { return get_media(ACCOUNTS_ENDPOINT, ".id,.avatar_static,.id,.header_static", NULL, id); } - -#ifdef __CC65__ -#pragma code-name (pop) -#endif diff --git a/src/mastodon/api/oauth.c b/src/mastodon/api/oauth.c index 81e30593..d541fa36 100644 --- a/src/mastodon/api/oauth.c +++ b/src/mastodon/api/oauth.c @@ -9,18 +9,13 @@ #include "strsplit.h" #include "dputs.h" #include "extended_conio.h" +#include "common.h" /* This is heavily based on screen-scraping and not very solid. * Maybe using https://github.com/lexbor/lexbor proxy-side would be * better. */ -#ifdef __CC65__ -#pragma code-name (push, "LOWCODE") -#endif - -#define BUF_SIZE 255 - #define LOGIN_URL "/auth/sign_in" #define REGISTER_URL "/api/v1/apps" #define REDIRECT_URI "urn:ietf:wg:oauth:2.0:oob" @@ -67,6 +62,10 @@ static char *get_csrf_token(char *body, size_t buf_size) { return token; } +#ifdef __CC65__ +#pragma code-name (push, "LC") +#endif + static char *get_oauth_code(char *body) { char *w, *token = NULL; size_t len; @@ -316,6 +315,10 @@ int do_login(void) { } +#ifdef __CC65__ +#pragma code-name (pop) +#endif + static char *prepare_app_register_post(void) { char *data; diff --git a/src/mastodon/cli/compose.c b/src/mastodon/cli/compose.c index 1573bc34..c4a72bc9 100644 --- a/src/mastodon/cli/compose.c +++ b/src/mastodon/cli/compose.c @@ -559,6 +559,7 @@ static void compose_toot(char *initial_buf) { int main(int argc, char **argv) { char *params; + char *text = NULL; surl_user_agent = "Mastodon for Apple II / "VERSION; @@ -619,7 +620,15 @@ int main(int argc, char **argv) { } } } - } else { + } else if (argc == 5) { + text = malloc(strlen(argv[4])+2); + if (text) { + text[0] = arobase; + strcpy(text+1, argv[4]); + while (strchr(text, '@')) { + *(strchr(text, '@')) = arobase; + } + } ref_status = NULL; } @@ -634,8 +643,12 @@ int main(int argc, char **argv) { compose_toot(orig_status); free(orig_status); } else { - compose_toot(""); + if (text == NULL) { + text = strdup(""); + } + compose_toot(text); } + free(text); set_hscrollwindow(0, scrw); params = malloc0(127); diff --git a/src/mastodon/cli/img.c b/src/mastodon/cli/img.c index b3a78d27..128e8ae0 100644 --- a/src/mastodon/cli/img.c +++ b/src/mastodon/cli/img.c @@ -15,10 +15,6 @@ * along with this program. If not, see . */ -#ifdef __CC65__ -#pragma code-name (push, "LC") -#endif - #include #include #include @@ -37,7 +33,6 @@ #include "common.h" #include "path_helper.h" #include "dgets.h" -#include "surl/surl_stream_av/stream_url.h" char *instance_url; char *oauth_token; @@ -106,7 +101,7 @@ static void stream_msg(char *msg) { cputs(msg); } -int stream_url(char *url, char *unused) { +int __fastcall__ surl_stream_av(char *unused, char *url) { #ifdef __APPLE2ENH__ videomode(VIDEOMODE_40COL); #endif @@ -240,7 +235,7 @@ int main(int argc, char **argv) { #ifdef __CC65__ bzero((char *)HGR_PAGE, HGR_LEN); clrscr(); - stream_url(m->media_url[0], NULL); + surl_stream_av(NULL, m->media_url[0]); clrscr(); init_text(); #endif @@ -292,10 +287,9 @@ int main(int argc, char **argv) { } #ifdef __CC65__ -#pragma code-name (pop) +#pragma code-name (push, "LC") #endif - static void save_image(void) { unsigned char prev_legend = legend; char buf[FILENAME_MAX + 1]; @@ -347,3 +341,6 @@ static void save_image(void) { if (!prev_legend) toggle_legend(0); } +#ifdef __CC65__ +#pragma code-name (pop) +#endif diff --git a/src/mastodon/cli/login.c b/src/mastodon/cli/login.c index 96c4507d..8b92762d 100644 --- a/src/mastodon/cli/login.c +++ b/src/mastodon/cli/login.c @@ -37,8 +37,6 @@ #include "runtime_once_clean.h" #include "config.h" -#define BUF_SIZE 255 - unsigned char scrw, scrh; char *instance_url = NULL; char *client_id = NULL; diff --git a/src/mastodon/cli/tl.c b/src/mastodon/cli/tl.c index f1bb3378..17c7f4f7 100644 --- a/src/mastodon/cli/tl.c +++ b/src/mastodon/cli/tl.c @@ -24,7 +24,9 @@ #include "scrollwindow.h" #include "runtime_once_clean.h" -#define BUF_SIZE 255 +#ifdef __CC65__ +#pragma code-name (push, "LC") +#endif #pragma register-vars(push, on) @@ -182,6 +184,10 @@ static void item_free(list *l, char i) { } } +#ifdef __CC65__ +#pragma code-name (pop) +#endif + static item *item_get(list *l, char i, char full) { if (l->kind == SHOW_NOTIFICATIONS) { return (item *)api_get_notification(l->ids[i]); @@ -1307,7 +1313,10 @@ static void cli(void) { launch_command("mastodon", "conf", NULL, NULL); /* we're never coming back */ case COMPOSE: - launch_command("mastowrite", NULL, NULL, NULL); + if (current_list->account) + launch_command("mastowrite", current_list->account->acct, NULL, NULL); + else + launch_command("mastowrite", NULL, NULL, NULL); /* we're never coming back */ case REPLY: if (disp_status) diff --git a/src/quicktake/Makefile b/src/quicktake/Makefile index f988da7a..f4078839 100644 --- a/src/quicktake/Makefile +++ b/src/quicktake/Makefile @@ -49,7 +49,6 @@ slowtake_SOURCES := \ ../lib/realloc_safe.c \ ../lib/file_select.c \ ../lib/progress_bar.c \ - ../lib/hgr.c \ ../lib/hgr_addrs.c \ $(debug_SOURCES) @@ -62,6 +61,7 @@ slowtake_CC65SOURCES := \ ../lib/asm/scrollwindow.s \ ../lib/asm/path_helper.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/dputc.s \ ../lib/scroll.s \ ../lib/FVTABZ.s \ @@ -78,6 +78,7 @@ slowtake_GCCSOURCES := \ ../lib/serial/c/serial_control.c \ ../lib/c/scrollwindow.c \ ../lib/c/malloc0.c \ + ../lib/c/hgr.c \ ../lib/tgi_sdl.c \ ../lib/tgi_fastline.c diff --git a/src/quicktake/qt-edit-image.c b/src/quicktake/qt-edit-image.c index 5f663425..9cb01352 100644 --- a/src/quicktake/qt-edit-image.c +++ b/src/quicktake/qt-edit-image.c @@ -419,7 +419,7 @@ static uint8 reedit_image(const char *ofname, uint16 src_width) { : dither_alg == DITHER_SIERRA ? "Sierra Lite" : "None"); c = tolower(cgetc()); #ifdef __CC65__ - if (!hgr_mix_is_on()) { + if (!hgr_mix_is_on) { hgr_mixon(); } else #endif diff --git a/src/surl-server/surl_protocol.h b/src/surl-server/surl_protocol.h index 69c66474..54b01498 100644 --- a/src/surl-server/surl_protocol.h +++ b/src/surl-server/surl_protocol.h @@ -3,7 +3,7 @@ /* Update in .inc too! */ #define SURL_PROTOCOL_VERSION 21 -#define VERSION "21.0.0" +#define VERSION "21.0.1" #define SURL_CLIENT_READY 0x2F #define HGR_LEN 8192U diff --git a/src/wozamp/Makefile b/src/wozamp/Makefile index de9824f1..7bf41eed 100644 --- a/src/wozamp/Makefile +++ b/src/wozamp/Makefile @@ -17,7 +17,6 @@ upload_subdir := CC65_TARGET := apple2 BUILD_VIDEOPLAY := 1 STREAMER_VER := 6502 -STREAM_URL_SEGMENT := "CODE" VIDEOPLAY_START_ADDR := 0x1D00 EMBED_RBROWSER := EXTERNAL_RBROWSER := rbrowser.bin @@ -29,7 +28,6 @@ CC65_TARGET = apple2enh trgt = apple2c0 BUILD_VIDEOPLAY := 1 STREAMER_VER := 65c02 -STREAM_URL_SEGMENT := "CODE" VIDEOPLAY_START_ADDR := 0x1D00 EMBED_RBROWSER := radio-browser.c ../lib/surl/asm/surl_get_json.s EXTERNAL_RBROWSER := @@ -51,7 +49,6 @@ wozamp_SOURCES := \ wozamp_CL65SOURCES = \ ../lib/surl/surl_stream_audio/$(STREAMER_VER).s \ - ../lib/hgr.c \ ../lib/serial/asm/simple_serial.s \ ../lib/serial/asm/simple_serial_io.s \ ../lib/serial/asm/simple_serial_configure.s \ @@ -63,6 +60,7 @@ wozamp_CL65SOURCES = \ ../lib/asm/scrollwindow.s \ ../lib/asm/path_helper.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/dputc.s \ ../lib/scroll.s \ ../lib/FVTABZ.s \ @@ -90,7 +88,6 @@ rbrowser_SOURCES := \ rbrowser_CL65SOURCES = \ ../lib/surl/surl_stream_audio/$(STREAMER_VER).s \ - ../lib/hgr.c \ ../lib/serial/asm/simple_serial.s \ ../lib/serial/asm/simple_serial_io.s \ ../lib/serial/$(serial_hw)/common.s \ @@ -102,6 +99,7 @@ rbrowser_CL65SOURCES = \ ../lib/asm/scrollwindow.s \ ../lib/asm/path_helper.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/dputc.s \ ../lib/dputs.s \ ../lib/scroll.s \ @@ -130,9 +128,7 @@ rbrowser_CLCFLAGS = -t $(CC65_TARGET) \ ifdef BUILD_VIDEOPLAY videoplay_SOURCES := \ ../lib/surl/surl_stream_av/$(STREAMER_VER).s \ - ../lib/surl/surl_stream_av/stream_url.c \ videoplay.c \ - ../lib/hgr.c \ ../lib/FVTABZ.s \ ../lib/serial/asm/simple_serial.s \ ../lib/serial/asm/simple_serial_io.s \ @@ -144,12 +140,12 @@ videoplay_SOURCES := \ ../lib/asm/scrollwindow.s \ ../lib/asm/path_helper.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/fastirq$(iigs_suffix).s \ ../lib/extrazp.s videoplay_CLCFLAGS = -t $(CC65_TARGET) \ -DDOUBLE_BUFFER --asm-define DOUBLE_BUFFER \ - -DSTREAM_URL_SEGMENT='$(STREAM_URL_SEGMENT)' \ -I ../lib \ -Wl -D,__STACKSIZE__=0x0400 -C ../../config/apple2enh-wozamp-videoplay.cfg \ -vm -m videoplay.map $(USE_LANGCARD) -O --start-addr $(VIDEOPLAY_START_ADDR) diff --git a/src/wozamp/videoplay.c b/src/wozamp/videoplay.c index 154be9db..7c6d5143 100644 --- a/src/wozamp/videoplay.c +++ b/src/wozamp/videoplay.c @@ -13,7 +13,6 @@ #include "config.h" #include "splash-video.h" #include "scrollwindow.h" -#include "surl/surl_stream_av/stream_url.h" char *translit_charset; char monochrome = 1; @@ -65,7 +64,7 @@ int main(void) { } reopen_start_device(); - stream_url(url, NULL); + surl_stream_av(NULL, url); out: clrscr(); diff --git a/src/woztubes/Makefile b/src/woztubes/Makefile index e84b6605..a84407b1 100644 --- a/src/woztubes/Makefile +++ b/src/woztubes/Makefile @@ -13,7 +13,7 @@ suffix := upload_subdir := CC65_TARGET := apple2 STREAMER_VER := 6502 -START_ADDR := 0xD3A +START_ADDR := 0x113A else serial_hw := acia iigs_suffix := @@ -21,7 +21,7 @@ iigs_CFLAGS := CC65_TARGET = apple2enh trgt = apple2c0 STREAMER_VER := 65c02 -START_ADDR := 0xD3A +START_ADDR := 0x113A endif endif @@ -36,11 +36,9 @@ GCCCFLAGS = -g -O0 -DCONF_FILE_PATH=\"/etc/a2tools/tty.conf\" \ woztubes_SOURCES := \ ../lib/surl/surl_stream_av/$(STREAMER_VER).s \ - ../lib/surl/surl_stream_av/stream_url.c \ main.c \ video_providers.c \ config.c \ - ../lib/hgr.c \ ../lib/scroll.s \ ../lib/dputc.s \ ../lib/dgets.c \ @@ -58,6 +56,7 @@ woztubes_SOURCES := \ ../lib/asm/path_helper.s \ ../lib/asm/clrzone.s \ ../lib/asm/malloc0.s \ + ../lib/asm/hgr.s \ ../lib/surl/surl_ping.c \ ../lib/extrazp.s \ ../lib/citoa.s \ @@ -83,7 +82,6 @@ woztubes_CLCFLAGS = -t $(CC65_TARGET) -I ../lib \ -DBUF_1K_ADDR=0x800 -DBUF_1K_SIZE=0x3FF \ -DBUF_8K_ADDR=0x4000 -DBUF_8K_SIZE=0x1FFF \ -DDOUBLE_BUFFER --asm-define DOUBLE_BUFFER \ - -DSTREAM_URL_SEGMENT='"LOWCODE"' \ -Wl -D,__STACKSIZE__=0x0400 -C ../../config/apple2enh-woztubes.cfg \ -vm -m woztubes.map $(USE_LANGCARD) -O --start-addr $(START_ADDR) diff --git a/src/woztubes/main.c b/src/woztubes/main.c index b6be9e8e..12650d51 100644 --- a/src/woztubes/main.c +++ b/src/woztubes/main.c @@ -40,7 +40,6 @@ #include "splash.h" #include "malloc0.h" #include "citoa.h" -#include "surl/surl_stream_av/stream_url.h" #include "video_providers.h" char *url = NULL; @@ -243,7 +242,7 @@ static void load_video(char *host, InstanceTypeId instance_type, char *id) { } } - stream_url(video_url, captions_url); + surl_stream_av(captions_url, video_url); set_scrollwindow(20, scrh); #ifdef __APPLE2ENH__